diff options
| -rw-r--r-- | architecture.cpp | 159 | ||||
| -rw-r--r-- | binaryninjaapi.h | 39 | ||||
| -rw-r--r-- | binaryninjacore.h | 40 | ||||
| -rw-r--r-- | lowlevelil.cpp | 25 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 355 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 129 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 71 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 20 | ||||
| -rw-r--r-- | python/architecture.py | 154 | ||||
| -rw-r--r-- | python/function.py | 23 | ||||
| -rw-r--r-- | python/lowlevelil.py | 109 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 4 |
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": |
