summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp159
-rw-r--r--binaryninjaapi.h39
-rw-r--r--binaryninjacore.h40
-rw-r--r--lowlevelil.cpp25
-rw-r--r--lowlevelilinstruction.cpp355
-rw-r--r--lowlevelilinstruction.h129
-rw-r--r--mediumlevelilinstruction.cpp71
-rw-r--r--mediumlevelilinstruction.h20
-rw-r--r--python/architecture.py154
-rw-r--r--python/function.py23
-rw-r--r--python/lowlevelil.py109
-rw-r--r--python/mediumlevelil.py4
12 files changed, 1095 insertions, 33 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 78a67105..223af13d 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -491,6 +491,79 @@ void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, B
}
+char* Architecture::GetIntrinsicNameCallback(void* ctxt, uint32_t intrinsic)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ string result = arch->GetIntrinsicName(intrinsic);
+ return BNAllocString(result.c_str());
+}
+
+
+uint32_t* Architecture::GetAllIntrinsicsCallback(void* ctxt, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<uint32_t> regs = arch->GetAllIntrinsics();
+ *count = regs.size();
+
+ uint32_t* result = new uint32_t[regs.size()];
+ for (size_t i = 0; i < regs.size(); i++)
+ result[i] = regs[i];
+ return result;
+}
+
+
+BNNameAndType* Architecture::GetIntrinsicInputsCallback(void* ctxt, uint32_t intrinsic, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<NameAndType> inputs = arch->GetIntrinsicInputs(intrinsic);
+ *count = inputs.size();
+
+ BNNameAndType* result = new BNNameAndType[inputs.size()];
+ for (size_t i = 0; i < inputs.size(); i++)
+ {
+ result[i].name = BNAllocString(inputs[i].name.c_str());
+ result[i].type = BNNewTypeReference(inputs[i].type.GetValue()->GetObject());
+ result[i].typeConfidence = inputs[i].type.GetConfidence();
+ }
+ return result;
+}
+
+
+void Architecture::FreeNameAndTypeListCallback(void*, BNNameAndType* nt, size_t count)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ BNFreeString(nt[i].name);
+ BNFreeType(nt[i].type);
+ }
+ delete[] nt;
+}
+
+
+BNTypeWithConfidence* Architecture::GetIntrinsicOutputsCallback(void* ctxt, uint32_t intrinsic, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<Confidence<Ref<Type>>> outputs = arch->GetIntrinsicOutputs(intrinsic);
+ *count = outputs.size();
+
+ BNTypeWithConfidence* result = new BNTypeWithConfidence[outputs.size()];
+ for (size_t i = 0; i < outputs.size(); i++)
+ {
+ result[i].type = BNNewTypeReference(outputs[i].GetValue()->GetObject());
+ result[i].confidence = outputs[i].GetConfidence();
+ }
+ return result;
+}
+
+
+void Architecture::FreeTypeListCallback(void*, BNTypeWithConfidence* types, size_t count)
+{
+ for (size_t i = 0; i < count; i++)
+ BNFreeType(types[i].type);
+ delete[] types;
+}
+
+
bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors)
{
Architecture* arch = (Architecture*)ctxt;
@@ -612,6 +685,12 @@ void Architecture::Register(Architecture* arch)
callbacks.getRegisterStackName = GetRegisterStackNameCallback;
callbacks.getAllRegisterStacks = GetAllRegisterStacksCallback;
callbacks.getRegisterStackInfo = GetRegisterStackInfoCallback;
+ callbacks.getIntrinsicName = GetIntrinsicNameCallback;
+ callbacks.getAllIntrinsics = GetAllIntrinsicsCallback;
+ callbacks.getIntrinsicInputs = GetIntrinsicInputsCallback;
+ callbacks.freeNameAndTypeList = FreeNameAndTypeListCallback;
+ callbacks.getIntrinsicOutputs = GetIntrinsicOutputsCallback;
+ callbacks.freeTypeList = FreeTypeListCallback;
callbacks.assemble = AssembleCallback;
callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback;
callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback;
@@ -920,6 +999,32 @@ uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg)
}
+string Architecture::GetIntrinsicName(uint32_t intrinsic)
+{
+ char intrinsicStr[32];
+ sprintf(intrinsicStr, "intrinsic_%" PRIu32, intrinsic);
+ return intrinsicStr;
+}
+
+
+vector<uint32_t> Architecture::GetAllIntrinsics()
+{
+ return vector<uint32_t>();
+}
+
+
+vector<NameAndType> Architecture::GetIntrinsicInputs(uint32_t)
+{
+ return vector<NameAndType>();
+}
+
+
+vector<Confidence<Ref<Type>>> Architecture::GetIntrinsicOutputs(uint32_t)
+{
+ return vector<Confidence<Ref<Type>>>();
+}
+
+
vector<uint32_t> Architecture::GetModifiedRegistersOnWrite(uint32_t reg)
{
size_t count;
@@ -1477,6 +1582,60 @@ BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack)
}
+string CoreArchitecture::GetIntrinsicName(uint32_t intrinsic)
+{
+ char* name = BNGetArchitectureIntrinsicName(m_object, intrinsic);
+ string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+vector<uint32_t> CoreArchitecture::GetAllIntrinsics()
+{
+ size_t count;
+ uint32_t* regs = BNGetAllArchitectureIntrinsics(m_object, &count);
+
+ vector<uint32_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(regs[i]);
+
+ BNFreeRegisterList(regs);
+ return result;
+}
+
+
+vector<NameAndType> CoreArchitecture::GetIntrinsicInputs(uint32_t intrinsic)
+{
+ size_t count;
+ BNNameAndType* inputs = BNGetArchitectureIntrinsicInputs(m_object, intrinsic, &count);
+
+ vector<NameAndType> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ result.push_back(NameAndType(inputs[i].name, Confidence<Ref<Type>>(
+ new Type(BNNewTypeReference(inputs[i].type)), inputs[i].typeConfidence)));
+ }
+
+ BNFreeNameAndTypeList(inputs, count);
+ return result;
+}
+
+
+vector<Confidence<Ref<Type>>> CoreArchitecture::GetIntrinsicOutputs(uint32_t intrinsic)
+{
+ size_t count;
+ BNTypeWithConfidence* outputs = BNGetArchitectureIntrinsicOutputs(m_object, intrinsic, &count);
+
+ vector<Confidence<Ref<Type>>> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(Confidence<Ref<Type>>(new Type(BNNewTypeReference(outputs[i].type)), outputs[i].confidence));
+
+ BNFreeOutputTypeList(outputs, count);
+ return result;
+}
+
+
bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors)
{
char* errorStr = nullptr;
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index b74fa971..d1ca9cdb 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1566,6 +1566,16 @@ namespace BinaryNinja
void AddBranch(BNBranchType type, uint64_t target = 0, Architecture* arch = nullptr, bool hasDelaySlot = false);
};
+ struct NameAndType
+ {
+ std::string name;
+ Confidence<Ref<Type>> type;
+
+ NameAndType() {}
+ NameAndType(const Confidence<Ref<Type>>& t): type(t) {}
+ NameAndType(const std::string& n, const Confidence<Ref<Type>>& t): name(n), type(t) {}
+ };
+
class LowLevelILFunction;
class FunctionRecognizer;
class CallingConvention;
@@ -1633,6 +1643,13 @@ namespace BinaryNinja
static uint32_t* GetAllRegisterStacksCallback(void* ctxt, size_t* count);
static void GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result);
+ 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);
+ static void FreeNameAndTypeListCallback(void* ctxt, BNNameAndType* nt, size_t count);
+ static BNTypeWithConfidence* GetIntrinsicOutputsCallback(void* ctxt, uint32_t intrinsic, size_t* count);
+ static void FreeTypeListCallback(void* ctxt, BNTypeWithConfidence* types, size_t count);
+
static bool AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
static bool IsNeverBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
static bool IsAlwaysBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
@@ -1714,6 +1731,11 @@ namespace BinaryNinja
virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack);
uint32_t GetRegisterStackForRegister(uint32_t reg);
+ virtual std::string GetIntrinsicName(uint32_t intrinsic);
+ virtual std::vector<uint32_t> GetAllIntrinsics();
+ virtual std::vector<NameAndType> GetIntrinsicInputs(uint32_t intrinsic);
+ virtual std::vector<Confidence<Ref<Type>>> GetIntrinsicOutputs(uint32_t intrinsic);
+
virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors);
/*! IsNeverBranchPatchAvailable returns true if the instruction at addr can be patched to never branch.
@@ -1853,6 +1875,11 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetAllRegisterStacks() override;
virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) 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;
+ virtual std::vector<Confidence<Ref<Type>>> GetIntrinsicOutputs(uint32_t intrinsic) override;
+
virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override;
virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
@@ -2452,9 +2479,11 @@ namespace BinaryNinja
};
struct LowLevelILInstruction;
+ struct RegisterOrFlag;
struct SSARegister;
struct SSARegisterStack;
struct SSAFlag;
+ struct SSARegisterOrFlag;
class LowLevelILFunction: public CoreRefCountObject<BNLowLevelILFunction,
BNNewLowLevelILFunctionReference, BNFreeLowLevelILFunction>
@@ -2641,6 +2670,10 @@ namespace BinaryNinja
ExprId TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
ExprId BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
ExprId SystemCall(const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Intrinsic(const std::vector<RegisterOrFlag>& outputs, uint32_t intrinsic,
+ const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId IntrinsicSSA(const std::vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic,
+ const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation());
ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation());
ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation());
ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation());
@@ -2686,9 +2719,11 @@ namespace BinaryNinja
ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels);
ExprId AddOperandList(const std::vector<ExprId> operands);
ExprId AddIndexList(const std::vector<size_t> operands);
+ ExprId AddRegisterOrFlagList(const std::vector<RegisterOrFlag>& regs);
ExprId AddSSARegisterList(const std::vector<SSARegister>& regs);
ExprId AddSSARegisterStackList(const std::vector<SSARegisterStack>& regStacks);
ExprId AddSSAFlagList(const std::vector<SSAFlag>& flags);
+ ExprId AddSSARegisterOrFlagList(const std::vector<SSARegisterOrFlag>& regs);
ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size);
ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size);
@@ -2954,6 +2989,10 @@ namespace BinaryNinja
const ILSourceLocation& loc = ILSourceLocation());
ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation());
ExprId Trap(int64_t vector, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Intrinsic(const std::vector<Variable>& outputs, uint32_t intrinsic,
+ const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId IntrinsicSSA(const std::vector<SSAVariable>& outputs, uint32_t intrinsic,
+ const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation());
ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation());
ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation());
ExprId UnimplementedMemoryRef(size_t size, ExprId target,
diff --git a/binaryninjacore.h b/binaryninjacore.h
index bc58092d..a946df31 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -352,6 +352,7 @@ extern "C"
LLIL_SYSCALL,
LLIL_BP,
LLIL_TRAP,
+ LLIL_INTRINSIC,
LLIL_UNDEF,
LLIL_UNIMPL,
LLIL_UNIMPL_MEM,
@@ -394,11 +395,12 @@ extern "C"
LLIL_FLAG_BIT_SSA,
LLIL_CALL_SSA,
LLIL_SYSCALL_SSA,
- LLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ LLIL_CALL_PARAM, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA, LLIL_INTRINSIC, LLIL_INTRINSIC_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_LOAD_SSA,
LLIL_STORE_SSA,
+ LLIL_INTRINSIC_SSA,
LLIL_REG_PHI,
LLIL_REG_STACK_PHI,
LLIL_FLAG_PHI,
@@ -858,6 +860,7 @@ extern "C"
MLIL_ADD_OVERFLOW,
MLIL_SYSCALL, // Not valid in SSA form (see MLIL_SYSCALL_SSA)
MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA)
+ MLIL_INTRINSIC, // Not valid in SSA form (see MLIL_INTRINSIC_SSA)
MLIL_BP,
MLIL_TRAP,
MLIL_UNDEF,
@@ -905,6 +908,7 @@ extern "C"
MLIL_LOAD_STRUCT_SSA,
MLIL_STORE_SSA,
MLIL_STORE_STRUCT_SSA,
+ MLIL_INTRINSIC_SSA,
MLIL_VAR_PHI,
MLIL_MEM_PHI
};
@@ -1077,6 +1081,19 @@ extern "C"
BNLowLevelILFlagCondition condition;
};
+ struct BNNameAndType
+ {
+ char* name;
+ BNType* type;
+ uint8_t typeConfidence;
+ };
+
+ struct BNTypeWithConfidence
+ {
+ BNType* type;
+ uint8_t confidence;
+ };
+
struct BNCustomArchitecture
{
void* context;
@@ -1127,6 +1144,13 @@ extern "C"
uint32_t* (*getAllRegisterStacks)(void* ctxt, size_t* count);
void (*getRegisterStackInfo)(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result);
+ 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);
+ void (*freeNameAndTypeList)(void* ctxt, BNNameAndType* nt, size_t count);
+ BNTypeWithConfidence* (*getIntrinsicOutputs)(void* ctxt, uint32_t intrinsic, size_t* count);
+ void (*freeTypeList)(void* ctxt, BNTypeWithConfidence* types, size_t count);
+
bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
bool (*isNeverBranchPatchAvailable)(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
@@ -1203,12 +1227,6 @@ extern "C"
char* (*serialize)(void* ctxt);
};
- struct BNTypeWithConfidence
- {
- BNType* type;
- uint8_t confidence;
- };
-
struct BNCallingConventionWithConfidence
{
BNCallingConvention* convention;
@@ -2116,6 +2134,14 @@ extern "C"
BINARYNINJACOREAPI BNRegisterStackInfo BNGetArchitectureRegisterStackInfo(BNArchitecture* arch, uint32_t regStack);
BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterStackForRegister(BNArchitecture* arch, uint32_t reg);
+ BINARYNINJACOREAPI char* BNGetArchitectureIntrinsicName(BNArchitecture* arch, uint32_t intrinsic);
+ BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureIntrinsics(BNArchitecture* arch, size_t* count);
+ BINARYNINJACOREAPI BNNameAndType* BNGetArchitectureIntrinsicInputs(BNArchitecture* arch, uint32_t intrinsic, size_t* count);
+ BINARYNINJACOREAPI void BNFreeNameAndTypeList(BNNameAndType* nt, size_t count);
+ BINARYNINJACOREAPI BNTypeWithConfidence* BNGetArchitectureIntrinsicOutputs(BNArchitecture* arch, uint32_t intrinsic,
+ size_t* count);
+ BINARYNINJACOREAPI void BNFreeOutputTypeList(BNTypeWithConfidence* types, size_t count);
+
BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
BINARYNINJACOREAPI bool BNIsArchitectureNeverBranchPatchAvailable(BNArchitecture* arch, const uint8_t* data,
diff --git a/lowlevelil.cpp b/lowlevelil.cpp
index c72d4b68..0f2b29be 100644
--- a/lowlevelil.cpp
+++ b/lowlevelil.cpp
@@ -216,6 +216,17 @@ ExprId LowLevelILFunction::AddIndexList(const vector<size_t> operands)
}
+ExprId LowLevelILFunction::AddRegisterOrFlagList(const vector<RegisterOrFlag>& regs)
+{
+ uint64_t* operandList = new uint64_t[regs.size()];
+ for (size_t i = 0; i < regs.size(); i++)
+ operandList[i] = regs[i].ToIdentifier();
+ ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size());
+ delete[] operandList;
+ return result;
+}
+
+
ExprId LowLevelILFunction::AddSSARegisterList(const vector<SSARegister>& regs)
{
uint64_t* operandList = new uint64_t[regs.size() * 2];
@@ -258,6 +269,20 @@ ExprId LowLevelILFunction::AddSSAFlagList(const vector<SSAFlag>& flags)
}
+ExprId LowLevelILFunction::AddSSARegisterOrFlagList(const vector<SSARegisterOrFlag>& regs)
+{
+ uint64_t* operandList = new uint64_t[regs.size() * 2];
+ for (size_t i = 0; i < regs.size(); i++)
+ {
+ operandList[i * 2] = regs[i].regOrFlag.ToIdentifier();
+ operandList[(i * 2) + 1] = regs[i].version;
+ }
+ ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size() * 2);
+ delete[] operandList;
+ return result;
+}
+
+
ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size)
{
if (operand.constant)
diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp
index 9909e8ee..2c00db68 100644
--- a/lowlevelilinstruction.cpp
+++ b/lowlevelilinstruction.cpp
@@ -64,6 +64,7 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType>
{HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
{LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand},
{LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
+ {IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand},
{ConstantLowLevelOperandUsage, IntegerLowLevelOperand},
{VectorLowLevelOperandUsage, IntegerLowLevelOperand},
{StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand},
@@ -80,6 +81,8 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType>
{SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
{SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand},
{SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand},
+ {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand},
+ {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand},
{SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand},
{TargetListLowLevelOperandUsage, IndexListLowLevelOperand},
{RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}
@@ -202,6 +205,10 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{LLIL_ZX, {SourceExprLowLevelOperandUsage}},
{LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}},
{LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}},
+ {LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage,
+ ParameterExprsLowLevelOperandUsage}},
+ {LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage,
+ ParameterExprsLowLevelOperandUsage}},
{LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}},
{LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}},
{LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}},
@@ -268,6 +275,8 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage
case SSARegisterStackListLowLevelOperand:
case SSAFlagListLowLevelOperand:
case RegisterStackAdjustmentsLowLevelOperand:
+ case RegisterOrFlagListLowLevelOperand:
+ case SSARegisterOrFlagListLowLevelOperand:
// SSA registers/flags and lists take two operand slots
operand += 2;
break;
@@ -287,6 +296,72 @@ unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_
LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages();
+RegisterOrFlag::RegisterOrFlag(): isFlag(false), index(BN_INVALID_REGISTER)
+{
+}
+
+
+RegisterOrFlag::RegisterOrFlag(bool flag, uint32_t i): isFlag(flag), index(i)
+{
+}
+
+
+uint32_t RegisterOrFlag::GetRegister() const
+{
+ if (isFlag)
+ throw LowLevelILInstructionAccessException();
+ return index;
+}
+
+
+uint32_t RegisterOrFlag::GetFlag() const
+{
+ if (!isFlag)
+ throw LowLevelILInstructionAccessException();
+ return index;
+}
+
+
+RegisterOrFlag& RegisterOrFlag::operator=(const RegisterOrFlag& v)
+{
+ isFlag = v.isFlag;
+ index = v.index;
+ return *this;
+}
+
+
+bool RegisterOrFlag::operator==(const RegisterOrFlag& v) const
+{
+ if (isFlag != v.isFlag)
+ return false;
+ return index == v.index;
+}
+
+
+bool RegisterOrFlag::operator!=(const RegisterOrFlag& v) const
+{
+ return !((*this) == v);
+}
+
+
+bool RegisterOrFlag::operator<(const RegisterOrFlag& v) const
+{
+ return ToIdentifier() < v.ToIdentifier();
+}
+
+
+uint64_t RegisterOrFlag::ToIdentifier() const
+{
+ return ((uint64_t)index) | (isFlag ? (1LL << 32) : 0);
+}
+
+
+RegisterOrFlag RegisterOrFlag::FromIdentifier(uint64_t id)
+{
+ return RegisterOrFlag((id & (1LL << 32)) != 0, (uint32_t)id);
+}
+
+
SSARegister::SSARegister(): reg(BN_INVALID_REGISTER), version(0)
{
}
@@ -428,6 +503,63 @@ bool SSAFlag::operator<(const SSAFlag& v) const
}
+SSARegisterOrFlag::SSARegisterOrFlag(): version(0)
+{
+}
+
+
+SSARegisterOrFlag::SSARegisterOrFlag(const RegisterOrFlag& rf, size_t i): regOrFlag(rf), version(i)
+{
+}
+
+
+SSARegisterOrFlag::SSARegisterOrFlag(const SSARegister& v): regOrFlag(false, v.reg), version(v.version)
+{
+}
+
+
+SSARegisterOrFlag::SSARegisterOrFlag(const SSAFlag& v): regOrFlag(true, v.flag), version(v.version)
+{
+}
+
+
+SSARegisterOrFlag::SSARegisterOrFlag(const SSARegisterOrFlag& v): regOrFlag(v.regOrFlag), version(v.version)
+{
+}
+
+
+SSARegisterOrFlag& SSARegisterOrFlag::operator=(const SSARegisterOrFlag& v)
+{
+ regOrFlag = v.regOrFlag;
+ version = v.version;
+ return *this;
+}
+
+
+bool SSARegisterOrFlag::operator==(const SSARegisterOrFlag& v) const
+{
+ if (regOrFlag != v.regOrFlag)
+ return false;
+ return version == v.version;
+}
+
+
+bool SSARegisterOrFlag::operator!=(const SSARegisterOrFlag& v) const
+{
+ return !((*this) == v);
+}
+
+
+bool SSARegisterOrFlag::operator<(const SSARegisterOrFlag& v) const
+{
+ if (regOrFlag < v.regOrFlag)
+ return true;
+ if (v.regOrFlag < regOrFlag)
+ return false;
+ return version < v.version;
+}
+
+
bool LowLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const
{
return count == a.count;
@@ -644,6 +776,60 @@ LowLevelILInstructionList::operator vector<LowLevelILInstruction>() const
}
+const RegisterOrFlag LowLevelILRegisterOrFlagList::ListIterator::operator*()
+{
+ return RegisterOrFlag::FromIdentifier(*pos);
+}
+
+
+LowLevelILRegisterOrFlagList::LowLevelILRegisterOrFlagList(LowLevelILFunction* func,
+ const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count)
+{
+}
+
+
+LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ return result;
+}
+
+
+LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ return result;
+}
+
+
+size_t LowLevelILRegisterOrFlagList::size() const
+{
+ return m_list.size();
+}
+
+
+const RegisterOrFlag LowLevelILRegisterOrFlagList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw LowLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+LowLevelILRegisterOrFlagList::operator vector<RegisterOrFlag>() const
+{
+ vector<RegisterOrFlag> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
const SSARegister LowLevelILSSARegisterList::ListIterator::operator*()
{
LowLevelILIntegerList::const_iterator cur = pos;
@@ -818,6 +1004,64 @@ LowLevelILSSAFlagList::operator vector<SSAFlag>() const
}
+const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::ListIterator::operator*()
+{
+ LowLevelILIntegerList::const_iterator cur = pos;
+ RegisterOrFlag rf = RegisterOrFlag::FromIdentifier(*cur);
+ ++cur;
+ size_t version = (size_t)*cur;
+ return SSARegisterOrFlag(rf, version);
+}
+
+
+LowLevelILSSARegisterOrFlagList::LowLevelILSSARegisterOrFlagList(LowLevelILFunction* func,
+ const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1))
+{
+}
+
+
+LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ return result;
+}
+
+
+LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ return result;
+}
+
+
+size_t LowLevelILSSARegisterOrFlagList::size() const
+{
+ return m_list.size() / 2;
+}
+
+
+const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw LowLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+LowLevelILSSARegisterOrFlagList::operator vector<SSARegisterOrFlag>() const
+{
+ vector<SSARegisterOrFlag> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
LowLevelILOperand::LowLevelILOperand(const LowLevelILInstruction& instr,
LowLevelILOperandUsage usage, size_t operandIndex):
m_instr(instr), m_usage(usage), m_operandIndex(operandIndex)
@@ -905,6 +1149,14 @@ uint32_t LowLevelILOperand::GetSemanticFlagGroup() const
}
+uint32_t LowLevelILOperand::GetIntrinsic() const
+{
+ if (m_type != IntrinsicLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsRegister(m_operandIndex);
+}
+
+
SSARegister LowLevelILOperand::GetSSARegister() const
{
if (m_type != SSARegisterLowLevelOperand)
@@ -952,6 +1204,14 @@ LowLevelILInstructionList LowLevelILOperand::GetExprList() const
}
+LowLevelILRegisterOrFlagList LowLevelILOperand::GetRegisterOrFlagList() const
+{
+ if (m_type != RegisterOrFlagListLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsRegisterOrFlagList(m_operandIndex);
+}
+
+
LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const
{
if (m_type != SSARegisterListLowLevelOperand)
@@ -978,6 +1238,14 @@ LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const
}
+LowLevelILSSARegisterOrFlagList LowLevelILOperand::GetSSARegisterOrFlagList() const
+{
+ if (m_type != SSARegisterOrFlagListLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsSSARegisterOrFlagList(m_operandIndex);
+}
+
+
map<uint32_t, int32_t> LowLevelILOperand::GetRegisterStackAdjustments() const
{
if (m_type != RegisterStackAdjustmentsLowLevelOperand)
@@ -1174,6 +1442,12 @@ LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(siz
}
+LowLevelILRegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsRegisterOrFlagList(size_t operand) const
+{
+ return LowLevelILRegisterOrFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+}
+
+
LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const
{
return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
@@ -1192,6 +1466,12 @@ LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size
}
+LowLevelILSSARegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsSSARegisterOrFlagList(size_t operand) const
+{
+ return LowLevelILSSARegisterOrFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+}
+
+
map<uint32_t, int32_t> LowLevelILInstructionBase::GetRawOperandAsRegisterStackAdjustments(size_t operand) const
{
LowLevelILIntegerList list(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
@@ -1224,6 +1504,14 @@ void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterList(size_t operand
}
+void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterOrFlagList(size_t operandIndex,
+ const vector<SSARegisterOrFlag>& outputs)
+{
+ UpdateRawOperand(operandIndex, outputs.size() * 2);
+ UpdateRawOperand(operandIndex + 1, function->AddSSARegisterOrFlagList(outputs));
+}
+
+
RegisterValue LowLevelILInstructionBase::GetValue() const
{
return function->GetExprValue(*(const LowLevelILInstruction*)this);
@@ -1585,6 +1873,14 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL
AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func);
AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func);
break;
+ case LLIL_INTRINSIC:
+ for (auto& i : GetParameterExprs<LLIL_INTRINSIC>())
+ i.VisitExprs(func);
+ break;
+ case LLIL_INTRINSIC_SSA:
+ for (auto& i : GetParameterExprs<LLIL_INTRINSIC_SSA>())
+ i.VisitExprs(func);
+ break;
default:
break;
}
@@ -1839,6 +2135,16 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()),
subExprHandler(AsTwoOperandWithCarry().GetRightExpr()),
subExprHandler(AsTwoOperandWithCarry().GetCarryExpr()));
+ case LLIL_INTRINSIC:
+ for (auto& i : GetParameterExprs<LLIL_INTRINSIC>())
+ params.push_back(subExprHandler(i));
+ return dest->Intrinsic(GetOutputRegisterOrFlagList<LLIL_INTRINSIC>(), GetIntrinsic<LLIL_INTRINSIC>(),
+ params, *this);
+ case LLIL_INTRINSIC_SSA:
+ for (auto& i : GetParameterExprs<LLIL_INTRINSIC_SSA>())
+ params.push_back(subExprHandler(i));
+ return dest->IntrinsicSSA(GetOutputSSARegisterOrFlagList<LLIL_INTRINSIC_SSA>(), GetIntrinsic<LLIL_INTRINSIC_SSA>(),
+ params, *this);
default:
throw LowLevelILInstructionAccessException();
}
@@ -2103,6 +2409,15 @@ SSARegister LowLevelILInstruction::GetLowSSARegister() const
}
+uint32_t LowLevelILInstruction::GetIntrinsic() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(IntrinsicLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsRegister(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
int64_t LowLevelILInstruction::GetConstant() const
{
size_t operandIndex;
@@ -2242,6 +2557,24 @@ LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const
}
+LowLevelILRegisterOrFlagList LowLevelILInstruction::GetOutputRegisterOrFlagList() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(OutputRegisterOrFlagListLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsRegisterOrFlagList(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
+LowLevelILSSARegisterOrFlagList LowLevelILInstruction::GetOutputSSARegisterOrFlagList() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(OutputSSARegisterOrFlagListLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSARegisterOrFlagList(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const
{
size_t operandIndex;
@@ -2759,7 +3092,7 @@ ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId des
AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer,
output.size() * 2, AddSSARegisterList(output)), dest,
AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer),
- AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0,
+ AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0,
params.size(), AddOperandList(params)));
}
@@ -2771,7 +3104,7 @@ ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, cons
AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer,
output.size() * 2, AddSSARegisterList(output)),
AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer),
- AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0,
+ AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0,
params.size(), AddOperandList(params)));
}
@@ -2878,6 +3211,24 @@ ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc)
}
+ExprId LowLevelILFunction::Intrinsic(const vector<RegisterOrFlag>& outputs, uint32_t intrinsic,
+ const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_INTRINSIC, loc, 0, 0,
+ outputs.size(), AddRegisterOrFlagList(outputs), intrinsic,
+ AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params)));
+}
+
+
+ExprId LowLevelILFunction::IntrinsicSSA(const vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic,
+ const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_INTRINSIC_SSA, loc, 0, 0,
+ outputs.size() * 2, AddSSARegisterOrFlagList(outputs), intrinsic,
+ AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params)));
+}
+
+
ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_BP, loc, 0, 0);
diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h
index bb5041a6..4679f556 100644
--- a/lowlevelilinstruction.h
+++ b/lowlevelilinstruction.h
@@ -54,6 +54,31 @@ namespace BinaryNinja
class LowLevelILOperand;
class LowLevelILOperandList;
+ struct RegisterOrFlag
+ {
+ bool isFlag;
+ uint32_t index;
+
+ RegisterOrFlag();
+ RegisterOrFlag(bool flag, uint32_t i);
+
+ bool IsRegister() const { return !isFlag; }
+ bool IsFlag() const { return isFlag; }
+ uint32_t GetRegister() const;
+ uint32_t GetFlag() const;
+
+ RegisterOrFlag& operator=(const RegisterOrFlag& v);
+ bool operator==(const RegisterOrFlag& v) const;
+ bool operator!=(const RegisterOrFlag& v) const;
+ bool operator<(const RegisterOrFlag& v) const;
+
+ uint64_t ToIdentifier() const;
+ static RegisterOrFlag FromIdentifier(uint64_t id);
+
+ static RegisterOrFlag Register(uint32_t reg) { return RegisterOrFlag(false, reg); }
+ static RegisterOrFlag Flag(uint32_t flag) { return RegisterOrFlag(true, flag); }
+ };
+
struct SSARegister
{
uint32_t reg;
@@ -99,6 +124,23 @@ namespace BinaryNinja
bool operator<(const SSAFlag& v) const;
};
+ struct SSARegisterOrFlag
+ {
+ RegisterOrFlag regOrFlag;
+ size_t version;
+
+ SSARegisterOrFlag();
+ SSARegisterOrFlag(const RegisterOrFlag& rf, size_t i);
+ SSARegisterOrFlag(const SSARegister& v);
+ SSARegisterOrFlag(const SSAFlag& v);
+ SSARegisterOrFlag(const SSARegisterOrFlag& v);
+
+ SSARegisterOrFlag& operator=(const SSARegisterOrFlag& v);
+ bool operator==(const SSARegisterOrFlag& v) const;
+ bool operator!=(const SSARegisterOrFlag& v) const;
+ bool operator<(const SSARegisterOrFlag& v) const;
+ };
+
enum LowLevelILOperandType
{
IntegerLowLevelOperand,
@@ -108,6 +150,7 @@ namespace BinaryNinja
RegisterStackLowLevelOperand,
FlagLowLevelOperand,
FlagConditionLowLevelOperand,
+ IntrinsicLowLevelOperand,
SemanticFlagClassLowLevelOperand,
SemanticFlagGroupLowLevelOperand,
SSARegisterLowLevelOperand,
@@ -115,9 +158,11 @@ namespace BinaryNinja
SSAFlagLowLevelOperand,
IndexListLowLevelOperand,
ExprListLowLevelOperand,
+ RegisterOrFlagListLowLevelOperand,
SSARegisterListLowLevelOperand,
SSARegisterStackListLowLevelOperand,
SSAFlagListLowLevelOperand,
+ SSARegisterOrFlagListLowLevelOperand,
RegisterStackAdjustmentsLowLevelOperand
};
@@ -152,6 +197,7 @@ namespace BinaryNinja
HighSSARegisterLowLevelOperandUsage,
LowRegisterLowLevelOperandUsage,
LowSSARegisterLowLevelOperandUsage,
+ IntrinsicLowLevelOperandUsage,
ConstantLowLevelOperandUsage,
VectorLowLevelOperandUsage,
StackAdjustmentLowLevelOperandUsage,
@@ -168,6 +214,8 @@ namespace BinaryNinja
SourceSSARegistersLowLevelOperandUsage,
SourceSSARegisterStacksLowLevelOperandUsage,
SourceSSAFlagsLowLevelOperandUsage,
+ OutputRegisterOrFlagListLowLevelOperandUsage,
+ OutputSSARegisterOrFlagListLowLevelOperandUsage,
SourceMemoryVersionsLowLevelOperandUsage,
TargetListLowLevelOperandUsage,
RegisterStackAdjustmentsLowLevelOperandUsage
@@ -365,6 +413,33 @@ namespace BinaryNinja
operator std::vector<LowLevelILInstruction>() const;
};
+ class LowLevelILRegisterOrFlagList
+ {
+ struct ListIterator
+ {
+ LowLevelILIntegerList::const_iterator pos;
+ bool operator==(const ListIterator& a) const { return pos == a.pos; }
+ bool operator!=(const ListIterator& a) const { return pos != a.pos; }
+ bool operator<(const ListIterator& a) const { return pos < a.pos; }
+ ListIterator& operator++() { ++pos; return *this; }
+ const RegisterOrFlag operator*();
+ };
+
+ LowLevelILIntegerList m_list;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ LowLevelILRegisterOrFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const RegisterOrFlag operator[](size_t i) const;
+
+ operator std::vector<RegisterOrFlag>() const;
+ };
+
class LowLevelILSSARegisterList
{
struct ListIterator
@@ -446,6 +521,33 @@ namespace BinaryNinja
operator std::vector<SSAFlag>() const;
};
+ class LowLevelILSSARegisterOrFlagList
+ {
+ struct ListIterator
+ {
+ LowLevelILIntegerList::const_iterator pos;
+ bool operator==(const ListIterator& a) const { return pos == a.pos; }
+ bool operator!=(const ListIterator& a) const { return pos != a.pos; }
+ bool operator<(const ListIterator& a) const { return pos < a.pos; }
+ ListIterator& operator++() { ++pos; ++pos; return *this; }
+ const SSARegisterOrFlag operator*();
+ };
+
+ LowLevelILIntegerList m_list;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ LowLevelILSSARegisterOrFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const SSARegisterOrFlag operator[](size_t i) const;
+
+ operator std::vector<SSARegisterOrFlag>() const;
+ };
+
struct LowLevelILInstructionBase: public BNLowLevelILInstruction
{
#ifdef BINARYNINJACORE_LIBRARY
@@ -474,13 +576,16 @@ namespace BinaryNinja
SSAFlag GetRawOperandAsSSAFlag(size_t operand) const;
LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const;
LowLevelILInstructionList GetRawOperandAsExprList(size_t operand) const;
+ LowLevelILRegisterOrFlagList GetRawOperandAsRegisterOrFlagList(size_t operand) const;
LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const;
LowLevelILSSARegisterStackList GetRawOperandAsSSARegisterStackList(size_t operand) const;
LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const;
+ LowLevelILSSARegisterOrFlagList GetRawOperandAsSSARegisterOrFlagList(size_t operand) const;
std::map<uint32_t, int32_t> GetRawOperandAsRegisterStackAdjustments(size_t operand) const;
void UpdateRawOperand(size_t operandIndex, ExprId value);
void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector<SSARegister>& regs);
+ void UpdateRawOperandAsSSARegisterOrFlagList(size_t operandIndex, const std::vector<SSARegisterOrFlag>& outputs);
RegisterValue GetValue() const;
PossibleValueSet GetPossibleValues() const;
@@ -604,6 +709,7 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> SSARegister GetHighSSARegister() const { return As<N>().GetHighSSARegister(); }
template <BNLowLevelILOperation N> uint32_t GetLowRegister() const { return As<N>().GetLowRegister(); }
template <BNLowLevelILOperation N> SSARegister GetLowSSARegister() const { return As<N>().GetLowSSARegister(); }
+ template <BNLowLevelILOperation N> uint32_t GetIntrinsic() const { return As<N>().GetIntrinsic(); }
template <BNLowLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); }
template <BNLowLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); }
template <BNLowLevelILOperation N> size_t GetStackAdjustment() const { return As<N>().GetStackAdjustment(); }
@@ -619,6 +725,8 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetSourceSSARegisters() const { return As<N>().GetSourceSSARegisters(); }
template <BNLowLevelILOperation N> LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const { return As<N>().GetSourceSSARegisterStacks(); }
template <BNLowLevelILOperation N> LowLevelILSSAFlagList GetSourceSSAFlags() const { return As<N>().GetSourceSSAFlags(); }
+ template <BNLowLevelILOperation N> LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const { return As<N>().GetOutputRegisterOrFlagList(); }
+ template <BNLowLevelILOperation N> LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const { return As<N>().GetOutputSSARegisterOrFlagList(); }
template <BNLowLevelILOperation N> LowLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); }
template <BNLowLevelILOperation N> LowLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); }
template <BNLowLevelILOperation N> std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const { return As<N>().GetRegisterStackAdjustments(); }
@@ -632,6 +740,7 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); }
template <BNLowLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); }
template <BNLowLevelILOperation N> void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetOutputSSARegisters(regs); }
+ template <BNLowLevelILOperation N> void SetOutputSSARegisterOrFlagList(const std::vector<SSARegisterOrFlag>& outputs) { As<N>().SetOutputSSARegisterOrFlagList(outputs); }
bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const;
@@ -664,6 +773,7 @@ namespace BinaryNinja
SSARegister GetHighSSARegister() const;
uint32_t GetLowRegister() const;
SSARegister GetLowSSARegister() const;
+ uint32_t GetIntrinsic() const;
int64_t GetConstant() const;
int64_t GetVector() const;
size_t GetStackAdjustment() const;
@@ -679,6 +789,8 @@ namespace BinaryNinja
LowLevelILSSARegisterList GetSourceSSARegisters() const;
LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const;
LowLevelILSSAFlagList GetSourceSSAFlags() const;
+ LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const;
+ LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const;
LowLevelILIndexList GetSourceMemoryVersions() const;
LowLevelILIndexList GetTargetList() const;
std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const;
@@ -706,6 +818,7 @@ namespace BinaryNinja
uint32_t GetFlag() const;
uint32_t GetSemanticFlagClass() const;
uint32_t GetSemanticFlagGroup() const;
+ uint32_t GetIntrinsic() const;
BNLowLevelILFlagCondition GetFlagCondition() const;
SSARegister GetSSARegister() const;
SSARegisterStack GetSSARegisterStack() const;
@@ -715,6 +828,8 @@ namespace BinaryNinja
LowLevelILSSARegisterList GetSSARegisterList() const;
LowLevelILSSARegisterStackList GetSSARegisterStackList() const;
LowLevelILSSAFlagList GetSSAFlagList() const;
+ LowLevelILRegisterOrFlagList GetRegisterOrFlagList() const;
+ LowLevelILSSARegisterOrFlagList GetSSARegisterOrFlagList() const;
std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const;
};
@@ -1022,6 +1137,20 @@ namespace BinaryNinja
void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_INTRINSIC>: public LowLevelILInstructionBase
+ {
+ LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const { return GetRawOperandAsRegisterOrFlagList(0); }
+ uint32_t GetIntrinsic() const { return GetRawOperandAsRegister(2); }
+ LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_INTRINSIC_SSA>: public LowLevelILInstructionBase
+ {
+ LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const { return GetRawOperandAsSSARegisterOrFlagList(0); }
+ uint32_t GetIntrinsic() const { return GetRawOperandAsRegister(2); }
+ LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); }
+ void SetOutputSSARegisterOrFlagList(const std::vector<SSARegisterOrFlag>& outputs) { UpdateRawOperandAsSSARegisterOrFlagList(0, outputs); }
+ };
+
template <> struct LowLevelILInstructionAccessor<LLIL_REG_PHI>: public LowLevelILInstructionBase
{
SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); }
diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp
index e911c298..7e1e663f 100644
--- a/mediumlevelilinstruction.cpp
+++ b/mediumlevelilinstruction.cpp
@@ -54,6 +54,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType>
{OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand},
{ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand},
{VectorMediumLevelOperandUsage, IntegerMediumLevelOperand},
+ {IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand},
{TargetMediumLevelOperandUsage, IndexMediumLevelOperand},
{TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand},
{FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand},
@@ -64,6 +65,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType>
{OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand},
{OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand},
{OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand},
+ {OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand},
{OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand},
{ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand},
{SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand},
@@ -127,23 +129,27 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>>
{MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}},
{MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage,
ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}},
- {MLIL_CALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage,
+ {MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage,
OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage,
ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}},
- {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage,
+ {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage,
OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage,
ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage,
StackExprMediumLevelOperandUsage}},
- {MLIL_SYSCALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage,
+ {MLIL_SYSCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage,
OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage,
SourceMemoryVersionMediumLevelOperandUsage}},
- {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage,
+ {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage,
OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage,
ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}},
{MLIL_RET, {SourceExprsMediumLevelOperandUsage}},
{MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage,
FalseTargetMediumLevelOperandUsage}},
{MLIL_GOTO, {TargetMediumLevelOperandUsage}},
+ {MLIL_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage,
+ ParameterExprsMediumLevelOperandUsage}},
+ {MLIL_INTRINSIC_SSA, {OutputSSAVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage,
+ ParameterExprsMediumLevelOperandUsage}},
{MLIL_TRAP, {VectorMediumLevelOperandUsage}},
{MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}},
{MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}},
@@ -243,7 +249,7 @@ static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperan
// Represented as subexpression, so only takes one slot even though it is a list
operand++;
break;
- case OutputSSAVariablesMediumLevelOperandUsage:
+ case OutputSSAVariablesSubExprMediumLevelOperandUsage:
// OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand
break;
case ParameterSSAVariablesMediumLevelOperandUsage:
@@ -681,6 +687,14 @@ size_t MediumLevelILOperand::GetIndex() const
}
+uint32_t MediumLevelILOperand::GetIntrinsic() const
+{
+ if (m_type != IntrinsicMediumLevelOperand)
+ throw MediumLevelILInstructionAccessException();
+ return (uint32_t)m_instr.GetRawOperandAsInteger(m_operandIndex);
+}
+
+
MediumLevelILInstruction MediumLevelILOperand::GetExpr() const
{
if (m_type != ExprMediumLevelOperand)
@@ -730,7 +744,7 @@ MediumLevelILSSAVariableList MediumLevelILOperand::GetSSAVariableList() const
{
if (m_type != SSAVariableListMediumLevelOperand)
throw MediumLevelILInstructionAccessException();
- if ((m_usage == OutputSSAVariablesMediumLevelOperandUsage) ||
+ if ((m_usage == OutputSSAVariablesSubExprMediumLevelOperandUsage) ||
(m_usage == ParameterSSAVariablesMediumLevelOperandUsage))
return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSAVariableList(1);
return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex);
@@ -1344,6 +1358,14 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL
AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func);
AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func);
break;
+ case MLIL_INTRINSIC:
+ for (auto& i : GetParameterExprs<MLIL_INTRINSIC>())
+ i.VisitExprs(func);
+ break;
+ case MLIL_INTRINSIC_SSA:
+ for (auto& i : GetParameterExprs<MLIL_INTRINSIC_SSA>())
+ i.VisitExprs(func);
+ break;
default:
break;
}
@@ -1609,6 +1631,16 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest,
return dest->Breakpoint(*this);
case MLIL_TRAP:
return dest->Trap(GetVector<MLIL_TRAP>(), *this);
+ case MLIL_INTRINSIC:
+ for (auto& i : GetParameterExprs<MLIL_INTRINSIC>())
+ params.push_back(subExprHandler(i));
+ return dest->Intrinsic(GetOutputVariables<MLIL_INTRINSIC>(),
+ GetIntrinsic<MLIL_INTRINSIC>(), params, *this);
+ case MLIL_INTRINSIC_SSA:
+ for (auto& i : GetParameterExprs<MLIL_INTRINSIC_SSA>())
+ params.push_back(subExprHandler(i));
+ return dest->IntrinsicSSA(GetOutputSSAVariables<MLIL_INTRINSIC_SSA>(),
+ GetIntrinsic<MLIL_INTRINSIC_SSA>(), params, *this);
case MLIL_UNDEF:
return dest->Undefined(*this);
case MLIL_UNIMPL:
@@ -1796,6 +1828,15 @@ int64_t MediumLevelILInstruction::GetVector() const
}
+uint32_t MediumLevelILInstruction::GetIntrinsic() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(IntrinsicMediumLevelOperandUsage, operandIndex))
+ return (uint32_t)GetRawOperandAsInteger(operandIndex);
+ throw MediumLevelILInstructionAccessException();
+}
+
+
size_t MediumLevelILInstruction::GetTarget() const
{
size_t operandIndex;
@@ -1878,6 +1919,8 @@ MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() c
{
size_t operandIndex;
if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSAVariableList(operandIndex);
+ if (GetOperandIndexForUsage(OutputSSAVariablesSubExprMediumLevelOperandUsage, operandIndex))
return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1);
throw MediumLevelILInstructionAccessException();
}
@@ -2577,6 +2620,22 @@ ExprId MediumLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc)
}
+ExprId MediumLevelILFunction::Intrinsic(const vector<Variable>& outputs, uint32_t intrinsic,
+ const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(MLIL_INTRINSIC, loc, 0, outputs.size(), AddVariableList(outputs),
+ intrinsic, params.size(), AddOperandList(params));
+}
+
+
+ExprId MediumLevelILFunction::IntrinsicSSA(const vector<SSAVariable>& outputs, uint32_t intrinsic,
+ const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(MLIL_INTRINSIC_SSA, loc, 0, outputs.size() * 2, AddSSAVariableList(outputs),
+ intrinsic, params.size(), AddOperandList(params));
+}
+
+
ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc)
{
return AddExprWithLocation(MLIL_UNDEF, loc, 0);
diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h
index 8e671aaf..de92764d 100644
--- a/mediumlevelilinstruction.h
+++ b/mediumlevelilinstruction.h
@@ -70,6 +70,7 @@ namespace BinaryNinja
{
IntegerMediumLevelOperand,
IndexMediumLevelOperand,
+ IntrinsicMediumLevelOperand,
ExprMediumLevelOperand,
VariableMediumLevelOperand,
SSAVariableMediumLevelOperand,
@@ -100,6 +101,7 @@ namespace BinaryNinja
OffsetMediumLevelOperandUsage,
ConstantMediumLevelOperandUsage,
VectorMediumLevelOperandUsage,
+ IntrinsicMediumLevelOperandUsage,
TargetMediumLevelOperandUsage,
TrueTargetMediumLevelOperandUsage,
FalseTargetMediumLevelOperandUsage,
@@ -110,6 +112,7 @@ namespace BinaryNinja
OutputVariablesMediumLevelOperandUsage,
OutputVariablesSubExprMediumLevelOperandUsage,
OutputSSAVariablesMediumLevelOperandUsage,
+ OutputSSAVariablesSubExprMediumLevelOperandUsage,
OutputSSAMemoryVersionMediumLevelOperandUsage,
ParameterExprsMediumLevelOperandUsage,
SourceExprsMediumLevelOperandUsage,
@@ -485,6 +488,7 @@ namespace BinaryNinja
template <BNMediumLevelILOperation N> uint64_t GetOffset() const { return As<N>().GetOffset(); }
template <BNMediumLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); }
template <BNMediumLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); }
+ template <BNMediumLevelILOperation N> uint32_t GetIntrinsic() const { return As<N>().GetIntrinsic(); }
template <BNMediumLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); }
template <BNMediumLevelILOperation N> size_t GetTrueTarget() const { return As<N>().GetTrueTarget(); }
template <BNMediumLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); }
@@ -535,6 +539,7 @@ namespace BinaryNinja
uint64_t GetOffset() const;
int64_t GetConstant() const;
int64_t GetVector() const;
+ uint32_t GetIntrinsic() const;
size_t GetTarget() const;
size_t GetTrueTarget() const;
size_t GetFalseTarget() const;
@@ -567,6 +572,7 @@ namespace BinaryNinja
uint64_t GetInteger() const;
size_t GetIndex() const;
+ uint32_t GetIntrinsic() const;
MediumLevelILInstruction GetExpr() const;
Variable GetVariable() const;
SSAVariable GetSSAVariable() const;
@@ -902,6 +908,20 @@ namespace BinaryNinja
size_t GetTarget() const { return GetRawOperandAsIndex(0); }
};
+ template <> struct MediumLevelILInstructionAccessor<MLIL_INTRINSIC>: public MediumLevelILInstructionBase
+ {
+ MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); }
+ uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); }
+ MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); }
+ };
+ template <> struct MediumLevelILInstructionAccessor<MLIL_INTRINSIC_SSA>: public MediumLevelILInstructionBase
+ {
+ MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsSSAVariableList(0); }
+ uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); }
+ MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); }
+ void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { UpdateRawOperandAsSSAVariableList(0, vars); }
+ };
+
template <> struct MediumLevelILInstructionAccessor<MLIL_TRAP>: public MediumLevelILInstructionBase
{
int64_t GetVector() const { return GetRawOperandAsInteger(0); }
diff --git a/python/architecture.py b/python/architecture.py
index 2b422962..3ccd2b11 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -33,6 +33,7 @@ import callingconvention
import platform
import log
import databuffer
+import types
class _ArchitectureMetaClass(type):
@@ -128,6 +129,7 @@ class Architecture(object):
flags_written_by_flag_write_type = {}
semantic_class_for_flag_write_type = {}
reg_stacks = {}
+ intrinsics = {}
__metaclass__ = _ArchitectureMetaClass
next_address = 0
@@ -304,6 +306,27 @@ class Architecture(object):
top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg)
self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i])
core.BNFreeRegisterList(regs)
+
+ count = ctypes.c_ulonglong()
+ intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count)
+ self.__dict__["intrinsics"] = {}
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i])
+ input_count = ctypes.c_ulonglong()
+ inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count)
+ input_list = []
+ for j in xrange(0, input_count.value):
+ input_name = inputs[j].name
+ type_obj = types.Type(core.BNNewTypeReference(inputs[j].type), confidence = inputs[j].typeConfidence)
+ input_list.append(function.IntrinsicInput(type_obj, input_name))
+ core.BNFreeNameAndTypeList(inputs, input_count.value)
+ output_count = ctypes.c_ulonglong()
+ outputs = core.BNGetArchitectureIntrinsicOutputs(self.handle, intrinsics[i], output_count)
+ output_list = []
+ for j in xrange(0, output_count.value):
+ output_list.append(types.Type(core.BNNewTypeReference(outputs[j].type), confidence = outputs[j].confidence))
+ core.BNFreeOutputTypeList(outputs, output_count.value)
+ self.intrinsics[name] = function.IntrinsicInfo(input_list, output_list)
else:
startup._init_plugins()
@@ -365,6 +388,12 @@ class Architecture(object):
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.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)
+ self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__(self._free_name_and_type_list)
+ self._cb.getIntrinsicOutputs = self._cb.getIntrinsicOutputs.__class__(self._get_intrinsic_outputs)
+ self._cb.freeTypeList = self._cb.freeTypeList.__class__(self._free_type_list)
self._cb.assemble = self._cb.assemble.__class__(self._assemble)
self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
self._is_never_branch_patch_available)
@@ -514,9 +543,28 @@ class Architecture(object):
self.__dict__["global_regs"] = self.__class__.global_regs
+ self._intrinsics = {}
+ self._intrinsics_by_index = {}
+ self.__dict__["intrinsics"] = self.__class__.intrinsics
+ intrinsic_index = 0
+ for intrinsic in self.__class__.intrinsics.keys():
+ if intrinsic not in self._intrinsics:
+ info = self.__class__.intrinsics[intrinsic]
+ for i in xrange(0, len(info.inputs)):
+ if isinstance(info.inputs[i], types.Type):
+ info.inputs[i] = function.IntrinsicInput(info.inputs[i])
+ elif isinstance(info.inputs[i], tuple):
+ info.inputs[i] = function.IntrinsicInput(info.inputs[i][0], info.inputs[i][1])
+ info.index = intrinsic_index
+ self._intrinsics[intrinsic] = intrinsic_index
+ self._intrinsics_by_index[intrinsic_index] = (intrinsic, info)
+ intrinsic_index += 1
+
self._pending_reg_lists = {}
self._pending_token_lists = {}
self._pending_condition_lists = {}
+ self._pending_name_and_type_lists = {}
+ self._pending_type_lists = {}
def __eq__(self, value):
if not isinstance(value, Architecture):
@@ -1116,6 +1164,95 @@ class Architecture(object):
result[0].topRelativeCount = 0
result[0].stackTopReg = 0
+ def _get_intrinsic_name(self, ctxt, intrinsic):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ return core.BNAllocString(self._intrinsics_by_index[intrinsic][0])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
+ def _get_all_intrinsics(self, ctxt, count):
+ try:
+ regs = self._intrinsics_by_index.keys()
+ count[0] = len(regs)
+ reg_buf = (ctypes.c_uint * len(regs))()
+ for i in xrange(0, len(regs)):
+ reg_buf[i] = regs[i]
+ result = ctypes.cast(reg_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, reg_buf)
+ return result.value
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_intrinsic_inputs(self, ctxt, intrinsic, count):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ inputs = self._intrinsics_by_index[intrinsic][1].inputs
+ count[0] = len(inputs)
+ input_buf = (core.BNNameAndType * len(inputs))()
+ for i in xrange(0, len(inputs)):
+ input_buf[i].name = inputs[i].name
+ input_buf[i].type = core.BNNewTypeReference(inputs[i].type.handle)
+ input_buf[i].typeConfidence = inputs[i].type.confidence
+ result = ctypes.cast(input_buf, ctypes.c_void_p)
+ self._pending_name_and_type_lists[result.value] = (result, input_buf, len(inputs))
+ return result.value
+ count[0] = 0
+ return None
+ except:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _free_name_and_type_list(self, ctxt, buf_raw):
+ try:
+ buf = ctypes.cast(buf_raw, ctypes.c_void_p)
+ if buf.value not in self._pending_name_and_type_lists:
+ raise ValueError("freeing name and type list that wasn't allocated")
+ name_and_types = self._pending_name_and_type_lists[buf.value][1]
+ count = self._pending_name_and_type_lists[buf.value][2]
+ for i in xrange(0, count):
+ core.BNFreeType(name_and_types[i].type)
+ del self._pending_name_and_type_lists[buf.value]
+ except (ValueError, KeyError):
+ log.log_error(traceback.format_exc())
+
+ def _get_intrinsic_outputs(self, ctxt, intrinsic, count):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ outputs = self._intrinsics_by_index[intrinsic][1].outputs
+ count[0] = len(outputs)
+ output_buf = (core.BNTypeWithConfidence * len(outputs))()
+ for i in xrange(0, len(outputs)):
+ output_buf[i].type = core.BNNewTypeReference(outputs[i].handle)
+ output_buf[i].confidence = outputs[i].confidence
+ result = ctypes.cast(output_buf, ctypes.c_void_p)
+ self._pending_type_lists[result.value] = (result, output_buf, len(outputs))
+ return result.value
+ count[0] = 0
+ return None
+ except:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _free_type_list(self, ctxt, buf_raw):
+ try:
+ buf = ctypes.cast(buf_raw, ctypes.c_void_p)
+ if buf.value not in self._pending_type_lists:
+ raise ValueError("freeing type list that wasn't allocated")
+ types = self._pending_type_lists[buf.value][1]
+ count = self._pending_type_lists[buf.value][2]
+ for i in xrange(0, count):
+ core.BNFreeType(types[i].type)
+ del self._pending_type_lists[buf.value]
+ except (ValueError, KeyError):
+ log.log_error(traceback.format_exc())
+
def _assemble(self, ctxt, code, addr, result, errors):
try:
data, error_str = self.perform_assemble(code, addr)
@@ -1701,6 +1838,23 @@ class Architecture(object):
return sem_group.index
return sem_group
+ def get_intrinsic_name(self, intrinsic):
+ """
+ ``get_intrinsic_name`` gets an intrinsic name from an intrinsic number.
+
+ :param int intrinsic: intrinsic number
+ :return: the corresponding intrinsic string
+ :rtype: str
+ """
+ return core.BNGetArchitectureIntrinsicName(self.handle, intrinsic)
+
+ def get_intrinsic_index(self, intrinsic):
+ if isinstance(intrinsic, str):
+ return self._intrinsics[intrinsic]
+ elif isinstance(intrinsic, lowlevelil.ILIntrinsic):
+ return intrinsic.index
+ return intrinsic
+
def get_flag_write_type_name(self, write_type):
"""
``get_flag_write_type_name`` gets the flag write type name for the given flag.
diff --git a/python/function.py b/python/function.py
index 10583b58..7607657f 100644
--- a/python/function.py
+++ b/python/function.py
@@ -427,7 +427,7 @@ class Function(object):
"""Function platform (read-only)"""
if self._platform:
return self._platform
- else:
+ else:
plat = core.BNGetFunctionPlatform(self.handle)
if plat is None:
return None
@@ -1878,6 +1878,27 @@ class RegisterStackInfo(object):
return "<reg stack: %d regs, stack top in %s>" % (len(self.storage_regs), self.stack_top_reg)
+class IntrinsicInput(object):
+ def __init__(self, type_obj, name=""):
+ self.name = name
+ self.type = type_obj
+
+ def __repr__(self):
+ if len(self.name) == 0:
+ return "<input: %s>" % str(self.type)
+ return "<input: %s %s>" % (str(self.type), self.name)
+
+
+class IntrinsicInfo(object):
+ def __init__(self, inputs, outputs, index=None):
+ self.inputs = inputs
+ self.outputs = outputs
+ self.index = index
+
+ def __repr__(self):
+ return "<intrinsic: %s -> %s>" % (repr(self.inputs), repr(self.outputs))
+
+
class InstructionBranch(object):
def __init__(self, branch_type, target = 0, arch = None):
self.type = branch_type
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index a2d77c9f..33296ce8 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -131,6 +131,25 @@ class ILSemanticFlagGroup(object):
return self.index == other.index
+class ILIntrinsic(object):
+ def __init__(self, arch, intrinsic):
+ self.arch = arch
+ self.index = intrinsic
+ self.name = self.arch.get_intrinsic_name(self.index)
+ if self.name in self.arch.intrinsics:
+ self.inputs = self.arch.intrinsics[self.name].inputs
+ self.outputs = self.arch.intrinsics[self.name].outputs
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.index == other.index
+
+
class SSARegister(object):
def __init__(self, reg, version):
self.reg = reg
@@ -158,6 +177,15 @@ class SSAFlag(object):
return "<ssa %s version %d>" % (repr(self.flag), self.version)
+class SSARegisterOrFlag(object):
+ def __init__(self, reg_or_flag, version):
+ self.reg_or_flag = reg_or_flag
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.reg_or_flag), self.version)
+
+
class LowLevelILOperationAndSize(object):
def __init__(self, operation, size):
self.operation = operation
@@ -250,6 +278,8 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")],
LowLevelILOperation.LLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_SYSCALL: [],
+ LowLevelILOperation.LLIL_INTRINSIC: [("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_BP: [],
LowLevelILOperation.LLIL_TRAP: [("vector", "int")],
LowLevelILOperation.LLIL_UNDEF: [],
@@ -292,7 +322,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")],
LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")],
LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")],
- LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "expr_list")],
+ LowLevelILOperation.LLIL_CALL_PARAM: [("src", "expr_list")],
LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")],
@@ -336,6 +366,8 @@ class LowLevelILInstruction(object):
value = ILRegister(func.arch, instr.operands[i])
elif operand_type == "reg_stack":
value = ILRegisterStack(func.arch, instr.operands[i])
+ elif operand_type == "intrinsic":
+ value = ILIntrinsic(func.arch, instr.operands[i])
elif operand_type == "reg_ssa":
reg = ILRegister(func.arch, instr.operands[i])
i += 1
@@ -369,25 +401,36 @@ class LowLevelILInstruction(object):
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value):
- value.append(operand_list[i])
+ for j in xrange(count.value):
+ value.append(operand_list[j])
core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "expr_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value):
- value.append(LowLevelILInstruction(func, operand_list[i]))
+ for j in xrange(count.value):
+ value.append(LowLevelILInstruction(func, operand_list[j]))
+ core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_or_flag_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for j in xrange(count.value):
+ if (operand_list[j] & (1 << 32)) != 0:
+ value.append(ILFlag(func.arch, operand_list[j] & 0xffffffff))
+ else:
+ value.append(ILRegister(func.arch, operand_list[j] & 0xffffffff))
core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "reg_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value / 2):
- reg = operand_list[i * 2]
- reg_version = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ reg = operand_list[j * 2]
+ reg_version = operand_list[(j * 2) + 1]
value.append(SSARegister(ILRegister(func.arch, reg), reg_version))
core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "reg_stack_ssa_list":
@@ -395,9 +438,9 @@ class LowLevelILInstruction(object):
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value / 2):
- reg_stack = operand_list[i * 2]
- reg_version = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ reg_stack = operand_list[j * 2]
+ reg_version = operand_list[(j * 2) + 1]
value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), reg_version))
core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "flag_ssa_list":
@@ -405,19 +448,32 @@ class LowLevelILInstruction(object):
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value / 2):
- flag = operand_list[i * 2]
- flag_version = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ flag = operand_list[j * 2]
+ flag_version = operand_list[(j * 2) + 1]
value.append(SSAFlag(ILFlag(func.arch, flag), flag_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_or_flag_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for j in xrange(count.value / 2):
+ if (operand_list[j * 2] & (1 << 32)) != 0:
+ reg_or_flag = ILFlag(func.arch, operand_list[j * 2] & 0xffffffff)
+ else:
+ reg_or_flag = ILRegister(func.arch, operand_list[j * 2] & 0xffffffff)
+ reg_version = operand_list[(j * 2) + 1]
+ value.append(SSARegisterOrFlag(reg_or_flag, reg_version))
+ core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "reg_stack_adjust":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = {}
- for i in xrange(count.value / 2):
- reg_stack = operand_list[i * 2]
- adjust = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ reg_stack = operand_list[j * 2]
+ adjust = operand_list[(j * 2) + 1]
if adjust & 0x80000000:
adjust |= ~0x80000000
value[func.arch.get_reg_stack_name(reg_stack)] = adjust
@@ -1714,6 +1770,25 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_SYSCALL)
+ def intrinsic(self, outputs, intrinsic, params):
+ """
+ ``intrinsic`` return an intrinsic expression.
+
+ :return: an intrinsic expression.
+ :rtype: LowLevelILExpr
+ """
+ output_list = []
+ for output in outputs:
+ if isinstance(output, ILFlag):
+ output_list.append((1 << 32) | output.index)
+ else:
+ output_list.append(output.index)
+ param_list = []
+ for param in params:
+ param_list.append(param.index)
+ return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list),
+ self.arch.get_intrinsic_index(intrinsic), len(params), self.add_operand_list(param_list))
+
def breakpoint(self):
"""
``breakpoint`` returns a processor breakpoint expression.
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 8594ea36..3c4ba3fd 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -150,6 +150,8 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")],
MediumLevelILOperation.MLIL_BP: [],
MediumLevelILOperation.MLIL_TRAP: [("vector", "int")],
+ MediumLevelILOperation.MLIL_INTRINSIC: [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_INTRINSIC_SSA: [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
MediumLevelILOperation.MLIL_UNDEF: [],
MediumLevelILOperation.MLIL_UNIMPL: [],
MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")],
@@ -223,6 +225,8 @@ class MediumLevelILInstruction(object):
value = instr.operands[i]
elif operand_type == "expr":
value = MediumLevelILInstruction(func, instr.operands[i])
+ elif operand_type == "intrinsic":
+ value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i])
elif operand_type == "var":
value = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
elif operand_type == "var_ssa":