diff options
| author | Brian Potchik <brian@vector35.com> | 2024-03-02 14:38:47 -0500 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2024-03-02 14:38:47 -0500 |
| commit | 2e3b9c925390cc8b1d72a41d0564bb2862d3dba2 (patch) | |
| tree | f40495cd494b8c157a0298259019873a624dc7e2 | |
| parent | ff2aa7435c3847f6969364f5d04d0943918429be (diff) | |
Add support for memory intrinsics.
| -rw-r--r-- | architecture.cpp | 26 | ||||
| -rw-r--r-- | binaryninjaapi.h | 13 | ||||
| -rw-r--r-- | binaryninjacore.h | 23 | ||||
| -rw-r--r-- | docs/dev/bnil-llil.md | 19 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 26 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 22 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 20 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 12 | ||||
| -rw-r--r-- | python/architecture.py | 24 | ||||
| -rw-r--r-- | python/lowlevelil.py | 75 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 67 | ||||
| -rw-r--r-- | rust/src/architecture.rs | 16 | ||||
| -rw-r--r-- | rust/src/mlil/instruction.rs | 3 |
13 files changed, 319 insertions, 27 deletions
diff --git a/architecture.cpp b/architecture.cpp index 7c9cc9b5..979ba3e2 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -595,6 +595,13 @@ void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, B } +BNIntrinsicClass Architecture::GetIntrinsicClassCallback(void* ctxt, uint32_t intrinsic) +{ + CallbackRef<Architecture> arch(ctxt); + return arch->GetIntrinsicClass(intrinsic); +} + + char* Architecture::GetIntrinsicNameCallback(void* ctxt, uint32_t intrinsic) { CallbackRef<Architecture> arch(ctxt); @@ -803,6 +810,7 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterStackName = GetRegisterStackNameCallback; callbacks.getAllRegisterStacks = GetAllRegisterStacksCallback; callbacks.getRegisterStackInfo = GetRegisterStackInfoCallback; + callbacks.getIntrinsicClass = GetIntrinsicClassCallback; callbacks.getIntrinsicName = GetIntrinsicNameCallback; callbacks.getAllIntrinsics = GetAllIntrinsicsCallback; callbacks.getIntrinsicInputs = GetIntrinsicInputsCallback; @@ -1118,6 +1126,12 @@ uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg) } +BNIntrinsicClass Architecture::GetIntrinsicClass(uint32_t intrinsic) +{ + return GeneralIntrinsicClass; +} + + string Architecture::GetIntrinsicName(uint32_t intrinsic) { return fmt::format("intrinsic_{}", intrinsic); @@ -1756,6 +1770,12 @@ BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack) } +BNIntrinsicClass CoreArchitecture::GetIntrinsicClass(uint32_t intrinsic) +{ + return BNGetArchitectureIntrinsicClass(m_object, intrinsic); +} + + string CoreArchitecture::GetIntrinsicName(uint32_t intrinsic) { char* name = BNGetArchitectureIntrinsicName(m_object, intrinsic); @@ -2129,6 +2149,12 @@ BNRegisterStackInfo ArchitectureExtension::GetRegisterStackInfo(uint32_t regStac } +BNIntrinsicClass ArchitectureExtension::GetIntrinsicClass(uint32_t intrinsic) +{ + return m_base->GetIntrinsicClass(intrinsic); +} + + string ArchitectureExtension::GetIntrinsicName(uint32_t intrinsic) { return m_base->GetIntrinsicName(intrinsic); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a0178ca8..741f399d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -7491,6 +7491,7 @@ namespace BinaryNinja { static uint32_t* GetAllRegisterStacksCallback(void* ctxt, size_t* count); static void GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result); + static BNIntrinsicClass GetIntrinsicClassCallback(void* ctxt, uint32_t intrinsic); static char* GetIntrinsicNameCallback(void* ctxt, uint32_t intrinsic); static uint32_t* GetAllIntrinsicsCallback(void* ctxt, size_t* count); static BNNameAndType* GetIntrinsicInputsCallback(void* ctxt, uint32_t intrinsic, size_t* count); @@ -7774,11 +7775,7 @@ namespace BinaryNinja { virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack); uint32_t GetRegisterStackForRegister(uint32_t reg); - /*! Gets an intrinsic name from an intrinsic number. - - \param intrinsic Intrinsic number - \return The corresponding intrinsic string - */ + virtual BNIntrinsicClass GetIntrinsicClass(uint32_t intrinsic); virtual std::string GetIntrinsicName(uint32_t intrinsic); virtual std::vector<uint32_t> GetAllIntrinsics(); virtual std::vector<NameAndType> GetIntrinsicInputs(uint32_t intrinsic); @@ -8058,6 +8055,7 @@ namespace BinaryNinja { virtual std::vector<uint32_t> GetAllRegisterStacks() override; virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override; + virtual BNIntrinsicClass GetIntrinsicClass(uint32_t intrinsic) override; virtual std::string GetIntrinsicName(uint32_t intrinsic) override; virtual std::vector<uint32_t> GetAllIntrinsics() override; virtual std::vector<NameAndType> GetIntrinsicInputs(uint32_t intrinsic) override; @@ -8141,6 +8139,7 @@ namespace BinaryNinja { virtual std::vector<uint32_t> GetAllRegisterStacks() override; virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override; + virtual BNIntrinsicClass GetIntrinsicClass(uint32_t intrinsic) override; virtual std::string GetIntrinsicName(uint32_t intrinsic) override; virtual std::vector<uint32_t> GetAllIntrinsics() override; virtual std::vector<NameAndType> GetIntrinsicInputs(uint32_t intrinsic) override; @@ -11999,6 +11998,8 @@ namespace BinaryNinja { const std::vector<ExprId>& params, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId IntrinsicSSA(const std::vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic, const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryIntrinsicSSA(const std::vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic, + const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); /*! Returns a processor breakpoint expression. @@ -12649,6 +12650,8 @@ namespace BinaryNinja { const ILSourceLocation& loc = ILSourceLocation()); ExprId IntrinsicSSA(const std::vector<SSAVariable>& outputs, uint32_t intrinsic, const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryIntrinsicSSA(const std::vector<SSAVariable>& outputs, uint32_t intrinsic, + const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); ExprId FreeVarSlot(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); ExprId FreeVarSlotSSA(const Variable& var, size_t newVersion, size_t prevVersion, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index 8fd5e8a6..d5fcdcce 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 54 +#define BN_CURRENT_CORE_ABI_VERSION 55 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 53 +#define BN_MINIMUM_CORE_ABI_VERSION 55 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -599,15 +599,16 @@ extern "C" LLIL_SYSCALL_SSA, LLIL_TAILCALL_SSA, LLIL_CALL_PARAM, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA, LLIL_INTRINSIC, LLIL_INTRINSIC_SSA, - // LLIL_TAILCALL, LLIL_TAILCALL_SSA instructions + // LLIL_MEMORY_INTRINSIC_SSA, LLIL_TAILCALL, LLIL_TAILCALL_SSA instructions LLIL_CALL_STACK_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions LLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions LLIL_SEPARATE_PARAM_LIST_SSA, // Only valid within the LLIL_CALL_PARAM instruction - LLIL_SHARED_PARAM_SLOT_SSA, // Only valid within the LLIL_CALL_PARAM or LLIL_SEPARATE_PARAM_LIST_SSA - // instructions + LLIL_SHARED_PARAM_SLOT_SSA, // Only valid within the LLIL_CALL_PARAM or LLIL_SEPARATE_PARAM_LIST_SSA instructions + LLIL_MEMORY_INTRINSIC_OUTPUT_SSA, // Only valid within the LLIL_MEMORY_INTRINSIC_SSA instruction LLIL_LOAD_SSA, LLIL_STORE_SSA, LLIL_INTRINSIC_SSA, + LLIL_MEMORY_INTRINSIC_SSA, LLIL_REG_PHI, LLIL_REG_STACK_PHI, LLIL_FLAG_PHI, @@ -933,6 +934,12 @@ extern "C" ILPreventAliasAnalysis = 0x20 } BNILInstructionAttribute; + typedef enum BNIntrinsicClass + { + GeneralIntrinsicClass, + MemoryIntrinsicClass + } BNIntrinsicClass; + typedef struct BNLowLevelILInstruction { BNLowLevelILOperation operation; @@ -1241,15 +1248,17 @@ extern "C" MLIL_SYSCALL_UNTYPED_SSA, MLIL_TAILCALL_SSA, MLIL_TAILCALL_UNTYPED_SSA, - MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA family + MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA, MLIL_INTRINSIC_SSA family // instructions MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA family // instructions + MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, // Only valid within the MLIL_MEMORY_INTRINSIC_SSA instruction MLIL_LOAD_SSA, MLIL_LOAD_STRUCT_SSA, MLIL_STORE_SSA, MLIL_STORE_STRUCT_SSA, MLIL_INTRINSIC_SSA, + MLIL_MEMORY_INTRINSIC_SSA, MLIL_FREE_VAR_SLOT_SSA, MLIL_VAR_PHI, MLIL_MEM_PHI @@ -1787,6 +1796,7 @@ extern "C" uint32_t* (*getAllRegisterStacks)(void* ctxt, size_t* count); void (*getRegisterStackInfo)(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result); + BNIntrinsicClass (*getIntrinsicClass)(void* ctxt, uint32_t intrinsic); char* (*getIntrinsicName)(void* ctxt, uint32_t intrinsic); uint32_t* (*getAllIntrinsics)(void* ctxt, size_t* count); BNNameAndType* (*getIntrinsicInputs)(void* ctxt, uint32_t intrinsic, size_t* count); @@ -3975,6 +3985,7 @@ extern "C" BINARYNINJACOREAPI BNRegisterStackInfo BNGetArchitectureRegisterStackInfo(BNArchitecture* arch, uint32_t regStack); BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterStackForRegister(BNArchitecture* arch, uint32_t reg); + BINARYNINJACOREAPI BNIntrinsicClass BNGetArchitectureIntrinsicClass(BNArchitecture* arch, uint32_t intrinsic); BINARYNINJACOREAPI char* BNGetArchitectureIntrinsicName(BNArchitecture* arch, uint32_t intrinsic); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureIntrinsics(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI BNNameAndType* BNGetArchitectureIntrinsicInputs( diff --git a/docs/dev/bnil-llil.md b/docs/dev/bnil-llil.md index 97ce11bc..cf1cc5f6 100644 --- a/docs/dev/bnil-llil.md +++ b/docs/dev/bnil-llil.md @@ -156,7 +156,7 @@ Now with some knowledge of the `LowLevelIL` class let's try to do something with Going into gross detail on all the instructions is out of scope of this article, but we'll go over the different instructions types and speak generally about how they are used. - + ### Registers, Constants & Flags When parsing an instruction tree the terminals are registers, constants and flags. This provide the basis from which all instructions are built. @@ -267,7 +267,7 @@ The double precision instruction multiply, divide, modulus instructions are part * `LLIL_FABS` - Floating point absolute value * `LLIL_FLOAT_TO_INT` - Floating point convert a floating point to an integer * `LLIL_INT_TO_FLOAT` - Floating point convert an integer to a floating point -* `LLIL_FLOAT_CONV` - +* `LLIL_FLOAT_CONV` - * `LLIL_ROUND_TO_INT` - Rounds to the nearest integer * `LLIL_FLOOR` - Returns the floor of a floating point value * `LLIL_CEILING` - Returns the ceiling of a floating point value @@ -294,6 +294,7 @@ The rest of the instructions are pretty much self-explanatory to anyone with fam * `LLIL_EXTERN_PTR` - A synthesized (fake) pointer to something which doesn't exist within the memory space of the current binary * `LLIL_INTRINSIC ` - Intrinsics are operations with `output` and `params` and an `intrinsic` where the exact behavior is not modelled but the dataflow system can be improved by annotating the inputs and outputs. An example intrinsic would CPU AES instructions where the exact behavior is not modelled, but the inputs and outputs are. * `LLIL_INTRINSIC_SSA ` - SSA form of the `LLIL_INTRINSIC` operation +* `LLIL_MEMORY_INTRINSIC_SSA ` - Memory versioning SSA form of the `LLIL_INTRINSIC` operation * `LLIL_NOP` - No operation * `LLIL_SX` - Sign extend * `LLIL_TRAP` - Trap instruction @@ -306,10 +307,10 @@ The rest of the instructions are pretty much self-explanatory to anyone with fam ### Currently Undocumented -* `LLIL_FLAG ` - -* `LLIL_FLAG_BIT ` - -* `LLIL_FLAG_GROUP ` - -* `LLIL_FLAG_BIT_SSA ` - -* `LLIL_FLAG_PHI ` - -* `LLIL_FLAG_SSA ` - -* `LLIL_TAILCALL_SSA ` - +* `LLIL_FLAG ` - +* `LLIL_FLAG_BIT ` - +* `LLIL_FLAG_GROUP ` - +* `LLIL_FLAG_BIT_SSA ` - +* `LLIL_FLAG_PHI ` - +* `LLIL_FLAG_SSA ` - +* `LLIL_TAILCALL_SSA ` - diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 973d8e3f..e0d5922d 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -78,6 +78,7 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> LowLevelILInstructi {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, + {OutputMemoryIntrinsicLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, {TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}}; @@ -203,6 +204,8 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> LowLevelILI ParameterExprsLowLevelOperandUsage}}, {LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + {LLIL_MEMORY_INTRINSIC_SSA, {OutputMemoryIntrinsicLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, {LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, {LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, @@ -267,6 +270,9 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage case DestSSARegisterStackLowLevelOperandUsage: // PartialSSARegisterStackSourceLowLevelOperandUsage follows at same operand break; + case OutputMemoryIntrinsicLowLevelOperandUsage: + // OutputMemoryVersionLowLevelOperandUsage follows at same operand + break; default: switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) { @@ -2020,6 +2026,10 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL for (auto i : GetParameterExprs<LLIL_INTRINSIC_SSA>()) i.VisitExprs(func); break; + case LLIL_MEMORY_INTRINSIC_SSA: + for (auto i : GetParameterExprs<LLIL_MEMORY_INTRINSIC_SSA>()) + i.VisitExprs(func); + break; case LLIL_SEPARATE_PARAM_LIST_SSA: for (auto i : GetParameterExprs<LLIL_SEPARATE_PARAM_LIST_SSA>()) i.VisitExprs(func); @@ -2322,6 +2332,11 @@ ExprId LowLevelILInstruction::CopyTo( params.push_back(subExprHandler(i)); return dest->IntrinsicSSA( GetOutputSSARegisterOrFlagList<LLIL_INTRINSIC_SSA>(), GetIntrinsic<LLIL_INTRINSIC_SSA>(), params, *this); + case LLIL_MEMORY_INTRINSIC_SSA: + for (auto i : GetParameterExprs<LLIL_MEMORY_INTRINSIC_SSA>()) + params.push_back(subExprHandler(i)); + return dest->MemoryIntrinsicSSA(GetOutputSSARegisterOrFlagList<LLIL_MEMORY_INTRINSIC_SSA>(), GetIntrinsic<LLIL_MEMORY_INTRINSIC_SSA>(), + params, GetDestMemoryVersion<LLIL_MEMORY_INTRINSIC_SSA>(), GetSourceMemoryVersion<LLIL_MEMORY_INTRINSIC_SSA>(), *this); case LLIL_SEPARATE_PARAM_LIST_SSA: for (auto i : GetParameterExprs<LLIL_SEPARATE_PARAM_LIST_SSA>()) params.push_back(subExprHandler(i)); @@ -2769,6 +2784,8 @@ LowLevelILSSARegisterOrFlagList LowLevelILInstruction::GetOutputSSARegisterOrFla size_t operandIndex; if (GetOperandIndexForUsage(OutputSSARegisterOrFlagListLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSARegisterOrFlagList(operandIndex); + if (GetOperandIndexForUsage(OutputMemoryIntrinsicLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterOrFlagList(1); throw LowLevelILInstructionAccessException(); } @@ -3475,6 +3492,15 @@ ExprId LowLevelILFunction::IntrinsicSSA(const vector<SSARegisterOrFlag>& outputs } +ExprId LowLevelILFunction::MemoryIntrinsicSSA(const vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic, const vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MEMORY_INTRINSIC_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_MEMORY_INTRINSIC_OUTPUT_SSA, loc, 0, 0, newMemVersion, outputs.size() * 2, AddSSARegisterOrFlagList(outputs)), + intrinsic, AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params)), prevMemVersion); +} + + ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_BP, loc, 0, 0); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index e51a11cf..898e72b8 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -240,6 +240,7 @@ namespace BinaryNinja SourceSSAFlagsLowLevelOperandUsage, OutputRegisterOrFlagListLowLevelOperandUsage, OutputSSARegisterOrFlagListLowLevelOperandUsage, + OutputMemoryIntrinsicLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage, TargetsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage, @@ -1701,6 +1702,27 @@ namespace BinaryNinja UpdateRawOperandAsSSARegisterOrFlagList(0, outputs); } }; + template <> + struct LowLevelILInstructionAccessor<LLIL_MEMORY_INTRINSIC_SSA> : public LowLevelILInstructionBase + { + LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const + { + return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterOrFlagList(1); + } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + uint32_t GetIntrinsic() const { return GetRawOperandAsRegister(1); } + LowLevelILInstructionList GetParameterExprs() const + { + return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); + } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + void SetOutputSSARegisterOrFlagList(const _STD_VECTOR<SSARegisterOrFlag>& outputs) + { + GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterOrFlagList(1, outputs); + } + }; template <> struct LowLevelILInstructionAccessor<LLIL_SEPARATE_PARAM_LIST_SSA> : public LowLevelILInstructionBase diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 151a8463..0306a404 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -165,6 +165,8 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> ParameterExprsMediumLevelOperandUsage}}, {MLIL_INTRINSIC_SSA, {OutputSSAVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + {MLIL_MEMORY_INTRINSIC_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, {MLIL_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, {MLIL_FREE_VAR_SLOT_SSA, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage}}, @@ -1590,7 +1592,8 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL i.VisitExprs(func); break; case MLIL_INTRINSIC_SSA: - for (auto i : GetParameterExprs<MLIL_INTRINSIC_SSA>()) + case MLIL_MEMORY_INTRINSIC_SSA: + for (auto i : GetParameterExprs()) i.VisitExprs(func); break; default: @@ -1904,6 +1907,12 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, params.push_back(subExprHandler(i)); return dest->IntrinsicSSA( GetOutputSSAVariables<MLIL_INTRINSIC_SSA>(), GetIntrinsic<MLIL_INTRINSIC_SSA>(), params, *this); + case MLIL_MEMORY_INTRINSIC_SSA: + for (auto i : GetParameterExprs<MLIL_MEMORY_INTRINSIC_SSA>()) + params.push_back(subExprHandler(i)); + return dest->MemoryIntrinsicSSA(GetOutputSSAVariables<MLIL_MEMORY_INTRINSIC_SSA>(), + GetIntrinsic<MLIL_MEMORY_INTRINSIC_SSA>(), params, GetDestMemoryVersion<MLIL_MEMORY_INTRINSIC_SSA>(), + GetSourceMemoryVersion<MLIL_MEMORY_INTRINSIC_SSA>(), *this); case MLIL_FREE_VAR_SLOT: return dest->FreeVarSlot(GetDestVariable<MLIL_FREE_VAR_SLOT>(), *this); case MLIL_FREE_VAR_SLOT_SSA: @@ -2930,6 +2939,15 @@ ExprId MediumLevelILFunction::IntrinsicSSA( } +ExprId MediumLevelILFunction::MemoryIntrinsicSSA(const vector<SSAVariable>& outputs, uint32_t intrinsic, + const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MEMORY_INTRINSIC_SSA, loc, 0, + AddExprWithLocation(MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, loc, 0, newMemVersion, outputs.size() * 2, AddSSAVariableList(outputs)), intrinsic, + params.size(), AddOperandList(params), prevMemVersion); +} + + ExprId MediumLevelILFunction::FreeVarSlot(const Variable& var, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_FREE_VAR_SLOT, loc, 0, var.ToIdentifier()); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 9c893c0b..861bf395 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -1422,6 +1422,18 @@ namespace BinaryNinja MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) { UpdateRawOperandAsSSAVariableList(0, vars); } }; + template <> + struct MediumLevelILInstructionAccessor<MLIL_MEMORY_INTRINSIC_SSA> : public MediumLevelILInstructionBase + { + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + }; template <> struct MediumLevelILInstructionAccessor<MLIL_FREE_VAR_SLOT> : public MediumLevelILInstructionBase diff --git a/python/architecture.py b/python/architecture.py index 677192e4..c979eacb 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -28,7 +28,7 @@ import binaryninja from . import _binaryninjacore as core from .enums import ( Endianness, ImplicitRegisterExtend, BranchType, LowLevelILFlagCondition, FlagRole, LowLevelILOperation, - InstructionTextTokenType, InstructionTextTokenContext + InstructionTextTokenType, InstructionTextTokenContext, IntrinsicClass ) from .log import log_error from . import lowlevelil @@ -300,6 +300,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__(self._get_register_stack_name) self._cb.getAllRegisterStacks = self._cb.getAllRegisterStacks.__class__(self._get_all_register_stacks) self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__(self._get_register_stack_info) + self._cb.getIntrinsicClass = self._cb.getIntrinsicClass.__class__(self._get_intrinsic_class) self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__(self._get_intrinsic_name) self._cb.getAllIntrinsics = self._cb.getAllIntrinsics.__class__(self._get_all_intrinsics) self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__(self._get_intrinsic_inputs) @@ -481,6 +482,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): self.system_regs = self.__class__.system_regs self._intrinsics: Dict[IntrinsicName, IntrinsicIndex] = {} + self._intrinsic_class_by_index: Dict[IntrinsicIndex, IntrinsicClass] = {} self._intrinsics_by_index: Dict[IntrinsicIndex, Tuple[IntrinsicName, IntrinsicInfo]] = {} intrinsic_index = IntrinsicIndex(0) for intrinsic in self.__class__.intrinsics.keys(): @@ -1125,6 +1127,11 @@ class Architecture(metaclass=_ArchitectureMetaClass): result[0].topRelativeCount = 0 result[0].stackTopReg = 0 + def _get_intrinsic_class(self, ctxt, intrinsic): + if intrinsic in self._intrinsic_class_by_index: + return self._intrinsic_class_by_index[intrinsic] + return IntrinsicClass.GeneralIntrinsicClass + def _get_intrinsic_name(self, ctxt, intrinsic): try: if intrinsic in self._intrinsics_by_index: @@ -1549,6 +1556,16 @@ class Architecture(metaclass=_ArchitectureMetaClass): raise ValueError("argument 'group_index' must be an integer") return self._semantic_flag_groups_by_index[group_index] + def get_intrinsic_class(self, intrinsic: IntrinsicIndex) -> IntrinsicClass: + """ + ``get_intrinsic_class`` gets the intrinsic class from an intrinsic number. + + :param int intrinsic: intrinsic number + :return: intrinsic class + :rtype: IntrinsicClass + """ + return IntrinsicClass(core.BNGetArchitectureIntrinsicClass(self.handle, intrinsic)) + def get_intrinsic_name(self, intrinsic: IntrinsicIndex) -> IntrinsicName: """ ``get_intrinsic_name`` gets an intrinsic name from an intrinsic number. @@ -2261,9 +2278,11 @@ class CoreArchitecture(Architecture): intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count) assert intrinsics is not None, "core.BNGetAllArchitectureIntrinsics returned None" self._intrinsics: Dict[IntrinsicName, IntrinsicIndex] = {} + self._intrinsic_class_by_index: Dict[IntrinsicIndex, IntrinsicClass] = {} self._intrinsics_by_index: Dict[IntrinsicIndex, Tuple[IntrinsicName, IntrinsicInfo]] = {} self._intrinsics_info: Dict[IntrinsicName, IntrinsicInfo] = {} for i in range(count.value): + intrinsic_class = IntrinsicClass(core.BNGetArchitectureIntrinsicClass(self.handle, intrinsics[i])) name = IntrinsicName(core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i])) input_count = ctypes.c_ulonglong() inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count) @@ -2285,6 +2304,8 @@ class CoreArchitecture(Architecture): types.Type.create(core.BNNewTypeReference(outputs[j].type), confidence=outputs[j].confidence) ) core.BNFreeOutputTypeList(outputs, output_count.value) + if intrinsic_class is not IntrinsicClass.GeneralIntrinsicClass: + self._intrinsic_class_by_index[intrinsics[i]] = intrinsic_class self._intrinsics_info[name] = IntrinsicInfo(input_list, output_list) self._intrinsics[name] = intrinsics[i] self._intrinsics_by_index[intrinsics[i]] = (name, self._intrinsics_info[name]) @@ -2719,6 +2740,7 @@ class ArchitectureHook(CoreArchitecture): self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__() self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__() if len(self.__class__.intrinsics) == 0: + self._cb.getIntrinsicClass = self._cb.getIntrinsicClass.__class__() self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__() self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__() self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__() diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 9b2bd4ae..590cae83 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -385,6 +385,10 @@ class LowLevelILInstruction(BaseILInstruction): ("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr") ], LowLevelILOperation.LLIL_INTRINSIC_SSA: [ ("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr") + ], LowLevelILOperation.LLIL_MEMORY_INTRINSIC_OUTPUT_SSA: [ + ("dest_memory", "int"), ("output", "reg_ssa_list") + ], LowLevelILOperation.LLIL_MEMORY_INTRINSIC_SSA: [ + ("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int") ], LowLevelILOperation.LLIL_BP: [], LowLevelILOperation.LLIL_TRAP: [("vector", "int")], LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [ ("src", "expr") @@ -550,7 +554,7 @@ class LowLevelILInstruction(BaseILInstruction): def tokens(self) -> TokenList: """LLIL tokens (read-only)""" # special case for those instructions that don't have tokens - if isinstance(self, (LowLevelILCallOutputSsa, LowLevelILCallParam, LowLevelILCallStackSsa)): + if isinstance(self, (LowLevelILCallOutputSsa, LowLevelILCallParam, LowLevelILCallStackSsa, LowLevelILMemoryIntrinsicOutputSsa)): return [] count = ctypes.c_ulonglong() @@ -2625,6 +2629,71 @@ class LowLevelILIntrinsicSsa(LowLevelILInstruction, SSA): @dataclass(frozen=True, repr=False, eq=False) +class LowLevelILMemoryIntrinsicOutputSsa(LowLevelILInstruction, SSA): + def __repr__(self): + return f"<LowLevelILMemoryIntrinsicOutputSsa: {self.dest_memory} {self.output}>" + + @property + def dest_memory(self) -> int: + return self._get_int(0) + + @property + def output(self) -> List[SSARegisterOrFlag]: + return self._get_reg_or_flag_ssa_list(1) + + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("dest_memory", self.dest_memory, "int"), + ("output", self.output, "List[SSARegisterOrFlag]"), + ] + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILMemoryIntrinsicSsa(LowLevelILInstruction, SSA): + @property + def output(self) -> List[SSARegisterOrFlag]: + inst = self._get_expr(0) + assert isinstance(inst, LowLevelILMemoryIntrinsicOutputSsa), "LowLevelILMemoryIntrinsicSsa expected LowLevelILMemoryIntrinsicOutputSsa as first operand" + return inst.output + + @property + def dest_memory(self) -> int: + inst = self._get_expr(0) + assert isinstance(inst, LowLevelILMemoryIntrinsicOutputSsa), "LowLevelILMemoryIntrinsicSsa expected LowLevelILMemoryIntrinsicOutputSsa as first operand" + return inst.dest_memory + + @property + def intrinsic(self) -> ILIntrinsic: + return self._get_intrinsic(1) + + @property + def param(self) -> LowLevelILCallParam: + # kept for backwards compatibility use 'params' instead + result = self._get_expr(2) + assert isinstance(result, LowLevelILCallParam) + return result + + @property + def params(self) -> List[LowLevelILInstruction]: + return self.param.src + + @property + def src_memory(self) -> int: + return self._get_int(3) + + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("output", self.output, "List[SSARegisterOrFlag]"), + ("intrinsic", self.intrinsic, "ILIntrinsic"), + ("params", self.params, "List[LowLevelILInstruction]"), + ("dest_memory", self.dest_memory, "int"), + ("src_memory", self.src_memory, "int"), + ] + + +@dataclass(frozen=True, repr=False, eq=False) class LowLevelILSetRegSsaPartial(LowLevelILInstruction, SetReg, SSA): @property def full_reg(self) -> SSARegister: @@ -2991,7 +3060,9 @@ ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: igno LowLevelILOperation.LLIL_ADD_OVERFLOW: LowLevelILAddOverflow, # [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SYSCALL: LowLevelILSyscall, # [], LowLevelILOperation.LLIL_INTRINSIC: LowLevelILIntrinsic, # [("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")], - LowLevelILOperation.LLIL_INTRINSIC_SSA: LowLevelILIntrinsicSsa, # [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")], + LowLevelILOperation.LLIL_INTRINSIC_SSA: LowLevelILIntrinsicSsa, # [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + LowLevelILOperation.LLIL_MEMORY_INTRINSIC_OUTPUT_SSA: LowLevelILMemoryIntrinsicOutputSsa, # [("dest_memory", "int"), ("output", "reg_or_flag_ssa_list")], + LowLevelILOperation.LLIL_MEMORY_INTRINSIC_SSA: LowLevelILMemoryIntrinsicSsa, # [("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")], LowLevelILOperation.LLIL_BP: LowLevelILBp, # [], LowLevelILOperation.LLIL_TRAP: LowLevelILTrap, # [("vector", "int")], LowLevelILOperation.LLIL_UNDEF: LowLevelILUndef, # [], diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 05eeb449..53f87cdc 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -263,6 +263,10 @@ class MediumLevelILInstruction(BaseILInstruction): ("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list") ], MediumLevelILOperation.MLIL_INTRINSIC_SSA: [ ("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list") + ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_OUTPUT_SSA: [ + ("dest_memory", "int"), ("output", "var_ssa_list") + ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_SSA: [ + ("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int") ], MediumLevelILOperation.MLIL_FREE_VAR_SLOT: [ ("dest", "var") ], MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA: [ @@ -2222,6 +2226,64 @@ class MediumLevelILIntrinsicSsa(MediumLevelILInstruction, SSA): @dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILMemoryIntrinsicOutputSsa(MediumLevelILInstruction, SSA): + def __repr__(self): + return f"<MediumLevelILMemoryIntrinsicOutputSsa: {self.dest_memory} {self.output}>" + + @property + def dest_memory(self) -> int: + return self._get_int(0) + + @property + def output(self) -> List[SSAVariable]: + return self._get_var_ssa_list(1, 2) + + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("dest_memory", self.dest_memory, "int"), + ("output", self.output, "List[SSAVariable]"), + ] + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILMemoryIntrinsicSsa(MediumLevelILInstruction, SSA): + @property + def output(self) -> List[SSAVariable]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILMemoryIntrinsicOutputSsa), "MediumLevelILMemoryIntrinsicSsa expected MediumLevelILMemoryIntrinsicOutputSsa as first operand" + return inst.output + + @property + def dest_memory(self) -> int: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILMemoryIntrinsicOutputSsa), "MediumLevelILMemoryIntrinsicSsa expected MediumLevelILMemoryIntrinsicOutputSsa as first operand" + return inst.dest_memory + + @property + def intrinsic(self) -> 'lowlevelil.ILIntrinsic': + return self._get_intrinsic(1) + + @property + def params(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(2, 3) + + @property + def src_memory(self) -> int: + return self._get_int(4) + + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("output", self.output, "List[SSAVariable]"), + ("dest_memory", self.dest_memory, "int"), + ("intrinsic", self.intrinsic, "ILIntrinsic"), + ("params", self.params, "List[MediumLevelILInstruction]"), + ("src_memory", self.src_memory, "int"), + ] + + +@dataclass(frozen=True, repr=False, eq=False) class MediumLevelILSetVarSsaField(MediumLevelILInstruction, SetVar, SSA): @property def dest(self) -> SSAVariable: @@ -2996,8 +3058,9 @@ ILInstruction = { MediumLevelILTailcall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_INTRINSIC: MediumLevelILIntrinsic, # [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], - MediumLevelILOperation.MLIL_INTRINSIC_SSA: - MediumLevelILIntrinsicSsa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_INTRINSIC_SSA: MediumLevelILIntrinsicSsa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_OUTPUT_SSA: MediumLevelILMemoryIntrinsicOutputSsa, # [("dest_memory", "int"), ("output", "var_ssa_list")], + MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_SSA: MediumLevelILMemoryIntrinsicSsa, # [("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: MediumLevelILSetVarSsaField, # [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index df34f1fe..1d343972 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -487,6 +487,9 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> { fn intrinsics(&self) -> Vec<Self::Intrinsic> { Vec::new() } + fn intrinsic_class(&self, _id: u32) -> binaryninjacore_sys::BNIntrinsicClass { + binaryninjacore_sys::BNIntrinsicClass::GeneralIntrinsicClass + } fn intrinsic_from_id(&self, _id: u32) -> Option<Self::Intrinsic> { None } @@ -1437,6 +1440,10 @@ impl Architecture for CoreArchitecture { } } + fn intrinsic_class(&self, id: u32) -> binaryninjacore_sys::BNIntrinsicClass { + unsafe { BNGetArchitectureIntrinsicClass(self.0, id) } + } + fn intrinsic_from_id(&self, id: u32) -> Option<CoreIntrinsic> { // TODO validate in debug builds Some(CoreIntrinsic(self.0, id)) @@ -2366,6 +2373,14 @@ where } } + extern "C" fn cb_intrinsic_class<A>(ctxt: *mut c_void, intrinsic: u32) -> BNIntrinsicClass + where + A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync, + { + let custom_arch = unsafe { &*(ctxt as *mut A) }; + custom_arch.intrinsic_class(intrinsic) + } + extern "C" fn cb_intrinsic_name<A>(ctxt: *mut c_void, intrinsic: u32) -> *mut c_char where A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync, @@ -2723,6 +2738,7 @@ where getAllRegisterStacks: Some(cb_reg_stacks::<A>), getRegisterStackInfo: Some(cb_reg_stack_info::<A>), + getIntrinsicClass: Some(cb_intrinsic_class::<A>), getIntrinsicName: Some(cb_intrinsic_name::<A>), getAllIntrinsics: Some(cb_intrinsics::<A>), getIntrinsicInputs: Some(cb_intrinsic_inputs::<A>), diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs index 438708db..306a1352 100644 --- a/rust/src/mlil/instruction.rs +++ b/rust/src/mlil/instruction.rs @@ -824,7 +824,8 @@ impl MediumLevelILInstruction { )), MLIL_TRAP => Op::Trap(Trap::new(function, op.address, op.operands[0])), // translated directly into a list for Expression or Variables - MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA => { + // TODO MLIL_MEMORY_INTRINSIC_SSA needs to be handled properly + MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_SSA => { unreachable!() } } |
