diff options
44 files changed, 7418 insertions, 1468 deletions
@@ -1,4 +1,4 @@ -[](https://binaryninja-slack-hwwdinrdce.now.sh/) +[](https://slack.binary.ninja/) # Binary Ninja API diff --git a/architecture.cpp b/architecture.cpp index 78c41dd3..ea27d805 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -237,6 +237,22 @@ char* Architecture::GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags) } +char* Architecture::GetSemanticFlagClassNameCallback(void* ctxt, uint32_t semClass) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetSemanticFlagClassName(semClass); + return BNAllocString(result.c_str()); +} + + +char* Architecture::GetSemanticFlagGroupNameCallback(void* ctxt, uint32_t semGroup) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetSemanticFlagGroupName(semGroup); + return BNAllocString(result.c_str()); +} + + uint32_t* Architecture::GetFullWidthRegistersCallback(void* ctxt, size_t* count) { Architecture* arch = (Architecture*)ctxt; @@ -289,17 +305,44 @@ uint32_t* Architecture::GetAllFlagWriteTypesCallback(void* ctxt, size_t* count) } -BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag) +uint32_t* Architecture::GetAllSemanticFlagClassesCallback(void* ctxt, size_t* count) { Architecture* arch = (Architecture*)ctxt; - return arch->GetFlagRole(flag); + vector<uint32_t> regs = arch->GetAllSemanticFlagClasses(); + *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; } -uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count) +uint32_t* Architecture::GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* count) { Architecture* arch = (Architecture*)ctxt; - vector<uint32_t> flags = arch->GetFlagsRequiredForFlagCondition(cond); + vector<uint32_t> regs = arch->GetAllSemanticFlagGroups(); + *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; +} + + +BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag, uint32_t semClass) +{ + Architecture* arch = (Architecture*)ctxt; + return arch->GetFlagRole(flag, semClass); +} + + +uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector<uint32_t> flags = arch->GetFlagsRequiredForFlagCondition(cond, semClass); *count = flags.size(); uint32_t* result = new uint32_t[flags.size()]; @@ -309,6 +352,44 @@ uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNL } +uint32_t* Architecture::GetFlagsRequiredForSemanticFlagGroupCallback(void* ctxt, uint32_t semGroup, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector<uint32_t> flags = arch->GetFlagsRequiredForSemanticFlagGroup(semGroup); + *count = flags.size(); + + uint32_t* result = new uint32_t[flags.size()]; + for (size_t i = 0; i < flags.size(); i++) + result[i] = flags[i]; + return result; +} + + +BNFlagConditionForSemanticClass* Architecture::GetFlagConditionsForSemanticFlagGroupCallback(void* ctxt, + uint32_t semGroup, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + map<uint32_t, BNLowLevelILFlagCondition> conditions = arch->GetFlagConditionsForSemanticFlagGroup(semGroup); + *count = conditions.size(); + + BNFlagConditionForSemanticClass* result = new BNFlagConditionForSemanticClass[conditions.size()]; + size_t i = 0; + for (auto& j : conditions) + { + result[i].semanticClass = j.first; + result[i].condition = j.second; + i++; + } + return result; +} + + +void Architecture::FreeFlagConditionsForSemanticFlagGroupCallback(void*, BNFlagConditionForSemanticClass* conditions) +{ + delete[] conditions; +} + + uint32_t* Architecture::GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count) { Architecture* arch = (Architecture*)ctxt; @@ -322,6 +403,13 @@ uint32_t* Architecture::GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint3 } +uint32_t Architecture::GetSemanticClassForFlagWriteTypeCallback(void* ctxt, uint32_t writeType) +{ + Architecture* arch = (Architecture*)ctxt; + return arch->GetSemanticClassForFlagWriteType(writeType); +} + + size_t Architecture::GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il) { @@ -331,12 +419,20 @@ size_t Architecture::GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOper } -size_t Architecture::GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, +size_t Architecture::GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il) { Architecture* arch = (Architecture*)ctxt; LowLevelILFunction func(il); - return arch->GetFlagConditionLowLevelIL(cond, func); + return arch->GetFlagConditionLowLevelIL(cond, semClass, func); +} + + +size_t Architecture::GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il) +{ + Architecture* arch = (Architecture*)ctxt; + LowLevelILFunction func(il); + return arch->GetSemanticFlagGroupLowLevelIL(semGroup, func); } @@ -380,6 +476,107 @@ uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count) } +char* Architecture::GetRegisterStackNameCallback(void* ctxt, uint32_t regStack) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetRegisterStackName(regStack); + return BNAllocString(result.c_str()); +} + + +uint32_t* Architecture::GetAllRegisterStacksCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector<uint32_t> regs = arch->GetAllRegisterStacks(); + *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; +} + + +void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result) +{ + Architecture* arch = (Architecture*)ctxt; + *result = arch->GetRegisterStackInfo(regStack); +} + + +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; @@ -483,6 +680,13 @@ bool Architecture::ApplyELFRelocationCallback(void* ctxt, BNBinaryView* view, BN // } +void Architecture::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + BNRegisterArchitecture(m_nameForRegister.c_str(), callbacks); +} + + void Architecture::Register(Architecture* arch) { BNCustomArchitecture callbacks; @@ -502,20 +706,38 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterName = GetRegisterNameCallback; callbacks.getFlagName = GetFlagNameCallback; callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback; + callbacks.getSemanticFlagClassName = GetSemanticFlagClassNameCallback; + callbacks.getSemanticFlagGroupName = GetSemanticFlagGroupNameCallback; callbacks.getFullWidthRegisters = GetFullWidthRegistersCallback; callbacks.getAllRegisters = GetAllRegistersCallback; callbacks.getAllFlags = GetAllFlagsCallback; callbacks.getAllFlagWriteTypes = GetAllFlagWriteTypesCallback; + callbacks.getAllSemanticFlagClasses = GetAllSemanticFlagClassesCallback; + callbacks.getAllSemanticFlagGroups = GetAllSemanticFlagGroupsCallback; callbacks.getFlagRole = GetFlagRoleCallback; callbacks.getFlagsRequiredForFlagCondition = GetFlagsRequiredForFlagConditionCallback; + callbacks.getFlagsRequiredForSemanticFlagGroup = GetFlagsRequiredForSemanticFlagGroupCallback; + callbacks.getFlagConditionsForSemanticFlagGroup = GetFlagConditionsForSemanticFlagGroupCallback; + callbacks.freeFlagConditionsForSemanticFlagGroup = FreeFlagConditionsForSemanticFlagGroupCallback; callbacks.getFlagsWrittenByFlagWriteType = GetFlagsWrittenByFlagWriteTypeCallback; + callbacks.getSemanticClassForFlagWriteType = GetSemanticClassForFlagWriteTypeCallback; callbacks.getFlagWriteLowLevelIL = GetFlagWriteLowLevelILCallback; callbacks.getFlagConditionLowLevelIL = GetFlagConditionLowLevelILCallback; + callbacks.getSemanticFlagGroupLowLevelIL = GetSemanticFlagGroupLowLevelILCallback; callbacks.freeRegisterList = FreeRegisterListCallback; callbacks.getRegisterInfo = GetRegisterInfoCallback; callbacks.getStackPointerRegister = GetStackPointerRegisterCallback; callbacks.getLinkRegister = GetLinkRegisterCallback; callbacks.getGlobalRegisters = GetGlobalRegistersCallback; + 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; @@ -530,9 +752,7 @@ void Architecture::Register(Architecture* arch) callbacks.applyELFRelocation = ApplyELFRelocationCallback; // callbacks.applyMachoRelocation = ApplyMachoRelocationCallback; callbacks.getRelocationInfo = GetRelocationInfoCallback; - - arch->AddRefForRegistration(); - BNRegisterArchitecture(arch->m_nameForRegister.c_str(), &callbacks); + arch->Register(&callbacks); } @@ -552,6 +772,7 @@ vector<Ref<Architecture>> Architecture::GetList() archs = BNGetArchitectureList(&count); vector<Ref<Architecture>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreArchitecture(archs[i])); @@ -635,6 +856,24 @@ string Architecture::GetFlagWriteTypeName(uint32_t flags) } +string Architecture::GetSemanticFlagClassName(uint32_t semClass) +{ + if (semClass == 0) + return ""; + char flagStr[32]; + sprintf(flagStr, "semantic%" PRIu32, semClass); + return flagStr; +} + + +string Architecture::GetSemanticFlagGroupName(uint32_t semGroup) +{ + char flagStr[32]; + sprintf(flagStr, "group%" PRIu32, semGroup); + return flagStr; +} + + vector<uint32_t> Architecture::GetFullWidthRegisters() { return vector<uint32_t>(); @@ -659,29 +898,58 @@ vector<uint32_t> Architecture::GetAllFlagWriteTypes() } -BNFlagRole Architecture::GetFlagRole(uint32_t) +vector<uint32_t> Architecture::GetAllSemanticFlagClasses() +{ + return vector<uint32_t>(); +} + + +vector<uint32_t> Architecture::GetAllSemanticFlagGroups() +{ + return vector<uint32_t>(); +} + + +BNFlagRole Architecture::GetFlagRole(uint32_t, uint32_t) { return SpecialFlagRole; } -vector<uint32_t> Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition) +vector<uint32_t> Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition, uint32_t) { return vector<uint32_t>(); } +vector<uint32_t> Architecture::GetFlagsRequiredForSemanticFlagGroup(uint32_t) +{ + return vector<uint32_t>(); +} + + +map<uint32_t, BNLowLevelILFlagCondition> Architecture::GetFlagConditionsForSemanticFlagGroup(uint32_t) +{ + return map<uint32_t, BNLowLevelILFlagCondition>(); +} + + vector<uint32_t> Architecture::GetFlagsWrittenByFlagWriteType(uint32_t) { return vector<uint32_t>(); } +uint32_t Architecture::GetSemanticClassForFlagWriteType(uint32_t) +{ + return 0; +} + + size_t Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - (void)flagWriteType; - BNFlagRole role = GetFlagRole(flag); + BNFlagRole role = GetFlagRole(flag, GetSemanticClassForFlagWriteType(flagWriteType)); return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } @@ -695,15 +963,23 @@ size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, siz } -ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) +{ + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); +} + + +ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); } -ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId Architecture::GetSemanticFlagGroupLowLevelIL(uint32_t, LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return il.Unimplemented(); } @@ -742,12 +1018,71 @@ bool Architecture::IsGlobalRegister(uint32_t reg) } +string Architecture::GetRegisterStackName(uint32_t regStack) +{ + char regStr[32]; + sprintf(regStr, "reg_stack_%" PRIu32, regStack); + return regStr; +} + + +vector<uint32_t> Architecture::GetAllRegisterStacks() +{ + return vector<uint32_t>(); +} + + +BNRegisterStackInfo Architecture::GetRegisterStackInfo(uint32_t) +{ + BNRegisterStackInfo result; + result.firstStorageReg = BN_INVALID_REGISTER; + result.topRelativeCount = BN_INVALID_REGISTER; + result.storageCount = 0; + result.topRelativeCount = 0; + result.stackTopReg = BN_INVALID_REGISTER; + return result; +} + + +uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg) +{ + return BNGetArchitectureRegisterStackForRegister(m_object, 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; uint32_t* regs = BNGetModifiedArchitectureRegistersOnWrite(m_object, reg, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -859,6 +1194,7 @@ vector<Ref<CallingConvention>> Architecture::GetCallingConventions() BNCallingConvention** list = BNGetArchitectureCallingConventions(m_object, &count); vector<Ref<CallingConvention>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreCallingConvention(BNNewCallingConventionReference(list[i]))); @@ -973,6 +1309,12 @@ bool Architecture::ApplyELFRelocation(BinaryView* view, BNRelocationInfo& rel, u // } +void Architecture::AddArchitectureRedirection(Architecture* from, Architecture* to) +{ + BNAddArchitectureRedirection(m_object, from->GetObject(), to->GetObject()); +} + + CoreArchitecture::CoreArchitecture(BNArchitecture* arch): Architecture(arch) { } @@ -1033,6 +1375,7 @@ bool CoreArchitecture::GetInstructionText(const uint8_t* data, uint64_t addr, si if (!BNGetInstructionText(m_object, data, addr, &len, &tokens, &count)) return false; + result.reserve(count); for (size_t i = 0; i < count; i++) { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, @@ -1077,12 +1420,31 @@ string CoreArchitecture::GetFlagWriteTypeName(uint32_t flags) } +string CoreArchitecture::GetSemanticFlagClassName(uint32_t semClass) +{ + char* name = BNGetArchitectureSemanticFlagClassName(m_object, semClass); + string result = name; + BNFreeString(name); + return result; +} + + +string CoreArchitecture::GetSemanticFlagGroupName(uint32_t semGroup) +{ + char* name = BNGetArchitectureSemanticFlagGroupName(m_object, semGroup); + string result = name; + BNFreeString(name); + return result; +} + + vector<uint32_t> CoreArchitecture::GetFullWidthRegisters() { size_t count; uint32_t* regs = BNGetFullWidthArchitectureRegisters(m_object, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1097,6 +1459,7 @@ vector<uint32_t> CoreArchitecture::GetAllRegisters() uint32_t* regs = BNGetAllArchitectureRegisters(m_object, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1111,6 +1474,7 @@ vector<uint32_t> CoreArchitecture::GetAllFlags() uint32_t* regs = BNGetAllArchitectureFlags(m_object, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1125,6 +1489,35 @@ vector<uint32_t> CoreArchitecture::GetAllFlagWriteTypes() uint32_t* regs = BNGetAllArchitectureFlagWriteTypes(m_object, &count); vector<uint32_t> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +vector<uint32_t> CoreArchitecture::GetAllSemanticFlagClasses() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureSemanticFlagClasses(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<uint32_t> CoreArchitecture::GetAllSemanticFlagGroups() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureSemanticFlagGroups(m_object, &count); + + vector<uint32_t> result; for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1133,18 +1526,33 @@ vector<uint32_t> CoreArchitecture::GetAllFlagWriteTypes() } -BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag) +BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag, uint32_t semClass) { - return BNGetArchitectureFlagRole(m_object, flag); + return BNGetArchitectureFlagRole(m_object, flag, semClass); +} + + +vector<uint32_t> CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass) +{ + size_t count; + uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, semClass, &count); + + vector<uint32_t> result; + for (size_t i = 0; i < count; i++) + result.push_back(flags[i]); + + BNFreeRegisterList(flags); + return result; } -vector<uint32_t> CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) +vector<uint32_t> CoreArchitecture::GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) { size_t count; - uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, &count); + uint32_t* flags = BNGetArchitectureFlagsRequiredForSemanticFlagGroup(m_object, semGroup, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(flags[i]); @@ -1153,12 +1561,28 @@ vector<uint32_t> CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelIL } +map<uint32_t, BNLowLevelILFlagCondition> CoreArchitecture::GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) +{ + size_t count; + BNFlagConditionForSemanticClass* conditions = BNGetArchitectureFlagConditionsForSemanticFlagGroup(m_object, + semGroup, &count); + + map<uint32_t, BNLowLevelILFlagCondition> result; + for (size_t i = 0; i < count; i++) + result[conditions[i].semanticClass] = conditions[i].condition; + + BNFreeFlagConditionsForSemanticFlagGroup(conditions); + return result; +} + + vector<uint32_t> CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t writeType) { size_t count; uint32_t* flags = BNGetArchitectureFlagsWrittenByFlagWriteType(m_object, writeType, &count); vector<uint32_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(flags[i]); @@ -1167,6 +1591,12 @@ vector<uint32_t> CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t write } +uint32_t CoreArchitecture::GetSemanticClassForFlagWriteType(uint32_t writeType) +{ + return BNGetArchitectureSemanticClassForFlagWriteType(m_object, writeType); +} + + size_t CoreArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) { @@ -1175,9 +1605,16 @@ size_t CoreArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t } -ExprId CoreArchitecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId CoreArchitecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) { - return (ExprId)BNGetArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return (ExprId)BNGetArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); +} + + +ExprId CoreArchitecture::GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) +{ + return (ExprId)BNGetArchitectureSemanticFlagGroupLowLevelIL(m_object, semGroup, il.GetObject()); } @@ -1205,6 +1642,59 @@ vector<uint32_t> CoreArchitecture::GetGlobalRegisters() uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count); vector<uint32_t> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +string CoreArchitecture::GetRegisterStackName(uint32_t regStack) +{ + char* name = BNGetArchitectureRegisterStackName(m_object, regStack); + string result = name; + BNFreeString(name); + return result; +} + + +vector<uint32_t> CoreArchitecture::GetAllRegisterStacks() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureRegisterStacks(m_object, &count); + + vector<uint32_t> result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack) +{ + return BNGetArchitectureRegisterStackInfo(m_object, 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]); @@ -1213,6 +1703,37 @@ vector<uint32_t> CoreArchitecture::GetGlobalRegisters() } +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; @@ -1301,4 +1822,365 @@ bool CoreArchitecture::ApplyELFRelocation(BinaryView* view, BNRelocationInfo& re bool CoreArchitecture::GetRelocationInfo(BinaryView* view, uint64_t relocType, BNRelocationInfo& reloc) { return BNGetRelocationInfo(m_object, view->GetObject(), relocType, &reloc); -}
\ No newline at end of file +} + +ArchitectureExtension::ArchitectureExtension(const string& name, Architecture* base): Architecture(name), m_base(base) +{ +} + + +void ArchitectureExtension::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + BNRegisterArchitectureExtension(m_nameForRegister.c_str(), m_base->GetObject(), callbacks); +} + + +BNEndianness ArchitectureExtension::GetEndianness() const +{ + return m_base->GetEndianness(); +} + + +size_t ArchitectureExtension::GetAddressSize() const +{ + return m_base->GetAddressSize(); +} + + +size_t ArchitectureExtension::GetDefaultIntegerSize() const +{ + return m_base->GetDefaultIntegerSize(); +} + + +size_t ArchitectureExtension::GetInstructionAlignment() const +{ + return m_base->GetInstructionAlignment(); +} + + +size_t ArchitectureExtension::GetMaxInstructionLength() const +{ + return m_base->GetMaxInstructionLength(); +} + + +size_t ArchitectureExtension::GetOpcodeDisplayLength() const +{ + return m_base->GetOpcodeDisplayLength(); +} + + +Ref<Architecture> ArchitectureExtension::GetAssociatedArchitectureByAddress(uint64_t& addr) +{ + Ref<Architecture> result = m_base->GetAssociatedArchitectureByAddress(addr); + if (result == m_base) + return this; + return result; +} + + +bool ArchitectureExtension::GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) +{ + return m_base->GetInstructionInfo(data, addr, maxLen, result); +} + + +bool ArchitectureExtension::GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, + vector<InstructionTextToken>& result) +{ + return m_base->GetInstructionText(data, addr, len, result); +} + + +bool ArchitectureExtension::GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) +{ + return m_base->GetInstructionLowLevelIL(data, addr, len, il); +} + + +string ArchitectureExtension::GetRegisterName(uint32_t reg) +{ + return m_base->GetRegisterName(reg); +} + + +string ArchitectureExtension::GetFlagName(uint32_t flag) +{ + return m_base->GetFlagName(flag); +} + + +string ArchitectureExtension::GetFlagWriteTypeName(uint32_t flags) +{ + return m_base->GetFlagWriteTypeName(flags); +} + + +string ArchitectureExtension::GetSemanticFlagClassName(uint32_t semClass) +{ + return m_base->GetSemanticFlagClassName(semClass); +} + + +string ArchitectureExtension::GetSemanticFlagGroupName(uint32_t semGroup) +{ + return m_base->GetSemanticFlagGroupName(semGroup); +} + + +vector<uint32_t> ArchitectureExtension::GetFullWidthRegisters() +{ + return m_base->GetFullWidthRegisters(); +} + + +vector<uint32_t> ArchitectureExtension::GetAllRegisters() +{ + return m_base->GetAllRegisters(); +} + + +vector<uint32_t> ArchitectureExtension::GetAllFlags() +{ + return m_base->GetAllFlags(); +} + + +vector<uint32_t> ArchitectureExtension::GetAllFlagWriteTypes() +{ + return m_base->GetAllFlagWriteTypes(); +} + + +vector<uint32_t> ArchitectureExtension::GetAllSemanticFlagClasses() +{ + return m_base->GetAllSemanticFlagClasses(); +} + + +vector<uint32_t> ArchitectureExtension::GetAllSemanticFlagGroups() +{ + return m_base->GetAllSemanticFlagGroups(); +} + + +BNFlagRole ArchitectureExtension::GetFlagRole(uint32_t flag, uint32_t semClass) +{ + return m_base->GetFlagRole(flag, semClass); +} + + +vector<uint32_t> ArchitectureExtension::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass) +{ + return m_base->GetFlagsRequiredForFlagCondition(cond, semClass); +} + + +vector<uint32_t> ArchitectureExtension::GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) +{ + return m_base->GetFlagsRequiredForSemanticFlagGroup(semGroup); +} + + +map<uint32_t, BNLowLevelILFlagCondition> ArchitectureExtension::GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) +{ + return m_base->GetFlagConditionsForSemanticFlagGroup(semGroup); +} + + +vector<uint32_t> ArchitectureExtension::GetFlagsWrittenByFlagWriteType(uint32_t writeType) +{ + return m_base->GetFlagsWrittenByFlagWriteType(writeType); +} + + +uint32_t ArchitectureExtension::GetSemanticClassForFlagWriteType(uint32_t writeType) +{ + return m_base->GetSemanticClassForFlagWriteType(writeType); +} + + +ExprId ArchitectureExtension::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, + uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) +{ + return m_base->GetFlagWriteLowLevelIL(op, size, flagWriteType, flag, operands, operandCount, il); +} + + +ExprId ArchitectureExtension::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) +{ + return m_base->GetFlagConditionLowLevelIL(cond, semClass, il); +} + + +ExprId ArchitectureExtension::GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) +{ + return m_base->GetSemanticFlagGroupLowLevelIL(semGroup, il); +} + + +BNRegisterInfo ArchitectureExtension::GetRegisterInfo(uint32_t reg) +{ + return m_base->GetRegisterInfo(reg); +} + + +uint32_t ArchitectureExtension::GetStackPointerRegister() +{ + return m_base->GetStackPointerRegister(); +} + + +uint32_t ArchitectureExtension::GetLinkRegister() +{ + return m_base->GetLinkRegister(); +} + + +vector<uint32_t> ArchitectureExtension::GetGlobalRegisters() +{ + return m_base->GetGlobalRegisters(); +} + + +string ArchitectureExtension::GetRegisterStackName(uint32_t regStack) +{ + return m_base->GetRegisterStackName(regStack); +} + + +vector<uint32_t> ArchitectureExtension::GetAllRegisterStacks() +{ + return m_base->GetAllRegisterStacks(); +} + + +BNRegisterStackInfo ArchitectureExtension::GetRegisterStackInfo(uint32_t regStack) +{ + return m_base->GetRegisterStackInfo(regStack); +} + + +string ArchitectureExtension::GetIntrinsicName(uint32_t intrinsic) +{ + return m_base->GetIntrinsicName(intrinsic); +} + + +vector<uint32_t> ArchitectureExtension::GetAllIntrinsics() +{ + return m_base->GetAllIntrinsics(); +} + + +vector<NameAndType> ArchitectureExtension::GetIntrinsicInputs(uint32_t intrinsic) +{ + return m_base->GetIntrinsicInputs(intrinsic); +} + + +vector<Confidence<Ref<Type>>> ArchitectureExtension::GetIntrinsicOutputs(uint32_t intrinsic) +{ + return m_base->GetIntrinsicOutputs(intrinsic); +} + + +bool ArchitectureExtension::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) +{ + return m_base->Assemble(code, addr, result, errors); +} + + +bool ArchitectureExtension::IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsNeverBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsAlwaysBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsInvertBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::ConvertToNop(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->ConvertToNop(data, addr, len); +} + + +bool ArchitectureExtension::AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->AlwaysBranch(data, addr, len); +} + + +bool ArchitectureExtension::InvertBranch(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->InvertBranch(data, addr, len); +} + + +bool ArchitectureExtension::SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) +{ + return m_base->SkipAndReturnValue(data, addr, len, value); +} + + +ArchitectureHook::ArchitectureHook(Architecture* base): CoreArchitecture(nullptr), m_base(base) +{ + // Architecture hooks allow existing architecture implementations to be extended without creating + // a new Architecture object for the changes. By deriving from the ArchitectureHook class and passing + // the original Architecture object of the architecture to be extended, any reimplemented functions + // will be called first before the original architecture's implementation. You MUST call the base + // class method to call the original implementation's version of the function, as calling the + // same function on the original Architecture object will call your implementation again. + + // Example of a hook to modify the lifting process: + + // class ArchitectureHookExample: public ArchitectureHook + // { + // public: + // ArchitectureHookExample(Architecture* existingArch) : ArchitectureHook(existingArch) + // { + // } + // + // virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, + // LowLevelILFunction& il) override + // { + // // Perform extra lifting here + // // ... + // // For unhandled cases, call the original architecture's implementation + // return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il); + // } + // }; +} + + +void ArchitectureHook::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + m_object = BNRegisterArchitectureHook(m_base->GetObject(), callbacks); +} diff --git a/backgroundtask.cpp b/backgroundtask.cpp index aebf980c..b2d4a738 100644 --- a/backgroundtask.cpp +++ b/backgroundtask.cpp @@ -67,6 +67,7 @@ vector<Ref<BackgroundTask>> BackgroundTask::GetRunningTasks() BNBackgroundTask** tasks = BNGetRunningBackgroundTasks(&count); vector<Ref<BackgroundTask>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BackgroundTask(BNNewBackgroundTaskReference(tasks[i]))); diff --git a/basicblock.cpp b/basicblock.cpp index 89ace134..33f57d40 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -120,6 +120,7 @@ vector<BasicBlockEdge> BasicBlock::GetOutgoingEdges() const BNBasicBlockEdge* array = BNGetBasicBlockOutgoingEdges(m_object, &count); vector<BasicBlockEdge> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { BasicBlockEdge edge; @@ -140,6 +141,7 @@ vector<BasicBlockEdge> BasicBlock::GetIncomingEdges() const BNBasicBlockEdge* array = BNGetBasicBlockIncomingEdges(m_object, &count); vector<BasicBlockEdge> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { BasicBlockEdge edge; @@ -269,10 +271,13 @@ vector<DisassemblyTextLine> BasicBlock::GetDisassemblyText(DisassemblySettings* BNDisassemblyTextLine* lines = BNGetBasicBlockDisassemblyText(m_object, settings->GetObject(), &count); vector<DisassemblyTextLine> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -413,3 +418,39 @@ bool BasicBlock::IsBackEdge(BasicBlock* source, BasicBlock* target) } return false; } + + +bool BasicBlock::IsILBlock() const +{ + return BNIsILBasicBlock(m_object); +} + + +bool BasicBlock::IsLowLevelILBlock() const +{ + return BNIsLowLevelILBasicBlock(m_object); +} + + +bool BasicBlock::IsMediumLevelILBlock() const +{ + return BNIsMediumLevelILBasicBlock(m_object); +} + + +Ref<LowLevelILFunction> BasicBlock::GetLowLevelILFunction() const +{ + BNLowLevelILFunction* func = BNGetBasicBlockLowLevelILFunction(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +Ref<MediumLevelILFunction> BasicBlock::GetMediumLevelILFunction() const +{ + BNMediumLevelILFunction* func = BNGetBasicBlockMediumLevelILFunction(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7fabe042..ad28273d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -486,6 +486,7 @@ namespace BinaryNinja }; class Architecture; + class BackgroundTask; class Platform; class Type; class DataBuffer; @@ -679,8 +680,10 @@ namespace BinaryNinja void erase(std::vector<std::string>::iterator i); void clear(); void push_back(const std::string& name); + // Returns count of names size_t size() const; - + // Returns size of output string + size_t StringSize() const; std::string GetString() const; BNQualifiedName GetAPIObject() const; @@ -864,6 +867,7 @@ namespace BinaryNinja static void FunctionAddedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void FunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void FunctionUpdatedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); + static void FunctionUpdateRequestedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void DataVariableAddedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void DataVariableRemovedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void DataVariableUpdatedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); @@ -884,6 +888,7 @@ namespace BinaryNinja virtual void OnAnalysisFunctionAdded(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnAnalysisFunctionRemoved(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnAnalysisFunctionUpdated(BinaryView* view, Function* func) { (void)view; (void)func; } + virtual void OnAnalysisFunctionUpdateRequested(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnDataVariableAdded(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnDataVariableRemoved(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnDataVariableUpdated(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } @@ -934,8 +939,6 @@ namespace BinaryNinja public: Symbol(BNSymbolType type, const std::string& shortName, const std::string& fullName, const std::string& rawName, uint64_t addr); Symbol(BNSymbolType type, const std::string& name, uint64_t addr); - //Symbol(const std::string& shortName, const std::string& fullName, const std::string& rawName, SymbolBinding binding, size_t size); - //Symbol(const std::string& name, SymbolBinding binding, size_t size); Symbol(BNSymbol* sym); BNSymbolType GetType() const; @@ -967,6 +970,7 @@ namespace BinaryNinja uint64_t address; InstructionTextToken(); + InstructionTextToken(uint8_t confidence, BNInstructionTextTokenType t, const std::string& txt); InstructionTextToken(BNInstructionTextTokenType type, const std::string& text, uint64_t value = 0, size_t size = 0, size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE); InstructionTextToken(BNInstructionTextTokenType type, BNInstructionTextTokenContext context, @@ -979,6 +983,7 @@ namespace BinaryNinja struct DisassemblyTextLine { uint64_t addr; + size_t instrIndex; std::vector<InstructionTextToken> tokens; }; @@ -1297,6 +1302,7 @@ namespace BinaryNinja Ref<AnalysisCompletionEvent> AddAnalysisCompletionEvent(const std::function<void()>& callback); BNAnalysisProgress GetAnalysisProgress(); + Ref<BackgroundTask> GetBackgroundAnalysisTask(); uint64_t GetNextFunctionStartAfterAddress(uint64_t addr); uint64_t GetNextBasicBlockStartAfterAddress(uint64_t addr); @@ -1373,6 +1379,9 @@ namespace BinaryNinja std::string GetStringMetadata(const std::string& key); std::vector<uint8_t> GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); + + uint64_t GetMaxFunctionSizeForAnalysis(); + void SetMaxFunctionSizeForAnalysis(uint64_t size); }; class BinaryData: public BinaryView @@ -1601,7 +1610,18 @@ 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 MediumLevelILFunction; class FunctionRecognizer; class CallingConvention; @@ -1636,23 +1656,45 @@ namespace BinaryNinja static char* GetRegisterNameCallback(void* ctxt, uint32_t reg); static char* GetFlagNameCallback(void* ctxt, uint32_t flag); static char* GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags); + static char* GetSemanticFlagClassNameCallback(void* ctxt, uint32_t semClass); + static char* GetSemanticFlagGroupNameCallback(void* ctxt, uint32_t semGroup); static uint32_t* GetFullWidthRegistersCallback(void* ctxt, size_t* count); static uint32_t* GetAllRegistersCallback(void* ctxt, size_t* count); static uint32_t* GetAllFlagsCallback(void* ctxt, size_t* count); static uint32_t* GetAllFlagWriteTypesCallback(void* ctxt, size_t* count); - static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag); - static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count); + static uint32_t* GetAllSemanticFlagClassesCallback(void* ctxt, size_t* count); + static uint32_t* GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* count); + static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag, uint32_t semClass); + static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count); + static uint32_t* GetFlagsRequiredForSemanticFlagGroupCallback(void* ctxt, uint32_t semGroup, size_t* count); + static BNFlagConditionForSemanticClass* GetFlagConditionsForSemanticFlagGroupCallback(void* ctxt, + uint32_t semGroup, size_t* count); + static void FreeFlagConditionsForSemanticFlagGroupCallback(void* ctxt, BNFlagConditionForSemanticClass* conditions); static uint32_t* GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count); + static uint32_t GetSemanticClassForFlagWriteTypeCallback(void* ctxt, uint32_t writeType); static size_t GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); static size_t GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); + static size_t GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il); static void FreeRegisterListCallback(void* ctxt, uint32_t* regs); static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result); static uint32_t GetStackPointerRegisterCallback(void* ctxt); static uint32_t GetLinkRegisterCallback(void* ctxt); static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count); + static char* GetRegisterStackNameCallback(void* ctxt, uint32_t regStack); + 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); @@ -1670,6 +1712,8 @@ namespace BinaryNinja // static bool ApplyMachoRelocationCallback(void* ctxt, BNBinaryView* view, BNRelocation* rel, uint8_t* data, size_t len); static bool GetRelocationInfoCallback(void* ctxt, BNBinaryView* view, uint64_t relocType, BNRelocationInfo* result); + virtual void Register(BNCustomArchitecture* callbacks); + public: Architecture(const std::string& name); @@ -1704,19 +1748,28 @@ namespace BinaryNinja virtual std::string GetRegisterName(uint32_t reg); virtual std::string GetFlagName(uint32_t flag); virtual std::string GetFlagWriteTypeName(uint32_t flags); + virtual std::string GetSemanticFlagClassName(uint32_t semClass); + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup); virtual std::vector<uint32_t> GetFullWidthRegisters(); virtual std::vector<uint32_t> GetAllRegisters(); virtual std::vector<uint32_t> GetAllFlags(); virtual std::vector<uint32_t> GetAllFlagWriteTypes(); - virtual BNFlagRole GetFlagRole(uint32_t flag); - virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond); + virtual std::vector<uint32_t> GetAllSemanticFlagClasses(); + virtual std::vector<uint32_t> GetAllSemanticFlagGroups(); + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0); + virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0); + virtual std::vector<uint32_t> GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup); + virtual std::map<uint32_t, BNLowLevelILFlagCondition> GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup); virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType); + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType); virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); ExprId GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); - virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); - ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t semClass, LowLevelILFunction& il); + ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t semClass, LowLevelILFunction& il); + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il); virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); @@ -1725,6 +1778,16 @@ namespace BinaryNinja std::vector<uint32_t> GetModifiedRegistersOnWrite(uint32_t reg); uint32_t GetRegisterByName(const std::string& name); + virtual std::string GetRegisterStackName(uint32_t regStack); + virtual std::vector<uint32_t> GetAllRegisterStacks(); + 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. @@ -1824,6 +1887,8 @@ namespace BinaryNinja (void)view; (void)relocType; (void)result; return false; } + + void AddArchitectureRedirection(Architecture* from, Architecture* to); }; class CoreArchitecture: public Architecture @@ -1844,21 +1909,45 @@ namespace BinaryNinja virtual std::string GetRegisterName(uint32_t reg) override; virtual std::string GetFlagName(uint32_t flag) override; virtual std::string GetFlagWriteTypeName(uint32_t flags) override; + //virtual bool ApplyPERelocation(BinaryView* view, Relocation* rel, uint8_t* dest, size_t len) override; + virtual bool ApplyELFRelocation(BinaryView* view, BNRelocationInfo& rel, uint8_t* dest, size_t len) override; + //virtual bool ApplyMachoRelocation(BinaryView* view, Relocation* rel, uint8_t* dest, size_t len) override; + virtual bool GetRelocationInfo(BinaryView* view, uint64_t relocType, BNRelocationInfo& result) override; + + virtual std::string GetSemanticFlagClassName(uint32_t semClass) override; + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup) override; virtual std::vector<uint32_t> GetFullWidthRegisters() override; virtual std::vector<uint32_t> GetAllRegisters() override; virtual std::vector<uint32_t> GetAllFlags() override; virtual std::vector<uint32_t> GetAllFlagWriteTypes() override; - virtual BNFlagRole GetFlagRole(uint32_t flag) override; - virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override; + virtual std::vector<uint32_t> GetAllSemanticFlagClasses() override; + virtual std::vector<uint32_t> GetAllSemanticFlagGroups() override; + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0) override; + virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0) override; + virtual std::vector<uint32_t> GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::map<uint32_t, BNLowLevelILFlagCondition> GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override; virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override; + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override; virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override; - virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) override; + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) override; + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override; virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; virtual uint32_t GetStackPointerRegister() override; virtual uint32_t GetLinkRegister() override; virtual std::vector<uint32_t> GetGlobalRegisters() override; + virtual std::string GetRegisterStackName(uint32_t regStack) override; + 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; @@ -1871,11 +1960,91 @@ namespace BinaryNinja virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override; virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override; virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override; + }; - //virtual bool ApplyPERelocation(BinaryView* view, Relocation* rel, uint8_t* dest, size_t len) override; - virtual bool ApplyELFRelocation(BinaryView* view, BNRelocationInfo& rel, uint8_t* dest, size_t len) override; - //virtual bool ApplyMachoRelocation(BinaryView* view, Relocation* rel, uint8_t* dest, size_t len) override; - virtual bool GetRelocationInfo(BinaryView* view, uint64_t relocType, BNRelocationInfo& result) override; + class ArchitectureExtension: public Architecture + { + protected: + Ref<Architecture> m_base; + + virtual void Register(BNCustomArchitecture* callbacks) override; + + public: + ArchitectureExtension(const std::string& name, Architecture* base); + + Ref<Architecture> GetBaseArchitecture() const { return m_base; } + + virtual BNEndianness GetEndianness() const override; + virtual size_t GetAddressSize() const override; + virtual size_t GetDefaultIntegerSize() const override; + virtual size_t GetInstructionAlignment() const override; + virtual size_t GetMaxInstructionLength() const override; + virtual size_t GetOpcodeDisplayLength() const override; + virtual Ref<Architecture> GetAssociatedArchitectureByAddress(uint64_t& addr) override; + virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override; + virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, + std::vector<InstructionTextToken>& result) override; + virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override; + virtual std::string GetRegisterName(uint32_t reg) override; + virtual std::string GetFlagName(uint32_t flag) override; + virtual std::string GetFlagWriteTypeName(uint32_t flags) override; + virtual std::string GetSemanticFlagClassName(uint32_t semClass) override; + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup) override; + virtual std::vector<uint32_t> GetFullWidthRegisters() override; + virtual std::vector<uint32_t> GetAllRegisters() override; + virtual std::vector<uint32_t> GetAllFlags() override; + virtual std::vector<uint32_t> GetAllFlagWriteTypes() override; + virtual std::vector<uint32_t> GetAllSemanticFlagClasses() override; + virtual std::vector<uint32_t> GetAllSemanticFlagGroups() override; + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0) override; + virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0) override; + virtual std::vector<uint32_t> GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::map<uint32_t, BNLowLevelILFlagCondition> GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override; + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override; + virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, + uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override; + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) override; + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override; + virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; + virtual uint32_t GetStackPointerRegister() override; + virtual uint32_t GetLinkRegister() override; + virtual std::vector<uint32_t> GetGlobalRegisters() override; + + virtual std::string GetRegisterStackName(uint32_t regStack) override; + 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; + virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + + virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override; + }; + + class ArchitectureHook: public CoreArchitecture + { + protected: + Ref<Architecture> m_base; + + virtual void Register(BNCustomArchitecture* callbacks) override; + + public: + ArchitectureHook(Architecture* base); }; class Structure; @@ -2136,6 +2305,12 @@ namespace BinaryNinja void SetUserBasicBlockHighlight(uint8_t r, uint8_t g, uint8_t b, uint8_t alpha = 255); static bool IsBackEdge(BasicBlock* source, BasicBlock* target); + + bool IsILBlock() const; + bool IsLowLevelILBlock() const; + bool IsMediumLevelILBlock() const; + Ref<LowLevelILFunction> GetLowLevelILFunction() const; + Ref<MediumLevelILFunction> GetMediumLevelILFunction() const; }; struct VariableNameAndType @@ -2256,28 +2431,34 @@ namespace BinaryNinja Ref<Type> GetType() const; Confidence<Ref<Type>> GetReturnType() const; + Confidence<std::vector<uint32_t>> GetReturnRegisters() const; Confidence<Ref<CallingConvention>> GetCallingConvention() const; Confidence<std::vector<Variable>> GetParameterVariables() const; Confidence<bool> HasVariableArguments() const; Confidence<size_t> GetStackAdjustment() const; + std::map<uint32_t, Confidence<int32_t>> GetRegisterStackAdjustments() const; Confidence<std::set<uint32_t>> GetClobberedRegisters() const; void SetAutoType(Type* type); void SetAutoReturnType(const Confidence<Ref<Type>>& type); + void SetAutoReturnRegisters(const Confidence<std::vector<uint32_t>>& returnRegs); void SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention); void SetAutoParameterVariables(const Confidence<std::vector<Variable>>& vars); void SetAutoHasVariableArguments(const Confidence<bool>& varArgs); void SetAutoCanReturn(const Confidence<bool>& returns); void SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust); + void SetAutoRegisterStackAdjustments(const std::map<uint32_t, Confidence<int32_t>>& regStackAdjust); void SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered); void SetUserType(Type* type); void SetReturnType(const Confidence<Ref<Type>>& type); + void SetReturnRegisters(const Confidence<std::vector<uint32_t>>& returnRegs); void SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention); void SetParameterVariables(const Confidence<std::vector<Variable>>& vars); void SetHasVariableArguments(const Confidence<bool>& varArgs); void SetCanReturn(const Confidence<bool>& returns); void SetStackAdjustment(const Confidence<size_t>& stackAdjust); + void SetRegisterStackAdjustments(const std::map<uint32_t, Confidence<int32_t>>& regStackAdjust); void SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered); void ApplyImportedTypes(Symbol* sym); @@ -2308,6 +2489,21 @@ namespace BinaryNinja std::vector<IndirectBranchInfo> GetIndirectBranches(); std::vector<IndirectBranchInfo> GetIndirectBranchesAt(Architecture* arch, uint64_t addr); + void SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence<size_t>& adjust); + void SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, + const std::map<uint32_t, Confidence<int32_t>>& adjust); + void SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, + const Confidence<int32_t>& adjust); + void SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence<size_t>& adjust); + void SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, + const std::map<uint32_t, Confidence<int32_t>>& adjust); + void SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, + const Confidence<int32_t>& adjust); + + Confidence<size_t> GetCallStackAdjustment(Architecture* arch, uint64_t addr); + std::map<uint32_t, Confidence<int32_t>> GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr); + Confidence<int32_t> GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack); + std::vector<std::vector<InstructionTextToken>> GetBlockAnnotations(Architecture* arch, uint64_t addr); BNIntegerDisplayType GetIntegerConstantDisplayType(Architecture* arch, uint64_t instrAddr, uint64_t value, @@ -2343,6 +2539,11 @@ namespace BinaryNinja Confidence<RegisterValue> GetGlobalPointerValue() const; Confidence<RegisterValue> GetRegisterValueAtExit(uint32_t reg) const; + + bool IsFunctionTooLarge(); + bool IsAnalysisSkipped(); + BNFunctionAnalysisSkipOverride GetAnalysisSkipOverride(); + void SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip); }; class AdvancedFunctionAnalysisDataRequestor @@ -2418,6 +2619,7 @@ namespace BinaryNinja void Abort(); std::vector<Ref<FunctionGraphBlock>> GetBlocks(); + bool HasBlocks() const; int GetWidth() const; int GetHeight() const; @@ -2425,6 +2627,12 @@ namespace BinaryNinja bool IsOptionSet(BNDisassemblyOption option) const; void SetOption(BNDisassemblyOption option, bool state = true); + + bool IsILGraph() const; + bool IsLowLevelILGraph() const; + bool IsMediumLevelILGraph() const; + Ref<LowLevelILFunction> GetLowLevelILFunction() const; + Ref<MediumLevelILFunction> GetMediumLevelILFunction() const; }; struct LowLevelILLabel: public BNLowLevelILLabel @@ -2458,8 +2666,11 @@ namespace BinaryNinja }; struct LowLevelILInstruction; + struct RegisterOrFlag; struct SSARegister; + struct SSARegisterStack; struct SSAFlag; + struct SSARegisterOrFlag; class LowLevelILFunction: public CoreRefCountObject<BNLowLevelILFunction, BNNewLowLevelILFunctionReference, BNFreeLowLevelILFunction> @@ -2501,6 +2712,14 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, ExprId val, + uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackPush(size_t size, uint32_t regStack, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterStackTopRelativeSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion, + ExprId entry, const SSARegister& top, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion, + uint32_t reg, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Load(size_t size, ExprId addr, uint32_t flags = 0, @@ -2518,8 +2737,29 @@ namespace BinaryNinja ExprId RegisterSSA(size_t size, const SSARegister& reg, const ILSourceLocation& loc = ILSourceLocation()); ExprId RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSplit(size_t size, uint32_t high, uint32_t low, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackPop(size_t size, uint32_t regStack, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackFreeReg(uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackFreeTopRelative(uint32_t regStack, ExprId entry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackTopRelativeSSA(size_t size, const SSARegisterStack& regStack, ExprId entry, + const SSARegister& top, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackAbsoluteSSA(size_t size, const SSARegisterStack& regStack, uint32_t reg, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackFreeTopRelativeSSA(uint32_t regStack, size_t destVersion, size_t srcVersion, + ExprId entry, const SSARegister& top, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackFreeAbsoluteSSA(uint32_t regStack, size_t destVersion, size_t srcVersion, + uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstSingle(float val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstDouble(double val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Flag(uint32_t flag, const ILSourceLocation& loc = ILSourceLocation()); ExprId FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc = ILSourceLocation()); ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, @@ -2562,19 +2802,19 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); - ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + ExprId DivDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); - ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + ExprId DivDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); - ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + ExprId ModDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); - ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + ExprId ModDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId Neg(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId Not(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); @@ -2588,16 +2828,19 @@ namespace BinaryNinja ExprId JumpTo(ExprId dest, const std::vector<BNLowLevelILLabel*>& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<SSARegister>& params, + ExprId CallStackAdjust(ExprId dest, size_t adjust, const std::map<uint32_t, int32_t>& regStackAdjust, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<ExprId>& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc = ILSourceLocation()); - ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<SSARegister>& params, + ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<ExprId>& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc = ILSourceLocation()); ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); - ExprId FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagGroup(uint32_t semGroup, const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareNotEqual(size_t size, ExprId a, ExprId b, @@ -2621,6 +2864,11 @@ 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, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntrinsicSSA(const std::vector<SSARegisterOrFlag>& outputs, uint32_t intrinsic, + const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation()); ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); @@ -2628,10 +2876,38 @@ namespace BinaryNinja ExprId UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc = ILSourceLocation()); ExprId RegisterPhi(const SSARegister& dest, const std::vector<SSARegister>& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackPhi(const SSARegisterStack& dest, const std::vector<SSARegisterStack>& sources, + const ILSourceLocation& loc = ILSourceLocation()); ExprId FlagPhi(const SSAFlag& dest, const std::vector<SSAFlag>& sources, const ILSourceLocation& loc = ILSourceLocation()); ExprId MemoryPhi(size_t dest, const std::vector<size_t>& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAdd(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSub(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatMult(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatDiv(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSqrt(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatNeg(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAbs(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatToInt(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntToFloat(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConvert(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RoundToInt(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Floor(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Ceil(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatTrunc(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, @@ -2642,8 +2918,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); @@ -2790,6 +3069,8 @@ namespace BinaryNinja ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); ExprId VarField(size_t size, const Variable& src, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSplit(size_t size, const Variable& high, const Variable& low, + const ILSourceLocation& loc = ILSourceLocation()); ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); ExprId VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); @@ -2797,11 +3078,16 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId VarAliasedField(size_t size, const Variable& src, size_t memVersion, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSplitSSA(size_t size, const SSAVariable& high, const SSAVariable& low, + const ILSourceLocation& loc = ILSourceLocation()); ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddressOfField(const Variable& var, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstSingle(float val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstDouble(double val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, @@ -2835,17 +3121,17 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId DivUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); - ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + ExprId DivDoublePrecSigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); - ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + ExprId DivDoublePrecUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId ModSigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId ModUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); - ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + ExprId ModDoublePrecSigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); - ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + ExprId ModDoublePrecUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); @@ -2902,6 +3188,13 @@ 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 FreeVarSlot(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FreeVarSlotSSA(const Variable& var, size_t newVersion, size_t prevVersion, + const ILSourceLocation& loc = ILSourceLocation()); ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); ExprId UnimplementedMemoryRef(size_t size, ExprId target, @@ -2910,6 +3203,28 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId MemoryPhi(size_t destMemVersion, const std::vector<size_t>& sourceMemVersions, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Floor(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Ceil(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, @@ -3060,7 +3375,10 @@ namespace BinaryNinja { Ref<BinaryView> view; uint64_t address, length; + size_t instrIndex; Ref<Function> function; + Ref<LowLevelILFunction> lowLevelILFunction; + Ref<MediumLevelILFunction> mediumLevelILFunction; PluginCommandContext(); }; @@ -3093,15 +3411,55 @@ namespace BinaryNinja std::function<bool(BinaryView*, Function*)> isValid; }; + struct RegisteredLowLevelILFunctionCommand + { + std::function<void(BinaryView*, LowLevelILFunction*)> action; + std::function<bool(BinaryView*, LowLevelILFunction*)> isValid; + }; + + struct RegisteredLowLevelILInstructionCommand + { + std::function<void(BinaryView*, const LowLevelILInstruction&)> action; + std::function<bool(BinaryView*, const LowLevelILInstruction&)> isValid; + }; + + struct RegisteredMediumLevelILFunctionCommand + { + std::function<void(BinaryView*, MediumLevelILFunction*)> action; + std::function<bool(BinaryView*, MediumLevelILFunction*)> isValid; + }; + + struct RegisteredMediumLevelILInstructionCommand + { + std::function<void(BinaryView*, const MediumLevelILInstruction&)> action; + std::function<bool(BinaryView*, const MediumLevelILInstruction&)> isValid; + }; + static void DefaultPluginCommandActionCallback(void* ctxt, BNBinaryView* view); static void AddressPluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr); static void RangePluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); static void FunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, BNFunction* func); + static void LowLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func); + static void LowLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr); + static void MediumLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func); + static void MediumLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr); static bool DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view); static bool AddressPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, uint64_t addr); static bool RangePluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); static bool FunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, BNFunction* func); + static bool LowLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func); + static bool LowLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr); + static bool MediumLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func); + static bool MediumLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr); public: PluginCommand(const BNPluginCommand& cmd); @@ -3111,25 +3469,45 @@ namespace BinaryNinja PluginCommand& operator=(const PluginCommand& cmd); static void Register(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view)>& action); + const std::function<void(BinaryView* view)>& action); static void Register(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view)>& action, - const std::function<bool(BinaryView* view)>& isValid); + const std::function<void(BinaryView* view)>& action, + const std::function<bool(BinaryView* view)>& isValid); static void RegisterForAddress(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, uint64_t addr)>& action); + const std::function<void(BinaryView* view, uint64_t addr)>& action); static void RegisterForAddress(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, uint64_t addr)>& action, - const std::function<bool(BinaryView* view, uint64_t addr)>& isValid); + const std::function<void(BinaryView* view, uint64_t addr)>& action, + const std::function<bool(BinaryView* view, uint64_t addr)>& isValid); static void RegisterForRange(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, uint64_t addr, uint64_t len)>& action); + const std::function<void(BinaryView* view, uint64_t addr, uint64_t len)>& action); static void RegisterForRange(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, uint64_t addr, uint64_t len)>& action, - const std::function<bool(BinaryView* view, uint64_t addr, uint64_t len)>& isValid); + const std::function<void(BinaryView* view, uint64_t addr, uint64_t len)>& action, + const std::function<bool(BinaryView* view, uint64_t addr, uint64_t len)>& isValid); static void RegisterForFunction(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, Function* func)>& action); + const std::function<void(BinaryView* view, Function* func)>& action); static void RegisterForFunction(const std::string& name, const std::string& description, - const std::function<void(BinaryView* view, Function* func)>& action, - const std::function<bool(BinaryView* view, Function* func)>& isValid); + const std::function<void(BinaryView* view, Function* func)>& action, + const std::function<bool(BinaryView* view, Function* func)>& isValid); + static void RegisterForLowLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, LowLevelILFunction* func)>& action); + static void RegisterForLowLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, LowLevelILFunction* func)>& action, + const std::function<bool(BinaryView* view, LowLevelILFunction* func)>& isValid); + static void RegisterForLowLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const LowLevelILInstruction& instr)>& action); + static void RegisterForLowLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const LowLevelILInstruction& instr)>& action, + const std::function<bool(BinaryView* view, const LowLevelILInstruction& instr)>& isValid); + static void RegisterForMediumLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, MediumLevelILFunction* func)>& action); + static void RegisterForMediumLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, MediumLevelILFunction* func)>& action, + const std::function<bool(BinaryView* view, MediumLevelILFunction* func)>& isValid); + static void RegisterForMediumLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const MediumLevelILInstruction& instr)>& action); + static void RegisterForMediumLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const MediumLevelILInstruction& instr)>& action, + const std::function<bool(BinaryView* view, const MediumLevelILInstruction& instr)>& isValid); static std::vector<PluginCommand> GetList(); static std::vector<PluginCommand> GetValidList(const PluginCommandContext& ctxt); @@ -3168,6 +3546,11 @@ namespace BinaryNinja static void GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); static void GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + static void GetIncomingVariableForParameterVariableCallback(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result); + static void GetParameterVariableForIncomingVariableCallback(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result); + public: Ref<Architecture> GetArchitecture() const; std::string GetName() const; @@ -3188,6 +3571,9 @@ namespace BinaryNinja virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters(); virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func); virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func); + + virtual Variable GetIncomingVariableForParameterVariable(const Variable& var, Function* func); + virtual Variable GetParameterVariableForIncomingVariable(const Variable& var, Function* func); }; class CoreCallingConvention: public CallingConvention @@ -3211,6 +3597,9 @@ namespace BinaryNinja virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters() override; virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override; virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func) override; + + virtual Variable GetIncomingVariableForParameterVariable(const Variable& var, Function* func) override; + virtual Variable GetParameterVariableForIncomingVariable(const Variable& var, Function* func) override; }; /*! diff --git a/binaryninjacore.h b/binaryninjacore.h index 4abbbbdb..b568bb75 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -295,13 +295,21 @@ extern "C" LLIL_SET_REG, // Not valid in SSA form (see LLIL_SET_REG_SSA) LLIL_SET_REG_SPLIT, // Not valid in SSA form (see LLIL_SET_REG_SPLIT_SSA) LLIL_SET_FLAG, // Not valid in SSA form (see LLIL_SET_FLAG_SSA) + LLIL_SET_REG_STACK_REL, // Not valid in SSA form (see LLIL_SET_REG_STACK_REL_SSA) + LLIL_REG_STACK_PUSH, // Not valid in SSA form (expanded) LLIL_LOAD, // Not valid in SSA form (see LLIL_LOAD_SSA) LLIL_STORE, // Not valid in SSA form (see LLIL_STORE_SSA) LLIL_PUSH, // Not valid in SSA form (expanded) LLIL_POP, // Not valid in SSA form (expanded) LLIL_REG, // Not valid in SSA form (see LLIL_REG_SSA) + LLIL_REG_SPLIT, // Not valid in SSA form (see LLIL_REG_SPLIT_SSA) + LLIL_REG_STACK_REL, // Not valid in SSA form (see LLIL_REG_STACK_REL_SSA) + LLIL_REG_STACK_POP, // Not valid in SSA form (expanded) + LLIL_REG_STACK_FREE_REG, // Not valid in SSA form (see LLIL_REG_STACK_FREE_REL_SSA, LLIL_REG_STACK_FREE_ABS_SSA) + LLIL_REG_STACK_FREE_REL, // Not valid in SSA from (see LLIL_REG_STACK_FREE_REL_SSA) LLIL_CONST, LLIL_CONST_PTR, + LLIL_FLOAT_CONST, LLIL_FLAG, // Not valid in SSA form (see LLIL_FLAG_SSA) LLIL_FLAG_BIT, // Not valid in SSA form (see LLIL_FLAG_BIT_SSA) LLIL_ADD, @@ -343,6 +351,7 @@ extern "C" LLIL_IF, LLIL_GOTO, LLIL_FLAG_COND, // Valid only in Lifted IL + LLIL_FLAG_GROUP, // Valid only in Lifted IL LLIL_CMP_E, LLIL_CMP_NE, LLIL_CMP_SLT, @@ -359,28 +368,63 @@ extern "C" LLIL_SYSCALL, LLIL_BP, LLIL_TRAP, + LLIL_INTRINSIC, LLIL_UNDEF, LLIL_UNIMPL, LLIL_UNIMPL_MEM, + // Floating point + LLIL_FADD, + LLIL_FSUB, + LLIL_FMUL, + LLIL_FDIV, + LLIL_FSQRT, + LLIL_FNEG, + LLIL_FABS, + LLIL_FLOAT_TO_INT, + LLIL_INT_TO_FLOAT, + LLIL_FLOAT_CONV, + LLIL_ROUND_TO_INT, + LLIL_FLOOR, + LLIL_CEIL, + LLIL_FTRUNC, + LLIL_FCMP_E, + LLIL_FCMP_NE, + LLIL_FCMP_LT, + LLIL_FCMP_LE, + LLIL_FCMP_GE, + LLIL_FCMP_GT, + LLIL_FCMP_O, + LLIL_FCMP_UO, + // The following instructions are only used in SSA form LLIL_SET_REG_SSA, LLIL_SET_REG_SSA_PARTIAL, LLIL_SET_REG_SPLIT_SSA, + LLIL_SET_REG_STACK_REL_SSA, + LLIL_SET_REG_STACK_ABS_SSA, LLIL_REG_SPLIT_DEST_SSA, // Only valid within an LLIL_SET_REG_SPLIT_SSA instruction + LLIL_REG_STACK_DEST_SSA, // Only valid within LLIL_SET_REG_STACK_REL_SSA or LLIL_SET_REG_STACK_ABS_SSA LLIL_REG_SSA, LLIL_REG_SSA_PARTIAL, + LLIL_REG_SPLIT_SSA, + LLIL_REG_STACK_REL_SSA, + LLIL_REG_STACK_ABS_SSA, + LLIL_REG_STACK_FREE_REL_SSA, + LLIL_REG_STACK_FREE_ABS_SSA, LLIL_SET_FLAG_SSA, LLIL_FLAG_SSA, 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, LLIL_MEM_PHI }; @@ -400,7 +444,15 @@ extern "C" LLFC_NEG, LLFC_POS, LLFC_O, - LLFC_NO + LLFC_NO, + LLFC_FE, + LLFC_FNE, + LLFC_FLT, + LLFC_FLE, + LLFC_FGE, + LLFC_FGT, + LLFC_FO, + LLFC_FUO }; enum BNFlagRole @@ -413,7 +465,9 @@ extern "C" OverflowFlagRole = 5, HalfCarryFlagRole = 6, EvenParityFlagRole = 7, - OddParityFlagRole = 8 + OddParityFlagRole = 8, + OrderedFlagRole = 9, + UnorderedFlagRole = 10 }; enum BNFunctionGraphType @@ -659,6 +713,13 @@ extern "C" BNImplicitRegisterExtend extend; }; + struct BNRegisterStackInfo + { + uint32_t firstStorageReg, firstTopRelativeReg; + uint32_t storageCount, topRelativeCount; + uint32_t stackTopReg; + }; + enum BNRegisterValueType { UndeterminedValue, @@ -759,10 +820,12 @@ extern "C" MLIL_STORE_STRUCT, // Not valid in SSA form (see MLIL_STORE_STRUCT_SSA) MLIL_VAR, // Not valid in SSA form (see MLIL_VAR_SSA) MLIL_VAR_FIELD, // Not valid in SSA form (see MLIL_VAR_SSA_FIELD) + MLIL_VAR_SPLIT, // Not valid in SSA form (see MLIL_VAR_SSA) MLIL_ADDRESS_OF, MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_CONST_PTR, + MLIL_FLOAT_CONST, MLIL_IMPORT, MLIL_ADD, MLIL_ADC, @@ -819,12 +882,38 @@ 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_FREE_VAR_SLOT, // Not valid in SSA from (see MLIL_FREE_VAR_SLOT_SSA) MLIL_BP, MLIL_TRAP, MLIL_UNDEF, MLIL_UNIMPL, MLIL_UNIMPL_MEM, + // Floating point + MLIL_FADD, + MLIL_FSUB, + MLIL_FMUL, + MLIL_FDIV, + MLIL_FSQRT, + MLIL_FNEG, + MLIL_FABS, + MLIL_FLOAT_TO_INT, + MLIL_INT_TO_FLOAT, + MLIL_FLOAT_CONV, + MLIL_ROUND_TO_INT, + MLIL_FLOOR, + MLIL_CEIL, + MLIL_FTRUNC, + MLIL_FCMP_E, + MLIL_FCMP_NE, + MLIL_FCMP_LT, + MLIL_FCMP_LE, + MLIL_FCMP_GE, + MLIL_FCMP_GT, + MLIL_FCMP_O, + MLIL_FCMP_UO, + // The following instructions are only used in SSA form MLIL_SET_VAR_SSA, MLIL_SET_VAR_SSA_FIELD, @@ -835,6 +924,7 @@ extern "C" MLIL_VAR_SSA_FIELD, MLIL_VAR_ALIASED, MLIL_VAR_ALIASED_FIELD, + MLIL_VAR_SPLIT_SSA, MLIL_CALL_SSA, MLIL_CALL_UNTYPED_SSA, MLIL_SYSCALL_SSA, @@ -845,6 +935,8 @@ extern "C" MLIL_LOAD_STRUCT_SSA, MLIL_STORE_SSA, MLIL_STORE_STRUCT_SSA, + MLIL_INTRINSIC_SSA, + MLIL_FREE_VAR_SLOT_SSA, MLIL_VAR_PHI, MLIL_MEM_PHI }; @@ -911,6 +1003,7 @@ extern "C" void (*functionAdded)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*functionRemoved)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*functionUpdated)(void* ctxt, BNBinaryView* view, BNFunction* func); + void (*functionUpdateRequested)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*dataVariableAdded)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*dataVariableRemoved)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*dataVariableUpdated)(void* ctxt, BNBinaryView* view, BNDataVariable* var); @@ -1052,6 +1145,25 @@ extern "C" size_t count; }; + struct BNFlagConditionForSemanticClass + { + uint32_t semanticClass; + BNLowLevelILFlagCondition condition; + }; + + struct BNNameAndType + { + char* name; + BNType* type; + uint8_t typeConfidence; + }; + + struct BNTypeWithConfidence + { + BNType* type; + uint8_t confidence; + }; + struct BNCustomArchitecture { void* context; @@ -1071,22 +1183,44 @@ extern "C" char* (*getRegisterName)(void* ctxt, uint32_t reg); char* (*getFlagName)(void* ctxt, uint32_t flag); char* (*getFlagWriteTypeName)(void* ctxt, uint32_t flags); + char* (*getSemanticFlagClassName)(void* ctxt, uint32_t semClass); + char* (*getSemanticFlagGroupName)(void* ctxt, uint32_t semGroup); uint32_t* (*getFullWidthRegisters)(void* ctxt, size_t* count); uint32_t* (*getAllRegisters)(void* ctxt, size_t* count); uint32_t* (*getAllFlags)(void* ctxt, size_t* count); uint32_t* (*getAllFlagWriteTypes)(void* ctxt, size_t* count); - BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag); - uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count); + uint32_t* (*getAllSemanticFlagClasses)(void* ctxt, size_t* count); + uint32_t* (*getAllSemanticFlagGroups)(void* ctxt, size_t* count); + BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag, uint32_t semClass); + uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count); + uint32_t* (*getFlagsRequiredForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count); + BNFlagConditionForSemanticClass* (*getFlagConditionsForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count); + void (*freeFlagConditionsForSemanticFlagGroup)(void* ctxt, BNFlagConditionForSemanticClass* conditions); uint32_t* (*getFlagsWrittenByFlagWriteType)(void* ctxt, uint32_t writeType, size_t* count); + uint32_t (*getSemanticClassForFlagWriteType)(void* ctxt, uint32_t writeType); size_t (*getFlagWriteLowLevelIL)(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); - size_t (*getFlagConditionLowLevelIL)(void* ctxt, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il); + size_t (*getFlagConditionLowLevelIL)(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, BNLowLevelILFunction* il); + size_t (*getSemanticFlagGroupLowLevelIL)(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il); void (*freeRegisterList)(void* ctxt, uint32_t* regs); void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result); uint32_t (*getStackPointerRegister)(void* ctxt); uint32_t (*getLinkRegister)(void* ctxt); uint32_t* (*getGlobalRegisters)(void* ctxt, size_t* count); + char* (*getRegisterStackName)(void* ctxt, uint32_t regStack); + 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); @@ -1131,6 +1265,7 @@ extern "C" struct BNDisassemblyTextLine { uint64_t addr; + size_t instrIndex; BNInstructionTextToken* tokens; size_t count; }; @@ -1168,12 +1303,6 @@ extern "C" char* (*serialize)(void* ctxt); }; - struct BNTypeWithConfidence - { - BNType* type; - uint8_t confidence; - }; - struct BNCallingConventionWithConfidence { BNCallingConvention* convention; @@ -1297,7 +1426,11 @@ extern "C" DefaultPluginCommand, AddressPluginCommand, RangePluginCommand, - FunctionPluginCommand + FunctionPluginCommand, + LowLevelILFunctionPluginCommand, + LowLevelILInstructionPluginCommand, + MediumLevelILFunctionPluginCommand, + MediumLevelILInstructionPluginCommand }; struct BNPluginCommand @@ -1311,11 +1444,19 @@ extern "C" void (*addressCommand)(void* ctxt, BNBinaryView* view, uint64_t addr); void (*rangeCommand)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); void (*functionCommand)(void* ctxt, BNBinaryView* view, BNFunction* func); + void (*lowLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func); + void (*lowLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); + void (*mediumLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); + void (*mediumLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); bool (*defaultIsValid)(void* ctxt, BNBinaryView* view); bool (*addressIsValid)(void* ctxt, BNBinaryView* view, uint64_t addr); bool (*rangeIsValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); bool (*functionIsValid)(void* ctxt, BNBinaryView* view, BNFunction* func); + bool (*lowLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func); + bool (*lowLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); + bool (*mediumLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); + bool (*mediumLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); }; struct BNCustomCallingConvention @@ -1341,6 +1482,11 @@ extern "C" uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count); void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); void (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func, BNRegisterValue* result); + + void (*getIncomingVariableForParameterVariable)(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result); + void (*getParameterVariableForIncomingVariable)(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result); }; struct BNVariableNameAndType @@ -1640,6 +1786,20 @@ extern "C" ArrayDataType }; + struct BNRegisterStackAdjustment + { + uint32_t regStack; + int32_t adjustment; + uint8_t confidence; + }; + + enum BNFunctionAnalysisSkipOverride + { + DefaultFunctionAnalysisSkip, + NeverSkipFunctionAnalysis, + AlwaysSkipFunctionAnalysis + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -1994,6 +2154,10 @@ extern "C" BINARYNINJACOREAPI BNArchitecture** BNGetArchitectureList(size_t* count); BINARYNINJACOREAPI void BNFreeArchitectureList(BNArchitecture** archs); BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitecture(const char* name, BNCustomArchitecture* arch); + BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureExtension(const char* name, + BNArchitecture* base, BNCustomArchitecture* arch); + BINARYNINJACOREAPI void BNAddArchitectureRedirection(BNArchitecture* arch, BNArchitecture* from, BNArchitecture* to); + BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureHook(BNArchitecture* base, BNCustomArchitecture* arch); BINARYNINJACOREAPI char* BNGetArchitectureName(BNArchitecture* arch); BINARYNINJACOREAPI BNEndianness BNGetArchitectureEndianness(BNArchitecture* arch); @@ -2015,24 +2179,36 @@ extern "C" BINARYNINJACOREAPI char* BNGetArchitectureRegisterName(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI char* BNGetArchitectureFlagName(BNArchitecture* arch, uint32_t flag); BINARYNINJACOREAPI char* BNGetArchitectureFlagWriteTypeName(BNArchitecture* arch, uint32_t flags); + BINARYNINJACOREAPI char* BNGetArchitectureSemanticFlagClassName(BNArchitecture* arch, uint32_t semClass); + BINARYNINJACOREAPI char* BNGetArchitectureSemanticFlagGroupName(BNArchitecture* arch, uint32_t semGroup); BINARYNINJACOREAPI uint32_t* BNGetFullWidthArchitectureRegisters(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureRegisters(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlags(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlagWriteTypes(BNArchitecture* arch, size_t* count); - BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagClasses(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagGroups(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag, uint32_t semClass); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForFlagCondition(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - size_t* count); + uint32_t semClass, size_t* count); + BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForSemanticFlagGroup(BNArchitecture* arch, + uint32_t semGroup, size_t* count); + BINARYNINJACOREAPI BNFlagConditionForSemanticClass* BNGetArchitectureFlagConditionsForSemanticFlagGroup(BNArchitecture* arch, + uint32_t semGroup, size_t* count); + BINARYNINJACOREAPI void BNFreeFlagConditionsForSemanticFlagGroup(BNFlagConditionForSemanticClass* conditions); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsWrittenByFlagWriteType(BNArchitecture* arch, uint32_t writeType, size_t* count); + BINARYNINJACOREAPI uint32_t BNGetArchitectureSemanticClassForFlagWriteType(BNArchitecture* arch, uint32_t writeType); BINARYNINJACOREAPI size_t BNGetArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op, size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); + BINARYNINJACOREAPI size_t BNGetArchitectureSemanticFlagGroupLowLevelIL(BNArchitecture* arch, + uint32_t semGroup, BNLowLevelILFunction* il); BINARYNINJACOREAPI uint32_t* BNGetModifiedArchitectureRegistersOnWrite(BNArchitecture* arch, uint32_t reg, size_t* count); BINARYNINJACOREAPI void BNFreeRegisterList(uint32_t* regs); BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg); @@ -2042,6 +2218,19 @@ extern "C" BINARYNINJACOREAPI bool BNIsArchitectureGlobalRegister(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterByName(BNArchitecture* arch, const char* name); + BINARYNINJACOREAPI char* BNGetArchitectureRegisterStackName(BNArchitecture* arch, uint32_t regStack); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureRegisterStacks(BNArchitecture* arch, size_t* count); + 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, @@ -2162,28 +2351,37 @@ extern "C" BINARYNINJACOREAPI BNType* BNGetFunctionType(BNFunction* func); BINARYNINJACOREAPI BNTypeWithConfidence BNGetFunctionReturnType(BNFunction* func); + BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionReturnRegisters(BNFunction* func); BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetFunctionCallingConvention(BNFunction* func); BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func); BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func); BINARYNINJACOREAPI BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func); + BINARYNINJACOREAPI BNRegisterStackAdjustment* BNGetFunctionRegisterStackAdjustments(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNFreeRegisterStackAdjustments(BNRegisterStackAdjustment* adjustments); BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func); - BINARYNINJACOREAPI void BNFreeClobberedRegisters(BNRegisterSetWithConfidence* regs); + BINARYNINJACOREAPI void BNFreeRegisterSet(BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetAutoFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetAutoFunctionReturnRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetAutoFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); BINARYNINJACOREAPI void BNSetAutoFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); BINARYNINJACOREAPI void BNSetAutoFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetAutoFunctionRegisterStackAdjustments(BNFunction* func, + BNRegisterStackAdjustment* adjustments, size_t count); BINARYNINJACOREAPI void BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetUserFunctionReturnRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetUserFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); BINARYNINJACOREAPI void BNSetUserFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); BINARYNINJACOREAPI void BNSetUserFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetUserFunctionRegisterStackAdjustments(BNFunction* func, + BNRegisterStackAdjustment* adjustments, size_t count); BINARYNINJACOREAPI void BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym); @@ -2214,6 +2412,11 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominanceFrontier(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockIteratedDominanceFrontier(BNBasicBlock** blocks, size_t incomingCount, size_t* outputCount); + BINARYNINJACOREAPI bool BNIsILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI bool BNIsLowLevelILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI bool BNIsMediumLevelILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetBasicBlockLowLevelILFunction(BNBasicBlock* block); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetBasicBlockMediumLevelILFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); @@ -2235,7 +2438,7 @@ extern "C" BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings); BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count); - BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count); + BINARYNINJACOREAPI void BNFreeVariableNameAndTypeList(BNVariableNameAndType* vars, size_t count); BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNTypeWithConfidence* type, const char* name); BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, @@ -2268,6 +2471,25 @@ extern "C" uint64_t addr, size_t* count); BINARYNINJACOREAPI void BNFreeIndirectBranchList(BNIndirectBranchInfo* branches); + BINARYNINJACOREAPI void BNSetAutoCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, + size_t adjust, uint8_t confidence); + BINARYNINJACOREAPI void BNSetUserCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, + size_t adjust, uint8_t confidence); + BINARYNINJACOREAPI void BNSetAutoCallRegisterStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, + BNRegisterStackAdjustment* adjust, size_t count); + BINARYNINJACOREAPI void BNSetUserCallRegisterStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, + BNRegisterStackAdjustment* adjust, size_t count); + BINARYNINJACOREAPI void BNSetAutoCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, + BNArchitecture* arch, uint64_t addr, uint32_t regStack, int32_t adjust, uint8_t confidence); + BINARYNINJACOREAPI void BNSetUserCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, + BNArchitecture* arch, uint64_t addr, uint32_t regStack, int32_t adjust, uint8_t confidence); + + BINARYNINJACOREAPI BNSizeWithConfidence BNGetCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI BNRegisterStackAdjustment* BNGetCallRegisterStackAdjustment(BNFunction* func, + BNArchitecture* arch, uint64_t addr, size_t* count); + BINARYNINJACOREAPI BNRegisterStackAdjustment BNGetCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, + BNArchitecture* arch, uint64_t addr, uint32_t regStack); + BINARYNINJACOREAPI BNInstructionTextLine* BNGetFunctionBlockAnnotations(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI void BNFreeInstructionTextLines(BNInstructionTextLine* lines, size_t count); @@ -2277,6 +2499,14 @@ extern "C" BINARYNINJACOREAPI void BNSetIntegerConstantDisplayType(BNFunction* func, BNArchitecture* arch, uint64_t instrAddr, uint64_t value, size_t operand, BNIntegerDisplayType type); + BINARYNINJACOREAPI bool BNIsFunctionTooLarge(BNFunction* func); + BINARYNINJACOREAPI bool BNIsFunctionAnalysisSkipped(BNFunction* func); + BINARYNINJACOREAPI BNFunctionAnalysisSkipOverride BNGetFunctionAnalysisSkipOverride(BNFunction* func); + BINARYNINJACOREAPI void BNSetFunctionAnalysisSkipOverride(BNFunction* func, BNFunctionAnalysisSkipOverride skip); + + BINARYNINJACOREAPI uint64_t BNGetMaxFunctionSizeForAnalysis(BNBinaryView* view); + BINARYNINJACOREAPI void BNSetMaxFunctionSizeForAnalysis(BNBinaryView* view, uint64_t size); + BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNAddAnalysisCompletionEvent(BNBinaryView* view, void* ctxt, void (*callback)(void* ctxt)); BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNNewAnalysisCompletionEventReference(BNAnalysisCompletionEvent* event); @@ -2284,6 +2514,7 @@ extern "C" BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); BINARYNINJACOREAPI BNAnalysisProgress BNGetAnalysisProgress(BNBinaryView* view); + BINARYNINJACOREAPI BNBackgroundTask* BNGetBackgroundAnalysisTask(BNBinaryView* view); BINARYNINJACOREAPI uint64_t BNGetNextFunctionStartAfterAddress(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI uint64_t BNGetNextBasicBlockStartAfterAddress(BNBinaryView* view, uint64_t addr); @@ -2386,11 +2617,17 @@ extern "C" BINARYNINJACOREAPI void BNSetFunctionGraphCompleteCallback(BNFunctionGraph* graph, void* ctxt, void (*func)(void* ctxt)); BINARYNINJACOREAPI void BNAbortFunctionGraph(BNFunctionGraph* graph); BINARYNINJACOREAPI BNFunctionGraphType BNGetFunctionGraphType(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsLowLevelILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsMediumLevelILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionGraphLowLevelILFunction(BNFunctionGraph* graph); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionGraphMediumLevelILFunction(BNFunctionGraph* graph); BINARYNINJACOREAPI BNFunctionGraphBlock** BNGetFunctionGraphBlocks(BNFunctionGraph* graph, size_t* count); BINARYNINJACOREAPI BNFunctionGraphBlock** BNGetFunctionGraphBlocksInRegion( BNFunctionGraph* graph, int left, int top, int right, int bottom, size_t* count); BINARYNINJACOREAPI void BNFreeFunctionGraphBlockList(BNFunctionGraphBlock** blocks, size_t count); + BINARYNINJACOREAPI bool BNFunctionGraphHasBlocks(BNFunctionGraph* graph); BINARYNINJACOREAPI int BNGetFunctionGraphWidth(BNFunctionGraph* graph); BINARYNINJACOREAPI int BNGetFunctionGraphHeight(BNFunctionGraph* graph); @@ -2855,29 +3092,45 @@ extern "C" // Plugin commands BINARYNINJACOREAPI void BNRegisterPluginCommand(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view), - bool (*isValid)(void* ctxt, BNBinaryView* view), void* context); + void (*action)(void* ctxt, BNBinaryView* view), bool (*isValid)(void* ctxt, BNBinaryView* view), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForAddress(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr), - bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr), + bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForRange(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), - bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), + bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForFunction(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, BNFunction* func), - bool (*isValid)(void* ctxt, BNBinaryView* view, BNFunction* func), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, BNFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForLowLevelILFunction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForLowLevelILInstruction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForMediumLevelILFunction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForMediumLevelILInstruction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), void* context); BINARYNINJACOREAPI BNPluginCommand* BNGetAllPluginCommands(size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommands(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForAddress(BNBinaryView* view, uint64_t addr, - size_t* count); + size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForRange(BNBinaryView* view, uint64_t addr, - uint64_t len, size_t* count); + uint64_t len, size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForFunction(BNBinaryView* view, BNFunction* func, - size_t* count); + size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForLowLevelILFunction(BNBinaryView* view, + BNLowLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForLowLevelILInstruction(BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForMediumLevelILFunction(BNBinaryView* view, + BNMediumLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForMediumLevelILInstruction(BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr, size_t* count); BINARYNINJACOREAPI void BNFreePluginCommandList(BNPluginCommand* commands); // Calling conventions @@ -2911,6 +3164,15 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); BINARYNINJACOREAPI BNRegisterValue BNGetIncomingFlagValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); + BINARYNINJACOREAPI BNVariable BNGetIncomingVariableForParameterVariable(BNCallingConvention* cc, + const BNVariable* var, BNFunction* func); + BINARYNINJACOREAPI BNVariable BNGetParameterVariableForIncomingVariable(BNCallingConvention* cc, + const BNVariable* var, BNFunction* func); + BINARYNINJACOREAPI BNVariable BNGetDefaultIncomingVariableForParameterVariable(BNCallingConvention* cc, + const BNVariable* var); + BINARYNINJACOREAPI BNVariable BNGetDefaultParameterVariableForIncomingVariable(BNCallingConvention* cc, + const BNVariable* var); + BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureDefaultCallingConvention(BNArchitecture* arch); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureCdeclCallingConvention(BNArchitecture* arch); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureStdcallCallingConvention(BNArchitecture* arch); @@ -3154,6 +3416,7 @@ extern "C" BINARYNINJACOREAPI bool BNPathExists(const char* path); BINARYNINJACOREAPI bool BNIsPathDirectory(const char* path); BINARYNINJACOREAPI bool BNIsPathRegularFile(const char* path); + BINARYNINJACOREAPI bool BNFileSize(const char* path, uint64_t* size); // Settings APIs BINARYNINJACOREAPI bool BNSettingGetBool(const char* settingGroup, const char* name, bool defaultValue); diff --git a/binaryview.cpp b/binaryview.cpp index 24a976e8..88c0a204 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -78,6 +78,15 @@ void BinaryDataNotification::FunctionUpdatedCallback(void* ctxt, BNBinaryView* o } +void BinaryDataNotification::FunctionUpdateRequestedCallback(void* ctxt, BNBinaryView* object, BNFunction* func) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(object)); + Ref<Function> funcObj = new Function(BNNewFunctionReference(func)); + notify->OnAnalysisFunctionUpdateRequested(view, funcObj); +} + + void BinaryDataNotification::DataVariableAddedCallback(void* ctxt, BNBinaryView* object, BNDataVariable* var) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; @@ -148,6 +157,7 @@ BinaryDataNotification::BinaryDataNotification() m_callbacks.functionAdded = FunctionAddedCallback; m_callbacks.functionRemoved = FunctionRemovedCallback; m_callbacks.functionUpdated = FunctionUpdatedCallback; + m_callbacks.functionUpdateRequested = FunctionUpdateRequestedCallback; m_callbacks.dataVariableAdded = DataVariableAddedCallback; m_callbacks.dataVariableRemoved = DataVariableRemovedCallback; m_callbacks.dataVariableUpdated = DataVariableUpdatedCallback; @@ -778,6 +788,9 @@ bool BinaryView::IsBackedByDatabase() const bool BinaryView::CreateDatabase(const string& path) { + auto parent = GetParentView(); + if (parent) + return parent->CreateDatabase(path); return m_file->CreateDatabase(path, this); } @@ -785,6 +798,9 @@ bool BinaryView::CreateDatabase(const string& path) bool BinaryView::CreateDatabase(const string& path, const function<void(size_t progress, size_t total)>& progressCallback) { + auto parent = GetParentView(); + if (parent) + return parent->CreateDatabase(path); return m_file->CreateDatabase(path, this, progressCallback); } @@ -874,6 +890,7 @@ vector<BNModificationStatus> BinaryView::GetModification(uint64_t offset, size_t len = BNGetModificationArray(m_object, offset, mod, len); vector<BNModificationStatus> result; + result.reserve(len); for (size_t i = 0; i < len; i++) result.push_back(mod[i]); @@ -1212,6 +1229,7 @@ vector<Ref<Function>> BinaryView::GetAnalysisFunctionList() BNFunction** list = BNGetAnalysisFunctionList(m_object, &count); vector<Ref<Function>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1250,6 +1268,7 @@ vector<Ref<Function>> BinaryView::GetAnalysisFunctionsForAddress(uint64_t addr) BNFunction** list = BNGetAnalysisFunctionsForAddress(m_object, addr, &count); vector<Ref<Function>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1282,6 +1301,7 @@ vector<Ref<BasicBlock>> BinaryView::GetBasicBlocksForAddress(uint64_t addr) BNBasicBlock** blocks = BNGetBasicBlocksForAddress(m_object, addr, &count); vector<Ref<BasicBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1296,6 +1316,7 @@ vector<Ref<BasicBlock>> BinaryView::GetBasicBlocksStartingAtAddress(uint64_t add BNBasicBlock** blocks = BNGetBasicBlocksStartingAtAddress(m_object, addr, &count); vector<Ref<BasicBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1310,6 +1331,7 @@ vector<ReferenceSource> BinaryView::GetCodeReferences(uint64_t addr) BNReferenceSource* refs = BNGetCodeReferences(m_object, addr, &count); vector<ReferenceSource> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1330,6 +1352,7 @@ vector<ReferenceSource> BinaryView::GetCodeReferences(uint64_t addr, uint64_t le BNReferenceSource* refs = BNGetCodeReferencesInRange(m_object, addr, len, &count); vector<ReferenceSource> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1368,6 +1391,7 @@ vector<Ref<Symbol>> BinaryView::GetSymbolsByName(const string& name) BNSymbol** syms = BNGetSymbolsByName(m_object, name.c_str(), &count); vector<Ref<Symbol>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1382,6 +1406,7 @@ vector<Ref<Symbol>> BinaryView::GetSymbols() BNSymbol** syms = BNGetSymbols(m_object, &count); vector<Ref<Symbol>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1396,6 +1421,7 @@ vector<Ref<Symbol>> BinaryView::GetSymbols(uint64_t start, uint64_t len) BNSymbol** syms = BNGetSymbolsInRange(m_object, start, len, &count); vector<Ref<Symbol>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1410,6 +1436,7 @@ vector<Ref<Symbol>> BinaryView::GetSymbolsOfType(BNSymbolType type) BNSymbol** syms = BNGetSymbolsOfType(m_object, type, &count); vector<Ref<Symbol>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1424,6 +1451,7 @@ vector<Ref<Symbol>> BinaryView::GetSymbolsOfType(BNSymbolType type, uint64_t sta BNSymbol** syms = BNGetSymbolsOfTypeInRange(m_object, type, start, len, &count); vector<Ref<Symbol>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1563,6 +1591,16 @@ BNAnalysisProgress BinaryView::GetAnalysisProgress() } +Ref<BackgroundTask> BinaryView::GetBackgroundAnalysisTask() +{ + BNBackgroundTask* task = BNGetBackgroundAnalysisTask(m_object); + if (!task) + return nullptr; + + return new BackgroundTask(BNNewBackgroundTaskReference(task)); +} + + uint64_t BinaryView::GetNextFunctionStartAfterAddress(uint64_t addr) { return BNGetNextFunctionStartAfterAddress(m_object, addr); @@ -1636,6 +1674,7 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line settings ? settings->GetObject() : nullptr, &count); vector<LinearDisassemblyLine> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1644,6 +1683,8 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.instrIndex = lines[i].contents.instrIndex; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1682,6 +1723,7 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi settings ? settings->GetObject() : nullptr, &count); vector<LinearDisassemblyLine> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1690,6 +1732,8 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.instrIndex = lines[i].contents.instrIndex; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1927,7 +1971,8 @@ vector<Ref<Segment>> BinaryView::GetSegments() size_t count; BNSegment** segments = BNGetSegments(m_object, &count); - vector<Ref<Segment>> result; + vector<Segment> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Segment(BNNewSegmentReference(segments[i]))); @@ -1988,6 +2033,7 @@ vector<Ref<Section>> BinaryView::GetSections() BNSection** sections = BNGetSections(m_object, &count); vector<Ref<Section>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Section(BNNewSectionReference(sections[i]))); @@ -2002,6 +2048,7 @@ vector<Ref<Section>> BinaryView::GetSectionsAt(uint64_t addr) BNSection** sections = BNGetSectionsAt(m_object, addr, &count); vector<Ref<Section>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new Section(BNNewSectionReference(sections[i]))); @@ -2026,6 +2073,7 @@ vector<string> BinaryView::GetUniqueSectionNames(const vector<string>& names) char** outgoingNames = BNGetUniqueSectionNames(m_object, incomingNames, names.size()); vector<string> result; + result.reserve(names.size()); for (size_t i = 0; i < names.size(); i++) result.push_back(outgoingNames[i]); @@ -2091,6 +2139,18 @@ uint64_t BinaryView::GetUIntMetadata(const string& key) } +uint64_t BinaryView::GetMaxFunctionSizeForAnalysis() +{ + return BNGetMaxFunctionSizeForAnalysis(m_object); +} + + +void BinaryView::SetMaxFunctionSizeForAnalysis(uint64_t size) +{ + BNSetMaxFunctionSizeForAnalysis(m_object, size); +} + + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index e23838f6..e8ef4f53 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -83,6 +83,7 @@ vector<Ref<BinaryViewType>> BinaryViewType::GetViewTypes() types = BNGetBinaryViewTypes(&count); vector<Ref<BinaryViewType>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreBinaryViewType(types[i])); @@ -98,6 +99,7 @@ vector<Ref<BinaryViewType>> BinaryViewType::GetViewTypesForData(BinaryView* data types = BNGetBinaryViewTypesForData(data->GetObject(), &count); vector<Ref<BinaryViewType>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreBinaryViewType(types[i])); diff --git a/callingconvention.cpp b/callingconvention.cpp index 945ba25f..a56b8f11 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -49,6 +49,8 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback; cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback; cc.getIncomingFlagValue = GetIncomingFlagValueCallback; + cc.getIncomingVariableForParameterVariable = GetIncomingVariableForParameterVariableCallback; + cc.getParameterVariableForIncomingVariable = GetParameterVariableForIncomingVariableCallback; AddRefForRegistration(); m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc); @@ -189,6 +191,28 @@ void CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, B } +void CallingConvention::GetIncomingVariableForParameterVariableCallback(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref<Function> funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + *result = cc->GetIncomingVariableForParameterVariable(*var, funcObj); +} + + +void CallingConvention::GetParameterVariableForIncomingVariableCallback(void* ctxt, const BNVariable* var, + BNFunction* func, BNVariable* result) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref<Function> funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + *result = cc->GetParameterVariableForIncomingVariable(*var, funcObj); +} + + Ref<Architecture> CallingConvention::GetArchitecture() const { return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object)); @@ -264,8 +288,16 @@ vector<uint32_t> CallingConvention::GetImplicitlyDefinedRegisters() } -RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*) +RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t reg, Function*) { + uint32_t regStack = GetArchitecture()->GetRegisterStackForRegister(reg); + if ((regStack != BN_INVALID_REGISTER) && (reg == GetArchitecture()->GetRegisterStackInfo(regStack).stackTopReg)) + { + RegisterValue value; + value.state = ConstantValue; + value.value = 0; + return value; + } return RegisterValue(); } @@ -276,6 +308,18 @@ RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*) } +Variable CallingConvention::GetIncomingVariableForParameterVariable(const Variable& var, Function*) +{ + return BNGetDefaultIncomingVariableForParameterVariable(m_object, &var); +} + + +Variable CallingConvention::GetParameterVariableForIncomingVariable(const Variable& var, Function*) +{ + return BNGetDefaultParameterVariableForIncomingVariable(m_object, &var); +} + + CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc) { } @@ -377,3 +421,15 @@ RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Functio { return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr)); } + + +Variable CoreCallingConvention::GetIncomingVariableForParameterVariable(const Variable& var, Function* func) +{ + return BNGetIncomingVariableForParameterVariable(m_object, &var, func ? func->GetObject() : nullptr); +} + + +Variable CoreCallingConvention::GetParameterVariableForIncomingVariable(const Variable& var, Function* func) +{ + return BNGetParameterVariableForIncomingVariable(m_object, &var, func ? func->GetObject() : nullptr); +} diff --git a/docs/about/open-source.md b/docs/about/open-source.md index 9f385633..a25fb24e 100644 --- a/docs/about/open-source.md +++ b/docs/about/open-source.md @@ -42,12 +42,12 @@ The previous tools are used in the generation of our documentation, but are not ## Building Qt -Binary Ninja uses [Qt 5.6] under an LGPLv3 license which requires that we host the original sources used to build Qt for our application along with instructions on how that source may be re-built and can replace the version of Qt shipped with Binary Ninja. +Binary Ninja uses [Qt 5.10] under an LGPLv3 license which requires that we host the original sources used to build Qt for our application along with instructions on how that source may be re-built and can replace the version of Qt shipped with Binary Ninja. Please note that we offer no support for running Binary Ninja with modified Qt libraries. 1. Follow the installation requirements on the [Building Qt 5 from Git] page. -2. Download the Qt 5.6.0 [tarball] from binary.ninja. (Note this is an unmodified 5.6 identical to that available from Qt's source control, but must be hosted locally according to the [Qt 5.6] terms.) +2. Download the Qt 5.10.0 [tarball] from binary.ninja. (Note this is an unmodified 5.10 identical to that available from Qt's source control, but must be hosted locally according to the [Qt 5.10] terms.) 3. Next, build QT using the aforementioned instructions. 4. On OS X, you will need to disable the code-signing signature since it would otherwise prevent changes to binaries or shared libraries. We recommend a tool such as [unsign]. 5. Finally, replace the built libraries: @@ -56,7 +56,7 @@ Please note that we offer no support for running Binary Ninja with modified Qt l - On Linux, replace the `libQt5Core.so.5`, `libQt5DBus.so.5`, `libQt5Gui.so.5`, `libQt5Network.so.5`, `libQt5Widgets.so.5`, `libQt5XcbQpa.so.5` files wherever Binary Ninja was extracted [Building Qt 5 from Git]: https://wiki.qt.io/Building-Qt-5-from-Git -[Qt 5.6]: https://www.qt.io/qt-licensing-terms/ +[Qt 5.10]: https://www.qt.io/qt-licensing-terms/ [capstone]: https://github.com/aquynh/capstone [capstone license]: https://github.com/aquynh/capstone/blob/master/LICENSE.TXT [breathe license]: https://github.com/michaeljones/breathe/blob/master/LICENSE @@ -97,7 +97,7 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [sphinx]: http://www.sphinx-doc.org/en/stable/index.html [sqlite license]: https://www.sqlite.org/copyright.html [sqlite]: https://www.sqlite.org/index.html -[tarball]: https://binary.ninja/qt5.6.0.tar.xz +[tarball]: https://binary.ninja/qt5.10.0.tar.xz [tomcrypt license]: https://github.com/libtom/libtomcrypt/blob/develop/LICENSE [tomcrypt]: https://github.com/libtom/libtomcrypt [unsign]: https://github.com/steakknife/unsign diff --git a/docs/getting-started.md b/docs/getting-started.md index 88945f7b..073ccd33 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -85,6 +85,10 @@ Switching views happens multiple ways. In some instances, it's automatic (clicki - `h` : Switch to hex view - `p` : Create a function - `[ESC]` : Navigate backward + - `[CMD] [` (OS X) : Navigate backward + - `[CMD] ]` (OS X) : Navigate forward + - `[CTRL] [` (Windows/Linux) : Navigate backward + - `[CTRL] ]` (Windows/Linux) : Navigate forward - `[SPACE]` : Toggle between linear view and graph view - `g` : Go To Address dialog - `n` : Name a symbol @@ -92,7 +96,7 @@ Switching views happens multiple ways. In some instances, it's automatic (clicki - `e` : Edits an instruction (by modifying the original binary -- currently only enabled for x86, and x64) - `x` : Focuses the cross-reference pane - `;` : Adds a comment - - `i` : Switches between disassembly and low-level il in graph view + - `i` : Cycles between disassembly, low-level il, and medium-level il in graph view - `y` : Change type - `a` : Change the data type to an ASCII string - [1248] : Change type directly to a data variable of the indicated widths @@ -210,15 +214,15 @@ By default the interactive python prompt has a number of convenient helper funct - `bv` / `current_view` / : the current [BinaryView](https://api.binary.ninja/binaryninja.BinaryView.html) - `current_function`: the current [Function](https://api.binary.ninja/binaryninja.Function.html) - `current_basic_block`: the current [BasicBlock](https://api.binary.ninja/binaryninja.BasicBlock.html) -- `current_llil`: the current [LowLevelILBasicBlock](https://api.binary.ninja/binaryninja.lowlevelil.LowLevelILBasicBlock.html) -- `current_mlil`: the current [MediumLevelILBasicBlock](https://api.binary.ninja/binaryninja.mediumlevelil.MediumLevelILBasicBlock.html) +- `current_llil`: the current [LowLevelILFunction](https://api.binary.ninja/binaryninja.lowlevelil.LowLevelILFunction.html) +- `current_mlil`: the current [MediumLevelILFunction](https://api.binary.ninja/binaryninja.mediumlevelil.MediumLevelILFunction.html) - `current_selection`: a tuple of the start and end addresses of the current selection - `write_at_cursor(data)`: function that writes data to the start of the current selection - `get_selected_data()`: function that returns the data in the current selection Note !!! Tip "Note" - The current script console only supports Python at the moment, but it's fully extensible for other programming languages for advanced users who with to implement their own bindings. + The current script console only supports Python at the moment, but it's fully extensible for other programming languages for advanced users who wish to implement their own bindings. ## Using Plugins @@ -260,6 +264,7 @@ Settings are stored in the _user_ directory in the file `settings.json`. Each to | ui | activeContent | boolean | True | Allow Binary Ninja to connect to the web to check for updates | | ui | colorblind | boolean | True | Choose colors that are visible to those with red/green colorblind | | ui | debug | boolean | False | Enable developer debugging features (Additional views: Lifted IL, and SSA forms) | +| ui | recent-file-limit | integer | 10 | Specify limit for number of recent files | | pdb | local-store-absolute | string | "" | Absolute path specifying where the pdb symbol store exists on this machine, overrides relative path | | pdb | local-store-relative | string | "symbols" | Path *relative* to the binaryninja _user_ directory, sepcifying the pdb symbol store | | pdb | auto-download-pdb | boolean | True | Automatically download pdb files from specified symbol servers | @@ -273,6 +278,7 @@ Below is an example `settings.json` setting various options: "activeContent" : false, "colorblind" : false, "debug" : true + "recent-file-limit" : 10 } "pdb" : { diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86 -Subproject 9a1bf01f4c456779544a445db45b1496c50ff37 +Subproject 217176e2dd84f09214d38b5cc727313f17d6a0d diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index a2ba4c9c..87f2c2cb 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -10,572 +10,37 @@ using namespace std; using namespace asmx86; -#define IL_FLAG_C 0 -#define IL_FLAG_P 2 -#define IL_FLAG_A 4 -#define IL_FLAG_Z 6 -#define IL_FLAG_S 7 -#define IL_FLAG_D 10 -#define IL_FLAG_O 11 - -#define IL_FLAGWRITE_ALL 1 -#define IL_FLAGWRITE_NOCARRY 2 -#define IL_FLAGWRITE_CO 3 - -#define REG_FSBASE 0x100 -#define REG_GSBASE 0x101 - -#define TRAP_DIV 0 -#define TRAP_ICEBP 1 -#define TRAP_NMI 2 -#define TRAP_BP 3 -#define TRAP_OVERFLOW 4 -#define TRAP_BOUND 5 -#define TRAP_ILL 6 -#define TRAP_NOT_AVAIL 7 -#define TRAP_DOUBLE 8 -#define TRAP_TSS 10 -#define TRAP_NO_SEG 11 -#define TRAP_STACK 12 -#define TRAP_GPF 13 -#define TRAP_PAGE 14 -#define TRAP_FPU 16 -#define TRAP_ALIGN 17 -#define TRAP_MCE 18 -#define TRAP_SIMD 19 - -static uint8_t GetShiftCountForScale(uint8_t scale) -{ - switch (scale) - { - case 2: - return 1; - case 4: - return 2; - case 8: - return 3; - default: - return 0; - } -} - - -static uint32_t GetStackPointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_SP; - case 4: - return REG_ESP; - default: - return REG_RSP; - } -} - - -static uint32_t GetFramePointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_BP; - case 4: - return REG_EBP; - default: - return REG_RBP; - } -} - - -static uint32_t GetCountRegister(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_CX; - case 4: - return REG_ECX; - default: - return REG_RCX; - } -} - - -static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t i, size_t addrSize) -{ - size_t offset; - if (operand.operand != MEM) - offset = il.Operand(i, il.Undefined()); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE) && operand.relative) - offset = il.Operand(i, il.ConstPointer(addrSize, operand.immediate)); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE)) - offset = il.Operand(i, il.Const(addrSize, operand.immediate)); - else if ((operand.components[1] == NONE) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[0])); - else if (operand.components[1] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.scale == 1) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[1])); - else if ((operand.components[0] == NONE) && (operand.scale == 1)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))); - } - else if (operand.components[0] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))), il.Const(addrSize, operand.immediate))); - } - else if ((operand.scale == 1) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1]))); - } - else if (operand.scale == 1) - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1])), il.Const(addrSize, operand.immediate))); - } - else if (operand.immediate == 0) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))))); - } - else - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))), il.Const(addrSize, operand.immediate))); - } - - if (operand.segment == SEG_FS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_FSBASE), offset)); - if (operand.segment == SEG_GS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_GSBASE), offset)); - return offset; -} - - -static size_t ReadILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, bool isAddress = false) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - return il.Undefined(); - case IMM: - if (isAddress) - return il.Operand(i, il.ConstPointer(operand.size, operand.immediate)); - else - return il.Operand(i, il.Const(operand.size, operand.immediate)); - case MEM: - return il.Operand(i, il.Load(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize))); - default: - return il.Operand(i, il.Register(operand.size, operand.operand)); - } -} - - -static size_t WriteILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, size_t value) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - case IMM: - return il.Undefined(); - case MEM: - return il.Operand(i, il.Store(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize), value)); - default: - return il.Operand(i, il.SetRegister(operand.size, operand.operand, value)); - } -} - - -static size_t DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize) -{ - BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); - if (label) - return il.Goto(*label); - else - return il.Jump(il.ConstPointer(addrSize, target)); -} - - -static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, size_t cond, size_t addrSize, uint64_t t, uint64_t f) -{ - BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t); - BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f); - - if (trueLabel && falseLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, *falseLabel)); - return; - } - - LowLevelILLabel trueCode, falseCode; - - if (trueLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, falseCode)); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); - return; - } - - if (falseLabel) - { - il.AddInstruction(il.If(cond, trueCode, *falseLabel)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - return; - } - - il.AddInstruction(il.If(cond, trueCode, falseCode)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); -} - - -static void DirFlagIf(size_t addrSize, - LowLevelILFunction& il, - std::function<void (size_t addrSize, LowLevelILFunction& il)> addPreTestIl, - std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagSetIl, - std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagClearIl) -{ - LowLevelILLabel dirFlagSet, dirFlagClear, dirFlagDone; - - addPreTestIl(addrSize, il); - - il.AddInstruction(il.If(il.Flag(IL_FLAG_D), dirFlagSet, dirFlagClear)); - il.MarkLabel(dirFlagSet); - - addDirFlagSetIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagClear); - - addDirFlagClearIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagDone); -} - - -static void Repeat(size_t addrSize, - Instruction& instr, - LowLevelILFunction& il, - std::function<void (size_t addrSize, LowLevelILFunction& il)> addil) -{ - LowLevelILLabel trueLabel, falseLabel, doneLabel; - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(trueLabel); - il.AddInstruction(il.If(il.CompareEqual(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 0)), doneLabel, falseLabel)); - il.MarkLabel(falseLabel); - } - - addil(addrSize, il); - - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.SetRegister(addrSize, GetCountRegister(addrSize), - il.Sub(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 1)))); - if (instr.flags & X86_FLAG_REPE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_E), trueLabel, doneLabel)); - else if (instr.flags & X86_FLAG_REPNE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_NE), trueLabel, doneLabel)); - else - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(doneLabel); - } -} - - // This is a wrapper for the x86 architecture. Its useful for extending and improving // the existing core x86 architecture. -class x86ArchitectureExtension: public Architecture +class x86ArchitectureExtension: public ArchitectureHook { - Architecture* m_arch; public: - x86ArchitectureExtension() : Architecture("x86_extension") - { - m_arch = new CoreArchitecture(BNGetArchitectureByName("x86")); - } - - virtual size_t GetAddressSize() const override - { - return 4; - } - - virtual BNEndianness GetEndianness() const override + x86ArchitectureExtension(Architecture* x86) : ArchitectureHook(x86) { - return LittleEndian; - } - - virtual size_t GetInstructionAlignment() const override - { - return 1; - } - - virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override - { - return m_arch->GetInstructionInfo(data, addr, maxLen, result); - } - - virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector<InstructionTextToken>& result) override - { - return m_arch->GetInstructionText(data, addr, len, result); } virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { Instruction instr; - if (!asmx86::Disassemble32(data, addr, len, &instr)) + if (asmx86::Disassemble32(data, addr, len, &instr)) { - il.AddInstruction(il.Undefined()); - return false; + switch (instr.operation) + { + case CPUID: + // The default implementation of CPUID doesn't set registers to constant values + // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 + il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read + il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); + il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); + il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); + il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); + len = instr.length; + return true; + default: + break; + } } - - size_t addrSize = 4; - switch (instr.operation) - { - case CPUID: - // The default implementation of CPUID doesn't set registers to constant values - // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 - il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read - il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); - il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); - il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); - il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); - len = instr.length; - return true; - - case JMP: - if (instr.operands[0].operand == IMM) - il.AddInstruction(DirectJump(this, il, instr.operands[0].immediate, addrSize)); - else - il.AddInstruction(il.Jump(ReadILOperand(il, instr, 0, addrSize, true))); - return false; - - case JO: - ConditionalJump(this, il, il.FlagCondition(LLFC_O), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNO: - ConditionalJump(this, il, il.FlagCondition(LLFC_NO), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JB: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JAE: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JE: - ConditionalJump(this, il, il.FlagCondition(LLFC_E), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNE: - ConditionalJump(this, il, il.FlagCondition(LLFC_NE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JBE: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JA: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JS: - ConditionalJump(this, il, il.FlagCondition(LLFC_NEG), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNS: - ConditionalJump(this, il, il.FlagCondition(LLFC_POS), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPE: - ConditionalJump(this, il, il.Not(0, il.Flag(IL_FLAG_P)), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPO: - ConditionalJump(this, il, il.Flag(IL_FLAG_P), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JL: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JGE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JLE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JG: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JCXZ: - ConditionalJump(this, il, il.CompareEqual(2, il.Register(2, REG_CX), il.Const(2, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JECXZ: - ConditionalJump(this, il, il.CompareEqual(4, il.Register(4, REG_ECX), il.Const(4, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JRCXZ: - ConditionalJump(this, il, il.CompareEqual(8, il.Register(8, REG_RCX), il.Const(8, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - default: - return m_arch->GetInstructionLowLevelIL(data, addr, len, il); - } - } - - virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override - { - return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il); - } - - virtual string GetRegisterName(uint32_t reg) override - { - return m_arch->GetRegisterName(reg); - } - - virtual string GetFlagName(uint32_t flag) override - { - return m_arch->GetFlagName(flag); - } - - virtual vector<uint32_t> GetAllFlags() override - { - return m_arch->GetAllFlags(); - } - - virtual string GetFlagWriteTypeName(uint32_t flags) override - { - return m_arch->GetFlagWriteTypeName(flags); - } - - virtual vector<uint32_t> GetAllFlagWriteTypes() override - { - return m_arch->GetAllFlagWriteTypes(); - } - - virtual BNFlagRole GetFlagRole(uint32_t flag) override - { - return m_arch->GetFlagRole(flag); - } - - virtual vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override - { - return m_arch->GetFlagsRequiredForFlagCondition(cond); - } - - virtual vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override - { - return m_arch->GetFlagsWrittenByFlagWriteType(writeType); - } - - virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsNeverBranchPatchAvailable(data, addr, len); - } - - virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len); - } - - virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsInvertBranchPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len); - } - - virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->ConvertToNop(data, addr, len); - } - - virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->AlwaysBranch(data, addr, len); - } - - virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->InvertBranch(data, addr, len); - } - - virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override - { - return m_arch->SkipAndReturnValue(data, addr, len, value); - } - - virtual vector<uint32_t> GetFullWidthRegisters() override - { - return m_arch->GetFullWidthRegisters(); - } - - virtual vector<uint32_t> GetGlobalRegisters() override - { - return m_arch->GetGlobalRegisters(); - } - - virtual vector<uint32_t> GetAllRegisters() override - { - return m_arch->GetAllRegisters(); - } - - virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override - { - return m_arch->GetRegisterInfo(reg); - } - - virtual uint32_t GetStackPointerRegister() override - { - return m_arch->GetStackPointerRegister(); - } - - virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override - { - return m_arch->Assemble(code, addr, result, errors); + return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il); } }; @@ -585,21 +50,13 @@ extern "C" BINARYNINJAPLUGIN void CorePluginDependencies() { // Make sure we load after the original x86 plugin loads - SetCurrentPluginLoadOrder(LatePluginLoadOrder); + AddRequiredPluginDependency("arch_x86"); } BINARYNINJAPLUGIN bool CorePluginInit() { - Architecture* x86ext = new x86ArchitectureExtension(); + Architecture* x86ext = new x86ArchitectureExtension(Architecture::GetByName("x86")); Architecture::Register(x86ext); - - // Register the architectures with the binary format parsers so that they know when to use - // these architectures for disassembling an executable file - BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext); - x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5); - x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7); return true; } } diff --git a/function.cpp b/function.cpp index 1226e399..835ab144 100644 --- a/function.cpp +++ b/function.cpp @@ -174,6 +174,7 @@ vector<Ref<BasicBlock>> Function::GetBasicBlocks() const BNBasicBlock** blocks = BNGetFunctionBasicBlockList(m_object, &count); vector<Ref<BasicBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -379,6 +380,7 @@ vector<StackVariableReference> Function::GetStackVariablesReferencedByInstructio BNStackVariableReference* refs = BNGetStackVariablesReferencedByInstruction(m_object, arch->GetObject(), addr, &count); vector<StackVariableReference> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { StackVariableReference ref; @@ -490,6 +492,18 @@ Confidence<Ref<Type>> Function::GetReturnType() const } +Confidence<vector<uint32_t>> Function::GetReturnRegisters() const +{ + BNRegisterSetWithConfidence regs = BNGetFunctionReturnRegisters(m_object); + vector<uint32_t> regList; + for (size_t i = 0; i < regs.count; i++) + regList.push_back(regs.regs[i]); + Confidence<vector<uint32_t>> result(regList, regs.confidence); + BNFreeRegisterSet(®s); + return result; +} + + Confidence<Ref<CallingConvention>> Function::GetCallingConvention() const { BNCallingConventionWithConfidence cc = BNGetFunctionCallingConvention(m_object); @@ -502,10 +516,9 @@ Confidence<vector<Variable>> Function::GetParameterVariables() const { BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object); vector<Variable> varList; + varList.reserve(vars.count); for (size_t i = 0; i < vars.count; i++) - { varList.emplace_back(vars.vars[i].type, vars.vars[i].index, vars.vars[i].storage); - } Confidence<vector<Variable>> result(varList, vars.confidence); BNFreeParameterVariables(&vars); return result; @@ -526,6 +539,18 @@ Confidence<size_t> Function::GetStackAdjustment() const } +map<uint32_t, Confidence<int32_t>> Function::GetRegisterStackAdjustments() const +{ + size_t count; + BNRegisterStackAdjustment* regStackAdjust = BNGetFunctionRegisterStackAdjustments(m_object, &count); + map<uint32_t, Confidence<int32_t>> result; + for (size_t i = 0; i < count; i++) + result[regStackAdjust[i].regStack] = Confidence<int32_t>(regStackAdjust[i].adjustment, regStackAdjust[i].confidence); + BNFreeRegisterStackAdjustments(regStackAdjust); + return result; +} + + Confidence<set<uint32_t>> Function::GetClobberedRegisters() const { BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object); @@ -533,7 +558,7 @@ Confidence<set<uint32_t>> Function::GetClobberedRegisters() const for (size_t i = 0; i < regs.count; i++) regSet.insert(regs.regs[i]); Confidence<set<uint32_t>> result(regSet, regs.confidence); - BNFreeClobberedRegisters(®s); + BNFreeRegisterSet(®s); return result; } @@ -553,6 +578,19 @@ void Function::SetAutoReturnType(const Confidence<Ref<Type>>& type) } +void Function::SetAutoReturnRegisters(const Confidence<std::vector<uint32_t>>& returnRegs) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[returnRegs.GetValue().size()]; + regs.count = returnRegs.GetValue().size(); + for (size_t i = 0; i < regs.count; i++) + regs.regs[i] = returnRegs.GetValue()[i]; + regs.confidence = returnRegs.GetConfidence(); + BNSetAutoFunctionReturnRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention) { BNCallingConventionWithConfidence cc; @@ -608,6 +646,22 @@ void Function::SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust) } +void Function::SetAutoRegisterStackAdjustments(const map<uint32_t, Confidence<int32_t>>& regStackAdjust) +{ + BNRegisterStackAdjustment* adjust = new BNRegisterStackAdjustment[regStackAdjust.size()]; + size_t i = 0; + for (auto& j : regStackAdjust) + { + adjust[i].regStack = j.first; + adjust[i].adjustment = j.second.GetValue(); + adjust[i].confidence = j.second.GetConfidence(); + i++; + } + BNSetAutoFunctionRegisterStackAdjustments(m_object, adjust, regStackAdjust.size()); + delete[] adjust; +} + + void Function::SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered) { BNRegisterSetWithConfidence regs; @@ -638,6 +692,19 @@ void Function::SetReturnType(const Confidence<Ref<Type>>& type) } +void Function::SetReturnRegisters(const Confidence<std::vector<uint32_t>>& returnRegs) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[returnRegs.GetValue().size()]; + regs.count = returnRegs.GetValue().size(); + for (size_t i = 0; i < regs.count; i++) + regs.regs[i] = returnRegs.GetValue()[i]; + regs.confidence = returnRegs.GetConfidence(); + BNSetUserFunctionReturnRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention) { BNCallingConventionWithConfidence cc; @@ -693,6 +760,22 @@ void Function::SetStackAdjustment(const Confidence<size_t>& stackAdjust) } +void Function::SetRegisterStackAdjustments(const map<uint32_t, Confidence<int32_t>>& regStackAdjust) +{ + BNRegisterStackAdjustment* adjust = new BNRegisterStackAdjustment[regStackAdjust.size()]; + size_t i = 0; + for (auto& j : regStackAdjust) + { + adjust[i].regStack = j.first; + adjust[i].adjustment = j.second.GetValue(); + adjust[i].confidence = j.second.GetConfidence(); + i++; + } + BNSetUserFunctionRegisterStackAdjustments(m_object, adjust, regStackAdjust.size()); + delete[] adjust; +} + + void Function::SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered) { BNRegisterSetWithConfidence regs; @@ -742,7 +825,7 @@ map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout() result[vars[i].var.storage].push_back(var); } - BNFreeVariableList(vars, count); + BNFreeVariableNameAndTypeList(vars, count); return result; } @@ -810,7 +893,7 @@ map<Variable, VariableNameAndType> Function::GetVariables() result[vars[i].var] = var; } - BNFreeVariableList(vars, count); + BNFreeVariableNameAndTypeList(vars, count); return result; } @@ -897,6 +980,7 @@ vector<IndirectBranchInfo> Function::GetIndirectBranches() BNIndirectBranchInfo* branches = BNGetIndirectBranches(m_object, &count); vector<IndirectBranchInfo> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { IndirectBranchInfo b; @@ -919,6 +1003,7 @@ vector<IndirectBranchInfo> Function::GetIndirectBranchesAt(Architecture* arch, u BNIndirectBranchInfo* branches = BNGetIndirectBranchesAt(m_object, arch->GetObject(), addr, &count); vector<IndirectBranchInfo> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { IndirectBranchInfo b; @@ -935,15 +1020,107 @@ vector<IndirectBranchInfo> Function::GetIndirectBranchesAt(Architecture* arch, u } +void Function::SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence<size_t>& adjust) +{ + BNSetAutoCallStackAdjustment(m_object, arch->GetObject(), addr, adjust.GetValue(), adjust.GetConfidence()); +} + + +void Function::SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, + const map<uint32_t, Confidence<int32_t>>& adjust) +{ + BNRegisterStackAdjustment* values = new BNRegisterStackAdjustment[adjust.size()]; + size_t i = 0; + for (auto& j : adjust) + { + values[i].regStack = j.first; + values[i].adjustment = j.second.GetValue(); + values[i].confidence = j.second.GetConfidence(); + i++; + } + BNSetAutoCallRegisterStackAdjustment(m_object, arch->GetObject(), addr, values, adjust.size()); + delete[] values; +} + + +void Function::SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, + const Confidence<int32_t>& adjust) +{ + BNSetAutoCallRegisterStackAdjustmentForRegisterStack(m_object, arch->GetObject(), addr, regStack, + adjust.GetValue(), adjust.GetConfidence()); +} + + +void Function::SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence<size_t>& adjust) +{ + BNSetUserCallStackAdjustment(m_object, arch->GetObject(), addr, adjust.GetValue(), adjust.GetConfidence()); +} + + +void Function::SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, + const map<uint32_t, Confidence<int32_t>>& adjust) +{ + BNRegisterStackAdjustment* values = new BNRegisterStackAdjustment[adjust.size()]; + size_t i = 0; + for (auto& j : adjust) + { + values[i].regStack = j.first; + values[i].adjustment = j.second.GetValue(); + values[i].confidence = j.second.GetConfidence(); + i++; + } + BNSetUserCallRegisterStackAdjustment(m_object, arch->GetObject(), addr, values, adjust.size()); + delete[] values; +} + + +void Function::SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, + const Confidence<int32_t>& adjust) +{ + BNSetUserCallRegisterStackAdjustmentForRegisterStack(m_object, arch->GetObject(), addr, regStack, + adjust.GetValue(), adjust.GetConfidence()); +} + + +Confidence<size_t> Function::GetCallStackAdjustment(Architecture* arch, uint64_t addr) +{ + BNSizeWithConfidence result = BNGetCallStackAdjustment(m_object, arch->GetObject(), addr); + return Confidence<size_t>(result.value, result.confidence); +} + + +map<uint32_t, Confidence<int32_t>> Function::GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr) +{ + size_t count; + BNRegisterStackAdjustment* adjust = BNGetCallRegisterStackAdjustment(m_object, arch->GetObject(), addr, &count); + + map<uint32_t, Confidence<int32_t>> result; + for (size_t i = 0; i < count; i++) + result[adjust[i].regStack] = Confidence<int32_t>(adjust[i].adjustment, adjust[i].confidence); + BNFreeRegisterStackAdjustments(adjust); + return result; +} + + +Confidence<int32_t> Function::GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack) +{ + BNRegisterStackAdjustment result = BNGetCallRegisterStackAdjustmentForRegisterStack(m_object, + arch->GetObject(), addr, regStack); + return Confidence<int32_t>(result.adjustment, result.confidence); +} + + vector<vector<InstructionTextToken>> Function::GetBlockAnnotations(Architecture* arch, uint64_t addr) { size_t count; BNInstructionTextLine* lines = BNGetFunctionBlockAnnotations(m_object, arch->GetObject(), addr, &count); vector<vector<InstructionTextToken>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { vector<InstructionTextToken> line; + line.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -1155,10 +1332,13 @@ vector<DisassemblyTextLine> Function::GetTypeTokens(DisassemblySettings* setting settings ? settings->GetObject() : nullptr, &count); vector<DisassemblyTextLine> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -1180,6 +1360,30 @@ vector<DisassemblyTextLine> Function::GetTypeTokens(DisassemblySettings* setting } +bool Function::IsFunctionTooLarge() +{ + return BNIsFunctionTooLarge(m_object); +} + + +bool Function::IsAnalysisSkipped() +{ + return BNIsFunctionAnalysisSkipped(m_object); +} + + +BNFunctionAnalysisSkipOverride Function::GetAnalysisSkipOverride() +{ + return BNGetFunctionAnalysisSkipOverride(m_object); +} + + +void Function::SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip) +{ + BNSetFunctionAnalysisSkipOverride(m_object, skip); +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/functiongraph.cpp b/functiongraph.cpp index 7e5ec079..9948d70e 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -110,6 +110,7 @@ vector<Ref<FunctionGraphBlock>> FunctionGraph::GetBlocks() BNFunctionGraphBlock** blocks = BNGetFunctionGraphBlocks(m_graph, &count); vector<Ref<FunctionGraphBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { auto block = m_cachedBlocks.find(blocks[i]); @@ -130,6 +131,12 @@ vector<Ref<FunctionGraphBlock>> FunctionGraph::GetBlocks() } +bool FunctionGraph::HasBlocks() const +{ + return BNFunctionGraphHasBlocks(m_graph); +} + + int FunctionGraph::GetWidth() const { return BNGetFunctionGraphWidth(m_graph); @@ -148,6 +155,7 @@ vector<Ref<FunctionGraphBlock>> FunctionGraph::GetBlocksInRegion(int left, int t BNFunctionGraphBlock** blocks = BNGetFunctionGraphBlocksInRegion(m_graph, left, top, right, bottom, &count); vector<Ref<FunctionGraphBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { auto block = m_cachedBlocks.find(blocks[i]); @@ -178,3 +186,39 @@ void FunctionGraph::SetOption(BNDisassemblyOption option, bool state) { BNSetFunctionGraphOption(m_graph, option, state); } + + +bool FunctionGraph::IsILGraph() const +{ + return BNIsILFunctionGraph(m_graph); +} + + +bool FunctionGraph::IsLowLevelILGraph() const +{ + return BNIsLowLevelILFunctionGraph(m_graph); +} + + +bool FunctionGraph::IsMediumLevelILGraph() const +{ + return BNIsMediumLevelILFunctionGraph(m_graph); +} + + +Ref<LowLevelILFunction> FunctionGraph::GetLowLevelILFunction() const +{ + BNLowLevelILFunction* func = BNGetFunctionGraphLowLevelILFunction(m_graph); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +Ref<MediumLevelILFunction> FunctionGraph::GetMediumLevelILFunction() const +{ + BNMediumLevelILFunction* func = BNGetFunctionGraphMediumLevelILFunction(m_graph); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 20b2515b..469fb175 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -89,10 +89,13 @@ const vector<DisassemblyTextLine>& FunctionGraphBlock::GetLines() BNDisassemblyTextLine* lines = BNGetFunctionGraphBlockLines(m_object, &count); vector<DisassemblyTextLine> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -125,6 +128,7 @@ const vector<FunctionGraphEdge>& FunctionGraphBlock::GetOutgoingEdges() BNFunctionGraphEdge* edges = BNGetFunctionGraphBlockOutgoingEdges(m_object, &count); vector<FunctionGraphEdge> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { FunctionGraphEdge edge; @@ -102,6 +102,7 @@ void BinaryNinja::Log(BNLogLevel level, const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(level, fmt, args); + va_end(args); } @@ -110,6 +111,7 @@ void BinaryNinja::LogDebug(const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(DebugLog, fmt, args); + va_end(args); } @@ -118,6 +120,7 @@ void BinaryNinja::LogInfo(const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(InfoLog, fmt, args); + va_end(args); } @@ -126,6 +129,7 @@ void BinaryNinja::LogWarn(const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(WarningLog, fmt, args); + va_end(args); } @@ -134,6 +138,7 @@ void BinaryNinja::LogError(const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(ErrorLog, fmt, args); + va_end(args); } @@ -142,6 +147,7 @@ void BinaryNinja::LogAlert(const char* fmt, ...) va_list args; va_start(args, fmt); PerformLog(AlertLog, fmt, args); + va_end(args); } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 6c59b704..79138159 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -176,6 +176,7 @@ vector<uint64_t> LowLevelILFunction::GetOperandList(ExprId expr, size_t listOper size_t count; uint64_t* operands = BNLowLevelILGetOperandList(m_object, expr, listOperand, &count); vector<uint64_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(operands[i]); BNLowLevelILFreeOperandList(operands); @@ -216,6 +217,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]; @@ -230,6 +242,20 @@ ExprId LowLevelILFunction::AddSSARegisterList(const vector<SSARegister>& regs) } +ExprId LowLevelILFunction::AddSSARegisterStackList(const vector<SSARegisterStack>& regStacks) +{ + uint64_t* operandList = new uint64_t[regStacks.size() * 2]; + for (size_t i = 0; i < regStacks.size(); i++) + { + operandList[i * 2] = regStacks[i].regStack; + operandList[(i * 2) + 1] = regStacks[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regStacks.size() * 2); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::AddSSAFlagList(const vector<SSAFlag>& flags) { uint64_t* operandList = new uint64_t[flags.size() * 2]; @@ -244,6 +270,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) @@ -274,7 +314,11 @@ ExprId LowLevelILFunction::GetExprForRegisterOrConstantOperation(BNLowLevelILOpe if (operandCount == 0) return AddExpr(op, size, 0); if (operandCount == 1) + { + if (op == LLIL_SET_REG) + return GetExprForRegisterOrConstant(operands[0], size); return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size)); + } if (operandCount == 2) { return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), @@ -390,11 +434,10 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<Ins return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -411,11 +454,10 @@ bool LowLevelILFunction::GetInstructionText(Function* func, Architecture* arch, return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -440,6 +482,7 @@ vector<Ref<BasicBlock>> LowLevelILFunction::GetBasicBlocks() const BNBasicBlock** blocks = BNGetLowLevelILBasicBlockList(m_object, &count); vector<Ref<BasicBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index d85e4f17..8fb87a9e 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -37,27 +37,34 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> LowLevelILInstructionBase::operandTypeForUsage = { {SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, {SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {SourceRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, {SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, {SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {SourceSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, {SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, {DestExprLowLevelOperandUsage, ExprLowLevelOperand}, {DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {DestRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, {DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {SemanticFlagClassLowLevelOperandUsage, SemanticFlagClassLowLevelOperand}, + {SemanticFlagGroupLowLevelOperandUsage, SemanticFlagGroupLowLevelOperand}, {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {TopSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, {RightExprLowLevelOperandUsage, ExprLowLevelOperand}, {CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, - {HighExprLowLevelOperandUsage, ExprLowLevelOperand}, - {LowExprLowLevelOperandUsage, ExprLowLevelOperand}, {ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, {HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand}, {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, @@ -70,11 +77,15 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> {FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, {OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, {OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, - {ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {ParameterExprsLowLevelOperandUsage, ExprListLowLevelOperand}, {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand}, {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, + {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, - {TargetListLowLevelOperandUsage, IndexListLowLevelOperand} + {TargetListLowLevelOperandUsage, IndexListLowLevelOperand}, + {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand} }; @@ -95,6 +106,15 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> SourceExprLowLevelOperandUsage}}, {LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_STACK_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_REG_STACK_PUSH, {DestRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_STACK_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, + PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, + TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_STACK_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, + PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, @@ -105,6 +125,20 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> {LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, {LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, {LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, + {LLIL_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage}}, + {LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}}, + {LLIL_REG_STACK_REL, {SourceRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_REG_STACK_POP, {SourceRegisterStackLowLevelOperandUsage}}, + {LLIL_REG_STACK_FREE_REG, {DestRegisterLowLevelOperandUsage}}, + {LLIL_REG_STACK_FREE_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage}}, + {LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_REG_STACK_ABS_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage}}, + {LLIL_REG_STACK_FREE_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, + PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, + TopSSARegisterLowLevelOperandUsage}}, + {LLIL_REG_STACK_FREE_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, + PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage}}, {LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, {LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, @@ -112,24 +146,28 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, {LLIL_CALL, {DestExprLowLevelOperandUsage}}, - {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage}}, + {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, + RegisterStackAdjustmentsLowLevelOperandUsage}}, {LLIL_RET, {DestExprLowLevelOperandUsage}}, {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, {LLIL_GOTO, {TargetLowLevelOperandUsage}}, - {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage}}, + {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage, SemanticFlagClassLowLevelOperandUsage}}, + {LLIL_FLAG_GROUP, {SemanticFlagGroupLowLevelOperandUsage}}, {LLIL_TRAP, {VectorLowLevelOperandUsage}}, {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, - StackMemoryVersionLowLevelOperandUsage, ParameterSSARegistersLowLevelOperandUsage}}, + StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, - ParameterSSARegistersLowLevelOperandUsage}}, + ParameterExprsLowLevelOperandUsage}}, {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, + {LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, {LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, {LLIL_CONST, {ConstantLowLevelOperandUsage}}, {LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, + {LLIL_FLOAT_CONST, {ConstantLowLevelOperandUsage}}, {LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, {LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, {LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, @@ -163,10 +201,10 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> {LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, {LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, {LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, - {LLIL_DIVU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_DIVS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, - {LLIL_MODS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, {LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, {LLIL_NEG, {SourceExprLowLevelOperandUsage}}, {LLIL_NOT, {SourceExprLowLevelOperandUsage}}, @@ -174,19 +212,45 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, - {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}} + {LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage}}, + {LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage}}, + {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, + {LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FMUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FDIV, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FSQRT, {SourceExprLowLevelOperandUsage}}, + {LLIL_FNEG, {SourceExprLowLevelOperandUsage}}, + {LLIL_FABS, {SourceExprLowLevelOperandUsage}}, + {LLIL_FLOAT_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_INT_TO_FLOAT, {SourceExprLowLevelOperandUsage}}, + {LLIL_FLOAT_CONV, {SourceExprLowLevelOperandUsage}}, + {LLIL_ROUND_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_FLOOR, {SourceExprLowLevelOperandUsage}}, + {LLIL_CEIL, {SourceExprLowLevelOperandUsage}}, + {LLIL_FTRUNC, {SourceExprLowLevelOperandUsage}}, + {LLIL_FCMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_LT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_LE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_GE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_GT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_FCMP_UO, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}} }; -static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> - GetOperandIndexForOperandUsages() +static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> GetOperandIndexForOperandUsages() { unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> result; + result.reserve(LowLevelILInstructionBase::operationOperandUsage.size()); for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) { result[operation.first] = unordered_map<LowLevelILOperandUsage, size_t>(); size_t operand = 0; + result[operation.first].reserve(operation.second.size()); for (auto usage : operation.second) { result[operation.first][usage] = operand; @@ -194,10 +258,12 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage { case HighSSARegisterLowLevelOperandUsage: case LowSSARegisterLowLevelOperandUsage: + case PartialSSARegisterStackSourceLowLevelOperandUsage: + case TopSSARegisterLowLevelOperandUsage: // Represented as subexpression, so only takes one slot even though it is an SSA register operand++; break; - case ParameterSSARegistersLowLevelOperandUsage: + case ParameterExprsLowLevelOperandUsage: // Represented as subexpression, so only takes one slot even though it is a list operand++; break; @@ -207,14 +273,22 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage case StackSSARegisterLowLevelOperandUsage: // StackMemoryVersionLowLevelOperandUsage follows at same operand break; + case DestSSARegisterStackLowLevelOperandUsage: + // PartialSSARegisterStackSourceLowLevelOperandUsage follows at same operand + break; default: switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) { case SSARegisterLowLevelOperand: + case SSARegisterStackLowLevelOperand: case SSAFlagLowLevelOperand: case IndexListLowLevelOperand: case SSARegisterListLowLevelOperand: + case SSARegisterStackListLowLevelOperand: case SSAFlagListLowLevelOperand: + case RegisterStackAdjustmentsLowLevelOperand: + case RegisterOrFlagListLowLevelOperand: + case SSARegisterOrFlagListLowLevelOperand: // SSA registers/flags and lists take two operand slots operand += 2; break; @@ -234,6 +308,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) { } @@ -281,6 +421,53 @@ bool SSARegister::operator<(const SSARegister& v) const } +SSARegisterStack::SSARegisterStack(): regStack(BN_INVALID_REGISTER), version(0) +{ +} + + +SSARegisterStack::SSARegisterStack(const uint32_t r, size_t i): regStack(r), version(i) +{ +} + + +SSARegisterStack::SSARegisterStack(const SSARegisterStack& v): regStack(v.regStack), version(v.version) +{ +} + + +SSARegisterStack& SSARegisterStack::operator=(const SSARegisterStack& v) +{ + regStack = v.regStack; + version = v.version; + return *this; +} + + +bool SSARegisterStack::operator==(const SSARegisterStack& v) const +{ + if (regStack != v.regStack) + return false; + return version == v.version; +} + + +bool SSARegisterStack::operator!=(const SSARegisterStack& v) const +{ + return !((*this) == v); +} + + +bool SSARegisterStack::operator<(const SSARegisterStack& v) const +{ + if (regStack < v.regStack) + return true; + if (v.regStack < regStack) + return false; + return version < v.version; +} + + SSAFlag::SSAFlag(): flag(BN_INVALID_REGISTER), version(0) { } @@ -328,6 +515,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; @@ -377,7 +621,7 @@ uint64_t LowLevelILIntegerList::ListIterator::operator*() LowLevelILIntegerList::LowLevelILIntegerList(LowLevelILFunction* func, - const BNLowLevelILInstruction& instr, size_t count) +const BNLowLevelILInstruction& instr, size_t count) { m_start.function = func; #ifdef BINARYNINJACORE_LIBRARY @@ -486,6 +730,118 @@ LowLevelILIndexList::operator vector<size_t>() const } +const LowLevelILInstruction LowLevelILInstructionList::ListIterator::operator*() +{ + return LowLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), + (size_t)*pos, instructionIndex); +} + + +LowLevelILInstructionList::LowLevelILInstructionList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count, size_t instrIndex): + m_list(func, instr, count), m_instructionIndex(instrIndex) +{ +} + + +LowLevelILInstructionList::const_iterator LowLevelILInstructionList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +LowLevelILInstructionList::const_iterator LowLevelILInstructionList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +size_t LowLevelILInstructionList::size() const +{ + return m_list.size(); +} + + +const LowLevelILInstruction LowLevelILInstructionList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILInstructionList::operator vector<LowLevelILInstruction>() const +{ + vector<LowLevelILInstruction> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +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; @@ -544,6 +900,64 @@ LowLevelILSSARegisterList::operator vector<SSARegister>() const } +const SSARegisterStack LowLevelILSSARegisterStackList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t regStack = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSARegisterStack(regStack, version); +} + + +LowLevelILSSARegisterStackList::LowLevelILSSARegisterStackList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSARegisterStackList::size() const +{ + return m_list.size() / 2; +} + + +const SSARegisterStack LowLevelILSSARegisterStackList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSARegisterStackList::operator vector<SSARegisterStack>() const +{ + vector<SSARegisterStack> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + const SSAFlag LowLevelILSSAFlagList::ListIterator::operator*() { LowLevelILIntegerList::const_iterator cur = pos; @@ -602,6 +1016,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) @@ -649,6 +1121,14 @@ uint32_t LowLevelILOperand::GetRegister() const } +uint32_t LowLevelILOperand::GetRegisterStack() const +{ + if (m_type != RegisterStackLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + uint32_t LowLevelILOperand::GetFlag() const { if (m_type != FlagLowLevelOperand) @@ -665,17 +1145,53 @@ BNLowLevelILFlagCondition LowLevelILOperand::GetFlagCondition() const } +uint32_t LowLevelILOperand::GetSemanticFlagClass() const +{ + if (m_type != SemanticFlagClassLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetSemanticFlagGroup() const +{ + if (m_type != SemanticFlagGroupLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +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) throw LowLevelILInstructionAccessException(); if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || - (m_usage == StackSSARegisterLowLevelOperandUsage)) + (m_usage == StackSSARegisterLowLevelOperandUsage) || (m_usage == TopSSARegisterLowLevelOperandUsage)) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); return m_instr.GetRawOperandAsSSARegister(m_operandIndex); } +SSARegisterStack LowLevelILOperand::GetSSARegisterStack() const +{ + if (m_type != SSARegisterStackLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == DestSSARegisterStackLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterStack(0); + if (m_usage == PartialSSARegisterStackSourceLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0); + return m_instr.GetRawOperandAsSSARegisterStack(m_operandIndex); +} + + SSAFlag LowLevelILOperand::GetSSAFlag() const { if (m_type != SSAFlagLowLevelOperand) @@ -692,18 +1208,40 @@ LowLevelILIndexList LowLevelILOperand::GetIndexList() const } +LowLevelILInstructionList LowLevelILOperand::GetExprList() const +{ + if (m_type != ExprListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(0); +} + + +LowLevelILRegisterOrFlagList LowLevelILOperand::GetRegisterOrFlagList() const +{ + if (m_type != RegisterOrFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegisterOrFlagList(m_operandIndex); +} + + LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const { if (m_type != SSARegisterListLowLevelOperand) throw LowLevelILInstructionAccessException(); if (m_usage == OutputSSARegistersLowLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1); - if (m_usage == ParameterSSARegistersLowLevelOperandUsage) - return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(0); return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex); } +LowLevelILSSARegisterStackList LowLevelILOperand::GetSSARegisterStackList() const +{ + if (m_type != SSARegisterStackListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSARegisterStackList(m_operandIndex); +} + + LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const { if (m_type != SSAFlagListLowLevelOperand) @@ -712,6 +1250,22 @@ 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) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegisterStackAdjustments(m_operandIndex); +} + + const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() { LowLevelILOperandUsage usage = *pos; @@ -869,6 +1423,18 @@ SSARegister LowLevelILInstructionBase::GetRawOperandAsSSARegister(size_t operand } +SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsSSARegisterStack(size_t operand) const +{ + return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const +{ + return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 2]); +} + + SSAFlag LowLevelILInstructionBase::GetRawOperandAsSSAFlag(size_t operand) const { return SSAFlag((uint32_t)operands[operand], (size_t)operands[operand + 1]); @@ -881,18 +1447,61 @@ LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t o } +LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const +{ + return LowLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand], + instructionIndex); +} + + +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]); } +LowLevelILSSARegisterStackList LowLevelILInstructionBase::GetRawOperandAsSSARegisterStackList(size_t operand) const +{ + return LowLevelILSSARegisterStackList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size_t operand) const { return LowLevelILSSAFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); } +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]); + map<uint32_t, int32_t> result; + for (auto i = list.begin(); i != list.end(); ) + { + uint32_t regStack = (uint32_t)*i; + ++i; + if (i == list.end()) + break; + int32_t adjust = (int32_t)*i; + ++i; + result[regStack] = adjust; + } + return result; +} + + void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) { operands[operandIndex] = value; @@ -907,6 +1516,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); @@ -1130,12 +1747,38 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL case LLIL_SET_REG_SPLIT_SSA: GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>().VisitExprs(func); break; + case LLIL_SET_REG_STACK_REL: + GetDestExpr<LLIL_SET_REG_STACK_REL>().VisitExprs(func); + GetSourceExpr<LLIL_SET_REG_STACK_REL>().VisitExprs(func); + break; + case LLIL_REG_STACK_PUSH: + GetSourceExpr<LLIL_REG_STACK_PUSH>().VisitExprs(func); + break; + case LLIL_SET_REG_STACK_REL_SSA: + GetDestExpr<LLIL_SET_REG_STACK_REL_SSA>().VisitExprs(func); + GetSourceExpr<LLIL_SET_REG_STACK_REL_SSA>().VisitExprs(func); + break; + case LLIL_SET_REG_STACK_ABS_SSA: + GetSourceExpr<LLIL_SET_REG_STACK_ABS_SSA>().VisitExprs(func); + break; case LLIL_SET_FLAG: GetSourceExpr<LLIL_SET_FLAG>().VisitExprs(func); break; case LLIL_SET_FLAG_SSA: GetSourceExpr<LLIL_SET_FLAG_SSA>().VisitExprs(func); break; + case LLIL_REG_STACK_REL: + GetSourceExpr<LLIL_REG_STACK_REL>().VisitExprs(func); + break; + case LLIL_REG_STACK_FREE_REL: + GetDestExpr<LLIL_REG_STACK_FREE_REL>().VisitExprs(func); + break; + case LLIL_REG_STACK_REL_SSA: + GetSourceExpr<LLIL_REG_STACK_REL_SSA>().VisitExprs(func); + break; + case LLIL_REG_STACK_FREE_REL_SSA: + GetDestExpr<LLIL_REG_STACK_FREE_REL_SSA>().VisitExprs(func); + break; case LLIL_LOAD: GetSourceExpr<LLIL_LOAD>().VisitExprs(func); break; @@ -1167,6 +1810,12 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL break; case LLIL_CALL_SSA: GetDestExpr<LLIL_CALL_SSA>().VisitExprs(func); + for (auto& i : GetParameterExprs<LLIL_CALL_SSA>()) + i.VisitExprs(func); + break; + case LLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<LLIL_SYSCALL_SSA>()) + i.VisitExprs(func); break; case LLIL_RET: GetDestExpr<LLIL_RET>().VisitExprs(func); @@ -1179,6 +1828,16 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL case LLIL_LOW_PART: case LLIL_BOOL_TO_INT: case LLIL_UNIMPL_MEM: + case LLIL_FSQRT: + case LLIL_FNEG: + case LLIL_FABS: + case LLIL_FLOAT_TO_INT: + case LLIL_INT_TO_FLOAT: + case LLIL_FLOAT_CONV: + case LLIL_ROUND_TO_INT: + case LLIL_FLOOR: + case LLIL_CEIL: + case LLIL_FTRUNC: AsOneOperand().GetSourceExpr().VisitExprs(func); break; case LLIL_ADD: @@ -1198,6 +1857,10 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL case LLIL_DIVS: case LLIL_MODU: case LLIL_MODS: + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: case LLIL_CMP_E: case LLIL_CMP_NE: case LLIL_CMP_SLT: @@ -1210,6 +1873,17 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL case LLIL_CMP_UGT: case LLIL_TEST_BIT: case LLIL_ADD_OVERFLOW: + case LLIL_FADD: + case LLIL_FSUB: + case LLIL_FMUL: + case LLIL_FDIV: + case LLIL_FCMP_E: + case LLIL_FCMP_NE: + case LLIL_FCMP_LT: + case LLIL_FCMP_LE: + case LLIL_FCMP_GE: + case LLIL_FCMP_GT: + case LLIL_FCMP_UO: AsTwoOperand().GetLeftExpr().VisitExprs(func); AsTwoOperand().GetRightExpr().VisitExprs(func); break; @@ -1221,13 +1895,13 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); break; - case LLIL_DIVU_DP: - case LLIL_DIVS_DP: - case LLIL_MODU_DP: - case LLIL_MODS_DP: - AsDoublePrecision().GetHighExpr().VisitExprs(func); - AsDoublePrecision().GetLowExpr().VisitExprs(func); - AsDoublePrecision().GetRightExpr().VisitExprs(func); + 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; @@ -1247,6 +1921,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const { vector<BNLowLevelILLabel*> labelList; + vector<ExprId> params; BNLowLevelILLabel* labelA; BNLowLevelILLabel* labelB; switch (operation) @@ -1270,6 +1945,25 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->SetRegisterSplitSSA(size, GetHighSSARegister<LLIL_SET_REG_SPLIT_SSA>(), GetLowSSARegister<LLIL_SET_REG_SPLIT_SSA>(), subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>()), *this); + case LLIL_SET_REG_STACK_REL: + return dest->SetRegisterStackTopRelative(size, GetDestRegisterStack<LLIL_SET_REG_STACK_REL>(), + subExprHandler(GetDestExpr<LLIL_SET_REG_STACK_REL>()), + subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_REL>()), flags, *this); + case LLIL_REG_STACK_PUSH: + return dest->RegisterStackPush(size, GetDestRegisterStack<LLIL_REG_STACK_PUSH>(), + subExprHandler(GetSourceExpr<LLIL_REG_STACK_PUSH>()), flags, *this); + case LLIL_SET_REG_STACK_REL_SSA: + return dest->SetRegisterStackTopRelativeSSA(size, GetDestSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().regStack, + GetDestSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().version, + GetSourceSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().version, + subExprHandler(GetDestExpr<LLIL_SET_REG_STACK_REL_SSA>()), GetTopSSARegister<LLIL_SET_REG_STACK_REL_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_REL_SSA>()), *this); + case LLIL_SET_REG_STACK_ABS_SSA: + return dest->SetRegisterStackAbsoluteSSA(size, GetDestSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().regStack, + GetDestSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().version, + GetSourceSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().version, + GetDestRegister<LLIL_SET_REG_STACK_ABS_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_ABS_SSA>()), *this); case LLIL_SET_FLAG: return dest->SetFlag(GetDestFlag<LLIL_SET_FLAG>(), subExprHandler(GetSourceExpr<LLIL_SET_FLAG>()), *this); case LLIL_SET_FLAG_SSA: @@ -1294,6 +1988,40 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_REG_SSA_PARTIAL: return dest->RegisterSSAPartial(size, GetSourceSSARegister<LLIL_REG_SSA_PARTIAL>(), GetPartialRegister<LLIL_REG_SSA_PARTIAL>(), *this); + case LLIL_REG_SPLIT: + return dest->RegisterSplit(size, GetHighRegister<LLIL_REG_SPLIT>(), + GetLowRegister<LLIL_REG_SPLIT>(), *this); + case LLIL_REG_SPLIT_SSA: + return dest->RegisterSplitSSA(size, GetHighSSARegister<LLIL_REG_SPLIT_SSA>(), + GetLowSSARegister<LLIL_REG_SPLIT_SSA>(), *this); + case LLIL_REG_STACK_REL: + return dest->RegisterStackTopRelative(size, GetSourceRegisterStack<LLIL_REG_STACK_REL>(), + subExprHandler(GetSourceExpr<LLIL_REG_STACK_REL>()), *this); + case LLIL_REG_STACK_POP: + return dest->RegisterStackPop(size, GetSourceRegisterStack<LLIL_REG_STACK_POP>(), flags, *this); + case LLIL_REG_STACK_FREE_REG: + return dest->RegisterStackFreeReg(GetDestRegister<LLIL_REG_STACK_FREE_REG>(), *this); + case LLIL_REG_STACK_FREE_REL: + return dest->RegisterStackFreeTopRelative(GetDestRegisterStack<LLIL_REG_STACK_FREE_REL>(), + subExprHandler(GetDestExpr<LLIL_REG_STACK_FREE_REL>()), *this); + case LLIL_REG_STACK_REL_SSA: + return dest->RegisterStackTopRelativeSSA(size, GetSourceSSARegisterStack<LLIL_REG_STACK_REL_SSA>(), + subExprHandler(GetSourceExpr<LLIL_REG_STACK_REL_SSA>()), + GetTopSSARegister<LLIL_REG_STACK_REL_SSA>(), *this); + case LLIL_REG_STACK_ABS_SSA: + return dest->RegisterStackAbsoluteSSA(size, GetSourceSSARegisterStack<LLIL_REG_STACK_ABS_SSA>(), + GetSourceRegister<LLIL_REG_STACK_ABS_SSA>(), *this); + case LLIL_REG_STACK_FREE_REL_SSA: + return dest->RegisterStackFreeTopRelativeSSA(GetDestSSARegisterStack<LLIL_REG_STACK_FREE_REL_SSA>().regStack, + GetDestSSARegisterStack<LLIL_REG_STACK_FREE_REL_SSA>().version, + GetSourceSSARegisterStack<LLIL_REG_STACK_FREE_REL_SSA>().version, + subExprHandler(GetDestExpr<LLIL_REG_STACK_FREE_REL_SSA>()), + GetTopSSARegister<LLIL_REG_STACK_FREE_REL_SSA>(), *this); + case LLIL_REG_STACK_FREE_ABS_SSA: + return dest->RegisterStackFreeAbsoluteSSA(GetDestSSARegisterStack<LLIL_REG_STACK_FREE_ABS_SSA>().regStack, + GetDestSSARegisterStack<LLIL_REG_STACK_FREE_ABS_SSA>().version, + GetSourceSSARegisterStack<LLIL_REG_STACK_FREE_ABS_SSA>().version, + GetDestRegister<LLIL_REG_STACK_FREE_ABS_SSA>(), *this); case LLIL_FLAG: return dest->Flag(GetSourceFlag<LLIL_FLAG>(), *this); case LLIL_FLAG_SSA: @@ -1308,7 +2036,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Call(subExprHandler(GetDestExpr<LLIL_CALL>()), *this); case LLIL_CALL_STACK_ADJUST: return dest->CallStackAdjust(subExprHandler(GetDestExpr<LLIL_CALL_STACK_ADJUST>()), - GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), *this); + GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), GetRegisterStackAdjustments<LLIL_CALL_STACK_ADJUST>(), *this); case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this); case LLIL_JUMP_TO: @@ -1335,19 +2063,28 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Undefined(*this); return dest->If(subExprHandler(GetConditionExpr<LLIL_IF>()), *labelA, *labelB, *this); case LLIL_FLAG_COND: - return dest->FlagCondition(GetFlagCondition<LLIL_FLAG_COND>(), *this); + return dest->FlagCondition(GetFlagCondition<LLIL_FLAG_COND>(), GetSemanticFlagClass<LLIL_FLAG_COND>(), *this); + case LLIL_FLAG_GROUP: + return dest->FlagGroup(GetSemanticFlagGroup<LLIL_FLAG_GROUP>(), *this); case LLIL_TRAP: return dest->Trap(GetVector<LLIL_TRAP>(), *this); case LLIL_CALL_SSA: + for (auto& i : GetParameterExprs<LLIL_CALL_SSA>()) + params.push_back(subExprHandler(i)); return dest->CallSSA(GetOutputSSARegisters<LLIL_CALL_SSA>(), subExprHandler(GetDestExpr<LLIL_CALL_SSA>()), - GetParameterSSARegisters<LLIL_CALL_SSA>(), GetStackSSARegister<LLIL_CALL_SSA>(), - GetDestMemoryVersion<LLIL_CALL_SSA>(), GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this); + params, GetStackSSARegister<LLIL_CALL_SSA>(), GetDestMemoryVersion<LLIL_CALL_SSA>(), + GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this); case LLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<LLIL_SYSCALL_SSA>()) + params.push_back(subExprHandler(i)); return dest->SystemCallSSA(GetOutputSSARegisters<LLIL_SYSCALL_SSA>(), - GetParameterSSARegisters<LLIL_SYSCALL_SSA>(), GetStackSSARegister<LLIL_SYSCALL_SSA>(), - GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this); + params, GetStackSSARegister<LLIL_SYSCALL_SSA>(), GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), + GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this); case LLIL_REG_PHI: return dest->RegisterPhi(GetDestSSARegister<LLIL_REG_PHI>(), GetSourceSSARegisters<LLIL_REG_PHI>(), *this); + case LLIL_REG_STACK_PHI: + return dest->RegisterStackPhi(GetDestSSARegisterStack<LLIL_REG_STACK_PHI>(), + GetSourceSSARegisterStacks<LLIL_REG_STACK_PHI>(), *this); case LLIL_FLAG_PHI: return dest->FlagPhi(GetDestSSAFlag<LLIL_FLAG_PHI>(), GetSourceSSAFlags<LLIL_FLAG_PHI>(), *this); case LLIL_MEM_PHI: @@ -1356,6 +2093,8 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Const(size, GetConstant<LLIL_CONST>(), *this); case LLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant<LLIL_CONST_PTR>(), *this); + case LLIL_FLOAT_CONST: + return dest->FloatConstRaw(size, GetConstant<LLIL_FLOAT_CONST>(), *this); case LLIL_POP: case LLIL_NORET: case LLIL_SYSCALL: @@ -1371,6 +2110,16 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_LOW_PART: case LLIL_BOOL_TO_INT: case LLIL_UNIMPL_MEM: + case LLIL_FSQRT: + case LLIL_FNEG: + case LLIL_FABS: + case LLIL_FLOAT_TO_INT: + case LLIL_INT_TO_FLOAT: + case LLIL_FLOAT_CONV: + case LLIL_ROUND_TO_INT: + case LLIL_FLOOR: + case LLIL_CEIL: + case LLIL_FTRUNC: return dest->AddExprWithLocation(operation, *this, size, flags, subExprHandler(AsOneOperand().GetSourceExpr())); case LLIL_ADD: @@ -1390,6 +2139,10 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_DIVS: case LLIL_MODU: case LLIL_MODS: + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: case LLIL_CMP_E: case LLIL_CMP_NE: case LLIL_CMP_SLT: @@ -1402,6 +2155,18 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_CMP_UGT: case LLIL_TEST_BIT: case LLIL_ADD_OVERFLOW: + case LLIL_FADD: + case LLIL_FSUB: + case LLIL_FMUL: + case LLIL_FDIV: + case LLIL_FCMP_E: + case LLIL_FCMP_NE: + case LLIL_FCMP_LT: + case LLIL_FCMP_LE: + case LLIL_FCMP_GE: + case LLIL_FCMP_GT: + case LLIL_FCMP_O: + case LLIL_FCMP_UO: return dest->AddExprWithLocation(operation, *this, size, flags, subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); case LLIL_ADC: @@ -1412,14 +2177,16 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); - case LLIL_DIVU_DP: - case LLIL_DIVS_DP: - case LLIL_MODU_DP: - case LLIL_MODS_DP: - return dest->AddExprWithLocation(operation, *this, size, flags, - subExprHandler(AsDoublePrecision().GetHighExpr()), - subExprHandler(AsDoublePrecision().GetLowExpr()), - subExprHandler(AsDoublePrecision().GetRightExpr())); + case LLIL_INTRINSIC: + for (auto& i : GetParameterExprs<LLIL_INTRINSIC>()) + params.push_back(subExprHandler(i)); + return dest->Intrinsic(GetOutputRegisterOrFlagList<LLIL_INTRINSIC>(), GetIntrinsic<LLIL_INTRINSIC>(), + params, flags, *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(); } @@ -1457,6 +2224,15 @@ uint32_t LowLevelILInstruction::GetSourceRegister() const } +uint32_t LowLevelILInstruction::GetSourceRegisterStack() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceRegisterStackLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + uint32_t LowLevelILInstruction::GetSourceFlag() const { size_t operandIndex; @@ -1475,6 +2251,17 @@ SSARegister LowLevelILInstruction::GetSourceSSARegister() const } +SSARegisterStack LowLevelILInstruction::GetSourceSSARegisterStack() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(PartialSSARegisterStackSourceLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0); + if (GetOperandIndexForUsage(SourceSSARegisterStackLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterStack(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + SSAFlag LowLevelILInstruction::GetSourceSSAFlag() const { size_t operandIndex; @@ -1502,6 +2289,15 @@ uint32_t LowLevelILInstruction::GetDestRegister() const } +uint32_t LowLevelILInstruction::GetDestRegisterStack() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestRegisterStackLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + uint32_t LowLevelILInstruction::GetDestFlag() const { size_t operandIndex; @@ -1520,6 +2316,15 @@ SSARegister LowLevelILInstruction::GetDestSSARegister() const } +SSARegisterStack LowLevelILInstruction::GetDestSSARegisterStack() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSARegisterStackLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterStack(0); + throw LowLevelILInstructionAccessException(); +} + + SSAFlag LowLevelILInstruction::GetDestSSAFlag() const { size_t operandIndex; @@ -1529,64 +2334,73 @@ SSAFlag LowLevelILInstruction::GetDestSSAFlag() const } -uint32_t LowLevelILInstruction::GetPartialRegister() const +uint32_t LowLevelILInstruction::GetSemanticFlagClass() const { size_t operandIndex; - if (GetOperandIndexForUsage(PartialRegisterLowLevelOperandUsage, operandIndex)) + if (GetOperandIndexForUsage(SemanticFlagClassLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegister(operandIndex); throw LowLevelILInstructionAccessException(); } -SSARegister LowLevelILInstruction::GetStackSSARegister() const +uint32_t LowLevelILInstruction::GetSemanticFlagGroup() const { size_t operandIndex; - if (GetOperandIndexForUsage(StackSSARegisterLowLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + if (GetOperandIndexForUsage(SemanticFlagGroupLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); throw LowLevelILInstructionAccessException(); } -LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const +uint32_t LowLevelILInstruction::GetPartialRegister() const { size_t operandIndex; - if (GetOperandIndexForUsage(LeftExprLowLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex); + if (GetOperandIndexForUsage(PartialRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); throw LowLevelILInstructionAccessException(); } -LowLevelILInstruction LowLevelILInstruction::GetRightExpr() const +SSARegister LowLevelILInstruction::GetStackSSARegister() const { size_t operandIndex; - if (GetOperandIndexForUsage(RightExprLowLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex); + if (GetOperandIndexForUsage(StackSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); throw LowLevelILInstructionAccessException(); } -LowLevelILInstruction LowLevelILInstruction::GetCarryExpr() const +SSARegister LowLevelILInstruction::GetTopSSARegister() const { size_t operandIndex; - if (GetOperandIndexForUsage(CarryExprLowLevelOperandUsage, operandIndex)) + if (GetOperandIndexForUsage(TopSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex); throw LowLevelILInstructionAccessException(); } -LowLevelILInstruction LowLevelILInstruction::GetHighExpr() const +LowLevelILInstruction LowLevelILInstruction::GetRightExpr() const { size_t operandIndex; - if (GetOperandIndexForUsage(HighExprLowLevelOperandUsage, operandIndex)) + if (GetOperandIndexForUsage(RightExprLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex); throw LowLevelILInstructionAccessException(); } -LowLevelILInstruction LowLevelILInstruction::GetLowExpr() const +LowLevelILInstruction LowLevelILInstruction::GetCarryExpr() const { size_t operandIndex; - if (GetOperandIndexForUsage(LowExprLowLevelOperandUsage, operandIndex)) + if (GetOperandIndexForUsage(CarryExprLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex); throw LowLevelILInstructionAccessException(); } @@ -1637,6 +2451,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; @@ -1740,11 +2563,11 @@ LowLevelILSSARegisterList LowLevelILInstruction::GetOutputSSARegisters() const } -LowLevelILSSARegisterList LowLevelILInstruction::GetParameterSSARegisters() const +LowLevelILInstructionList LowLevelILInstruction::GetParameterExprs() const { size_t operandIndex; - if (GetOperandIndexForUsage(ParameterSSARegistersLowLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(0); + if (GetOperandIndexForUsage(ParameterExprsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsExprList(0); throw LowLevelILInstructionAccessException(); } @@ -1758,6 +2581,15 @@ LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const } +LowLevelILSSARegisterStackList LowLevelILInstruction::GetSourceSSARegisterStacks() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegisterStacksLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterStackList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const { size_t operandIndex; @@ -1767,6 +2599,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; @@ -1785,6 +2635,15 @@ LowLevelILIndexList LowLevelILInstruction::GetTargetList() const } +map<uint32_t, int32_t> LowLevelILInstruction::GetRegisterStackAdjustments() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RegisterStackAdjustmentsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegisterStackAdjustments(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + ExprId LowLevelILFunction::Nop(const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_NOP, loc, 0, 0); @@ -1828,6 +2687,39 @@ ExprId LowLevelILFunction::SetRegisterSplitSSA(size_t size, const SSARegister& h } +ExprId LowLevelILFunction::SetRegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, + ExprId val, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_STACK_REL, loc, size, flags, regStack, entry, val); +} + + +ExprId LowLevelILFunction::RegisterStackPush(size_t size, uint32_t regStack, ExprId val, + uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_PUSH, loc, size, flags, regStack, val); +} + + +ExprId LowLevelILFunction::SetRegisterStackTopRelativeSSA(size_t size, uint32_t regStack, + size_t destVersion, size_t srcVersion, ExprId entry, const SSARegister& top, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_STACK_REL_SSA, loc, size, 0, + AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion), + entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version), val); +} + + +ExprId LowLevelILFunction::SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack, + size_t destVersion, size_t srcVersion, uint32_t reg, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_STACK_ABS_SSA, loc, size, 0, + AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion), + reg, val); +} + + ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SET_FLAG, loc, 0, 0, flag, val); @@ -1899,6 +2791,77 @@ ExprId LowLevelILFunction::RegisterSSAPartial(size_t size, const SSARegister& fu } +ExprId LowLevelILFunction::RegisterSplit(size_t size, uint32_t high, uint32_t low, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SPLIT, loc, size, 0, high, low); +} + + +ExprId LowLevelILFunction::RegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SPLIT_SSA, loc, size, 0, high.reg, high.version, low.reg, low.version); +} + + +ExprId LowLevelILFunction::RegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_REL, loc, size, 0, regStack, entry); +} + + +ExprId LowLevelILFunction::RegisterStackPop(size_t size, uint32_t regStack, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_POP, loc, size, flags, regStack); +} + + +ExprId LowLevelILFunction::RegisterStackFreeReg(uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_FREE_REG, loc, 0, 0, reg); +} + + +ExprId LowLevelILFunction::RegisterStackFreeTopRelative(uint32_t regStack, ExprId entry, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_FREE_REG, loc, 0, 0, regStack, entry); +} + + +ExprId LowLevelILFunction::RegisterStackTopRelativeSSA(size_t size, const SSARegisterStack& regStack, ExprId entry, + const SSARegister& top, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_REL_SSA, loc, size, 0, regStack.regStack, regStack.version, entry, + AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version)); +} + + +ExprId LowLevelILFunction::RegisterStackAbsoluteSSA(size_t size, const SSARegisterStack& regStack, uint32_t reg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_ABS_SSA, loc, size, 0, regStack.regStack, regStack.version, reg); +} + + +ExprId LowLevelILFunction::RegisterStackFreeTopRelativeSSA(uint32_t regStack, + size_t destVersion, size_t srcVersion, ExprId entry, const SSARegister& top, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_FREE_REL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, 0, 0, regStack, destVersion, srcVersion), + entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version)); +} + + +ExprId LowLevelILFunction::RegisterStackFreeAbsoluteSSA(uint32_t regStack, + size_t destVersion, size_t srcVersion, uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_FREE_ABS_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, 0, 0, regStack, destVersion, srcVersion), reg); +} + + ExprId LowLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_CONST, loc, size, 0, val); @@ -1911,6 +2874,36 @@ ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourc } +ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLOAT_CONST, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc) +{ + union + { + float f; + uint32_t i; + } bits; + bits.f = val; + return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 4, 0, bits.i); +} + + +ExprId LowLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc) +{ + union + { + double f; + uint64_t i; + } bits; + bits.f = val; + return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 8, 0, bits.i); +} + + ExprId LowLevelILFunction::Flag(uint32_t flag, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLAG, loc, 0, 0, flag); @@ -2054,10 +3047,10 @@ ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t } -ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, +ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, high, low, div); + return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, a, b); } @@ -2067,10 +3060,10 @@ ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t f } -ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, +ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, high, low, div); + return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, a, b); } @@ -2081,10 +3074,10 @@ ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t } -ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, +ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, high, low, div); + return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, a, b); } @@ -2094,10 +3087,10 @@ ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t f } -ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, +ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, high, low, div); + return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, a, b); } @@ -2150,33 +3143,41 @@ ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) } -ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc) +ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, + const std::map<uint32_t, int32_t>& regStackAdjust, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust); + vector<size_t> list; + for (auto& i : regStackAdjust) + { + list.push_back(i.first); + list.push_back(i.second); + } + return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust, list.size(), + AddIndexList(list)); } -ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<SSARegister>& params, +ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<ExprId>& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_CALL_SSA, loc, 0, 0, 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, - params.size() * 2, AddSSARegisterList(params))); + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, + params.size(), AddOperandList(params))); } -ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<SSARegister>& params, +ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<ExprId>& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SYSCALL_SSA, loc, 0, 0, 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, - params.size() * 2, AddSSARegisterList(params))); + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, + params.size(), AddOperandList(params))); } @@ -2192,9 +3193,15 @@ ExprId LowLevelILFunction::NoReturn(const ILSourceLocation& loc) } -ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc) +ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond); + return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond, semClass); +} + + +ExprId LowLevelILFunction::FlagGroup(uint32_t semGroup, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_GROUP, loc, 0, 0, semGroup); } @@ -2276,6 +3283,24 @@ ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) } +ExprId LowLevelILFunction::Intrinsic(const vector<RegisterOrFlag>& outputs, uint32_t intrinsic, + const vector<ExprId>& params, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_INTRINSIC, loc, 0, flags, + 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); @@ -2314,6 +3339,14 @@ ExprId LowLevelILFunction::RegisterPhi(const SSARegister& dest, const vector<SSA } +ExprId LowLevelILFunction::RegisterStackPhi(const SSARegisterStack& dest, const vector<SSARegisterStack>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_STACK_PHI, loc, 0, 0, dest.regStack, dest.version, + sources.size() * 2, AddSSARegisterStackList(sources)); +} + + ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector<SSAFlag>& sources, const ILSourceLocation& loc) { @@ -2326,3 +3359,135 @@ ExprId LowLevelILFunction::MemoryPhi(size_t dest, const vector<size_t>& sources, { return AddExprWithLocation(LLIL_MEM_PHI, loc, 0, 0, dest, sources.size(), AddIndexList(sources)); } + + +ExprId LowLevelILFunction::FloatAdd(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FADD, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::FloatSub(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FSUB, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::FloatMult(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FMUL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::FloatDiv(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FDIV, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::FloatSqrt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FSQRT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatNeg(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FNEG, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatAbs(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FABS, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatToInt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLOAT_TO_INT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::IntToFloat(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_INT_TO_FLOAT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatConvert(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLOAT_CONV, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::RoundToInt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROUND_TO_INT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Floor(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLOOR, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Ceil(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CEIL, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatTrunc(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FTRUNC, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_E, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_NE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_LT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_LE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_GE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_GT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_O, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_UO, loc, size, 0, a, b); +} diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 169c7a60..675baa3c 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -49,12 +49,36 @@ namespace BinaryNinja struct LowLevelILOneOperandInstruction; struct LowLevelILTwoOperandInstruction; struct LowLevelILTwoOperandWithCarryInstruction; - struct LowLevelILDoublePrecisionInstruction; struct LowLevelILLabel; struct MediumLevelILInstruction; 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; @@ -70,6 +94,21 @@ namespace BinaryNinja bool operator<(const SSARegister& v) const; }; + struct SSARegisterStack + { + uint32_t regStack; + size_t version; + + SSARegisterStack(); + SSARegisterStack(uint32_t r, size_t i); + SSARegisterStack(const SSARegisterStack& v); + + SSARegisterStack& operator=(const SSARegisterStack& v); + bool operator==(const SSARegisterStack& v) const; + bool operator!=(const SSARegisterStack& v) const; + bool operator<(const SSARegisterStack& v) const; + }; + struct SSAFlag { uint32_t flag; @@ -85,46 +124,80 @@ 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, IndexLowLevelOperand, ExprLowLevelOperand, RegisterLowLevelOperand, + RegisterStackLowLevelOperand, FlagLowLevelOperand, FlagConditionLowLevelOperand, + IntrinsicLowLevelOperand, + SemanticFlagClassLowLevelOperand, + SemanticFlagGroupLowLevelOperand, SSARegisterLowLevelOperand, + SSARegisterStackLowLevelOperand, SSAFlagLowLevelOperand, IndexListLowLevelOperand, + ExprListLowLevelOperand, + RegisterOrFlagListLowLevelOperand, SSARegisterListLowLevelOperand, - SSAFlagListLowLevelOperand + SSARegisterStackListLowLevelOperand, + SSAFlagListLowLevelOperand, + SSARegisterOrFlagListLowLevelOperand, + RegisterStackAdjustmentsLowLevelOperand }; enum LowLevelILOperandUsage { SourceExprLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage, + SourceRegisterStackLowLevelOperandUsage, SourceFlagLowLevelOperandUsage, SourceSSARegisterLowLevelOperandUsage, + SourceSSARegisterStackLowLevelOperandUsage, SourceSSAFlagLowLevelOperandUsage, DestExprLowLevelOperandUsage, DestRegisterLowLevelOperandUsage, + DestRegisterStackLowLevelOperandUsage, DestFlagLowLevelOperandUsage, DestSSARegisterLowLevelOperandUsage, + DestSSARegisterStackLowLevelOperandUsage, DestSSAFlagLowLevelOperandUsage, + SemanticFlagClassLowLevelOperandUsage, + SemanticFlagGroupLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, + PartialSSARegisterStackSourceLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, + TopSSARegisterLowLevelOperandUsage, LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage, - HighExprLowLevelOperandUsage, - LowExprLowLevelOperandUsage, ConditionExprLowLevelOperandUsage, HighRegisterLowLevelOperandUsage, HighSSARegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, + IntrinsicLowLevelOperandUsage, ConstantLowLevelOperandUsage, VectorLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, @@ -137,11 +210,15 @@ namespace BinaryNinja FlagConditionLowLevelOperandUsage, OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, - ParameterSSARegistersLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage, + SourceSSARegisterStacksLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage, + OutputRegisterOrFlagListLowLevelOperandUsage, + OutputSSARegisterOrFlagListLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage, - TargetListLowLevelOperandUsage + TargetListLowLevelOperandUsage, + RegisterStackAdjustmentsLowLevelOperandUsage }; } @@ -166,6 +243,24 @@ namespace std }; #ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSARegisterStack> +#else + template<> struct hash<BinaryNinja::SSARegisterStack> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegisterStack argument_type; +#else + typedef BinaryNinja::SSARegisterStack argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.regStack) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY template<> struct hash<BinaryNinjaCore::SSAFlag> #else template<> struct hash<BinaryNinja::SSAFlag> @@ -288,6 +383,63 @@ namespace BinaryNinja operator std::vector<size_t>() const; }; + class LowLevelILInstructionList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + size_t instructionIndex; + 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 LowLevelILInstruction operator*(); + }; + + LowLevelILIntegerList m_list; + size_t m_instructionIndex; + + public: + typedef ListIterator const_iterator; + + LowLevelILInstructionList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t count, size_t instrIndex); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILInstruction operator[](size_t i) const; + + 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 @@ -315,6 +467,33 @@ namespace BinaryNinja operator std::vector<SSARegister>() const; }; + class LowLevelILSSARegisterStackList + { + 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 SSARegisterStack operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterStackList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegisterStack operator[](size_t i) const; + + operator std::vector<SSARegisterStack>() const; + }; + class LowLevelILSSAFlagList { struct ListIterator @@ -342,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 @@ -365,13 +571,21 @@ namespace BinaryNinja BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSARegisterStack GetRawOperandAsSSARegisterStack(size_t operand) const; + SSARegisterStack GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const; 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; @@ -428,10 +642,6 @@ namespace BinaryNinja { return *(LowLevelILTwoOperandWithCarryInstruction*)this; } - LowLevelILDoublePrecisionInstruction& AsDoublePrecision() - { - return *(LowLevelILDoublePrecisionInstruction*)this; - } template <BNLowLevelILOperation N> const LowLevelILInstructionAccessor<N>& As() const @@ -456,10 +666,6 @@ namespace BinaryNinja { return *(const LowLevelILTwoOperandWithCarryInstruction*)this; } - const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const - { - return *(const LowLevelILDoublePrecisionInstruction*)this; - } }; struct LowLevelILInstruction: public LowLevelILInstructionBase @@ -478,26 +684,32 @@ namespace BinaryNinja // Templated accessors for instruction operands, use these for efficient access to a known instruction template <BNLowLevelILOperation N> LowLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } template <BNLowLevelILOperation N> uint32_t GetSourceRegister() const { return As<N>().GetSourceRegister(); } + template <BNLowLevelILOperation N> uint32_t GetSourceRegisterStack() const { return As<N>().GetSourceRegisterStack(); } template <BNLowLevelILOperation N> uint32_t GetSourceFlag() const { return As<N>().GetSourceFlag(); } template <BNLowLevelILOperation N> SSARegister GetSourceSSARegister() const { return As<N>().GetSourceSSARegister(); } + template <BNLowLevelILOperation N> SSARegisterStack GetSourceSSARegisterStack() const { return As<N>().GetSourceSSARegisterStack(); } template <BNLowLevelILOperation N> SSAFlag GetSourceSSAFlag() const { return As<N>().GetSourceSSAFlag(); } template <BNLowLevelILOperation N> LowLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } template <BNLowLevelILOperation N> uint32_t GetDestRegister() const { return As<N>().GetDestRegister(); } + template <BNLowLevelILOperation N> uint32_t GetDestRegisterStack() const { return As<N>().GetDestRegisterStack(); } template <BNLowLevelILOperation N> uint32_t GetDestFlag() const { return As<N>().GetDestFlag(); } template <BNLowLevelILOperation N> SSARegister GetDestSSARegister() const { return As<N>().GetDestSSARegister(); } + template <BNLowLevelILOperation N> SSARegisterStack GetDestSSARegisterStack() const { return As<N>().GetDestSSARegisterStack(); } template <BNLowLevelILOperation N> SSAFlag GetDestSSAFlag() const { return As<N>().GetDestSSAFlag(); } + template <BNLowLevelILOperation N> uint32_t GetSemanticFlagClass() const { return As<N>().GetSemanticFlagClass(); } + template <BNLowLevelILOperation N> uint32_t GetSemanticFlagGroup() const { return As<N>().GetSemanticFlagGroup(); } template <BNLowLevelILOperation N> uint32_t GetPartialRegister() const { return As<N>().GetPartialRegister(); } template <BNLowLevelILOperation N> SSARegister GetStackSSARegister() const { return As<N>().GetStackSSARegister(); } + template <BNLowLevelILOperation N> SSARegister GetTopSSARegister() const { return As<N>().GetTopSSARegister(); } template <BNLowLevelILOperation N> LowLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } template <BNLowLevelILOperation N> LowLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } template <BNLowLevelILOperation N> LowLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } - template <BNLowLevelILOperation N> LowLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } - template <BNLowLevelILOperation N> LowLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } template <BNLowLevelILOperation N> LowLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } template <BNLowLevelILOperation N> uint32_t GetHighRegister() const { return As<N>().GetHighRegister(); } 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(); } @@ -509,21 +721,26 @@ namespace BinaryNinja template <BNLowLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } template <BNLowLevelILOperation N> BNLowLevelILFlagCondition GetFlagCondition() const { return As<N>().GetFlagCondition(); } template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetOutputSSARegisters() const { return As<N>().GetOutputSSARegisters(); } - template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetParameterSSARegisters() const { return As<N>().GetParameterSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); } 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(); } template <BNLowLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } template <BNLowLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); } template <BNLowLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); } template <BNLowLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); } template <BNLowLevelILOperation N> void SetStackSSAVersion(size_t version) { As<N>().SetStackSSAVersion(version); } + template <BNLowLevelILOperation N> void SetTopSSAVersion(size_t version) { As<N>().SetTopSSAVersion(version); } 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 SetParameterSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetParameterSSARegisters(regs); } + template <BNLowLevelILOperation N> void SetOutputSSARegisterOrFlagList(const std::vector<SSARegisterOrFlag>& outputs) { As<N>().SetOutputSSARegisterOrFlagList(outputs); } bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; @@ -531,26 +748,32 @@ namespace BinaryNinja // on type mismatch. These are slower than the templated versions above. LowLevelILInstruction GetSourceExpr() const; uint32_t GetSourceRegister() const; + uint32_t GetSourceRegisterStack() const; uint32_t GetSourceFlag() const; SSARegister GetSourceSSARegister() const; + SSARegisterStack GetSourceSSARegisterStack() const; SSAFlag GetSourceSSAFlag() const; LowLevelILInstruction GetDestExpr() const; uint32_t GetDestRegister() const; + uint32_t GetDestRegisterStack() const; uint32_t GetDestFlag() const; SSARegister GetDestSSARegister() const; + SSARegisterStack GetDestSSARegisterStack() const; SSAFlag GetDestSSAFlag() const; + uint32_t GetSemanticFlagClass() const; + uint32_t GetSemanticFlagGroup() const; uint32_t GetPartialRegister() const; SSARegister GetStackSSARegister() const; + SSARegister GetTopSSARegister() const; LowLevelILInstruction GetLeftExpr() const; LowLevelILInstruction GetRightExpr() const; LowLevelILInstruction GetCarryExpr() const; - LowLevelILInstruction GetHighExpr() const; - LowLevelILInstruction GetLowExpr() const; LowLevelILInstruction GetConditionExpr() const; uint32_t GetHighRegister() const; 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; @@ -562,11 +785,15 @@ namespace BinaryNinja size_t GetDestMemoryVersion() const; BNLowLevelILFlagCondition GetFlagCondition() const; LowLevelILSSARegisterList GetOutputSSARegisters() const; - LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILInstructionList GetParameterExprs() const; 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; }; class LowLevelILOperand @@ -587,13 +814,23 @@ namespace BinaryNinja size_t GetIndex() const; LowLevelILInstruction GetExpr() const; uint32_t GetRegister() const; + uint32_t GetRegisterStack() const; 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; SSAFlag GetSSAFlag() const; LowLevelILIndexList GetIndexList() const; + LowLevelILInstructionList GetExprList() const; LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSARegisterStackList GetSSARegisterStackList() const; LowLevelILSSAFlagList GetSSAFlagList() const; + LowLevelILRegisterOrFlagList GetRegisterOrFlagList() const; + LowLevelILSSARegisterOrFlagList GetSSARegisterOrFlagList() const; + std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const; }; class LowLevelILOperandList @@ -651,13 +888,6 @@ namespace BinaryNinja LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } }; - struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase - { - LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } - LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } - LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } - }; - // Implementations of each instruction to fetch the correct operand value for the valid operands, these // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate // a compiler error. @@ -693,6 +923,37 @@ namespace BinaryNinja void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_REL>: public LowLevelILInstructionBase + { + uint32_t GetDestRegisterStack() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_PUSH>: public LowLevelILInstructionBase + { + uint32_t GetDestRegisterStack() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_REL_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); } + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetTopSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); } + void SetTopSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_ABS_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); } + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); } + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); } + }; template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG>: public LowLevelILInstructionBase { uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } @@ -743,6 +1004,56 @@ namespace BinaryNinja uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_REL>: public LowLevelILInstructionBase + { + uint32_t GetSourceRegisterStack() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_POP>: public LowLevelILInstructionBase + { + uint32_t GetSourceRegisterStack() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_FREE_REG>: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_FREE_REL>: public LowLevelILInstructionBase + { + uint32_t GetDestRegisterStack() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_REL_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + SSARegister GetTopSSARegister() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetTopSSAVersion(size_t version) { GetRawOperandAsExpr(3).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_ABS_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); } + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_FREE_REL_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); } + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetTopSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); } + void SetTopSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_FREE_ABS_SSA>: public LowLevelILInstructionBase + { + SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); } + SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); } + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(1); } + void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); } + }; template <> struct LowLevelILInstructionAccessor<LLIL_FLAG>: public LowLevelILInstructionBase { uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } @@ -764,6 +1075,19 @@ namespace BinaryNinja void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SPLIT>: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SPLIT_SSA>: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsSSARegister(2); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_JUMP>: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } @@ -781,6 +1105,7 @@ namespace BinaryNinja { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } + std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const { return GetRawOperandAsRegisterStackAdjustments(2); } }; template <> struct LowLevelILInstructionAccessor<LLIL_RET>: public LowLevelILInstructionBase { @@ -801,6 +1126,11 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_COND>: public LowLevelILInstructionBase { BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + uint32_t GetSemanticFlagClass() const { return GetRawOperandAsRegister(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_GROUP>: public LowLevelILInstructionBase + { + uint32_t GetSemanticFlagGroup() const { return GetRawOperandAsRegister(0); } }; template <> struct LowLevelILInstructionAccessor<LLIL_TRAP>: public LowLevelILInstructionBase @@ -815,12 +1145,11 @@ namespace BinaryNinja LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } - LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } + LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } - void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } }; template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL_SSA>: public LowLevelILInstructionBase { @@ -828,12 +1157,25 @@ namespace BinaryNinja size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } - LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } - void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, 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 @@ -841,6 +1183,11 @@ namespace BinaryNinja SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_PHI>: public LowLevelILInstructionBase + { + SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); } + LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const { return GetRawOperandAsSSARegisterStackList(2); } + }; template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_PHI>: public LowLevelILInstructionBase { SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } @@ -862,6 +1209,7 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_CONST>: public LowLevelILConstantInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_CONST_PTR>: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FLOAT_CONST>: public LowLevelILConstantInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_ADD>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_SUB>: public LowLevelILTwoOperandInstruction {}; @@ -880,6 +1228,10 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_DIVS>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_MODU>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_MODS>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVU_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVS_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODU_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODS_DP>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_CMP_E>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_CMP_NE>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SLT>: public LowLevelILTwoOperandInstruction {}; @@ -892,17 +1244,24 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_CMP_UGT>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_TEST_BIT>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_ADD_OVERFLOW>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FADD>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FSUB>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FMUL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FDIV>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_E>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_NE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_LT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_LE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_GE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_GT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_O>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FCMP_UO>: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_ADC>: public LowLevelILTwoOperandWithCarryInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_SBB>: public LowLevelILTwoOperandWithCarryInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_RLC>: public LowLevelILTwoOperandWithCarryInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_RRC>: public LowLevelILTwoOperandWithCarryInstruction {}; - template <> struct LowLevelILInstructionAccessor<LLIL_DIVU_DP>: public LowLevelILDoublePrecisionInstruction {}; - template <> struct LowLevelILInstructionAccessor<LLIL_DIVS_DP>: public LowLevelILDoublePrecisionInstruction {}; - template <> struct LowLevelILInstructionAccessor<LLIL_MODU_DP>: public LowLevelILDoublePrecisionInstruction {}; - template <> struct LowLevelILInstructionAccessor<LLIL_MODS_DP>: public LowLevelILDoublePrecisionInstruction {}; - template <> struct LowLevelILInstructionAccessor<LLIL_PUSH>: public LowLevelILOneOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_NEG>: public LowLevelILOneOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_NOT>: public LowLevelILOneOperandInstruction {}; @@ -911,4 +1270,14 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_LOW_PART>: public LowLevelILOneOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_BOOL_TO_INT>: public LowLevelILOneOperandInstruction {}; template <> struct LowLevelILInstructionAccessor<LLIL_UNIMPL_MEM>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FSQRT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FNEG>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FABS>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FLOAT_TO_INT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_INT_TO_FLOAT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FLOAT_CONV>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ROUND_TO_INT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FLOOR>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CEIL>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_FTRUNC>: public LowLevelILOneOperandInstruction {}; } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 2cd5a233..0a28bd49 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -157,6 +157,7 @@ vector<uint64_t> MediumLevelILFunction::GetOperandList(ExprId expr, size_t listO size_t count; uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count); vector<uint64_t> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(operands[i]); BNMediumLevelILFreeOperandList(operands); @@ -338,11 +339,10 @@ bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector< return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -359,11 +359,10 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -396,6 +395,7 @@ vector<Ref<BasicBlock>> MediumLevelILFunction::GetBasicBlocks() const BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count); vector<Ref<BasicBlock>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -680,6 +680,7 @@ unordered_map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchD BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); unordered_map<size_t, BNILBranchDependence> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index ec6aa1c6..fa66f553 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -45,8 +45,6 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> {LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, {RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, {CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {HighExprMediumLevelOperandUsage, ExprMediumLevelOperand}, - {LowExprMediumLevelOperandUsage, ExprMediumLevelOperand}, {StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, {ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, {HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, @@ -56,6 +54,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand}, {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, @@ -66,6 +65,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, @@ -112,10 +112,12 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> SourceExprMediumLevelOperandUsage}}, {MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, {MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage}}, {MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, {MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, {MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, {MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage}}, {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, @@ -127,28 +129,35 @@ 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_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, + {MLIL_FREE_VAR_SLOT_SSA, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage}}, {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_FLOAT_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, @@ -187,32 +196,50 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> CarryExprMediumLevelOperandUsage}}, {MLIL_RRC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage}}, - {MLIL_DIVU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, - RightExprMediumLevelOperandUsage}}, - {MLIL_DIVS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, - RightExprMediumLevelOperandUsage}}, - {MLIL_MODU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, - RightExprMediumLevelOperandUsage}}, - {MLIL_MODS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, - RightExprMediumLevelOperandUsage}}, + {MLIL_DIVU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, {MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, {MLIL_SX, {SourceExprMediumLevelOperandUsage}}, {MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, {MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, {MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, - {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}} + {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FSUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FMUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FDIV, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FSQRT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FNEG, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FABS, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FLOAT_TO_INT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_INT_TO_FLOAT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FLOAT_CONV, {SourceExprMediumLevelOperandUsage}}, + {MLIL_ROUND_TO_INT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FLOOR, {SourceExprMediumLevelOperandUsage}}, + {MLIL_CEIL, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FTRUNC, {SourceExprMediumLevelOperandUsage}}, + {MLIL_FCMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_LT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_LE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_GE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_GT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_O, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_FCMP_UO, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}} }; -static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> - GetOperandIndexForOperandUsages() +static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> GetOperandIndexForOperandUsages() { unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> result; + result.reserve(MediumLevelILInstructionBase::operationOperandUsage.size()); for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) { result[operation.first] = unordered_map<MediumLevelILOperandUsage, size_t>(); - + result[operation.first].reserve(operation.second.size()); size_t operand = 0; for (auto usage : operation.second) { @@ -229,7 +256,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: @@ -667,6 +694,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) @@ -716,7 +751,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); @@ -1266,6 +1301,16 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL case MLIL_LOAD_STRUCT: case MLIL_LOAD_SSA: case MLIL_LOAD_STRUCT_SSA: + case MLIL_FSQRT: + case MLIL_FNEG: + case MLIL_FABS: + case MLIL_FLOAT_TO_INT: + case MLIL_INT_TO_FLOAT: + case MLIL_FLOAT_CONV: + case MLIL_ROUND_TO_INT: + case MLIL_FLOOR: + case MLIL_CEIL: + case MLIL_FTRUNC: AsOneOperand().GetSourceExpr().VisitExprs(func); break; case MLIL_ADD: @@ -1285,6 +1330,10 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL case MLIL_DIVS: case MLIL_MODU: case MLIL_MODS: + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: case MLIL_CMP_E: case MLIL_CMP_NE: case MLIL_CMP_SLT: @@ -1297,6 +1346,18 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL case MLIL_CMP_UGT: case MLIL_TEST_BIT: case MLIL_ADD_OVERFLOW: + case MLIL_FADD: + case MLIL_FSUB: + case MLIL_FMUL: + case MLIL_FDIV: + case MLIL_FCMP_E: + case MLIL_FCMP_NE: + case MLIL_FCMP_LT: + case MLIL_FCMP_LE: + case MLIL_FCMP_GE: + case MLIL_FCMP_GT: + case MLIL_FCMP_O: + case MLIL_FCMP_UO: AsTwoOperand().GetLeftExpr().VisitExprs(func); AsTwoOperand().GetRightExpr().VisitExprs(func); break; @@ -1308,13 +1369,13 @@ void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumL AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); break; - case MLIL_DIVU_DP: - case MLIL_DIVS_DP: - case MLIL_MODU_DP: - case MLIL_MODS_DP: - AsDoublePrecision().GetHighExpr().VisitExprs(func); - AsDoublePrecision().GetLowExpr().VisitExprs(func); - AsDoublePrecision().GetRightExpr().VisitExprs(func); + 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; @@ -1380,6 +1441,9 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_VAR_FIELD: return dest->VarField(size, GetSourceVariable<MLIL_VAR_FIELD>(), GetOffset<MLIL_VAR_FIELD>(), *this); + case MLIL_VAR_SPLIT: + return dest->VarSplit(size, GetHighVariable<MLIL_VAR_SPLIT>(), + GetLowVariable<MLIL_VAR_SPLIT>(), *this); case MLIL_VAR_SSA: return dest->VarSSA(size, GetSourceSSAVariable<MLIL_VAR_SSA>(), *this); case MLIL_VAR_SSA_FIELD: @@ -1392,6 +1456,9 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->VarAliasedField(size, GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().var, GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().version, GetOffset<MLIL_VAR_ALIASED_FIELD>(), *this); + case MLIL_VAR_SPLIT_SSA: + return dest->VarSplitSSA(size, GetHighSSAVariable<MLIL_VAR_SPLIT_SSA>(), + GetLowSSAVariable<MLIL_VAR_SPLIT_SSA>(), *this); case MLIL_ADDRESS_OF: return dest->AddressOf(GetSourceVariable<MLIL_ADDRESS_OF>(), *this); case MLIL_ADDRESS_OF_FIELD: @@ -1477,6 +1544,16 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_BOOL_TO_INT: case MLIL_JUMP: case MLIL_UNIMPL_MEM: + case MLIL_FSQRT: + case MLIL_FNEG: + case MLIL_FABS: + case MLIL_FLOAT_TO_INT: + case MLIL_INT_TO_FLOAT: + case MLIL_FLOAT_CONV: + case MLIL_ROUND_TO_INT: + case MLIL_FLOOR: + case MLIL_CEIL: + case MLIL_FTRUNC: return dest->AddExprWithLocation(operation, *this, size, subExprHandler(AsOneOperand().GetSourceExpr())); case MLIL_ADD: @@ -1496,6 +1573,10 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_DIVS: case MLIL_MODU: case MLIL_MODS: + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: case MLIL_CMP_E: case MLIL_CMP_NE: case MLIL_CMP_SLT: @@ -1508,6 +1589,18 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_CMP_UGT: case MLIL_TEST_BIT: case MLIL_ADD_OVERFLOW: + case MLIL_FADD: + case MLIL_FSUB: + case MLIL_FMUL: + case MLIL_FDIV: + case MLIL_FCMP_E: + case MLIL_FCMP_NE: + case MLIL_FCMP_LT: + case MLIL_FCMP_LE: + case MLIL_FCMP_GE: + case MLIL_FCMP_GT: + case MLIL_FCMP_O: + case MLIL_FCMP_UO: return dest->AddExprWithLocation(operation, *this, size, subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); case MLIL_ADC: @@ -1518,14 +1611,6 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); - case MLIL_DIVU_DP: - case MLIL_DIVS_DP: - case MLIL_MODU_DP: - case MLIL_MODS_DP: - return dest->AddExprWithLocation(operation, *this, size, - subExprHandler(AsDoublePrecision().GetHighExpr()), - subExprHandler(AsDoublePrecision().GetLowExpr()), - subExprHandler(AsDoublePrecision().GetRightExpr())); case MLIL_JUMP_TO: for (auto target : GetTargetList<MLIL_JUMP_TO>()) { @@ -1553,12 +1638,30 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->Const(size, GetConstant<MLIL_CONST>(), *this); case MLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant<MLIL_CONST_PTR>(), *this); + case MLIL_FLOAT_CONST: + return dest->FloatConstRaw(size, GetConstant<MLIL_FLOAT_CONST>(), *this); case MLIL_IMPORT: return dest->ImportedAddress(size, GetConstant<MLIL_IMPORT>(), *this); case MLIL_BP: 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_FREE_VAR_SLOT: + return dest->FreeVarSlot(GetDestVariable<MLIL_FREE_VAR_SLOT>(), *this); + case MLIL_FREE_VAR_SLOT_SSA: + return dest->FreeVarSlotSSA(GetDestSSAVariable<MLIL_FREE_VAR_SLOT_SSA>().var, + GetDestSSAVariable<MLIL_FREE_VAR_SLOT_SSA>().version, + GetSourceSSAVariable<MLIL_FREE_VAR_SLOT_SSA>().version, *this); case MLIL_UNDEF: return dest->Undefined(*this); case MLIL_UNIMPL: @@ -1665,24 +1768,6 @@ MediumLevelILInstruction MediumLevelILInstruction::GetCarryExpr() const } -MediumLevelILInstruction MediumLevelILInstruction::GetHighExpr() const -{ - size_t operandIndex; - if (GetOperandIndexForUsage(HighExprMediumLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex); - throw MediumLevelILInstructionAccessException(); -} - - -MediumLevelILInstruction MediumLevelILInstruction::GetLowExpr() const -{ - size_t operandIndex; - if (GetOperandIndexForUsage(LowExprMediumLevelOperandUsage, operandIndex)) - return GetRawOperandAsExpr(operandIndex); - throw MediumLevelILInstructionAccessException(); -} - - MediumLevelILInstruction MediumLevelILInstruction::GetStackExpr() const { size_t operandIndex; @@ -1764,6 +1849,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; @@ -1846,6 +1940,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(); } @@ -2036,6 +2132,13 @@ ExprId MediumLevelILFunction::VarField(size_t size, const Variable& src, uint64_ } +ExprId MediumLevelILFunction::VarSplit(size_t size, const Variable& high, const Variable& low, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SPLIT, loc, size, high.ToIdentifier(), low.ToIdentifier()); +} + + ExprId MediumLevelILFunction::VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc) { @@ -2064,6 +2167,14 @@ ExprId MediumLevelILFunction::VarAliasedField(size_t size, const Variable& src, } +ExprId MediumLevelILFunction::VarSplitSSA(size_t size, const SSAVariable& high, const SSAVariable& low, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SPLIT_SSA, loc, size, high.var.ToIdentifier(), high.version, + low.var.ToIdentifier(), low.version); +} + + ExprId MediumLevelILFunction::AddressOf(const Variable& var, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_ADDRESS_OF, loc, 0, var.ToIdentifier()); @@ -2089,6 +2200,36 @@ ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSo } +ExprId MediumLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FLOAT_CONST, loc, size, val); +} + + +ExprId MediumLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc) +{ + union + { + float f; + uint32_t i; + } bits; + bits.f = val; + return AddExprWithLocation(MLIL_FLOAT_CONST, loc, 4, bits.i); +} + + +ExprId MediumLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc) +{ + union + { + double f; + uint64_t i; + } bits; + bits.f = val; + return AddExprWithLocation(MLIL_FLOAT_CONST, loc, 8, bits.i); +} + + ExprId MediumLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_IMPORT, loc, size, val); @@ -2223,17 +2364,17 @@ ExprId MediumLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right } -ExprId MediumLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, +ExprId MediumLevelILFunction::DivDoublePrecSigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { - return AddExprWithLocation(MLIL_DIVS_DP, loc, size, high, low, right); + return AddExprWithLocation(MLIL_DIVS_DP, loc, size, left, right); } -ExprId MediumLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, +ExprId MediumLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { - return AddExprWithLocation(MLIL_DIVU_DP, loc, size, high, low, right); + return AddExprWithLocation(MLIL_DIVU_DP, loc, size, left, right); } @@ -2251,17 +2392,17 @@ ExprId MediumLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right } -ExprId MediumLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, +ExprId MediumLevelILFunction::ModDoublePrecSigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { - return AddExprWithLocation(MLIL_MODS_DP, loc, size, high, low, right); + return AddExprWithLocation(MLIL_MODS_DP, loc, size, left, right); } -ExprId MediumLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, +ExprId MediumLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { - return AddExprWithLocation(MLIL_MODU_DP, loc, size, high, low, right); + return AddExprWithLocation(MLIL_MODU_DP, loc, size, left, right); } @@ -2500,6 +2641,35 @@ 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::FreeVarSlot(const Variable& var, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FREE_VAR_SLOT, loc, 0, var.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::FreeVarSlotSSA(const Variable& var, size_t newVersion, size_t prevVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FREE_VAR_SLOT_SSA, loc, 0, var.ToIdentifier(), newVersion, prevVersion); +} + + ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_UNDEF, loc, 0); @@ -2533,3 +2703,135 @@ ExprId MediumLevelILFunction::MemoryPhi(size_t destMemVersion, const vector<size return AddExprWithLocation(MLIL_MEM_PHI, loc, 0, destMemVersion, sourceMemVersions.size(), AddIndexList(sourceMemVersions)); } + + +ExprId MediumLevelILFunction::FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FADD, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FSUB, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FMUL, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FDIV, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FSQRT, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FNEG, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FABS, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FLOAT_TO_INT, loc, size, a); +} + + +ExprId MediumLevelILFunction::IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_INT_TO_FLOAT, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FLOAT_CONV, loc, size, a); +} + + +ExprId MediumLevelILFunction::RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROUND_TO_INT, loc, size, a); +} + + +ExprId MediumLevelILFunction::Floor(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FLOOR, loc, size, a); +} + + +ExprId MediumLevelILFunction::Ceil(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CEIL, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FTRUNC, loc, size, a); +} + + +ExprId MediumLevelILFunction::FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_E, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_NE, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_LT, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_LE, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_GE, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_GT, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_O, loc, size, a, b); +} + + +ExprId MediumLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_UO, loc, size, a, b); +} diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 8bab199f..e3167585 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -70,6 +70,7 @@ namespace BinaryNinja { IntegerMediumLevelOperand, IndexMediumLevelOperand, + IntrinsicMediumLevelOperand, ExprMediumLevelOperand, VariableMediumLevelOperand, SSAVariableMediumLevelOperand, @@ -91,8 +92,6 @@ namespace BinaryNinja LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, CarryExprMediumLevelOperandUsage, - HighExprMediumLevelOperandUsage, - LowExprMediumLevelOperandUsage, StackExprMediumLevelOperandUsage, ConditionExprMediumLevelOperandUsage, HighVariableMediumLevelOperandUsage, @@ -102,6 +101,7 @@ namespace BinaryNinja OffsetMediumLevelOperandUsage, ConstantMediumLevelOperandUsage, VectorMediumLevelOperandUsage, + IntrinsicMediumLevelOperandUsage, TargetMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage, @@ -112,6 +112,7 @@ namespace BinaryNinja OutputVariablesMediumLevelOperandUsage, OutputVariablesSubExprMediumLevelOperandUsage, OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceExprsMediumLevelOperandUsage, @@ -429,10 +430,6 @@ namespace BinaryNinja { return *(MediumLevelILTwoOperandWithCarryInstruction*)this; } - MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() - { - return *(MediumLevelILDoublePrecisionInstruction*)this; - } template <BNMediumLevelILOperation N> const MediumLevelILInstructionAccessor<N>& As() const @@ -457,10 +454,6 @@ namespace BinaryNinja { return *(const MediumLevelILTwoOperandWithCarryInstruction*)this; } - const MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() const - { - return *(const MediumLevelILDoublePrecisionInstruction*)this; - } }; struct MediumLevelILInstruction: public MediumLevelILInstructionBase @@ -486,8 +479,6 @@ namespace BinaryNinja template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } template <BNMediumLevelILOperation N> MediumLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } template <BNMediumLevelILOperation N> MediumLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } - template <BNMediumLevelILOperation N> MediumLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } - template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } template <BNMediumLevelILOperation N> MediumLevelILInstruction GetStackExpr() const { return As<N>().GetStackExpr(); } template <BNMediumLevelILOperation N> MediumLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } template <BNMediumLevelILOperation N> Variable GetHighVariable() const { return As<N>().GetHighVariable(); } @@ -497,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(); } @@ -538,8 +530,6 @@ namespace BinaryNinja MediumLevelILInstruction GetLeftExpr() const; MediumLevelILInstruction GetRightExpr() const; MediumLevelILInstruction GetCarryExpr() const; - MediumLevelILInstruction GetHighExpr() const; - MediumLevelILInstruction GetLowExpr() const; MediumLevelILInstruction GetStackExpr() const; MediumLevelILInstruction GetConditionExpr() const; Variable GetHighVariable() const; @@ -549,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; @@ -581,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; @@ -645,13 +637,6 @@ namespace BinaryNinja MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } }; - struct MediumLevelILDoublePrecisionInstruction: public MediumLevelILInstructionBase - { - MediumLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } - MediumLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } - MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } - }; - // Implementations of each instruction to fetch the correct operand value for the valid operands, these // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate // a compiler error. @@ -774,6 +759,11 @@ namespace BinaryNinja Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SPLIT>: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + }; template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA>: public MediumLevelILInstructionBase { @@ -797,6 +787,13 @@ namespace BinaryNinja uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SPLIT_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetHighSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetLowSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; template <> struct MediumLevelILInstructionAccessor<MLIL_ADDRESS_OF>: public MediumLevelILInstructionBase { @@ -911,6 +908,32 @@ 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_FREE_VAR_SLOT>: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_FREE_VAR_SLOT_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_TRAP>: public MediumLevelILInstructionBase { int64_t GetVector() const { return GetRawOperandAsInteger(0); } @@ -935,6 +958,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor<MLIL_CONST>: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_CONST_PTR>: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FLOAT_CONST>: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_IMPORT>: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_ADD>: public MediumLevelILTwoOperandInstruction {}; @@ -954,6 +978,10 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_MODU>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_MODS>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODU_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODS_DP>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_E>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_NE>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SLT>: public MediumLevelILTwoOperandInstruction {}; @@ -966,17 +994,24 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_UGT>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_TEST_BIT>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_ADD_OVERFLOW>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FADD>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FSUB>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FMUL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FDIV>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_E>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_NE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_LT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_LE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_GE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_GT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_O>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FCMP_UO>: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_ADC>: public MediumLevelILTwoOperandWithCarryInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_SBB>: public MediumLevelILTwoOperandWithCarryInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_RLC>: public MediumLevelILTwoOperandWithCarryInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_RRC>: public MediumLevelILTwoOperandWithCarryInstruction {}; - template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU_DP>: public MediumLevelILDoublePrecisionInstruction {}; - template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS_DP>: public MediumLevelILDoublePrecisionInstruction {}; - template <> struct MediumLevelILInstructionAccessor<MLIL_MODU_DP>: public MediumLevelILDoublePrecisionInstruction {}; - template <> struct MediumLevelILInstructionAccessor<MLIL_MODS_DP>: public MediumLevelILDoublePrecisionInstruction {}; - template <> struct MediumLevelILInstructionAccessor<MLIL_NEG>: public MediumLevelILOneOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_NOT>: public MediumLevelILOneOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_SX>: public MediumLevelILOneOperandInstruction {}; @@ -984,4 +1019,14 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor<MLIL_LOW_PART>: public MediumLevelILOneOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_BOOL_TO_INT>: public MediumLevelILOneOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor<MLIL_UNIMPL_MEM>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FSQRT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FNEG>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FABS>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FLOAT_TO_INT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_INT_TO_FLOAT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FLOAT_CONV>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ROUND_TO_INT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FLOOR>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CEIL>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_FTRUNC>: public MediumLevelILOneOperandInstruction {}; } diff --git a/metadata.cpp b/metadata.cpp index f9c48b04..c111233f 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -144,6 +144,7 @@ vector<Ref<Metadata>> Metadata::GetArray() size_t size = 0; BNMetadata** data = BNMetadataGetArray(m_object, &size); vector<Ref<Metadata>> result; + result.reserve(size); for (size_t i = 0; i < size; i++) result.push_back(new Metadata(data[i])); return result; diff --git a/platform.cpp b/platform.cpp index a9ab888f..724901fe 100644 --- a/platform.cpp +++ b/platform.cpp @@ -72,6 +72,7 @@ vector<Ref<Platform>> Platform::GetList() BNPlatform** list = BNGetPlatformList(&count); vector<Ref<Platform>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -86,6 +87,7 @@ vector<Ref<Platform>> Platform::GetList(Architecture* arch) BNPlatform** list = BNGetPlatformListByArchitecture(arch->GetObject(), &count); vector<Ref<Platform>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -100,6 +102,7 @@ vector<Ref<Platform>> Platform::GetList(const string& os) BNPlatform** list = BNGetPlatformListByOS(os.c_str(), &count); vector<Ref<Platform>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -114,6 +117,7 @@ vector<Ref<Platform>> Platform::GetList(const string& os, Architecture* arch) BNPlatform** list = BNGetPlatformListByOSAndArchitecture(os.c_str(), arch->GetObject(), &count); vector<Ref<Platform>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -128,6 +132,7 @@ vector<std::string> Platform::GetOSList() char** list = BNGetPlatformOSList(&count); vector<string> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(list[i]); @@ -178,6 +183,7 @@ vector<Ref<CallingConvention>> Platform::GetCallingConventions() const BNCallingConvention** list = BNGetPlatformCallingConventions(m_object, &count); vector<Ref<CallingConvention>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreCallingConvention(BNNewCallingConventionReference(list[i]))); @@ -19,6 +19,8 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -27,6 +29,7 @@ using namespace std; PluginCommandContext::PluginCommandContext() { address = length = 0; + instrIndex = BN_INVALID_EXPR; } @@ -97,6 +100,48 @@ void PluginCommand::FunctionPluginCommandActionCallback(void* ctxt, BNBinaryView } +void PluginCommand::LowLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func) +{ + RegisteredLowLevelILFunctionCommand* cmd = (RegisteredLowLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<LowLevelILFunction> funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + cmd->action(viewObject, funcObject); +} + + +void PluginCommand::LowLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr) +{ + RegisteredLowLevelILInstructionCommand* cmd = (RegisteredLowLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<LowLevelILFunction> funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + LowLevelILInstruction instrObject = funcObject->GetInstruction(instr); + cmd->action(viewObject, instrObject); +} + + +void PluginCommand::MediumLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func) +{ + RegisteredMediumLevelILFunctionCommand* cmd = (RegisteredMediumLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<MediumLevelILFunction> funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + cmd->action(viewObject, funcObject); +} + + +void PluginCommand::MediumLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr) +{ + RegisteredMediumLevelILInstructionCommand* cmd = (RegisteredMediumLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<MediumLevelILFunction> funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + MediumLevelILInstruction instrObject = funcObject->GetInstruction(instr); + cmd->action(viewObject, instrObject); +} + + bool PluginCommand::DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view) { RegisteredDefaultCommand* cmd = (RegisteredDefaultCommand*)ctxt; @@ -130,6 +175,48 @@ bool PluginCommand::FunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryVie } +bool PluginCommand::LowLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func) +{ + RegisteredLowLevelILFunctionCommand* cmd = (RegisteredLowLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<LowLevelILFunction> funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + return cmd->isValid(viewObject, funcObject); +} + + +bool PluginCommand::LowLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr) +{ + RegisteredLowLevelILInstructionCommand* cmd = (RegisteredLowLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<LowLevelILFunction> funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + LowLevelILInstruction instrObject = funcObject->GetInstruction(instr); + return cmd->isValid(viewObject, instrObject); +} + + +bool PluginCommand::MediumLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func) +{ + RegisteredMediumLevelILFunctionCommand* cmd = (RegisteredMediumLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<MediumLevelILFunction> funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + return cmd->isValid(viewObject, funcObject); +} + + +bool PluginCommand::MediumLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr) +{ + RegisteredMediumLevelILInstructionCommand* cmd = (RegisteredMediumLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<MediumLevelILFunction> funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + MediumLevelILInstruction instrObject = funcObject->GetInstruction(instr); + return cmd->isValid(viewObject, instrObject); +} + + void PluginCommand::Register(const string& name, const string& description, const function<void(BinaryView* view)>& action) { @@ -206,11 +293,95 @@ void PluginCommand::RegisterForFunction(const string& name, const string& descri } +void PluginCommand::RegisterForLowLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, LowLevelILFunction* func)>& action) +{ + RegisterForLowLevelILFunction(name, description, action, [](BinaryView*, LowLevelILFunction*) { return true; }); +} + + +void PluginCommand::RegisterForLowLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, LowLevelILFunction* func)>& action, + const function<bool(BinaryView* view, LowLevelILFunction* func)>& isValid) +{ + RegisteredLowLevelILFunctionCommand* cmd = new RegisteredLowLevelILFunctionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForLowLevelILFunction(name.c_str(), description.c_str(), + LowLevelILFunctionPluginCommandActionCallback, + LowLevelILFunctionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForLowLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const LowLevelILInstruction& instr)>& action) +{ + RegisterForLowLevelILInstruction(name, description, action, + [](BinaryView*, const LowLevelILInstruction&) { return true; }); +} + + +void PluginCommand::RegisterForLowLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const LowLevelILInstruction& instr)>& action, + const function<bool(BinaryView* view, const LowLevelILInstruction& instr)>& isValid) +{ + RegisteredLowLevelILInstructionCommand* cmd = new RegisteredLowLevelILInstructionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForLowLevelILInstruction(name.c_str(), description.c_str(), + LowLevelILInstructionPluginCommandActionCallback, + LowLevelILInstructionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForMediumLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, MediumLevelILFunction* func)>& action) +{ + RegisterForMediumLevelILFunction(name, description, action, + [](BinaryView*, MediumLevelILFunction*) { return true; }); +} + + +void PluginCommand::RegisterForMediumLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, MediumLevelILFunction* func)>& action, + const function<bool(BinaryView* view, MediumLevelILFunction* func)>& isValid) +{ + RegisteredMediumLevelILFunctionCommand* cmd = new RegisteredMediumLevelILFunctionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForMediumLevelILFunction(name.c_str(), description.c_str(), + MediumLevelILFunctionPluginCommandActionCallback, + MediumLevelILFunctionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForMediumLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const MediumLevelILInstruction& instr)>& action) +{ + RegisterForMediumLevelILInstruction(name, description, action, + [](BinaryView*, const MediumLevelILInstruction&) { return true; }); +} + + +void PluginCommand::RegisterForMediumLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const MediumLevelILInstruction& instr)>& action, + const function<bool(BinaryView* view, const MediumLevelILInstruction& instr)>& isValid) +{ + RegisteredMediumLevelILInstructionCommand* cmd = new RegisteredMediumLevelILInstructionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForMediumLevelILInstruction(name.c_str(), description.c_str(), + MediumLevelILInstructionPluginCommandActionCallback, + MediumLevelILInstructionPluginCommandIsValidCallback, cmd); +} + + vector<PluginCommand> PluginCommand::GetList() { vector<PluginCommand> result; size_t count; BNPluginCommand* commands = BNGetAllPluginCommands(&count); + result.reserve(count); for (size_t i = 0; i < count; i++) result.emplace_back(commands[i]); BNFreePluginCommandList(commands); @@ -258,6 +429,38 @@ bool PluginCommand::IsValid(const PluginCommandContext& ctxt) const if (!m_command.functionIsValid) return true; return m_command.functionIsValid(m_command.context, ctxt.view->GetObject(), ctxt.function->GetObject()); + case LowLevelILFunctionPluginCommand: + if (!ctxt.lowLevelILFunction) + return false; + if (!m_command.lowLevelILFunctionIsValid) + return true; + return m_command.lowLevelILFunctionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject()); + case LowLevelILInstructionPluginCommand: + if (!ctxt.lowLevelILFunction) + return false; + if (ctxt.instrIndex == BN_INVALID_EXPR) + return false; + if (!m_command.lowLevelILInstructionIsValid) + return true; + return m_command.lowLevelILInstructionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject(), ctxt.instrIndex); + case MediumLevelILFunctionPluginCommand: + if (!ctxt.mediumLevelILFunction) + return false; + if (!m_command.mediumLevelILFunctionIsValid) + return true; + return m_command.mediumLevelILFunctionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject()); + case MediumLevelILInstructionPluginCommand: + if (!ctxt.mediumLevelILFunction) + return false; + if (ctxt.instrIndex == BN_INVALID_EXPR) + return false; + if (!m_command.mediumLevelILInstructionIsValid) + return true; + return m_command.mediumLevelILInstructionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); default: return false; } @@ -283,6 +486,22 @@ void PluginCommand::Execute(const PluginCommandContext& ctxt) const case FunctionPluginCommand: m_command.functionCommand(m_command.context, ctxt.view->GetObject(), ctxt.function->GetObject()); break; + case LowLevelILFunctionPluginCommand: + m_command.lowLevelILFunctionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject()); + break; + case LowLevelILInstructionPluginCommand: + m_command.lowLevelILInstructionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject(), ctxt.instrIndex); + break; + case MediumLevelILFunctionPluginCommand: + m_command.mediumLevelILFunctionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject()); + break; + case MediumLevelILInstructionPluginCommand: + m_command.mediumLevelILInstructionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); + break; default: break; } diff --git a/python/architecture.py b/python/architecture.py index a893c1d4..c5f87ec6 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -44,7 +44,7 @@ class _ArchitectureMetaClass(type): archs = core.BNGetArchitectureList(count) result = [] for i in xrange(0, count.value): - result.append(Architecture(archs[i])) + result.append(CoreArchitecture._from_cache(archs[i])) core.BNFreeArchitectureList(archs) return result @@ -54,7 +54,7 @@ class _ArchitectureMetaClass(type): archs = core.BNGetArchitectureList(count) try: for i in xrange(0, count.value): - yield Architecture(archs[i]) + yield CoreArchitecture._from_cache(archs[i]) finally: core.BNFreeArchitectureList(archs) @@ -63,7 +63,7 @@ class _ArchitectureMetaClass(type): arch = core.BNGetArchitectureByName(name) if arch is None: raise KeyError("'%s' is not a valid architecture" % str(name)) - return Architecture(arch) + return CoreArchitecture._from_cache(arch) def register(cls): startup._init_plugins() @@ -120,232 +120,266 @@ class Architecture(object): global_regs = [] flags = [] flag_write_types = [] + semantic_flag_classes = [] + semantic_flag_groups = [] flag_roles = {} flags_required_for_flag_condition = {} + flags_required_for_semantic_flag_group = {} + flag_conditions_for_semantic_flag_group = {} flags_written_by_flag_write_type = {} + semantic_class_for_flag_write_type = {} + reg_stacks = {} + intrinsics = {} __metaclass__ = _ArchitectureMetaClass next_address = 0 - def __init__(self, handle=None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNArchitecture) - self.__dict__["name"] = core.BNGetArchitectureName(self.handle) - self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle)) - self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle) - self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle) - self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle) - self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle) - self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle) - self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle, - core.BNGetArchitectureStackPointerRegister(self.handle)) - self.__dict__["link_reg"] = core.BNGetArchitectureRegisterName(self.handle, - core.BNGetArchitectureLinkRegister(self.handle)) + def __init__(self): + startup._init_plugins() - count = ctypes.c_ulonglong() - regs = core.BNGetAllArchitectureRegisters(self.handle, count) - self.__dict__["regs"] = {} - for i in xrange(0, count.value): - name = core.BNGetArchitectureRegisterName(self.handle, regs[i]) - info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) - full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) - self.regs[name] = function.RegisterInfo(full_width_reg, info.size, info.offset, - ImplicitRegisterExtend(info.extend), regs[i]) - core.BNFreeRegisterList(regs) + if self.__class__.opcode_display_length > self.__class__.max_instr_length: + self.__class__.opcode_display_length = self.__class__.max_instr_length - count = ctypes.c_ulonglong() - flags = core.BNGetAllArchitectureFlags(self.handle, count) - self._flags = {} - self._flags_by_index = {} - self.__dict__["flags"] = [] - for i in xrange(0, count.value): - name = core.BNGetArchitectureFlagName(self.handle, flags[i]) - self._flags[name] = flags[i] - self._flags_by_index[flags[i]] = name - self.flags.append(name) - core.BNFreeRegisterList(flags) + self._cb = core.BNCustomArchitecture() + self._cb.context = 0 + self._cb.init = self._cb.init.__class__(self._init) + self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness) + self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) + self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) + self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment) + self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length) + self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length) + self._cb.getAssociatedArchitectureByAddress = \ + self._cb.getAssociatedArchitectureByAddress.__class__(self._get_associated_arch_by_address) + self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info) + self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text) + self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text) + self._cb.getInstructionLowLevelIL = self._cb.getInstructionLowLevelIL.__class__( + self._get_instruction_low_level_il) + self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name) + self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name) + self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name) + self._cb.getSemanticFlagClassName = self._cb.getSemanticFlagClassName.__class__(self._get_semantic_flag_class_name) + self._cb.getSemanticFlagGroupName = self._cb.getSemanticFlagGroupName.__class__(self._get_semantic_flag_group_name) + self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers) + self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers) + self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags) + self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types) + self._cb.getAllSemanticFlagClasses = self._cb.getAllSemanticFlagClasses.__class__(self._get_all_semantic_flag_classes) + self._cb.getAllSemanticFlagGroups = self._cb.getAllSemanticFlagGroups.__class__(self._get_all_semantic_flag_groups) + self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role) + self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__( + self._get_flags_required_for_flag_condition) + self._cb.getFlagsRequiredForSemanticFlagGroup = self._cb.getFlagsRequiredForSemanticFlagGroup.__class__( + self._get_flags_required_for_semantic_flag_group) + self._cb.getFlagConditionsForSemanticFlagGroup = self._cb.getFlagConditionsForSemanticFlagGroup.__class__( + self._get_flag_conditions_for_semantic_flag_group) + self._cb.freeFlagConditionsForSemanticFlagGroup = self._cb.freeFlagConditionsForSemanticFlagGroup.__class__( + self._free_flag_conditions_for_semantic_flag_group) + self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__( + self._get_flags_written_by_flag_write_type) + self._cb.getSemanticClassForFlagWriteType = self._cb.getSemanticClassForFlagWriteType.__class__( + self._get_semantic_class_for_flag_write_type) + self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__( + self._get_flag_write_low_level_il) + self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__( + self._get_flag_condition_low_level_il) + self._cb.getSemanticFlagGroupLowLevelIL = self._cb.getSemanticFlagGroupLowLevelIL.__class__( + self._get_semantic_flag_group_low_level_il) + self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) + self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info) + self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( + self._get_stack_pointer_register) + self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register) + self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers) + 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) + self._cb.isAlwaysBranchPatchAvailable = self._cb.isAlwaysBranchPatchAvailable.__class__( + self._is_always_branch_patch_available) + self._cb.isInvertBranchPatchAvailable = self._cb.isInvertBranchPatchAvailable.__class__( + self._is_invert_branch_patch_available) + self._cb.isSkipAndReturnZeroPatchAvailable = self._cb.isSkipAndReturnZeroPatchAvailable.__class__( + self._is_skip_and_return_zero_patch_available) + self._cb.isSkipAndReturnValuePatchAvailable = self._cb.isSkipAndReturnValuePatchAvailable.__class__( + self._is_skip_and_return_value_patch_available) + self._cb.convertToNop = self._cb.convertToNop.__class__(self._convert_to_nop) + self._cb.alwaysBranch = self._cb.alwaysBranch.__class__(self._always_branch) + self._cb.invertBranch = self._cb.invertBranch.__class__(self._invert_branch) + self._cb.skipAndReturnValue = self._cb.skipAndReturnValue.__class__(self._skip_and_return_value) - count = ctypes.c_ulonglong() - types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count) - self._flag_write_types = {} - self._flag_write_types_by_index = {} - self.__dict__["flag_write_types"] = [] - for i in xrange(0, count.value): - name = core.BNGetArchitectureFlagWriteTypeName(self.handle, types[i]) - self._flag_write_types[name] = types[i] - self._flag_write_types_by_index[types[i]] = name - self.flag_write_types.append(name) - core.BNFreeRegisterList(types) + self.__dict__["endianness"] = self.__class__.endianness + self.__dict__["address_size"] = self.__class__.address_size + self.__dict__["default_int_size"] = self.__class__.default_int_size + self.__dict__["instr_alignment"] = self.__class__.instr_alignment + self.__dict__["max_instr_length"] = self.__class__.max_instr_length + self.__dict__["opcode_display_length"] = self.__class__.opcode_display_length + self.__dict__["stack_pointer"] = self.__class__.stack_pointer + self.__dict__["link_reg"] = self.__class__.link_reg - self._flag_roles = {} - self.__dict__["flag_roles"] = {} - for flag in self.__dict__["flags"]: - role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag])) - self.__dict__["flag_roles"][flag] = role - self._flag_roles[self._flags[flag]] = role + self._all_regs = {} + self._full_width_regs = {} + self._regs_by_index = {} + self.__dict__["regs"] = self.__class__.regs + reg_index = 0 - self._flags_required_for_flag_condition = {} - self.__dict__["flags_required_for_flag_condition"] = {} - for cond in LowLevelILFlagCondition: - count = ctypes.c_ulonglong() - flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, count) - flag_indexes = [] - flag_names = [] - for i in xrange(0, count.value): - flag_indexes.append(flags[i]) - flag_names.append(self._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - self._flags_required_for_flag_condition[cond] = flag_indexes - self.__dict__["flags_required_for_flag_condition"][cond] = flag_names + # Registers used for storage in register stacks must be sequential, so allocate these in order first + self._all_reg_stacks = {} + self._reg_stacks_by_index = {} + self.__dict__["reg_stacks"] = self.__class__.reg_stacks + reg_stack_index = 0 + for reg_stack in self.reg_stacks: + info = self.reg_stacks[reg_stack] + for reg in info.storage_regs: + self._all_regs[reg] = reg_index + self._regs_by_index[reg_index] = reg + self.regs[reg].index = reg_index + reg_index += 1 + for reg in info.top_relative_regs: + self._all_regs[reg] = reg_index + self._regs_by_index[reg_index] = reg + self.regs[reg].index = reg_index + reg_index += 1 + if reg_stack not in self._all_reg_stacks: + self._all_reg_stacks[reg_stack] = reg_stack_index + self._reg_stacks_by_index[reg_stack_index] = reg_stack + self.reg_stacks[reg_stack].index = reg_stack_index + reg_stack_index += 1 - self._flags_written_by_flag_write_type = {} - self.__dict__["flags_written_by_flag_write_type"] = {} - for write_type in self.flag_write_types: - count = ctypes.c_ulonglong() - flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle, - self._flag_write_types[write_type], count) - flag_indexes = [] - flag_names = [] - for i in xrange(0, count.value): - flag_indexes.append(flags[i]) - flag_names.append(self._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes - self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names + for reg in self.regs: + info = self.regs[reg] + if reg not in self._all_regs: + self._all_regs[reg] = reg_index + self._regs_by_index[reg_index] = reg + self.regs[reg].index = reg_index + reg_index += 1 + if info.full_width_reg not in self._all_regs: + self._all_regs[info.full_width_reg] = reg_index + self._regs_by_index[reg_index] = info.full_width_reg + self.regs[info.full_width_reg].index = reg_index + reg_index += 1 + if info.full_width_reg not in self._full_width_regs: + self._full_width_regs[info.full_width_reg] = self._all_regs[info.full_width_reg] - count = ctypes.c_ulonglong() - regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) - self.__dict__["global_regs"] = [] - for i in xrange(0, count.value): - self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) - core.BNFreeRegisterList(regs) - else: - startup._init_plugins() + self._flags = {} + self._flags_by_index = {} + self.__dict__["flags"] = self.__class__.flags + flag_index = 0 + for flag in self.__class__.flags: + if flag not in self._flags: + self._flags[flag] = flag_index + self._flags_by_index[flag_index] = flag + flag_index += 1 - if self.__class__.opcode_display_length > self.__class__.max_instr_length: - self.__class__.opcode_display_length = self.__class__.max_instr_length + self._flag_write_types = {} + self._flag_write_types_by_index = {} + self.__dict__["flag_write_types"] = self.__class__.flag_write_types + write_type_index = 0 + for write_type in self.__class__.flag_write_types: + if write_type not in self._flag_write_types: + self._flag_write_types[write_type] = write_type_index + self._flag_write_types_by_index[write_type_index] = write_type + write_type_index += 1 - self._cb = core.BNCustomArchitecture() - self._cb.context = 0 - self._cb.init = self._cb.init.__class__(self._init) - self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness) - self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) - self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) - self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment) - self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length) - self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length) - self._cb.getAssociatedArchitectureByAddress = \ - self._cb.getAssociatedArchitectureByAddress.__class__(self._get_associated_arch_by_address) - self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info) - self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text) - self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text) - self._cb.getInstructionLowLevelIL = self._cb.getInstructionLowLevelIL.__class__( - self._get_instruction_low_level_il) - self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name) - self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name) - self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name) - self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers) - self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers) - self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags) - self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types) - self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role) - self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__( - self._get_flags_required_for_flag_condition) - self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__( - self._get_flags_written_by_flag_write_type) - self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__( - self._get_flag_write_low_level_il) - self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__( - self._get_flag_condition_low_level_il) - self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) - self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info) - self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( - self._get_stack_pointer_register) - self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register) - self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers) - self._cb.assemble = self._cb.assemble.__class__(self._assemble) - self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__( - self._is_never_branch_patch_available) - self._cb.isAlwaysBranchPatchAvailable = self._cb.isAlwaysBranchPatchAvailable.__class__( - self._is_always_branch_patch_available) - self._cb.isInvertBranchPatchAvailable = self._cb.isInvertBranchPatchAvailable.__class__( - self._is_invert_branch_patch_available) - self._cb.isSkipAndReturnZeroPatchAvailable = self._cb.isSkipAndReturnZeroPatchAvailable.__class__( - self._is_skip_and_return_zero_patch_available) - self._cb.isSkipAndReturnValuePatchAvailable = self._cb.isSkipAndReturnValuePatchAvailable.__class__( - self._is_skip_and_return_value_patch_available) - self._cb.convertToNop = self._cb.convertToNop.__class__(self._convert_to_nop) - self._cb.alwaysBranch = self._cb.alwaysBranch.__class__(self._always_branch) - self._cb.invertBranch = self._cb.invertBranch.__class__(self._invert_branch) - self._cb.skipAndReturnValue = self._cb.skipAndReturnValue.__class__(self._skip_and_return_value) + self._semantic_flag_classes = {} + self._semantic_flag_classes_by_index = {} + self.__dict__["semantic_flag_classes"] = self.__class__.semantic_flag_classes + semantic_class_index = 1 + for sem_class in self.__class__.semantic_flag_classes: + if sem_class not in self._semantic_flag_classes: + self._semantic_flag_classes[sem_class] = semantic_class_index + self._semantic_flag_classes_by_index[semantic_class_index] = sem_class + semantic_class_index += 1 - self._all_regs = {} - self._full_width_regs = {} - self._regs_by_index = {} - self.__dict__["regs"] = self.__class__.regs - reg_index = 0 - for reg in self.regs: - info = self.regs[reg] - if reg not in self._all_regs: - self._all_regs[reg] = reg_index - self._regs_by_index[reg_index] = reg - self.regs[reg].index = reg_index - reg_index += 1 - if info.full_width_reg not in self._all_regs: - self._all_regs[info.full_width_reg] = reg_index - self._regs_by_index[reg_index] = info.full_width_reg - self.regs[info.full_width_reg].index = reg_index - reg_index += 1 - if info.full_width_reg not in self._full_width_regs: - self._full_width_regs[info.full_width_reg] = self._all_regs[info.full_width_reg] + self._semantic_flag_groups = {} + self._semantic_flag_groups_by_index = {} + self.__dict__["semantic_flag_groups"] = self.__class__.semantic_flag_groups + semantic_group_index = 0 + for sem_group in self.__class__.semantic_flag_groups: + if sem_group not in self._semantic_flag_groups: + self._semantic_flag_groups[sem_group] = semantic_group_index + self._semantic_flag_groups_by_index[semantic_group_index] = sem_group + semantic_group_index += 1 - self._flags = {} - self._flags_by_index = {} - self.__dict__["flags"] = self.__class__.flags - flag_index = 0 - for flag in self.__class__.flags: - if flag not in self._flags: - self._flags[flag] = flag_index - self._flags_by_index[flag_index] = flag - flag_index += 1 + self._flag_roles = {} + self.__dict__["flag_roles"] = self.__class__.flag_roles + for flag in self.__class__.flag_roles: + role = self.__class__.flag_roles[flag] + if isinstance(role, str): + role = FlagRole[role] + self._flag_roles[self._flags[flag]] = role - self._flag_write_types = {} - self._flag_write_types_by_index = {} - self.__dict__["flag_write_types"] = self.__class__.flag_write_types - write_type_index = 0 - for write_type in self.__class__.flag_write_types: - if write_type not in self._flag_write_types: - self._flag_write_types[write_type] = write_type_index - self._flag_write_types_by_index[write_type_index] = write_type - write_type_index += 1 + self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition - self._flag_roles = {} - self.__dict__["flag_roles"] = self.__class__.flag_roles - for flag in self.__class__.flag_roles: - role = self.__class__.flag_roles[flag] - if isinstance(role, str): - role = FlagRole[role] - self._flag_roles[self._flags[flag]] = role + self._flags_required_by_semantic_flag_group = {} + self.__dict__["flags_required_for_semantic_flag_group"] = self.__class__.flags_required_for_semantic_flag_group + for group in self.__class__.flags_required_for_semantic_flag_group: + flags = [] + for flag in self.__class__.flags_required_for_semantic_flag_group[group]: + flags.append(self._flags[flag]) + self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flags - self._flags_required_for_flag_condition = {} - self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition - for cond in self.__class__.flags_required_for_flag_condition: - flags = [] - for flag in self.__class__.flags_required_for_flag_condition[cond]: - flags.append(self._flags[flag]) - self._flags_required_for_flag_condition[cond] = flags + self._flag_conditions_for_semantic_flag_group = {} + self.__dict__["flag_conditions_for_semantic_flag_group"] = self.__class__.flag_conditions_for_semantic_flag_group + for group in self.__class__.flag_conditions_for_semantic_flag_group: + class_cond = {} + for sem_class in self.__class__.flag_conditions_for_semantic_flag_group[group]: + if sem_class is None: + class_cond[0] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class] + else: + class_cond[self._semantic_flag_classes[sem_class]] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class] + self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_cond - self._flags_written_by_flag_write_type = {} - self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type - for write_type in self.__class__.flags_written_by_flag_write_type: - flags = [] - for flag in self.__class__.flags_written_by_flag_write_type[write_type]: - flags.append(self._flags[flag]) - self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags + self._flags_written_by_flag_write_type = {} + self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type + for write_type in self.__class__.flags_written_by_flag_write_type: + flags = [] + for flag in self.__class__.flags_written_by_flag_write_type[write_type]: + flags.append(self._flags[flag]) + self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags - self.__dict__["global_regs"] = self.__class__.global_regs + self._semantic_class_for_flag_write_type = {} + self.__dict__["semantic_class_for_flag_write_type"] = self.__class__.semantic_class_for_flag_write_type + for write_type in self.__class__.semantic_class_for_flag_write_type: + sem_class = self.__class__.semantic_class_for_flag_write_type[write_type] + if sem_class in self._semantic_flag_classes: + sem_class_index = self._semantic_flag_classes[sem_class] + else: + sem_class_index = 0 + self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class_index + + self.__dict__["global_regs"] = self.__class__.global_regs - self._pending_reg_lists = {} - self._pending_token_lists = {} + 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): @@ -405,49 +439,49 @@ class Architecture(object): def _get_endianness(self, ctxt): try: - return self.__class__.endianness + return self.endianness except: log.log_error(traceback.format_exc()) return Endianness.LittleEndian def _get_address_size(self, ctxt): try: - return self.__class__.address_size + return self.address_size except: log.log_error(traceback.format_exc()) return 8 def _get_default_integer_size(self, ctxt): try: - return self.__class__.default_int_size + return self.default_int_size except: log.log_error(traceback.format_exc()) return 4 def _get_instruction_alignment(self, ctxt): try: - return self.__class__.instr_alignment + return self.instr_alignment except: log.log_error(traceback.format_exc()) return 1 def _get_max_instruction_length(self, ctxt): try: - return self.__class__.max_instr_length + return self.max_instr_length except: log.log_error(traceback.format_exc()) return 16 def _get_opcode_display_length(self, ctxt): try: - return self.__class__.opcode_display_length + return self.opcode_display_length except: log.log_error(traceback.format_exc()) return 8 def _get_associated_arch_by_address(self, ctxt, addr): try: - result, new_addr = self.perform_get_associated_arch_by_address(addr[0]) + result, new_addr = self.get_associated_arch_by_address(addr[0]) addr[0] = new_addr return ctypes.cast(result.handle, ctypes.c_void_p).value except: @@ -458,7 +492,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(max_len) ctypes.memmove(buf, data, max_len) - info = self.perform_get_instruction_info(buf.raw, addr) + info = self.get_instruction_info(buf.raw, addr) if info is None: return False result[0].length = info.length @@ -484,7 +518,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length[0]) ctypes.memmove(buf, data, length[0]) - info = self.perform_get_instruction_text(buf.raw, addr) + info = self.get_instruction_text(buf.raw, addr) if info is None: return False tokens = info[0] @@ -524,7 +558,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length[0]) ctypes.memmove(buf, data, length[0]) - result = self.perform_get_instruction_low_level_il(buf.raw, addr, + result = self.get_instruction_low_level_il(buf.raw, addr, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))) if result is None: return False @@ -561,6 +595,24 @@ class Architecture(object): log.log_error(traceback.format_exc()) return core.BNAllocString("") + def _get_semantic_flag_class_name(self, ctxt, sem_class): + try: + if sem_class in self._semantic_flag_classes_by_index: + return core.BNAllocString(self._semantic_flag_classes_by_index[sem_class]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + + def _get_semantic_flag_group_name(self, ctxt, sem_group): + try: + if sem_group in self._semantic_flag_groups_by_index: + return core.BNAllocString(self._semantic_flag_groups_by_index[sem_group]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + def _get_full_width_registers(self, ctxt, count): try: regs = self._full_width_regs.values() @@ -608,11 +660,11 @@ class Architecture(object): def _get_all_flag_write_types(self, ctxt, count): try: - types = self._flag_write_types_by_index.keys() - count[0] = len(types) - type_buf = (ctypes.c_uint * len(types))() - for i in xrange(0, len(types)): - type_buf[i] = types[i] + write_types = self._flag_write_types_by_index.keys() + count[0] = len(write_types) + type_buf = (ctypes.c_uint * len(write_types))() + for i in xrange(0, len(write_types)): + type_buf[i] = write_types[i] result = ctypes.cast(type_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, type_buf) return result.value @@ -621,19 +673,73 @@ class Architecture(object): count[0] = 0 return None - def _get_flag_role(self, ctxt, flag): + def _get_all_semantic_flag_classes(self, ctxt, count): + try: + sem_classes = self._semantic_flag_classes_by_index.keys() + count[0] = len(sem_classes) + class_buf = (ctypes.c_uint * len(sem_classes))() + for i in xrange(0, len(sem_classes)): + class_buf[i] = sem_classes[i] + result = ctypes.cast(class_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, class_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_all_semantic_flag_groups(self, ctxt, count): try: - if flag in self._flag_roles: - return self._flag_roles[flag] + sem_groups = self._semantic_flag_groups_by_index.keys() + count[0] = len(sem_groups) + group_buf = (ctypes.c_uint * len(sem_groups))() + for i in xrange(0, len(sem_groups)): + group_buf[i] = sem_groups[i] + result = ctypes.cast(group_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, group_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_flag_role(self, ctxt, flag, sem_class): + try: + if sem_class in self._semantic_flag_classes_by_index: + sem_class = self._semantic_flag_classes_by_index[sem_class] + else: + sem_class = None + return self.get_flag_role(flag, sem_class) + except KeyError: + log.log_error(traceback.format_exc()) return FlagRole.SpecialFlagRole + + def _get_flags_required_for_flag_condition(self, ctxt, cond, sem_class, count): + try: + if sem_class in self._semantic_flag_classes_by_index: + sem_class = self._semantic_flag_classes_by_index[sem_class] + else: + sem_class = None + flag_names = self.get_flags_required_for_flag_condition(cond, sem_class) + flags = [] + for name in flag_names: + flags.append(self._flags[name]) + count[0] = len(flags) + flag_buf = (ctypes.c_uint * len(flags))() + for i in xrange(0, len(flags)): + flag_buf[i] = flags[i] + result = ctypes.cast(flag_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, flag_buf) + return result.value except KeyError: log.log_error(traceback.format_exc()) + count[0] = 0 return None - def _get_flags_required_for_flag_condition(self, ctxt, cond, count): + def _get_flags_required_for_semantic_flag_group(self, ctxt, sem_group, count): try: - if cond in self._flags_required_for_flag_condition: - flags = self._flags_required_for_flag_condition[cond] + if sem_group in self._flags_required_by_semantic_flag_group: + flags = self._flags_required_by_semantic_flag_group[sem_group] else: flags = [] count[0] = len(flags) @@ -643,11 +749,41 @@ class Architecture(object): result = ctypes.cast(flag_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, flag_buf) return result.value - except KeyError: + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_flag_conditions_for_semantic_flag_group(self, ctxt, sem_group, count): + try: + if sem_group in self._flag_conditions_for_semantic_flag_group: + class_cond = self._flag_conditions_for_semantic_flag_group[sem_group] + else: + class_cond = {} + count[0] = len(class_cond) + cond_buf = (core.BNFlagConditionForSemanticClass * len(class_cond))() + i = 0 + for class_index in class_cond.keys(): + cond_buf[i].semanticClass = class_index + cond_buf[i].condition = class_cond[class_index] + i += 1 + result = ctypes.cast(cond_buf, ctypes.c_void_p) + self._pending_condition_lists[result.value] = (result, cond_buf) + return result.value + except (KeyError, OSError): log.log_error(traceback.format_exc()) count[0] = 0 return None + def _free_flag_conditions_for_semantic_flag_group(self, ctxt, conditions): + try: + buf = ctypes.cast(conditions, ctypes.c_void_p) + if buf.value not in self._pending_condition_lists: + raise ValueError("freeing condition list that wasn't allocated") + del self._pending_condition_lists[buf.value] + except (ValueError, KeyError): + log.log_error(traceback.format_exc()) + def _get_flags_written_by_flag_write_type(self, ctxt, write_type, count): try: if write_type in self._flags_written_by_flag_write_type: @@ -666,6 +802,16 @@ class Architecture(object): count[0] = 0 return None + def _get_semantic_class_for_flag_write_type(self, ctxt, write_type): + try: + if write_type in self._semantic_class_for_flag_write_type: + return self._semantic_class_for_flag_write_type[write_type] + else: + return 0 + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return 0 + def _get_flag_write_low_level_il(self, ctxt, op, size, write_type, flag, operands, operand_count, il): try: write_type_name = None @@ -680,15 +826,31 @@ class Architecture(object): operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) else: operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) - return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, + return self.get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except (KeyError, OSError): log.log_error(traceback.format_exc()) return False - def _get_flag_condition_low_level_il(self, ctxt, cond, il): + def _get_flag_condition_low_level_il(self, ctxt, cond, sem_class, il): try: - return self.perform_get_flag_condition_low_level_il(cond, + if sem_class in self._semantic_flag_classes_by_index: + sem_class_name = self._semantic_flag_classes_by_index[sem_class] + else: + sem_class_name = None + return self.get_flag_condition_low_level_il(cond, sem_class_name, + lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index + except OSError: + log.log_error(traceback.format_exc()) + return 0 + + def _get_semantic_flag_group_low_level_il(self, ctxt, sem_group, il): + try: + if sem_group in self._semantic_flag_groups_by_index: + sem_group_name = self._semantic_flag_groups_by_index[sem_group] + else: + sem_group_name = None + return self.get_semantic_flag_group_low_level_il(sem_group_name, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except OSError: log.log_error(traceback.format_exc()) @@ -711,7 +873,7 @@ class Architecture(object): result[0].size = 0 result[0].extend = ImplicitRegisterExtend.NoExtend return - info = self.__class__.regs[self._regs_by_index[reg]] + info = self.regs[self._regs_by_index[reg]] result[0].fullWidthRegister = self._all_regs[info.full_width_reg] result[0].offset = info.offset result[0].size = info.size @@ -728,26 +890,50 @@ class Architecture(object): def _get_stack_pointer_register(self, ctxt): try: - return self._all_regs[self.__class__.stack_pointer] + return self._all_regs[self.stack_pointer] except KeyError: log.log_error(traceback.format_exc()) return 0 def _get_link_register(self, ctxt): try: - if self.__class__.link_reg is None: + if self.link_reg is None: return 0xffffffff - return self._all_regs[self.__class__.link_reg] + return self._all_regs[self.link_reg] except KeyError: log.log_error(traceback.format_exc()) return 0 def _get_global_registers(self, ctxt, count): try: - count[0] = len(self.__class__.global_regs) - reg_buf = (ctypes.c_uint * len(self.__class__.global_regs))() - for i in xrange(0, len(self.__class__.global_regs)): - reg_buf[i] = self._all_regs[self.__class__.global_regs[i]] + count[0] = len(self.global_regs) + reg_buf = (ctypes.c_uint * len(self.global_regs))() + for i in xrange(0, len(self.global_regs)): + reg_buf[i] = self._all_regs[self.global_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_register_stack_name(self, ctxt, reg_stack): + try: + if reg_stack in self._reg_stacks_by_index: + return core.BNAllocString(self._reg_stacks_by_index[reg_stack]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + + def _get_all_register_stacks(self, ctxt, count): + try: + regs = self._reg_stacks_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 @@ -756,9 +942,125 @@ class Architecture(object): count[0] = 0 return None + def _get_register_stack_info(self, ctxt, reg_stack, result): + try: + if reg_stack not in self._reg_stacks_by_index: + result[0].firstStorageReg = 0 + result[0].firstTopRelativeReg = 0 + result[0].storageCount = 0 + result[0].topRelativeCount = 0 + result[0].stackTopReg = 0 + return + info = self.reg_stacks[self._reg_stacks_by_index[reg_stack]] + result[0].firstStorageReg = self._all_regs[info.storage_regs[0]] + result[0].storageCount = len(info.storage_regs) + if len(info.top_relative_regs) > 0: + result[0].firstTopRelativeReg = self._all_regs[info.top_relative_regs[0]] + result[0].topRelativeCount = len(info.top_relative_regs) + else: + result[0].firstTopRelativeReg = 0 + result[0].topRelativeCount = 0 + result[0].stackTopReg = self._all_regs[info.stack_top_reg] + except KeyError: + log.log_error(traceback.format_exc()) + result[0].firstStorageReg = 0 + result[0].firstTopRelativeReg = 0 + result[0].storageCount = 0 + 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, length): + 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, length): + 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) + data, error_str = self.assemble(code, addr) errors[0] = core.BNAllocString(str(error_str)) if data is None: return False @@ -776,7 +1078,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - return self.perform_is_never_branch_patch_available(buf.raw, addr) + return self.is_never_branch_patch_available(buf.raw, addr) except: log.log_error(traceback.format_exc()) return False @@ -785,7 +1087,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - return self.perform_is_always_branch_patch_available(buf.raw, addr) + return self.is_always_branch_patch_available(buf.raw, addr) except: log.log_error(traceback.format_exc()) return False @@ -794,7 +1096,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - return self.perform_is_invert_branch_patch_available(buf.raw, addr) + return self.is_invert_branch_patch_available(buf.raw, addr) except: log.log_error(traceback.format_exc()) return False @@ -803,7 +1105,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - return self.perform_is_skip_and_return_zero_patch_available(buf.raw, addr) + return self.is_skip_and_return_zero_patch_available(buf.raw, addr) except: log.log_error(traceback.format_exc()) return False @@ -812,7 +1114,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - return self.perform_is_skip_and_return_value_patch_available(buf.raw, addr) + return self.is_skip_and_return_value_patch_available(buf.raw, addr) except: log.log_error(traceback.format_exc()) return False @@ -821,7 +1123,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - result = self.perform_convert_to_nop(buf.raw, addr) + result = self.convert_to_nop(buf.raw, addr) if result is None: return False result = str(result) @@ -837,7 +1139,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - result = self.perform_always_branch(buf.raw, addr) + result = self.always_branch(buf.raw, addr) if result is None: return False result = str(result) @@ -853,7 +1155,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - result = self.perform_invert_branch(buf.raw, addr) + result = self.invert_branch(buf.raw, addr) if result is None: return False result = str(result) @@ -869,7 +1171,7 @@ class Architecture(object): try: buf = ctypes.create_string_buffer(length) ctypes.memmove(buf, data, length) - result = self.perform_skip_and_return_value(buf.raw, addr, value) + result = self.skip_and_return_value(buf.raw, addr, value) if result is None: return False result = str(result) @@ -882,27 +1184,15 @@ class Architecture(object): return False def perform_get_associated_arch_by_address(self, addr): + """ + Deprecated method provided for compatibility. Architecture plugins should override ``get_associated_arch_by_address``. + """ return self, addr @abc.abstractmethod def perform_get_instruction_info(self, data, addr): """ - ``perform_get_instruction_info`` implements a method which interpretes the bytes passed in ``data`` as an - :py:Class:`InstructionInfo` object. The InstructionInfo object should have the length of the current instruction. - If the instruction is a branch instruction the method should add a branch of the proper type: - - ===================== =================================================== - BranchType Description - ===================== =================================================== - UnconditionalBranch Branch will always be taken - FalseBranch False branch condition - TrueBranch True branch condition - CallDestination Branch is a call instruction (Branch with Link) - FunctionReturn Branch returns from a function - SystemCall System call instruction - IndirectBranch Branch destination is a memory address or register - UnresolvedBranch Call instruction that isn't - ===================== =================================================== + Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_info``. :param str data: bytes to decode :param int addr: virtual address of the byte to be decoded @@ -914,8 +1204,7 @@ class Architecture(object): @abc.abstractmethod def perform_get_instruction_text(self, data, addr): """ - ``perform_get_instruction_text`` implements a method which interpretes the bytes passed in ``data`` as a - list of :py:class:`InstructionTextToken` objects. + Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_text``. :param str data: bytes to decode :param int addr: virtual address of the byte to be decoded @@ -927,10 +1216,7 @@ class Architecture(object): @abc.abstractmethod def perform_get_instruction_low_level_il(self, data, addr, il): """ - ``perform_get_instruction_low_level_il`` implements a method to interpret the bytes passed in ``data`` to - low-level IL instructions. The il instructions must be appended to the :py:class:`LowLevelILFunction`. - - .. note:: Architecture subclasses should implement this method. + Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_low_level_il``. :param str data: bytes to be interpreted as low-level IL instructions :param int addr: virtual address of start of ``data`` @@ -942,8 +1228,7 @@ class Architecture(object): @abc.abstractmethod def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_write_low_level_il``. :param LowLevelILOperation op: :param int size: @@ -959,28 +1244,32 @@ class Architecture(object): return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il) @abc.abstractmethod - def perform_get_flag_condition_low_level_il(self, cond, il): + def perform_get_flag_condition_low_level_il(self, cond, sem_class, il): """ - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_condition_low_level_il``. - :param LowLevelILFlagCondition cond: - :param LowLevelILFunction il: + :param LowLevelILFlagCondition cond: Flag condition to be computed + :param str sem_class: Semantic class to be used (None for default semantics) + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to :rtype: LowLevelILExpr """ - return self.get_default_flag_condition_low_level_il(cond, il) + return self.get_default_flag_condition_low_level_il(cond, sem_class, il) @abc.abstractmethod - def perform_assemble(self, code, addr): + def perform_get_semantic_flag_group_low_level_il(self, sem_group, il): """ - ``perform_assemble`` implements a method to convert the string of assembly instructions ``code`` loaded at - virtual address ``addr`` to the byte representation of those instructions. This can be done by simply shelling - out to an assembler like yasm or llvm-mc, since this method isn't performance sensitive. + Deprecated method provided for compatibility. Architecture plugins should override ``get_semantic_flag_group_low_level_il``. - .. note:: Architecture subclasses should implement this method. - .. note :: It is important that the assembler used accepts a syntax identical to the one emitted by the \ - disassembler. This will prevent confusing the user. - .. warning:: This method should never be called directly. + :param str sem_group: Semantic group to be computed + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to + :rtype: LowLevelILExpr + """ + return il.unimplemented() + + @abc.abstractmethod + def perform_assemble(self, code, addr): + """ + Deprecated method provided for compatibility. Architecture plugins should override ``assemble``. :param str code: string representation of the instructions to be assembled :param int addr: virtual address that the instructions will be loaded at @@ -992,8 +1281,7 @@ class Architecture(object): @abc.abstractmethod def perform_is_never_branch_patch_available(self, data, addr): """ - ``perform_is_never_branch_patch_available`` implements a check to determine if the instruction represented by - the bytes contained in ``data`` at address addr is a branch instruction that can be made to never branch. + Deprecated method provided for compatibility. Architecture plugins should override ``is_never_branch_patch_available``. .. note:: Architecture subclasses should implement this method. .. warning:: This method should never be called directly. @@ -1008,11 +1296,7 @@ class Architecture(object): @abc.abstractmethod def perform_is_always_branch_patch_available(self, data, addr): """ - ``perform_is_always_branch_patch_available`` implements a check to determine if the instruction represented by - the bytes contained in ``data`` at address addr is a conditional branch that can be made unconditional. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``is_always_branch_patch_available``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1024,11 +1308,7 @@ class Architecture(object): @abc.abstractmethod def perform_is_invert_branch_patch_available(self, data, addr): """ - ``perform_is_invert_branch_patch_available`` implements a check to determine if the instruction represented by - the bytes contained in ``data`` at address addr is a conditional branch which can be inverted. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``is_invert_branch_patch_available``. :param int addr: the virtual address of the instruction to be patched :return: True if the instruction can be patched, False otherwise @@ -1039,13 +1319,7 @@ class Architecture(object): @abc.abstractmethod def perform_is_skip_and_return_zero_patch_available(self, data, addr): """ - ``perform_is_skip_and_return_zero_patch_available`` implements a check to determine if the instruction represented by - the bytes contained in ``data`` at address addr is a *call-like* instruction which can made into instructions - that are equivilent to "return 0". For example if ``data`` was the x86 instruction ``call eax`` which could be - converted into ``xor eax,eax`` thus this function would return True. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``is_skip_and_return_zero_patch_available``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1057,13 +1331,7 @@ class Architecture(object): @abc.abstractmethod def perform_is_skip_and_return_value_patch_available(self, data, addr): """ - ``perform_is_skip_and_return_value_patch_available`` implements a check to determine if the instruction represented by - the bytes contained in ``data`` at address addr is a *call-like* instruction which can made into instructions - that are equivilent to "return 0". For example if ``data`` was the x86 instruction ``call 0xdeadbeef`` which could be - converted into ``mov eax, 42`` thus this function would return True. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``is_skip_and_return_value_patch_available``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1075,10 +1343,7 @@ class Architecture(object): @abc.abstractmethod def perform_convert_to_nop(self, data, addr): """ - ``perform_convert_to_nop`` implements a method which returns a nop sequence of len(data) bytes long. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``convert_to_nop``. :param str data: bytes at virtual address ``addr`` :param int addr: the virtual address of the instruction to be patched @@ -1090,11 +1355,7 @@ class Architecture(object): @abc.abstractmethod def perform_always_branch(self, data, addr): """ - ``perform_always_branch`` implements a method which converts the branch represented by the bytes in ``data`` to - at ``addr`` to an unconditional branch. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``always_branch``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1106,11 +1367,7 @@ class Architecture(object): @abc.abstractmethod def perform_invert_branch(self, data, addr): """ - ``perform_invert_branch`` implements a method which inverts the branch represented by the bytes in ``data`` to - at ``addr``. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``invert_branch``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1122,12 +1379,7 @@ class Architecture(object): @abc.abstractmethod def perform_skip_and_return_value(self, data, addr, value): """ - ``perform_skip_and_return_value`` implements a method which converts a *call-like* instruction represented by - the bytes in ``data`` at ``addr`` to one or more instructions that are equivilent to a function returning a - value. - - .. note:: Architecture subclasses should implement this method. - .. warning:: This method should never be called directly. + Deprecated method provided for compatibility. Architecture plugins should override ``skip_and_return_value``. :param str data: bytes to be checked :param int addr: the virtual address of the instruction to be patched @@ -1137,76 +1389,70 @@ class Architecture(object): """ return None + def perform_get_flag_role(self, flag, sem_class): + """ + Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_role``. + """ + if flag in self._flag_roles: + return self._flag_roles[flag] + return FlagRole.SpecialFlagRole + + def perform_get_flags_required_for_flag_condition(self, cond, sem_class): + """ + Deprecated method provided for compatibility. Architecture plugins should override ``get_flags_required_for_flag_condition``. + """ + if cond in self.flags_required_for_flag_condition: + return self.flags_required_for_flag_condition[cond] + return [] + def get_associated_arch_by_address(self, addr): - new_addr = ctypes.c_ulonglong() - new_addr.value = addr - result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr) - return Architecture(handle = result), new_addr.value + return self.perform_get_associated_arch_by_address(addr) def get_instruction_info(self, data, addr): """ ``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address ``addr`` with data ``data``. + .. note:: Architecture subclasses should implement this method. + .. note :: The instruction info object should always set the InstructionInfo.length to the instruction length, \ and the branches of the proper types shoulde be added if the instruction is a branch. + If the instruction is a branch instruction architecture plugins should add a branch of the proper type: + + ===================== =================================================== + BranchType Description + ===================== =================================================== + UnconditionalBranch Branch will always be taken + FalseBranch False branch condition + TrueBranch True branch condition + CallDestination Branch is a call instruction (Branch with Link) + FunctionReturn Branch returns from a function + SystemCall System call instruction + IndirectBranch Branch destination is a memory address or register + UnresolvedBranch Branch destination is an unknown address + ===================== =================================================== + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` :param int addr: virtual address of bytes in ``data`` :return: the InstructionInfo for the current instruction :rtype: InstructionInfo """ - info = core.BNInstructionInfo() - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info): - return None - result = function.InstructionInfo() - result.length = info.length - result.arch_transition_by_target_addr = info.archTransitionByTargetAddr - result.branch_delay = info.branchDelay - for i in xrange(0, info.branchCount): - target = info.branchTarget[i] - if info.branchArch[i]: - arch = Architecture(info.branchArch[i]) - else: - arch = None - result.add_branch(BranchType(info.branchType[i]), target, arch) - return result + return self.perform_get_instruction_info(data, addr) def get_instruction_text(self, data, addr): """ ``get_instruction_text`` returns a list of InstructionTextToken objects for the instruction at the given virtual address ``addr`` with data ``data``. + .. note:: Architecture subclasses should implement this method. + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` :param int addr: virtual address of bytes in ``data`` :return: an InstructionTextToken list for the current instruction :rtype: list(InstructionTextToken) """ - data = str(data) - count = ctypes.c_ulonglong() - length = ctypes.c_ulonglong() - length.value = len(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count): - return None, 0 - result = [] - for i in xrange(0, count.value): - token_type = InstructionTextTokenType(tokens[i].type) - text = tokens[i].text - value = tokens[i].value - size = tokens[i].size - operand = tokens[i].operand - context = tokens[i].context - confidence = tokens[i].confidence - address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - core.BNFreeInstructionText(tokens, count.value) - return result, length.value + return self.perform_get_instruction_text(data, addr) def get_instruction_low_level_il_instruction(self, bv, addr): il = lowlevelil.LowLevelILFunction(self) @@ -1222,19 +1468,15 @@ class Architecture(object): This is used to analyze arbitrary data at an address, if you are working with an existing binary, you likely want to be using ``Function.get_low_level_il_at``. + .. note:: Architecture subclasses should implement this method. + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` :param int addr: virtual address of bytes in ``data`` :param LowLevelILFunction il: The function the current instruction belongs to :return: the length of the current instruction :rtype: int """ - data = str(data) - length = ctypes.c_ulonglong() - length.value = len(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle) - return length.value + return self.perform_get_instruction_low_level_il(data, addr, il) def get_low_level_il_from_bytes(self, data, addr): """ @@ -1264,6 +1506,23 @@ class Architecture(object): """ return core.BNGetArchitectureRegisterName(self.handle, reg) + def get_reg_stack_name(self, reg_stack): + """ + ``get_reg_stack_name`` gets a register stack name from a register stack number. + + :param int reg_stack: register stack number + :return: the corresponding register string + :rtype: str + """ + return core.BNGetArchitectureRegisterStackName(self.handle, reg_stack) + + def get_reg_stack_for_reg(self, reg): + reg = self.get_reg_index(reg) + result = core.BNGetArchitectureRegisterStackForRegister(self.handle, reg) + if result == 0xffffffff: + return None + return self.get_reg_stack_name(result) + def get_flag_name(self, flag): """ ``get_flag_name`` gets a flag name from a flag number. @@ -1281,6 +1540,13 @@ class Architecture(object): return reg.index return reg + def get_reg_stack_index(self, reg_stack): + if isinstance(reg_stack, str): + return self.reg_stacks[reg_stack].index + elif isinstance(reg_stack, lowlevelil.ILRegisterStack): + return reg_stack.index + return reg_stack + def get_flag_index(self, flag): if isinstance(flag, str): return self._flags[flag] @@ -1288,6 +1554,69 @@ class Architecture(object): return flag.index return flag + def get_semantic_flag_class_index(self, sem_class): + if sem_class is None: + return 0 + elif isinstance(sem_class, str): + return self._semantic_flag_classes[sem_class] + elif isinstance(sem_class, lowlevelil.ILSemanticFlagClass): + return sem_class.index + return sem_class + + def get_semantic_flag_class_name(self, class_index): + """ + ``get_semantic_flag_class_name`` gets the name of a semantic flag class from the index. + + :param int _index: class_index + :return: the name of the semantic flag class + :rtype: str + """ + if not isinstance(class_index, (int, long)): + raise ValueError("argument 'class_index' must be an integer") + try: + return self._semantic_flag_classes_by_index[class_index] + except KeyError: + raise AttributeError("argument class_index is not a valid class index") + + def get_semantic_flag_group_index(self, sem_group): + if isinstance(sem_group, str): + return self._semantic_flag_groups[sem_group] + elif isinstance(sem_group, lowlevelil.ILSemanticFlagGroup): + return sem_group.index + return sem_group + + def get_semantic_flag_group_name(self, group_index): + """ + ``get_semantic_flag_group_name`` gets the name of a semantic flag group from the index. + + :param int group_index: group_index + :return: the name of the semantic flag group + :rtype: str + """ + if not isinstance(group_index, (int, long)): + raise ValueError("argument 'group_index' must be an integer") + try: + return self._semantic_flag_groups_by_index[group_index] + except KeyError: + raise AttributeError("argument group_index is not a valid group index") + + 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. @@ -1318,6 +1647,37 @@ class Architecture(object): """ return self._flag_write_types[write_type] + def get_semantic_flag_class_by_name(self, sem_class): + """ + ``get_semantic_flag_class_by_name`` gets the semantic flag class index by name. + + :param int sem_class: semantic flag class + :return: semantic flag class index + :rtype: str + """ + return self._semantic_flag_classes[sem_class] + + def get_semantic_flag_group_by_name(self, sem_group): + """ + ``get_semantic_flag_group_by_name`` gets the semantic flag group index by name. + + :param int sem_group: semantic flag group + :return: semantic flag group index + :rtype: str + """ + return self._semantic_flag_groups[sem_group] + + def get_flag_role(self, flag, sem_class = None): + """ + ``get_flag_role`` gets the role of a given flag. + + :param int flag: flag + :param int sem_class: optional semantic flag class + :return: flag role + :rtype: FlagRole + """ + return self.perform_get_flag_role(flag, sem_class) + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: @@ -1328,20 +1688,7 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - flag = self.get_flag_index(flag) - operand_list = (core.BNRegisterOrConstant * len(operands))() - for i in xrange(len(operands)): - if isinstance(operands[i], str): - operand_list[i].constant = False - operand_list[i].reg = self.regs[operands[i]].index - elif isinstance(operands[i], lowlevelil.ILRegister): - operand_list[i].constant = False - operand_list[i].reg = operands[i].index - else: - operand_list[i].constant = True - operand_list[i].value = operands[i] - return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle)) + return self.perform_get_flag_write_low_level_il(op, size, write_type, flag, operands, il) def get_default_flag_write_low_level_il(self, op, size, role, operands, il): """ @@ -1367,21 +1714,35 @@ class Architecture(object): return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, role, operand_list, len(operand_list), il.handle)) - def get_flag_condition_low_level_il(self, cond, il): + def get_flag_condition_low_level_il(self, cond, sem_class, il): + """ + :param LowLevelILFlagCondition cond: Flag condition to be computed + :param str sem_class: Semantic class to be used (None for default semantics) + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to + :rtype: LowLevelILExpr + """ + return self.perform_get_flag_condition_low_level_il(cond, sem_class, il) + + def get_default_flag_condition_low_level_il(self, cond, sem_class, il): """ :param LowLevelILFlagCondition cond: :param LowLevelILFunction il: + :param str sem_class: :rtype: LowLevelILExpr """ - return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + class_index = self.get_semantic_flag_class_index(sem_class) + return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, class_index, il.handle)) - def get_default_flag_condition_low_level_il(self, cond, il): + def get_semantic_flag_group_low_level_il(self, sem_group, il): """ - :param LowLevelILFlagCondition cond: + :param str sem_group: :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + return self.perform_get_semantic_flag_group_low_level_il(sem_group, il) + + def get_flags_required_for_flag_condition(self, cond, sem_class = None): + return self.perform_get_flags_required_for_flag_condition(cond, sem_class) def get_modified_regs_on_write(self, reg): """ @@ -1405,6 +1766,648 @@ class Architecture(object): ``assemble`` converts the string of assembly instructions ``code`` loaded at virtual address ``addr`` to the byte representation of those instructions. + .. note:: Architecture subclasses should implement this method. + + Architecture plugins can override this method to provide assembler functionality. This can be done by + simply shelling out to an assembler like yasm or llvm-mc, since this method isn't performance sensitive. + + .. note :: It is important that the assembler used accepts a syntax identical to the one emitted by the \ + disassembler. This will prevent confusing the user. + + :param str code: string representation of the instructions to be assembled + :param int addr: virtual address that the instructions will be loaded at + :return: the bytes for the assembled instructions or error string + :rtype: (a tuple of instructions and empty string) or (or None and error string) + :Example: + + >>> arch.assemble("je 10") + ('\\x0f\\x84\\x04\\x00\\x00\\x00', '') + >>> + """ + return self.perform_assemble(code, addr) + + def is_never_branch_patch_available(self, data, addr): + """ + ``is_never_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be made to **never branch**. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be checked + :param int addr: the virtual address of the instruction to be patched + :return: True if the instruction can be patched, False otherwise + :rtype: bool + :Example: + + >>> arch.is_never_branch_patch_available(arch.assemble("je 10")[0], 0) + True + >>> arch.is_never_branch_patch_available(arch.assemble("nop")[0], 0) + False + >>> + """ + return self.perform_is_never_branch_patch_available(data, addr) + + def is_always_branch_patch_available(self, data, addr): + """ + ``is_always_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be made to + **always branch**. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be checked + :param int addr: the virtual address of the instruction to be patched + :return: True if the instruction can be patched, False otherwise + :rtype: bool + :Example: + + >>> arch.is_always_branch_patch_available(arch.assemble("je 10")[0], 0) + True + >>> arch.is_always_branch_patch_available(arch.assemble("nop")[0], 0) + False + >>> + """ + return self.perform_is_always_branch_patch_available(data, addr) + + def is_invert_branch_patch_available(self, data, addr): + """ + ``is_always_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be inverted. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be checked + :param int addr: the virtual address of the instruction to be patched + :return: True if the instruction can be patched, False otherwise + :rtype: bool + :Example: + + >>> arch.is_invert_branch_patch_available(arch.assemble("je 10")[0], 0) + True + >>> arch.is_invert_branch_patch_available(arch.assemble("nop")[0], 0) + False + >>> + """ + return self.perform_is_invert_branch_patch_available(data, addr) + + def is_skip_and_return_zero_patch_available(self, data, addr): + """ + ``is_skip_and_return_zero_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like* + instruction that can be made into an instruction *returns zero*. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be checked + :param int addr: the virtual address of the instruction to be patched + :return: True if the instruction can be patched, False otherwise + :rtype: bool + :Example: + + >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call 0")[0], 0) + True + >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call eax")[0], 0) + True + >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("jmp eax")[0], 0) + False + >>> + """ + return self.perform_is_skip_and_return_zero_patch_available(data, addr) + + def is_skip_and_return_value_patch_available(self, data, addr): + """ + ``is_skip_and_return_value_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like* + instruction that can be made into an instruction *returns a value*. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be checked + :param int addr: the virtual address of the instruction to be patched + :return: True if the instruction can be patched, False otherwise + :rtype: bool + :Example: + + >>> arch.is_skip_and_return_value_patch_available(arch.assemble("call 0")[0], 0) + True + >>> arch.is_skip_and_return_value_patch_available(arch.assemble("jmp eax")[0], 0) + False + >>> + """ + return self.perform_is_skip_and_return_value_patch_available(data, addr) + + def convert_to_nop(self, data, addr): + """ + ``convert_to_nop`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of nop + instructions of the same length as data. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be converted + :param int addr: the virtual address of the instruction to be patched + :return: string containing len(data) worth of no-operation instructions + :rtype: str + :Example: + + >>> arch.convert_to_nop("\\x00\\x00", 0) + '\\x90\\x90' + >>> + """ + return self.perform_convert_to_nop(data, addr) + + def always_branch(self, data, addr): + """ + ``always_branch`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of bytes + of the same length which always branches. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be converted + :param int addr: the virtual address of the instruction to be patched + :return: string containing len(data) which always branches to the same location as the provided instruction + :rtype: str + :Example: + + >>> bytes = arch.always_branch(arch.assemble("je 10")[0], 0) + >>> arch.get_instruction_text(bytes, 0) + (['nop '], 1L) + >>> arch.get_instruction_text(bytes[1:], 0) + (['jmp ', '0x9'], 5L) + >>> + """ + return self.perform_always_branch(data, addr) + + def invert_branch(self, data, addr): + """ + ``invert_branch`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of bytes + of the same length which inverts the branch of provided instruction. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be converted + :param int addr: the virtual address of the instruction to be patched + :return: string containing len(data) which always branches to the same location as the provided instruction + :rtype: str + :Example: + + >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("je 10")[0], 0), 0) + (['jne ', '0xa'], 6L) + >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("jo 10")[0], 0), 0) + (['jno ', '0xa'], 6L) + >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("jge 10")[0], 0), 0) + (['jl ', '0xa'], 6L) + >>> + """ + return self.perform_invert_branch(data, addr) + + def skip_and_return_value(self, data, addr, value): + """ + ``skip_and_return_value`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of + bytes of the same length which doesn't call and instead *return a value*. + + .. note:: Architecture subclasses should implement this method. + + :param str data: bytes for the instruction to be converted + :param int addr: the virtual address of the instruction to be patched + :return: string containing len(data) which always branches to the same location as the provided instruction + :rtype: str + :Example: + + >>> arch.get_instruction_text(arch.skip_and_return_value(arch.assemble("call 10")[0], 0, 0), 0) + (['mov ', 'eax', ', ', '0x0'], 5L) + >>> + """ + return self.perform_skip_and_return_value(data, addr, value) + + def is_view_type_constant_defined(self, type_name, const_name): + """ + + :param str type_name: the BinaryView type name of the constant to query + :param str const_name: the constant name to query + :rtype: None + :Example: + + >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) + >>> arch.is_view_type_constant_defined("ELF", "R_COPY") + True + >>> arch.is_view_type_constant_defined("ELF", "NOT_THERE") + False + >>> + """ + return core.BNIsBinaryViewTypeArchitectureConstantDefined(self.handle, type_name, const_name) + + def get_view_type_constant(self, type_name, const_name, default_value=0): + """ + ``get_view_type_constant`` retrieves the view type constant for the given type_name and const_name. + + :param str type_name: the BinaryView type name of the constant to be retrieved + :param str const_name: the constant name to retrieved + :param int value: optional default value if the type_name is not present. default value is zero. + :return: The BinaryView type constant or the default_value if not found + :rtype: int + :Example: + + >>> ELF_RELOC_COPY = 5 + >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) + >>> arch.get_view_type_constant("ELF", "R_COPY") + 5L + >>> arch.get_view_type_constant("ELF", "NOT_HERE", 100) + 100L + """ + return core.BNGetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, default_value) + + def set_view_type_constant(self, type_name, const_name, value): + """ + ``set_view_type_constant`` creates a new binaryview type constant. + + :param str type_name: the BinaryView type name of the constant to be registered + :param str const_name: the constant name to register + :param int value: the value of the constant + :rtype: None + :Example: + + >>> ELF_RELOC_COPY = 5 + >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) + >>> + """ + core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) + + def register_calling_convention(self, cc): + """ + ``register_calling_convention`` registers a new calling convention for the Architecture. + + :param CallingConvention cc: CallingConvention object to be registered + :rtype: None + """ + core.BNRegisterCallingConvention(self.handle, cc.handle) + + +_architecture_cache = {} +class CoreArchitecture(Architecture): + def __init__(self, handle): + super(CoreArchitecture, self).__init__() + + self.handle = core.handle_of_type(handle, core.BNArchitecture) + self.__dict__["name"] = core.BNGetArchitectureName(self.handle) + self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle)) + self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle) + self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle) + self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle) + self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle) + self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle) + self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle, + core.BNGetArchitectureStackPointerRegister(self.handle)) + + link_reg = core.BNGetArchitectureLinkRegister(self.handle) + if link_reg == 0xffffffff: + self.__dict__["link_reg"] = None + else: + self.__dict__["link_reg"] = core.BNGetArchitectureRegisterName(self.handle, link_reg) + + count = ctypes.c_ulonglong() + regs = core.BNGetAllArchitectureRegisters(self.handle, count) + self._all_regs = {} + self._regs_by_index = {} + self._full_width_regs = {} + self.__dict__["regs"] = {} + for i in xrange(0, count.value): + name = core.BNGetArchitectureRegisterName(self.handle, regs[i]) + info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) + full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) + self.regs[name] = function.RegisterInfo(full_width_reg, info.size, info.offset, + ImplicitRegisterExtend(info.extend), regs[i]) + self._all_regs[name] = regs[i] + self._regs_by_index[regs[i]] = name + for i in xrange(0, count.value): + info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) + full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) + if full_width_reg not in self._full_width_regs: + self._full_width_regs[full_width_reg] = self._all_regs[full_width_reg] + core.BNFreeRegisterList(regs) + + count = ctypes.c_ulonglong() + flags = core.BNGetAllArchitectureFlags(self.handle, count) + self._flags = {} + self._flags_by_index = {} + self.__dict__["flags"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureFlagName(self.handle, flags[i]) + self._flags[name] = flags[i] + self._flags_by_index[flags[i]] = name + self.flags.append(name) + core.BNFreeRegisterList(flags) + + count = ctypes.c_ulonglong() + write_types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count) + self._flag_write_types = {} + self._flag_write_types_by_index = {} + self.__dict__["flag_write_types"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureFlagWriteTypeName(self.handle, write_types[i]) + self._flag_write_types[name] = write_types[i] + self._flag_write_types_by_index[write_types[i]] = name + self.flag_write_types.append(name) + core.BNFreeRegisterList(write_types) + + count = ctypes.c_ulonglong() + sem_classes = core.BNGetAllArchitectureSemanticFlagClasses(self.handle, count) + self._semantic_flag_classes = {} + self._semantic_flag_classes_by_index = {} + self.__dict__["semantic_flag_classes"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureSemanticFlagClassName(self.handle, sem_classes[i]) + self._semantic_flag_classes[name] = sem_classes[i] + self._semantic_flag_classes_by_index[sem_classes[i]] = name + self.semantic_flag_classes.append(name) + core.BNFreeRegisterList(sem_classes) + + count = ctypes.c_ulonglong() + sem_groups = core.BNGetAllArchitectureSemanticFlagGroups(self.handle, count) + self._semantic_flag_groups = {} + self._semantic_flag_groups_by_index = {} + self.__dict__["semantic_flag_groups"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureSemanticFlagGroupName(self.handle, sem_groups[i]) + self._semantic_flag_groups[name] = sem_groups[i] + self._semantic_flag_groups_by_index[sem_groups[i]] = name + self.semantic_flag_groups.append(name) + core.BNFreeRegisterList(sem_groups) + + self._flag_roles = {} + self.__dict__["flag_roles"] = {} + for flag in self.__dict__["flags"]: + role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag], 0)) + self.__dict__["flag_roles"][flag] = role + self._flag_roles[self._flags[flag]] = role + + self.__dict__["flags_required_for_flag_condition"] = {} + for cond in LowLevelILFlagCondition: + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, 0, count) + flag_names = [] + for i in xrange(0, count.value): + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + self.__dict__["flags_required_for_flag_condition"][cond] = flag_names + + self._flags_required_by_semantic_flag_group = {} + self.__dict__["flags_required_for_semantic_flag_group"] = {} + for group in self.semantic_flag_groups: + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsRequiredForSemanticFlagGroup(self.handle, + self._semantic_flag_groups[group], count) + flag_indexes = [] + flag_names = [] + for i in xrange(0, count.value): + flag_indexes.append(flags[i]) + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flag_indexes + self.__dict__["flags_required_for_semantic_flag_group"][cond] = flag_names + + self._flag_conditions_for_semantic_flag_group = {} + self.__dict__["flag_conditions_for_semantic_flag_group"] = {} + for group in self.semantic_flag_groups: + count = ctypes.c_ulonglong() + conditions = core.BNGetArchitectureFlagConditionsForSemanticFlagGroup(self.handle, + self._semantic_flag_groups[group], count) + class_index_cond = {} + class_cond = {} + for i in xrange(0, count.value): + class_index_cond[conditions[i].semanticClass] = conditions[i].condition + if conditions[i].semanticClass == 0: + class_cond[None] = conditions[i].condition + elif conditions[i].semanticClass in self._semantic_flag_classes_by_index: + class_cond[self._semantic_flag_classes_by_index[conditions[i].semanticClass]] = conditions[i].condition + core.BNFreeFlagConditionsForSemanticFlagGroup(conditions) + self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_index_cond + self.__dict__["flag_conditions_for_semantic_flag_group"][group] = class_cond + + self._flags_written_by_flag_write_type = {} + self.__dict__["flags_written_by_flag_write_type"] = {} + for write_type in self.flag_write_types: + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle, + self._flag_write_types[write_type], count) + flag_indexes = [] + flag_names = [] + for i in xrange(0, count.value): + flag_indexes.append(flags[i]) + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes + self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names + + self._semantic_class_for_flag_write_type = {} + self.__dict__["semantic_class_for_flag_write_type"] = {} + for write_type in self.flag_write_types: + sem_class = core.BNGetArchitectureSemanticClassForFlagWriteType(self.handle, + self._flag_write_types[write_type]) + if sem_class == 0: + sem_class_name = None + else: + sem_class_name = self._semantic_flag_classes_by_index[sem_class] + self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class + self.__dict__["semantic_class_for_flag_write_type"][write_type] = sem_class_name + + count = ctypes.c_ulonglong() + regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) + self.__dict__["global_regs"] = [] + for i in xrange(0, count.value): + self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) + core.BNFreeRegisterList(regs) + + count = ctypes.c_ulonglong() + regs = core.BNGetAllArchitectureRegisterStacks(self.handle, count) + self._all_reg_stacks = {} + self._reg_stacks_by_index = {} + self.__dict__["reg_stacks"] = {} + for i in xrange(0, count.value): + name = core.BNGetArchitectureRegisterStackName(self.handle, regs[i]) + info = core.BNGetArchitectureRegisterStackInfo(self.handle, regs[i]) + storage = [] + for j in xrange(0, info.storageCount): + storage.append(core.BNGetArchitectureRegisterName(self.handle, info.firstStorageReg + j)) + top_rel = [] + for j in xrange(0, info.topRelativeCount): + top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j)) + top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg) + self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i]) + self._all_reg_stacks[name] = regs[i] + self._reg_stacks_by_index[regs[i]] = name + core.BNFreeRegisterList(regs) + + count = ctypes.c_ulonglong() + intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count) + self._intrinsics = {} + self._intrinsics_by_index = {} + 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) + self._intrinsics[name] = intrinsics[i] + self._intrinsics_by_index[intrinsics[i]] = (name, self.intrinsics[name]) + core.BNFreeRegisterList(intrinsics) + global _architecture_cache + _architecture_cache[ctypes.addressof(handle.contents)] = self + + @classmethod + def _from_cache(cls, handle): + global _architecture_cache + return _architecture_cache.get(ctypes.addressof(handle.contents)) or cls(handle) + + def get_associated_arch_by_address(self, addr): + new_addr = ctypes.c_ulonglong() + new_addr.value = addr + result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr) + return CoreArchitecture._from_cache(handle = result), new_addr.value + + def get_instruction_info(self, data, addr): + """ + ``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address + ``addr`` with data ``data``. + + .. note :: The instruction info object should always set the InstructionInfo.length to the instruction length, \ + and the branches of the proper types shoulde be added if the instruction is a branch. + + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` + :param int addr: virtual address of bytes in ``data`` + :return: the InstructionInfo for the current instruction + :rtype: InstructionInfo + """ + info = core.BNInstructionInfo() + data = str(data) + buf = (ctypes.c_ubyte * len(data))() + ctypes.memmove(buf, data, len(data)) + if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info): + return None + result = function.InstructionInfo() + result.length = info.length + result.arch_transition_by_target_addr = info.archTransitionByTargetAddr + result.branch_delay = info.branchDelay + for i in xrange(0, info.branchCount): + target = info.branchTarget[i] + if info.branchArch[i]: + arch = CoreArchitecture._from_cache(info.branchArch[i]) + else: + arch = None + result.add_branch(BranchType(info.branchType[i]), target, arch) + return result + + def get_instruction_text(self, data, addr): + """ + ``get_instruction_text`` returns a list of InstructionTextToken objects for the instruction at the given virtual + address ``addr`` with data ``data``. + + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` + :param int addr: virtual address of bytes in ``data`` + :return: an InstructionTextToken list for the current instruction + :rtype: list(InstructionTextToken) + """ + data = str(data) + count = ctypes.c_ulonglong() + length = ctypes.c_ulonglong() + length.value = len(data) + buf = (ctypes.c_ubyte * len(data))() + ctypes.memmove(buf, data, len(data)) + tokens = ctypes.POINTER(core.BNInstructionTextToken)() + if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count): + return None, 0 + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + confidence = tokens[i].confidence + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + core.BNFreeInstructionText(tokens, count.value) + return result, length.value + + def get_instruction_low_level_il(self, data, addr, il): + """ + ``get_instruction_low_level_il`` appends LowLevelILExpr objects to ``il`` for the instruction at the given + virtual address ``addr`` with data ``data``. + + This is used to analyze arbitrary data at an address, if you are working with an existing binary, you likely + want to be using ``Function.get_low_level_il_at``. + + :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` + :param int addr: virtual address of bytes in ``data`` + :param LowLevelILFunction il: The function the current instruction belongs to + :return: the length of the current instruction + :rtype: int + """ + data = str(data) + length = ctypes.c_ulonglong() + length.value = len(data) + buf = (ctypes.c_ubyte * len(data))() + ctypes.memmove(buf, data, len(data)) + core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle) + return length.value + + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): + """ + :param LowLevelILOperation op: + :param int size: + :param str write_type: + :param list(str or int) operands: a list of either items that are either string register names or constant \ + integer values + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + flag = self.get_flag_index(flag) + operand_list = (core.BNRegisterOrConstant * len(operands))() + for i in xrange(len(operands)): + if isinstance(operands[i], str): + operand_list[i].constant = False + operand_list[i].reg = self.regs[operands[i]].index + elif isinstance(operands[i], lowlevelil.ILRegister): + operand_list[i].constant = False + operand_list[i].reg = operands[i].index + else: + operand_list[i].constant = True + operand_list[i].value = operands[i] + return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, + self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle)) + + def get_flag_condition_low_level_il(self, cond, sem_class, il): + """ + :param LowLevelILFlagCondition cond: Flag condition to be computed + :param str sem_class: Semantic class to be used (None for default semantics) + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to + :rtype: LowLevelILExpr + """ + class_index = self.get_semantic_flag_class_index(sem_class) + return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, + class_index, il.handle)) + + def get_semantic_flag_group_low_level_il(self, sem_group, il): + """ + :param str sem_group: + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + group_index = self.get_semantic_flag_group_index(sem_group) + return lowlevelil.LowLevelILExpr(core.BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group_index, il.handle)) + + def assemble(self, code, addr=0): + """ + ``assemble`` converts the string of assembly instructions ``code`` loaded at virtual address ``addr`` to the + byte representation of those instructions. + :param str code: string representation of the instructions to be assembled :param int addr: virtual address that the instructions will be loaded at :return: the bytes for the assembled instructions or error string @@ -1511,7 +2514,7 @@ class Architecture(object): def is_skip_and_return_value_patch_available(self, data, addr): """ - ``is_skip_and_return_zero_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like* + ``is_skip_and_return_value_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like* instruction that can be made into an instruction *returns a value*. :param str data: bytes for the instruction to be checked @@ -1520,9 +2523,9 @@ class Architecture(object): :rtype: bool :Example: - >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call 0")[0], 0) + >>> arch.is_skip_and_return_value_patch_available(arch.assemble("call 0")[0], 0) True - >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("jmp eax")[0], 0) + >>> arch.is_skip_and_return_value_patch_available(arch.assemble("jmp eax")[0], 0) False >>> """ @@ -1634,67 +2637,62 @@ class Architecture(object): ctypes.memmove(result, buf, len(data)) return result.raw - def is_view_type_constant_defined(self, type_name, const_name): - """ - - :param str type_name: the BinaryView type name of the constant to query - :param str const_name: the constant name to query - :rtype: None - :Example: - - >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) - >>> arch.is_view_type_constant_defined("ELF", "R_COPY") - True - >>> arch.is_view_type_constant_defined("ELF", "NOT_THERE") - False - >>> + def get_flag_role(self, flag, sem_class = None): """ - return core.BNIsBinaryViewTypeArchitectureConstantDefined(self.handle, type_name, const_name) + ``get_flag_role`` gets the role of a given flag. - def get_view_type_constant(self, type_name, const_name, default_value=0): + :param int flag: flag + :param int sem_class: optional semantic flag class + :return: flag role + :rtype: FlagRole """ - ``get_view_type_constant`` retrieves the view type constant for the given type_name and const_name. - - :param str type_name: the BinaryView type name of the constant to be retrieved - :param str const_name: the constant name to retrieved - :param int value: optional default value if the type_name is not present. default value is zero. - :return: The BinaryView type constant or the default_value if not found - :rtype: int - :Example: - - >>> ELF_RELOC_COPY = 5 - >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) - >>> arch.get_view_type_constant("ELF", "R_COPY") - 5L - >>> arch.get_view_type_constant("ELF", "NOT_HERE", 100) - 100L - """ - return core.BNGetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, default_value) + flag = self.get_flag_index(flag) + sem_class = self.get_semantic_flag_class_index(sem_class) + return FlagRole(core.BNGetArchitectureFlagRole(self.handle, flag, sem_class)) - def set_view_type_constant(self, type_name, const_name, value): - """ - ``set_view_type_constant`` creates a new binaryview type constant. + def get_flags_required_for_flag_condition(self, cond, sem_class = None): + sem_class = self.get_semantic_flag_class_index(sem_class) + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, sem_class, count) + flag_names = [] + for i in xrange(0, count.value): + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + return flag_names - :param str type_name: the BinaryView type name of the constant to be registered - :param str const_name: the constant name to register - :param int value: the value of the constant - :rtype: None - :Example: - >>> ELF_RELOC_COPY = 5 - >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY) - >>> - """ - core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) +class ArchitectureHook(CoreArchitecture): + def __init__(self, base_arch): + self.base_arch = base_arch + super(ArchitectureHook, self).__init__(base_arch.handle) - def register_calling_convention(self, cc): - """ - ``register_calling_convention`` registers a new calling convention for the Architecture. + # To improve performance of simpler hooks, use null callback for functions that are not being overridden + if self.get_associated_arch_by_address.__code__ == CoreArchitecture.get_associated_arch_by_address.__code__: + self._cb.getAssociatedArchitectureByAddress = self._cb.getAssociatedArchitectureByAddress.__class__() + if self.get_instruction_info.__code__ == CoreArchitecture.get_instruction_info.__code__: + self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__() + if self.get_instruction_text.__code__ == CoreArchitecture.get_instruction_text.__code__: + self._cb.getInstructionText = self._cb.getInstructionText.__class__() + if self.__class__.stack_pointer is None: + self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__() + if self.__class__.link_reg is None: + self._cb.getLinkRegister = self._cb.getLinkRegister.__class__() + if len(self.__class__.regs) == 0: + self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__() + self._cb.getRegisterName = self._cb.getRegisterName.__class__() + if len(self.__class__.reg_stacks) == 0: + self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__() + self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__() + if len(self.__class__.intrinsics) == 0: + self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__() + self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__() + self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__() + self._cb.getIntrinsicOutputs = self._cb.getIntrinsicOutputs.__class__() + self._cb.freeTypeList = self._cb.freeTypeList.__class__() - :param CallingConvention cc: CallingConvention object to be registered - :rtype: None - """ - core.BNRegisterCallingConvention(self.handle, cc.handle) + def register(self): + self.__class__._registered_cb = self._cb + self.handle = core.BNRegisterArchitectureHook(self.base_arch.handle, self._cb) class ReferenceSource(object): diff --git a/python/basicblock.py b/python/basicblock.py index 8e64c1c1..4dc783c3 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -100,7 +100,7 @@ class BasicBlock(object): arch = core.BNGetBasicBlockArchitecture(self.handle) if arch is None: return None - self._arch = architecture.Architecture(arch) + self._arch = architecture.CoreArchitecture._from_cache(arch) return self._arch @property @@ -256,6 +256,21 @@ class BasicBlock(object): def highlight(self, value): self.set_user_highlight(value) + @property + def is_il(self): + """Whether the basic block contains IL""" + return core.BNIsILBasicBlock(self.handle) + + @property + def is_low_level_il(self): + """Whether the basic block contains Low Level IL""" + return core.BNIsLowLevelILBasicBlock(self.handle) + + @property + def is_medium_level_il(self): + """Whether the basic block contains Medium Level IL""" + return core.BNIsMediumLevelILBasicBlock(self.handle) + @classmethod def get_iterated_dominance_frontier(self, blocks): if len(blocks) == 0: @@ -322,6 +337,10 @@ class BasicBlock(object): result = [] for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(self, 'il_function'): + il_instr = self.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -333,7 +352,7 @@ class BasicBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - result.append(function.DisassemblyTextLine(addr, tokens)) + result.append(function.DisassemblyTextLine(addr, tokens, il_instr)) core.BNFreeDisassemblyTextLines(lines, count.value) return result diff --git a/python/binaryview.py b/python/binaryview.py index 19bff9e5..0b090a9a 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -65,6 +65,9 @@ class BinaryDataNotification(object): def function_updated(self, view, func): pass + def function_update_requested(self, view, func): + pass + def data_var_added(self, view, var): pass @@ -105,7 +108,8 @@ class StringReference(object): class AnalysisCompletionEvent(object): """ The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving - callbacks when analysis is complete. + callbacks when analysis is complete. The callback runs once. A completion event must be added + for each new analysis in order to be notified of each analysis completion. :Example: >>> def on_complete(self): @@ -180,6 +184,7 @@ class BinaryDataNotificationCallbacks(object): self._cb.functionAdded = self._cb.functionAdded.__class__(self._function_added) self._cb.functionRemoved = self._cb.functionRemoved.__class__(self._function_removed) self._cb.functionUpdated = self._cb.functionUpdated.__class__(self._function_updated) + self._cb.functionUpdateRequested = self._cb.functionUpdateRequested.__class__(self._function_update_requested) self._cb.dataVariableAdded = self._cb.dataVariableAdded.__class__(self._data_var_added) self._cb.dataVariableRemoved = self._cb.dataVariableRemoved.__class__(self._data_var_removed) self._cb.dataVariableUpdated = self._cb.dataVariableUpdated.__class__(self._data_var_updated) @@ -230,6 +235,12 @@ class BinaryDataNotificationCallbacks(object): except: log.log_error(traceback.format_exc()) + def _function_update_requested(self, ctxt, view, func): + try: + self.notify.function_update_requested(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + except: + log.log_error(traceback.format_exc()) + def _data_var_added(self, ctxt, view, var): try: address = var[0].address @@ -400,7 +411,7 @@ class BinaryViewType(object): arch = core.BNGetArchitectureForViewType(self.handle, ident, endian) if arch is None: return None - return architecture.Architecture(arch) + return architecture.CoreArchitecture._from_cache(arch) def register_platform(self, ident, arch, plat): core.BNRegisterPlatformForViewType(self.handle, ident, arch.handle, plat.handle) @@ -857,7 +868,7 @@ class BinaryView(object): arch = core.BNGetDefaultArchitecture(self.handle) if arch is None: return None - return architecture.Architecture(handle=arch) + return architecture.CoreArchitecture._from_cache(handle=arch) @arch.setter def arch(self, value): @@ -1054,6 +1065,15 @@ class BinaryView(object): result = core.BNGetGlobalPointerValue(self.handle) return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + @property + def max_function_size_for_analysis(self): + """Maximum size of function (sum of basic block sizes in bytes) for auto analysis""" + return core.BNGetMaxFunctionSizeForAnalysis(self.handle) + + @max_function_size_for_analysis.setter + def max_function_size_for_analysis(self, size): + core.BNSetMaxFunctionSizeForAnalysis(self.handle, size) + def __len__(self): return int(core.BNGetViewLength(self.handle)) @@ -2146,6 +2166,8 @@ class BinaryView(object): """ if plat is None: plat = self.platform + if plat is None: + return None func = core.BNGetAnalysisFunction(self.handle, plat.handle, addr) if func is None: return None @@ -2240,7 +2262,7 @@ class BinaryView(object): else: func = None if refs[i].arch: - arch = architecture.Architecture(refs[i].arch) + arch = architecture.CoreArchitecture._from_cache(refs[i].arch) else: arch = None addr = refs[i].addr diff --git a/python/callingconvention.py b/python/callingconvention.py index e72475c9..e3ec7261 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -28,6 +28,7 @@ import log import types import function import binaryview +from enums import VariableSourceType class CallingConvention(object): @@ -68,11 +69,13 @@ class CallingConvention(object): self._cb.getImplicitlyDefinedRegisters = self._cb.getImplicitlyDefinedRegisters.__class__(self._get_implicitly_defined_regs) self._cb.getIncomingRegisterValue = self._cb.getIncomingRegisterValue.__class__(self._get_incoming_reg_value) self._cb.getIncomingFlagValue = self._cb.getIncomingFlagValue.__class__(self._get_incoming_flag_value) + self._cb.getIncomingVariableForParameterVariable = self._cb.getIncomingVariableForParameterVariable.__class__(self._get_incoming_var_for_parameter_var) + self._cb.getParameterVariableForIncomingVariable = self._cb.getParameterVariableForIncomingVariable.__class__(self._get_parameter_var_for_incoming_var) self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb) self.__class__._registered_calling_conventions.append(self) else: self.handle = handle - self.arch = architecture.Architecture(core.BNGetCallingConventionArchitecture(self.handle)) + self.arch = architecture.CoreArchitecture._from_cache(core.BNGetCallingConventionArchitecture(self.handle)) self.__dict__["name"] = core.BNGetCallingConventionName(self.handle) self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle) self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle) @@ -301,6 +304,42 @@ class CallingConvention(object): result[0].state = api_obj.state result[0].value = api_obj.value + def _get_incoming_var_for_parameter_var(self, ctxt, in_var, func, result): + try: + if func is None: + func_obj = None + else: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) + out_var = self.perform_get_incoming_var_for_parameter_var(in_var_obj, func_obj) + result[0].type = out_var.source_type + result[0].index = out_var.index + result[0].storage = out_var.storage + except: + log.log_error(traceback.format_exc()) + result[0].type = in_var[0].type + result[0].index = in_var[0].index + result[0].storage = in_var[0].storage + + def _get_parameter_var_for_incoming_var(self, ctxt, in_var, func, result): + try: + if func is None: + func_obj = None + else: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) + out_var = self.perform_get_parameter_var_for_incoming_var(in_var_obj, func_obj) + result[0].type = out_var.source_type + result[0].index = out_var.index + result[0].storage = out_var.storage + except: + log.log_error(traceback.format_exc()) + result[0].type = in_var[0].type + result[0].index = in_var[0].index + result[0].storage = in_var[0].storage + def __repr__(self): return "<calling convention: %s %s>" % (self.arch.name, self.name) @@ -308,11 +347,34 @@ class CallingConvention(object): return self.name def perform_get_incoming_reg_value(self, reg, func): + reg_stack = self.arch.get_reg_stack_for_reg(reg) + if reg_stack is not None: + if reg == self.arch.reg_stacks[reg_stack].stack_top_reg: + return function.RegisterValue.constant(0) return function.RegisterValue() def perform_get_incoming_flag_value(self, reg, func): return function.RegisterValue() + def perform_get_incoming_var_for_parameter_var(self, in_var, func): + in_buf = core.BNVariable() + in_buf.type = in_var.source_type + in_buf.index = in_var.index + in_buf.storage = in_var.storage + out_var = core.BNGetDefaultIncomingVariableForParameterVariable(self.handle, in_buf) + name = None + if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType): + name = func.arch.get_reg_name(out_var.storage) + return function.Variable(func, out_var.type, out_var.index, out_var.storage, name) + + def perform_get_parameter_var_for_incoming_var(self, in_var, func): + in_buf = core.BNVariable() + in_buf.type = in_var.source_type + in_buf.index = in_var.index + in_buf.storage = in_var.storage + out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_buf) + return function.Variable(func, out_var.type, out_var.index, out_var.storage) + def with_confidence(self, confidence): return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), confidence = confidence) @@ -330,3 +392,30 @@ class CallingConvention(object): if func is not None: func_handle = func.handle return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle)) + + def get_incoming_var_for_parameter_var(self, in_var, func): + in_buf = core.BNVariable() + in_buf.type = in_var.source_type + in_buf.index = in_var.index + in_buf.storage = in_var.storage + if func is None: + func_obj = None + else: + func_obj = func.handle + out_var = core.BNGetIncomingVariableForParameterVariable(self.handle, in_buf, func_obj) + name = None + if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType): + name = func.arch.get_reg_name(out_var.storage) + return function.Variable(func, out_var.type, out_var.index, out_var.storage, name) + + def get_parameter_var_for_incoming_var(self, in_var, func): + in_buf = core.BNVariable() + in_buf.type = in_var.source_type + in_buf.index = in_var.index + in_buf.storage = in_var.storage + if func is None: + func_obj = None + else: + func_obj = func.handle + out_var = core.BNGetParameterVariableForIncomingVariable(self.handle, in_buf, func_obj) + return function.Variable(func, out_var.type, out_var.index, out_var.storage) diff --git a/python/examples/arch_hook.py b/python/examples/arch_hook.py new file mode 100644 index 00000000..452bd2b6 --- /dev/null +++ b/python/examples/arch_hook.py @@ -0,0 +1,16 @@ +from binaryninja.architecture import Architecture, ArchitectureHook + +class X86ReturnHook(ArchitectureHook): + def get_instruction_text(self, data, addr): + # Call the original implementation's method by calling the superclass + result, length = super(X86ReturnHook, self).get_instruction_text(data, addr) + + # Patch the name of the 'retn' instruction to 'ret' + if len(result) > 0 and result[0].text == 'retn': + result[0].text = 'ret' + + return result, length + +# Install the hook by constructing it with the desired architecture to hook, then registering it +X86ReturnHook(Architecture['x86']).register() + diff --git a/python/examples/nes.py b/python/examples/nes.py index 39544c9f..00451abd 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -423,7 +423,7 @@ class M6502(Architecture): return instr, operand, length, value - def perform_get_instruction_info(self, data, addr): + def get_instruction_info(self, data, addr): instr, operand, length, value = self.decode_instruction(data, addr) if instr is None: return None @@ -445,7 +445,7 @@ class M6502(Architecture): result.add_branch(BranchType.FalseBranch, addr + 2) return result - def perform_get_instruction_text(self, data, addr): + def get_instruction_text(self, data, addr): instr, operand, length, value = self.decode_instruction(data, addr) if instr is None: return None @@ -455,7 +455,7 @@ class M6502(Architecture): tokens += OperandTokens[operand](value) return tokens, length - def perform_get_instruction_low_level_il(self, data, addr, il): + def get_instruction_low_level_il(self, data, addr, il): instr, operand, length, value = self.decode_instruction(data, addr) if instr is None: return None @@ -470,48 +470,48 @@ class M6502(Architecture): return length - def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): if flag == 'c': if (op == LowLevelILOperation.LLIL_SUB) or (op == LowLevelILOperation.LLIL_SBB): # Subtraction carry flag is inverted from the commom implementation return il.not_expr(0, self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il)) # Other operations use a normal carry flag return self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il) - return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il) + return Architecture.get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il) - def perform_is_never_branch_patch_available(self, data, addr): + def is_never_branch_patch_available(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return True return False - def perform_is_invert_branch_patch_available(self, data, addr): + def is_invert_branch_patch_available(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return True return False - def perform_is_always_branch_patch_available(self, data, addr): + def is_always_branch_patch_available(self, data, addr): return False - def perform_is_skip_and_return_zero_patch_available(self, data, addr): + def is_skip_and_return_zero_patch_available(self, data, addr): return (data[0] == "\x20") and (len(data) == 3) - def perform_is_skip_and_return_value_patch_available(self, data, addr): + def is_skip_and_return_value_patch_available(self, data, addr): return (data[0] == "\x20") and (len(data) == 3) - def perform_convert_to_nop(self, data, addr): + def convert_to_nop(self, data, addr): return "\xea" * len(data) - def perform_never_branch(self, data, addr): + def never_branch(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return "\xea" * len(data) return None - def perform_invert_branch(self, data, addr): + def invert_branch(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return chr(ord(data[0]) ^ 0x20) + data[1:] return None - def perform_skip_and_return_value(self, data, addr, value): + def skip_and_return_value(self, data, addr, value): if (data[0] != "\x20") or (len(data) != 3): return None return "\xa9" + chr(value & 0xff) + "\xea" diff --git a/python/function.py b/python/function.py index 58bee8f4..6db44e6d 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,8 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, + FunctionAnalysisSkipOverride) import architecture import platform import highlight @@ -51,11 +52,11 @@ class LookupTableEntry(object): class RegisterValue(object): def __init__(self, arch = None, value = None, confidence = types.max_confidence): + self.is_constant = False if value is None: self.type = RegisterValueType.UndeterminedValue else: self.type = RegisterValueType(value.state) - self.is_constant = False if value.state == RegisterValueType.EntryValue: self.arch = arch if arch is not None: @@ -103,6 +104,54 @@ class RegisterValue(object): result.value = self.value return result + @classmethod + def undetermined(self): + return RegisterValue() + + @classmethod + def entry_value(self, arch, reg): + result = RegisterValue() + result.type = RegisterValueType.EntryValue + result.arch = arch + result.reg = reg + return result + + @classmethod + def constant(self, value): + result = RegisterValue() + result.type = RegisterValueType.ConstantValue + result.value = value + result.is_constant = True + return result + + @classmethod + def constant_ptr(self, value): + result = RegisterValue() + result.type = RegisterValueType.ConstantPointerValue + result.value = value + result.is_constant = True + return result + + @classmethod + def stack_frame_offset(self, offset): + result = RegisterValue() + result.type = RegisterValueType.StackFrameOffset + result.offset = offset + return result + + @classmethod + def imported_address(self, value): + result = RegisterValue() + result.type = RegisterValueType.ImportedAddressValue + result.value = value + return result + + @classmethod + def return_address(self): + result = RegisterValue() + result.type = RegisterValueType.ReturnAddressValue + return result + class ValueRange(object): def __init__(self, start, end, step): @@ -177,9 +226,9 @@ class PossibleValueSet(object): if self.type == RegisterValueType.LookupTableValue: return "<table: %s>" % ', '.join([repr(i) for i in self.table]) if self.type == RegisterValueType.InSetOfValues: - return "<in %s>" % repr(self.values) + return "<in set(%s)>" % '[{}]'.format(', '.join(hex(i) for i in self.values)) if self.type == RegisterValueType.NotInSetOfValues: - return "<not in %s>" % repr(self.values) + return "<not in set(%s)>" % '[{}]'.format(', '.join(hex(i) for i in self.values)) if self.type == RegisterValueType.ReturnAddressValue: return "<return address>" return "<undetermined>" @@ -219,14 +268,15 @@ class Variable(object): var.storage = storage self.identifier = core.BNToVariableIdentifier(var) - if name is None: - name = core.BNGetVariableName(func.handle, var) - if var_type is None: - var_type_conf = core.BNGetVariableType(func.handle, var) - if var_type_conf.type: - var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence) - else: - var_type = None + if func is not None: + if name is None: + name = core.BNGetVariableName(func.handle, var) + if var_type is None: + var_type_conf = core.BNGetVariableType(func.handle, var) + if var_type_conf.type: + var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence) + else: + var_type = None self.name = name self.type = var_type @@ -370,7 +420,7 @@ class Function(object): arch = core.BNGetFunctionArchitecture(self.handle) if arch is None: return None - self._arch = architecture.Architecture(arch) + self._arch = architecture.CoreArchitecture._from_cache(arch) return self._arch @property @@ -378,7 +428,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 @@ -485,7 +535,7 @@ class Function(object): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) - core.BNFreeVariableList(v, count.value) + core.BNFreeVariableNameAndTypeList(v, count.value) return result @property @@ -498,7 +548,7 @@ class Function(object): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) - core.BNFreeVariableList(v, count.value) + core.BNFreeVariableNameAndTypeList(v, count.value) return result @property @@ -508,7 +558,7 @@ class Function(object): branches = core.BNGetIndirectBranches(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(IndirectBranchInfo(architecture.Architecture(branches[i].sourceArch), branches[i].sourceAddr, architecture.Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -558,6 +608,30 @@ class Function(object): core.BNSetUserFunctionReturnType(self.handle, type_conf) @property + def return_regs(self): + """Registers that are used for the return value""" + result = core.BNGetFunctionReturnRegisters(self.handle) + reg_set = [] + for i in xrange(0, result.count): + reg_set.append(self.arch.get_reg_name(result.regs[i])) + regs = types.RegisterSet(reg_set, confidence = result.confidence) + core.BNFreeRegisterSet(result) + return regs + + @return_regs.setter + def return_regs(self, value): + regs = core.BNRegisterSetWithConfidence() + regs.regs = (ctypes.c_uint * len(value))() + regs.count = len(value) + for i in xrange(0, len(value)): + regs.regs[i] = self.arch.get_reg_index(value[i]) + if hasattr(value, 'confidence'): + regs.confidence = value.confidence + else: + regs.confidence = types.max_confidence + core.BNSetUserFunctionReturnRegisters(self.handle, regs) + + @property def calling_convention(self): """Calling convention used by the function""" result = core.BNGetFunctionCallingConvention(self.handle) @@ -641,6 +715,35 @@ class Function(object): core.BNSetUserFunctionStackAdjustment(self.handle, sc) @property + def reg_stack_adjustments(self): + """Number of entries removed from each register stack after return""" + count = ctypes.c_ulonglong() + adjust = core.BNGetFunctionRegisterStackAdjustments(self.handle, count) + result = {} + for i in xrange(0, count.value): + name = self.arch.get_reg_stack_name(adjust[i].regStack) + value = types.RegisterStackAdjustmentWithConfidence(adjust[i].adjustment, + confidence = adjust[i].confidence) + result[name] = value + core.BNFreeRegisterStackAdjustments(adjust) + return result + + @reg_stack_adjustments.setter + def reg_stack_adjustments(self, value): + adjust = (core.BNRegisterStackAdjustment * len(value))() + i = 0 + for reg_stack in value.keys(): + adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack) + if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence): + adjust[i].adjustment = value[reg_stack].value + adjust[i].confidence = value[reg_stack].confidence + else: + adjust[i].adjustment = value[reg_stack] + adjust[i].confidence = types.max_confidence + i += 1 + core.BNSetUserFunctionRegisterStackAdjustments(self.handle, adjust, len(value)) + + @property def clobbered_regs(self): """Registers that are modified by this function""" result = core.BNGetFunctionClobberedRegisters(self.handle) @@ -648,7 +751,7 @@ class Function(object): for i in xrange(0, result.count): reg_set.append(self.arch.get_reg_name(result.regs[i])) regs = types.RegisterSet(reg_set, confidence = result.confidence) - core.BNFreeClobberedRegisters(result) + core.BNFreeRegisterSet(result) return regs @clobbered_regs.setter @@ -715,6 +818,32 @@ class Function(object): for i in block: yield i + @property + def too_large(self): + """Whether the function is too large to automatically perform analysis (read-only)""" + return core.BNIsFunctionTooLarge(self.handle) + + @property + def analysis_skipped(self): + """Whether automatic analysis was skipped for this function""" + return core.BNIsFunctionAnalysisSkipped(self.handle) + + @analysis_skipped.setter + def analysis_skipped(self, skip): + if skip: + core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.AlwaysSkipFunctionAnalysis) + else: + core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.NeverSkipFunctionAnalysis) + + @property + def analysis_skip_override(self): + """Override for skipping of automatic analysis""" + return FunctionAnalysisSkipOverride(core.BNGetFunctionAnalysisSkipOverride(self.handle)) + + @analysis_skip_override.setter + def analysis_skip_override(self, override): + core.BNSetFunctionAnalysisSkipOverride(self.handle, override) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -1013,7 +1142,7 @@ class Function(object): branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(IndirectBranchInfo(architecture.Architecture(branches[i].sourceArch), branches[i].sourceAddr, architecture.Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -1055,6 +1184,18 @@ class Function(object): type_conf.confidence = value.confidence core.BNSetAutoFunctionReturnType(self.handle, type_conf) + def set_auto_return_regs(self, value): + regs = core.BNRegisterSetWithConfidence() + regs.regs = (ctypes.c_uint * len(value))() + regs.count = len(value) + for i in xrange(0, len(value)): + regs.regs[i] = self.arch.get_reg_index(value[i]) + if hasattr(value, 'confidence'): + regs.confidence = value.confidence + else: + regs.confidence = types.max_confidence + core.BNSetAutoFunctionReturnRegisters(self.handle, regs) + def set_auto_calling_convention(self, value): conv_conf = core.BNCallingConventionWithConfidence() if value is None: @@ -1112,6 +1253,20 @@ class Function(object): sc.confidence = types.max_confidence core.BNSetAutoFunctionStackAdjustment(self.handle, sc) + def set_auto_reg_stack_adjustments(self, value): + adjust = (core.BNRegisterStackAdjustment * len(value))() + i = 0 + for reg_stack in value.keys(): + adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack) + if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence): + adjust[i].adjustment = value[reg_stack].value + adjust[i].confidence = value[reg_stack].confidence + else: + adjust[i].adjustment = value[reg_stack] + adjust[i].confidence = types.max_confidence + i += 1 + core.BNSetAutoFunctionRegisterStackAdjustments(self.handle, adjust, len(value)) + def set_auto_clobbered_regs(self, value): regs = core.BNRegisterSetWithConfidence() regs.regs = (ctypes.c_uint * len(value))() @@ -1325,6 +1480,94 @@ class Function(object): result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg)) return RegisterValue(self.arch, result.value, confidence = result.confidence) + def set_auto_call_stack_adjustment(self, addr, adjust, arch=None): + if arch is None: + arch = self.arch + if not isinstance(adjust, types.SizeWithConfidence): + adjust = types.SizeWithConfidence(adjust) + core.BNSetAutoCallStackAdjustment(self.handle, arch.handle, addr, adjust.value, adjust.confidence) + + def set_auto_call_reg_stack_adjustment(self, addr, adjust, arch=None): + if arch is None: + arch = self.arch + adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))() + i = 0 + for reg_stack in adjust.keys(): + adjust_buf[i].regStack = arch.get_reg_stack_index(reg_stack) + value = adjust[reg_stack] + if not isinstance(value, types.RegisterStackAdjustmentWithConfidence): + value = types.RegisterStackAdjustmentWithConfidence(value) + adjust_buf[i].adjustment = value.value + adjust_buf[i].confidence = value.confidence + i += 1 + core.BNSetAutoCallRegisterStackAdjustment(self.handle, arch.handle, addr, adjust_buf, len(adjust)) + + def set_auto_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, adjust, arch=None): + if arch is None: + arch = self.arch + reg_stack = arch.get_reg_stack_index(reg_stack) + if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence): + adjust = types.RegisterStackAdjustmentWithConfidence(adjust) + core.BNSetAutoCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack, + adjust.value, adjust.confidence) + + def set_call_stack_adjustment(self, addr, adjust, arch=None): + if arch is None: + arch = self.arch + if not isinstance(adjust, types.SizeWithConfidence): + adjust = types.SizeWithConfidence(adjust) + core.BNSetUserCallStackAdjustment(self.handle, arch.handle, addr, adjust.value, adjust.confidence) + + def set_call_reg_stack_adjustment(self, addr, adjust, arch=None): + if arch is None: + arch = self.arch + adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))() + i = 0 + for reg_stack in adjust.keys(): + adjust_buf[i].regStack = arch.get_reg_stack_index(reg_stack) + value = adjust[reg_stack] + if not isinstance(value, types.RegisterStackAdjustmentWithConfidence): + value = types.RegisterStackAdjustmentWithConfidence(value) + adjust_buf[i].adjustment = value.value + adjust_buf[i].confidence = value.confidence + i += 1 + core.BNSetUserCallRegisterStackAdjustment(self.handle, arch.handle, addr, adjust_buf, len(adjust)) + + def set_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, adjust, arch=None): + if arch is None: + arch = self.arch + reg_stack = arch.get_reg_stack_index(reg_stack) + if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence): + adjust = types.RegisterStackAdjustmentWithConfidence(adjust) + core.BNSetUserCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack, + adjust.value, adjust.confidence) + + def get_call_stack_adjustment(self, addr, arch=None): + if arch is None: + arch = self.arch + result = core.BNGetCallStackAdjustment(self.handle, arch.handle, addr) + return types.SizeWithConfidence(result.value, confidence = result.confidence) + + def get_call_reg_stack_adjustment(self, addr, arch=None): + if arch is None: + arch = self.arch + count = ctypes.c_ulonglong() + adjust = core.BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, count) + result = {} + for i in xrange(0, count.value): + result[arch.get_reg_stack_name(adjust[i].regStack)] = types.RegisterStackAdjustmentWithConfidence( + adjust[i].adjustment, confidence = adjust[i].confidence) + core.BNFreeRegisterStackAdjustments(adjust) + return result + + def get_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, arch=None): + if arch is None: + arch = self.arch + reg_stack = arch.get_reg_stack_index(reg_stack) + adjust = core.BNGetCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack) + result = types.RegisterStackAdjustmentWithConfidence(adjust.adjustment, confidence = adjust.confidence) + return result + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): @@ -1355,9 +1598,10 @@ class AdvancedFunctionAnalysisDataRequestor(object): class DisassemblyTextLine(object): - def __init__(self, addr, tokens): + def __init__(self, addr, tokens, il_instr = None): self.address = addr self.tokens = tokens + self.il_instruction = il_instr def __str__(self): result = "" @@ -1382,8 +1626,9 @@ class FunctionGraphEdge(object): class FunctionGraphBlock(object): - def __init__(self, handle): + def __init__(self, handle, graph): self.handle = handle + self.graph = graph def __del__(self): core.BNFreeFunctionGraphBlock(self.handle) @@ -1402,13 +1647,22 @@ class FunctionGraphBlock(object): def basic_block(self): """Basic block associated with this part of the function graph (read-only)""" block = core.BNGetFunctionGraphBasicBlock(self.handle) - func = core.BNGetBasicBlockFunction(block) - if func is None: + func_handle = core.BNGetBasicBlockFunction(block) + if func_handle is None: core.BNFreeBasicBlock(block) - block = None + return None + + view = binaryview.BinaryView(handle = core.BNGetFunctionData(func_handle)) + func = Function(view, func_handle) + + if core.BNIsLowLevelILBasicBlock(block): + block = lowlevelil.LowLevelILBasicBlock(view, block, + lowlevelil.LowLevelILFunction(func.arch, core.BNGetBasicBlockLowLevelILFunction(block), func)) + elif core.BNIsMediumLevelILBasicBlock(block): + block = mediumlevelil.MediumLevelILBasicBlock(view, block, + mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func)) else: - block = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), block) - core.BNFreeFunction(func) + block = basicblock.BasicBlock(view, block) return block @property @@ -1417,7 +1671,7 @@ class FunctionGraphBlock(object): arch = core.BNGetFunctionGraphBlockArchitecture(self.handle) if arch is None: return None - return architecture.Architecture(arch) + return architecture.CoreArchitecture._from_cache(arch) @property def start(self): @@ -1454,9 +1708,14 @@ class FunctionGraphBlock(object): """Function graph block list of lines (read-only)""" count = ctypes.c_ulonglong() lines = core.BNGetFunctionGraphBlockLines(self.handle, count) + block = self.basic_block result = [] for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): + il_instr = block.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -1468,7 +1727,7 @@ class FunctionGraphBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - result.append(DisassemblyTextLine(addr, tokens)) + result.append(DisassemblyTextLine(addr, tokens, il_instr)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -1513,9 +1772,14 @@ class FunctionGraphBlock(object): def __iter__(self): count = ctypes.c_ulonglong() lines = core.BNGetFunctionGraphBlockLines(self.handle, count) + block = self.basic_block try: for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): + il_instr = block.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -1527,7 +1791,7 @@ class FunctionGraphBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - yield DisassemblyTextLine(addr, tokens) + yield DisassemblyTextLine(addr, tokens, il_instr) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1615,11 +1879,16 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocks(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) + result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result @property + def has_blocks(self): + """Whether the function graph has at least one block (read-only)""" + return core.BNFunctionGraphHasBlocks(self.handle) + + @property def width(self): """Function graph width (read-only)""" return core.BNGetFunctionGraphWidth(self.handle) @@ -1649,6 +1918,32 @@ class FunctionGraph(object): def settings(self): return DisassemblySettings(core.BNGetFunctionGraphSettings(self.handle)) + @property + def is_il(self): + return core.BNIsILFunctionGraph(self.handle) + + @property + def is_low_level_il(self): + return core.BNIsLowLevelILFunctionGraph(self.handle) + + @property + def is_medium_level_il(self): + return core.BNIsMediumLevelILFunctionGraph(self.handle) + + @property + def il_function(self): + if self.is_low_level_il: + il_func = core.BNGetFunctionGraphLowLevelILFunction(self.handle) + if not il_func: + return None + return lowlevelil.LowLevelILFunction(self.function.arch, il_func, self.function) + if self.is_medium_level_il: + il_func = core.BNGetFunctionGraphMediumLevelILFunction(self.handle) + if not il_func: + return None + return mediumlevelil.MediumLevelILFunction(self.function.arch, il_func, self.function) + return None + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -1663,7 +1958,7 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocks(self.handle, count) try: for i in xrange(0, count.value): - yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i])) + yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self) finally: core.BNFreeFunctionGraphBlockList(blocks, count.value) @@ -1706,7 +2001,7 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocksInRegion(self.handle, left, top, right, bottom, count) result = [] for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) + result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result @@ -1739,6 +2034,38 @@ class RegisterInfo(object): return "<reg: size %d, offset %d in %s%s>" % (self.size, self.offset, self.full_width_reg, extend) +class RegisterStackInfo(object): + def __init__(self, storage_regs, top_relative_regs, stack_top_reg, index=None): + self.storage_regs = storage_regs + self.top_relative_regs = top_relative_regs + self.stack_top_reg = stack_top_reg + self.index = index + + def __repr__(self): + 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/interaction.py b/python/interaction.py index 96cac42d..4f6ed67d 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -121,7 +121,7 @@ class IntegerField(object): class AddressField(object): """ ``AddressField`` prompts the user for an address. By passing the optional view and current_address parameters - offsets can be used instead of just an address. Th reslut is stored as in int in self.result. + offsets can be used instead of just an address. The result is stored as in int in self.result. Note: This API currenlty functions differently on the command line, as the view and current_address are disregarded. Additionally where as in the ui the result defaults to hexidecimal on the command line 0x must be diff --git a/python/lowlevelil.py b/python/lowlevelil.py index dfc5af5f..ab6170a5 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -26,6 +26,7 @@ from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionText import function import basicblock import mediumlevelil +import struct class LowLevelILLabel(object): @@ -61,6 +62,26 @@ class ILRegister(object): return self.info == other.info +class ILRegisterStack(object): + def __init__(self, arch, reg_stack): + self.arch = arch + self.index = reg_stack + self.name = self.arch.get_reg_stack_name(self.index) + + @property + def info(self): + return self.arch.reg_stacks[self.name] + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + return self.info == other.info + + class ILFlag(object): def __init__(self, arch, flag): self.arch = arch @@ -78,6 +99,57 @@ class ILFlag(object): return self.name +class ILSemanticFlagClass(object): + def __init__(self, arch, sem_class): + self.arch = arch + self.index = sem_class + self.name = self.arch.get_semantic_flag_class_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + return self.index == other.index + + +class ILSemanticFlagGroup(object): + def __init__(self, arch, sem_group): + self.arch = arch + self.index = sem_group + self.name = self.arch.get_semantic_flag_group_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + 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 @@ -87,6 +159,15 @@ class SSARegister(object): return "<ssa %s version %d>" % (repr(self.reg), self.version) +class SSARegisterStack(object): + def __init__(self, reg_stack, version): + self.reg_stack = reg_stack + self.version = version + + def __repr__(self): + return "<ssa %s version %d>" % (repr(self.reg_stack), self.version) + + class SSAFlag(object): def __init__(self, flag, version): self.flag = flag @@ -96,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 @@ -118,14 +208,22 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_NOP: [], LowLevelILOperation.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_REL: [("stack", "reg_stack"), ("dest", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_STACK_PUSH: [("stack", "reg_stack"), ("src", "expr")], LowLevelILOperation.LLIL_SET_FLAG: [("dest", "flag"), ("src", "expr")], LowLevelILOperation.LLIL_LOAD: [("src", "expr")], LowLevelILOperation.LLIL_STORE: [("dest", "expr"), ("src", "expr")], LowLevelILOperation.LLIL_PUSH: [("src", "expr")], LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], + LowLevelILOperation.LLIL_REG_SPLIT: [("hi", "reg"), ("lo", "reg")], + LowLevelILOperation.LLIL_REG_STACK_REL: [("stack", "reg_stack"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_STACK_POP: [("stack", "reg_stack")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REG: [("dest", "reg")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REL: [("stack", "reg_stack"), ("dest", "expr")], LowLevelILOperation.LLIL_CONST: [("constant", "int")], LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")], + LowLevelILOperation.LLIL_FLOAT_CONST: [("constant", "float")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], @@ -146,13 +244,13 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVU: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVS: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODU: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODS: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODS_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_NEG: [("src", "expr")], LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_SX: [("src", "expr")], @@ -161,12 +259,13 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], - LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")], + LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], LowLevelILOperation.LLIL_GOTO: [("dest", "int")], - LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond")], + LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond"), ("semantic_class", "sem_class")], + LowLevelILOperation.LLIL_FLAG_GROUP: [("semantic_group", "sem_group")], LowLevelILOperation.LLIL_CMP_E: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_NE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], @@ -181,17 +280,49 @@ 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: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], + LowLevelILOperation.LLIL_FADD: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FSUB: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FMUL: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FDIV: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FSQRT: [("src", "expr")], + LowLevelILOperation.LLIL_FNEG: [("src", "expr")], + LowLevelILOperation.LLIL_FABS: [("src", "expr")], + LowLevelILOperation.LLIL_FLOAT_TO_INT: [("src", "expr")], + LowLevelILOperation.LLIL_INT_TO_FLOAT: [("src", "expr")], + LowLevelILOperation.LLIL_FLOAT_CONV: [("src", "expr")], + LowLevelILOperation.LLIL_ROUND_TO_INT: [("src", "expr")], + LowLevelILOperation.LLIL_FLOOR: [("src", "expr")], + LowLevelILOperation.LLIL_CEIL: [("src", "expr")], + LowLevelILOperation.LLIL_FTRUNC: [("src", "expr")], + LowLevelILOperation.LLIL_FCMP_E: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_NE: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_LT: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_O: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_UO: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg_ssa"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_REL_SSA: [("stack", "expr"), ("dest", "expr"), ("top", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_ABS_SSA: [("stack", "expr"), ("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")], + LowLevelILOperation.LLIL_REG_STACK_DEST_SSA: [("src", "reg_stack_ssa_dest_and_src")], LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")], LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "reg")], + LowLevelILOperation.LLIL_REG_SPLIT_SSA: [("hi", "reg_ssa"), ("lo", "reg_ssa")], + LowLevelILOperation.LLIL_REG_STACK_REL_SSA: [("stack", "reg_stack_ssa"), ("src", "expr"), ("top", "expr")], + LowLevelILOperation.LLIL_REG_STACK_ABS_SSA: [("stack", "reg_stack_ssa"), ("src", "reg")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REL_SSA: [("stack", "expr"), ("dest", "expr"), ("top", "expr")], + LowLevelILOperation.LLIL_REG_STACK_FREE_ABS_SSA: [("stack", "expr"), ("dest", "reg")], LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag_ssa"), ("src", "expr")], LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag_ssa")], LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag_ssa"), ("bit", "int")], @@ -199,10 +330,11 @@ 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", "reg_ssa_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")], + LowLevelILOperation.LLIL_REG_STACK_PHI: [("dest", "reg_stack_ssa"), ("src", "reg_stack_ssa_list")], LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")], LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -229,20 +361,50 @@ class LowLevelILInstruction(object): name, operand_type = operand if operand_type == "int": value = instr.operands[i] + elif operand_type == "float": + if instr.size == 4: + value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0] + elif instr.size == 8: + value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0] + else: + value = instr.operands[i] elif operand_type == "expr": value = LowLevelILInstruction(func, instr.operands[i]) elif operand_type == "reg": 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 value = SSARegister(reg, instr.operands[i]) + elif operand_type == "reg_stack_ssa": + reg_stack = ILRegisterStack(func.arch, instr.operands[i]) + i += 1 + value = SSARegisterStack(reg_stack, instr.operands[i]) + elif operand_type == "reg_stack_ssa_dest_and_src": + reg_stack = ILRegisterStack(func.arch, instr.operands[i]) + i += 1 + value = SSARegisterStack(reg_stack, instr.operands[i]) + i += 1 + self.operands.append(value) + self.dest = value + value = SSARegisterStack(reg_stack, instr.operands[i]) elif operand_type == "flag": value = ILFlag(func.arch, instr.operands[i]) elif operand_type == "flag_ssa": flag = ILFlag(func.arch, instr.operands[i]) i += 1 value = SSAFlag(flag, instr.operands[i]) + elif operand_type == "sem_class": + if instr.operands[i] == 0: + value = None + else: + value = ILSemanticFlagClass(func.arch, instr.operands[i]) + elif operand_type == "sem_group": + value = ILSemanticFlagGroup(func.arch, instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": @@ -250,29 +412,83 @@ 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 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": + 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): + 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": 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): - 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 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 + core.BNLowLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value i += 1 @@ -710,6 +926,38 @@ class LowLevelILFunction(object): lo = self.arch.get_reg_index(lo) return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags) + def set_reg_stack_top_relative(self, size, reg_stack, entry, value, flags = 0): + """ + ``set_reg_stack_top_relative`` sets the top-relative entry ``entry`` of size ``size`` in register + stack ``reg_stack`` to the expression ``value`` + + :param int size: size of the register parameter in bytes + :param str reg_stack: the register stack name + :param LowLevelILExpr entry: an expression for which stack entry to set + :param LowLevelILExpr value: an expression to set the entry to + :param str flags: which flags are set by this operation + :return: The expression ``reg_stack[entry] = value`` + :rtype: LowLevelILExpr + """ + reg_stack = self.arch.get_reg_stack_index(reg_stack) + return self.expr(LowLevelILOperation.LLIL_SET_REG_STACK_REL, reg_stack, entry.index, value.index, + size = size, flags = flags) + + def reg_stack_push(self, size, reg_stack, value, flags = 0): + """ + ``reg_stack_push`` pushes the expression ``value`` of size ``size`` onto the top of the register + stack ``reg_stack`` + + :param int size: size of the register parameter in bytes + :param str reg_stack: the register stack name + :param LowLevelILExpr value: an expression to push + :param str flags: which flags are set by this operation + :return: The expression ``reg_stack.push(value)`` + :rtype: LowLevelILExpr + """ + reg_stack = self.arch.get_reg_stack_index(reg_stack) + return self.expr(LowLevelILOperation.LLIL_REG_STACK_PUSH, reg_stack, value.index, size = size, flags = flags) + def set_flag(self, flag, value): """ ``set_flag`` sets the flag ``flag`` to the LowLevelILExpr ``value`` @@ -723,7 +971,7 @@ class LowLevelILFunction(object): def load(self, size, addr): """ - ``laod`` Reads ``size`` bytes from the expression ``addr`` + ``load`` Reads ``size`` bytes from the expression ``addr`` :param int size: number of bytes to read :param LowLevelILExpr addr: the expression to read memory from @@ -768,7 +1016,7 @@ class LowLevelILFunction(object): def reg(self, size, reg): """ - ``reg`` returns a register of size ``size`` with name ``name`` + ``reg`` returns a register of size ``size`` with name ``reg`` :param int size: the size of the register in bytes :param str reg: the name of the register @@ -778,6 +1026,47 @@ class LowLevelILFunction(object): reg = self.arch.get_reg_index(reg) return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size) + def reg_split(self, size, hi, lo): + """ + ``reg_split`` combines registers of size ``size`` with names ``hi`` and ``lo`` + + :param int size: the size of the register in bytes + :param str hi: register holding high part of value + :param str lo: register holding low part of value + :return: The expression ``hi:lo`` + :rtype: LowLevelILExpr + """ + hi = self.arch.get_reg_index(hi) + lo = self.arch.get_reg_index(lo) + return self.expr(LowLevelILOperation.LLIL_REG_SPLIT, hi, lo, size=size) + + def reg_stack_top_relative(self, size, reg_stack, entry): + """ + ``reg_stack_top_relative`` returns a register stack entry of size ``size`` at top-relative + location ``entry`` in register stack with name ``reg_stack`` + + :param int size: the size of the register in bytes + :param str reg_stack: the name of the register stack + :param LowLevelILExpr entry: an expression for which stack entry to fetch + :return: The expression ``reg_stack[entry]`` + :rtype: LowLevelILExpr + """ + reg_stack = self.arch.get_reg_stack_index(reg_stack) + return self.expr(LowLevelILOperation.LLIL_REG_STACK_REL, reg_stack, entry.index, size=size) + + def reg_stack_pop(self, size, reg_stack): + """ + ``reg_stack_pop`` returns the top entry of size ``size`` in register stack with name ``reg_stack``, and + removes the entry from the stack + + :param int size: the size of the register in bytes + :param str reg_stack: the name of the register stack + :return: The expression ``reg_stack.pop`` + :rtype: LowLevelILExpr + """ + reg_stack = self.arch.get_reg_stack_index(reg_stack) + return self.expr(LowLevelILOperation.LLIL_REG_STACK_POP, reg_stack, size=size) + def const(self, size, value): """ ``const`` returns an expression for the constant integer ``value`` with size ``size`` @@ -800,6 +1089,38 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size) + def float_const_raw(self, size, value): + """ + ``float_const_raw`` returns an expression for the constant raw binary floating point + value ``value`` with size ``size`` + + :param int size: the size of the constant in bytes + :param int value: integer value for the raw binary representation of the constant + :return: A constant expression of given value and size + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, value, size=size) + + def float_const_single(self, value): + """ + ``float_const_single`` returns an expression for the single precision floating point value ``value`` + + :param float value: float value for the constant + :return: A constant expression of given value and size + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("I", struct.pack("f", value))[0], size=4) + + def float_const_double(self, value): + """ + ``float_const_double`` returns an expression for the double precision floating point value ``value`` + + :param float value: float value for the constant + :return: A constant expression of given value and size + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("Q", struct.pack("d", value))[0], size=8) + def flag(self, reg): """ ``flag`` returns a flag expression for the given flag name. @@ -1059,7 +1380,7 @@ class LowLevelILFunction(object): :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``muls.dp.<size>{<flags>}(a, b)`` + :return: The expression ``mulu.dp.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MULU_DP, a.index, b.index, size=size, flags=flags) @@ -1078,21 +1399,20 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags) - def div_double_prec_signed(self, size, hi, lo, b, flags=None): + def div_double_prec_signed(self, size, a, b, flags=None): """ - ``div_double_prec_signed`` signed double precision divide using expression ``hi`` and expression ``lo`` as a + ``div_double_prec_signed`` signed double precision divide using expression ``a`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes - :param LowLevelILExpr hi: high LHS expression - :param LowLevelILExpr lo: low LHS expression + :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``divs.dp.<size>{<flags>}(hi:lo, b)`` + :return: The expression ``divs.dp.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVS_DP, a.index, b.index, size=size, flags=flags) def div_unsigned(self, size, a, b, flags=None): """ @@ -1103,26 +1423,25 @@ class LowLevelILFunction(object): :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``divs.<size>{<flags>}(a, b)`` + :return: The expression ``divu.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVU, a.index, b.index, size=size, flags=flags) - def div_double_prec_unsigned(self, size, hi, lo, b, flags=None): + def div_double_prec_unsigned(self, size, a, b, flags=None): """ - ``div_double_prec_unsigned`` unsigned double precision divide using expression ``hi`` and expression ``lo`` as + ``div_double_prec_unsigned`` unsigned double precision divide using expression ``a`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes - :param LowLevelILExpr hi: high LHS expression - :param LowLevelILExpr lo: low LHS expression + :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``divs.dp.<size>{<flags>}(hi:lo, b)`` + :return: The expression ``divu.dp.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVU_DP, a.index, b.index, size=size, flags=flags) def mod_signed(self, size, a, b, flags=None): """ @@ -1138,21 +1457,20 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags) - def mod_double_prec_signed(self, size, hi, lo, b, flags=None): + def mod_double_prec_signed(self, size, a, b, flags=None): """ - ``mod_double_prec_signed`` signed double precision modulus using expression ``hi`` and expression ``lo`` as a single + ``mod_double_prec_signed`` signed double precision modulus using expression ``a`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes - :param LowLevelILExpr hi: high LHS expression - :param LowLevelILExpr lo: low LHS expression + :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``mods.dp.<size>{<flags>}(hi:lo, b)`` + :return: The expression ``mods.dp.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODS_DP, a.index, b.index, size=size, flags=flags) def mod_unsigned(self, size, a, b, flags=None): """ @@ -1166,23 +1484,22 @@ class LowLevelILFunction(object): :return: The expression ``modu.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODU, a.index, b.index, size=size, flags=flags) - def mod_double_prec_unsigned(self, size, hi, lo, b, flags=None): + def mod_double_prec_unsigned(self, size, a, b, flags=None): """ - ``mod_double_prec_unsigned`` unsigned double precision modulus using expression ``hi`` and expression ``lo`` as + ``mod_double_prec_unsigned`` unsigned double precision modulus using expression ``a`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes - :param LowLevelILExpr hi: high LHS expression - :param LowLevelILExpr lo: low LHS expression + :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set - :return: The expression ``modu.dp.<size>{<flags>}(hi:lo, b)`` + :return: The expression ``modu.dp.<size>{<flags>}(a, b)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODU_DP, a.index, b.index, size=size, flags=flags) def neg_expr(self, size, value, flags=None): """ @@ -1226,7 +1543,7 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to zero extend - :return: The expression ``sx.<size>(value)`` + :return: The expression ``zx.<size>(value)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags) @@ -1295,11 +1612,12 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_NORET) - def flag_condition(self, cond): + def flag_condition(self, cond, sem_class = None): """ ``flag_condition`` returns a flag_condition expression for the given LowLevelILFlagCondition :param LowLevelILFlagCondition cond: Flag condition expression to retrieve + :param str sem_class: Optional semantic flag class :return: A flag_condition expression :rtype: LowLevelILExpr """ @@ -1307,7 +1625,19 @@ class LowLevelILFunction(object): cond = LowLevelILFlagCondition[cond] elif isinstance(cond, LowLevelILFlagCondition): cond = cond.value - return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond) + class_index = self.arch.get_semantic_flag_class_index(sem_class) + return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond, class_index) + + def flag_group(self, sem_group): + """ + ``flag_group`` returns a flag_group expression for the given semantic flag group + + :param str sem_group: Semantic flag group to access + :return: A flag_group expression + :rtype: LowLevelILExpr + """ + group = self.arch.get_semantic_flag_group_index(sem_group) + return self.expr(LowLevelILOperation.LLIL_FLAG_GROUP, group) def compare_equal(self, size, a, b): """ @@ -1451,6 +1781,25 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SYSCALL) + def intrinsic(self, outputs, intrinsic, params, flags=None): + """ + ``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), flags = flags) + def breakpoint(self): """ ``breakpoint`` returns a processor breakpoint expression. @@ -1501,6 +1850,280 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_UNIMPL_MEM, addr.index, size = size) + def float_add(self, size, a, b, flags=None): + """ + ``float_add`` adds floating point expression ``a`` to expression ``b`` potentially setting flags ``flags`` + and returning an expression of ``size`` bytes. + + :param int size: the size of the result in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``fadd.<size>{<flags>}(a, b)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FADD, a.index, b.index, size=size, flags=flags) + + def float_sub(self, size, a, b, flags=None): + """ + ``float_sub`` subtracts floating point expression ``b`` from expression ``a`` potentially setting flags ``flags`` + and returning an expression of ``size`` bytes. + + :param int size: the size of the result in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``fsub.<size>{<flags>}(a, b)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FSUB, a.index, b.index, size=size, flags=flags) + + def float_mult(self, size, a, b, flags=None): + """ + ``float_mult`` multiplies floating point expression ``a`` by expression ``b`` potentially setting flags ``flags`` + and returning an expression of ``size`` bytes. + + :param int size: the size of the result in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``fmul.<size>{<flags>}(a, b)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FMUL, a.index, b.index, size=size, flags=flags) + + def float_div(self, size, a, b, flags=None): + """ + ``float_div`` divides floating point expression ``a`` by expression ``b`` potentially setting flags ``flags`` + and returning an expression of ``size`` bytes. + + :param int size: the size of the result in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``fdiv.<size>{<flags>}(a, b)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FDIV, a.index, b.index, size=size, flags=flags) + + def float_sqrt(self, size, value, flags=None): + """ + ``float_sqrt`` returns square root of floating point expression ``value`` of size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``sqrt.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FSQRT, value.index, size=size, flags=flags) + + def float_neg(self, size, value, flags=None): + """ + ``float_neg`` returns sign negation of floating point expression ``value`` of size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``fneg.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FNEG, value.index, size=size, flags=flags) + + def float_abs(self, size, value, flags=None): + """ + ``float_abs`` returns absolute value of floating point expression ``value`` of size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``fabs.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FABS, value.index, size=size, flags=flags) + + def float_to_int(self, size, value, flags=None): + """ + ``float_to_int`` returns integer value of floating point expression ``value`` of size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``int.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOAT_TO_INT, value.index, size=size, flags=flags) + + def int_to_float(self, size, value, flags=None): + """ + ``int_to_float`` returns floating point value of integer expression ``value`` of size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``float.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_INT_TO_FLOAT, value.index, size=size, flags=flags) + + def float_convert(self, size, value, flags=None): + """ + ``int_to_float`` converts floating point value of expression ``value`` to size ``size`` potentially setting flags + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``fconvert.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOAT_CONV, value.index, size=size, flags=flags) + + def round_to_int(self, size, value, flags=None): + """ + ``round_to_int`` rounds a floating point value to the nearest integer + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``roundint.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_ROUND_TO_INT, value.index, size=size, flags=flags) + + def floor(self, size, value, flags=None): + """ + ``floor`` rounds a floating point value to an integer towards negative infinity + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``roundint.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FLOOR, value.index, size=size, flags=flags) + + def ceil(self, size, value, flags=None): + """ + ``ceil`` rounds a floating point value to an integer towards positive infinity + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``roundint.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CEIL, value.index, size=size, flags=flags) + + def float_trunc(self, size, value, flags=None): + """ + ``float_trunc`` rounds a floating point value to an integer towards zero + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to negate + :param str flags: optional, flags to set + :return: The expression ``roundint.<size>{<flags>}(value)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FTRUNC, value.index, size=size, flags=flags) + + def float_compare_equal(self, size, a, b): + """ + ``float_compare_equal`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is equal to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f== b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_E, a.index, b.index) + + def float_compare_not_equal(self, size, a, b): + """ + ``float_compare_not_equal`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is not equal to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f!= b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_NE, a.index, b.index) + + def float_compare_less_than(self, size, a, b): + """ + ``float_compare_less_than`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is less than to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f< b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_LT, a.index, b.index) + + def float_compare_less_equal(self, size, a, b): + """ + ``float_compare_less_equal`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is less than or equal to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f<= b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_LE, a.index, b.index) + + def float_compare_greater_equal(self, size, a, b): + """ + ``float_compare_greater_equal`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is greater than or equal to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f>= b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_GE, a.index, b.index) + + def float_compare_greater_than(self, size, a, b): + """ + ``float_compare_greater_than`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is greater than or equal to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``a f> b`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_GT, a.index, b.index) + + def float_compare_unordered(self, size, a, b): + """ + ``float_compare_unordered`` returns floating point comparison expression of size ``size`` checking if + expression ``a`` is unordered relative to expression ``b`` + + :param int size: the size of the operands in bytes + :param LowLevelILExpr a: LHS expression + :param LowLevelILExpr b: RHS expression + :param str flags: flags to set + :return: The expression ``is_unordered(a, b)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_FCMP_UO, a.index, b.index) + def goto(self, label): """ ``goto`` returns a goto expression which jumps to the provided LowLevelILLabel. @@ -1736,6 +2359,7 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): def __hash__(self): return hash((self.start, self.end, self.il_function)) + def LLIL_TEMP(n): return n | 0x80000000 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 6f5515bb..caf19e8e 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -27,6 +27,7 @@ import function import basicblock import lowlevelil import types +import struct class SSAVariable(object): @@ -85,10 +86,12 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_STORE_STRUCT: [("dest", "expr"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_SPLIT: [("high", "var"), ("low", "var")], MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], + MediumLevelILOperation.MLIL_FLOAT_CONST: [("constant", "float")], MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], @@ -108,13 +111,13 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_DIVU: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_NEG: [("src", "expr")], MediumLevelILOperation.MLIL_NOT: [("src", "expr")], MediumLevelILOperation.MLIL_SX: [("src", "expr")], @@ -147,9 +150,35 @@ 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_FREE_VAR_SLOT: [("dest", "var")], + MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA: [("prev", "var_ssa_dest_and_src")], MediumLevelILOperation.MLIL_UNDEF: [], MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], + MediumLevelILOperation.MLIL_FADD: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FSUB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FMUL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FDIV: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FSQRT: [("src", "expr")], + MediumLevelILOperation.MLIL_FNEG: [("src", "expr")], + MediumLevelILOperation.MLIL_FABS: [("src", "expr")], + MediumLevelILOperation.MLIL_FLOAT_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_INT_TO_FLOAT: [("src", "expr")], + MediumLevelILOperation.MLIL_FLOAT_CONV: [("src", "expr")], + MediumLevelILOperation.MLIL_ROUND_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_FLOOR: [("src", "expr")], + MediumLevelILOperation.MLIL_CEIL: [("src", "expr")], + MediumLevelILOperation.MLIL_FTRUNC: [("src", "expr")], + MediumLevelILOperation.MLIL_FCMP_E: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_NE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_LT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_O: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_UO: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa"), ("src", "expr")], @@ -159,6 +188,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var_ssa"), ("offset", "int")], MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var_ssa")], MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var_ssa"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa")], MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")], @@ -192,8 +222,17 @@ class MediumLevelILInstruction(object): name, operand_type = operand if operand_type == "int": value = instr.operands[i] + elif operand_type == "float": + if instr.size == 4: + value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0] + elif instr.size == 8: + value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0] + else: + 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": diff --git a/python/platform.py b/python/platform.py index 5e63d836..a79e3b9a 100644 --- a/python/platform.py +++ b/python/platform.py @@ -105,7 +105,7 @@ class Platform(object): else: self.handle = handle self.__dict__["name"] = core.BNGetPlatformName(self.handle) - self.arch = architecture.Architecture(core.BNGetPlatformArchitecture(self.handle)) + self.arch = architecture.CoreArchitecture._from_cache(core.BNGetPlatformArchitecture(self.handle)) def __del__(self): core.BNFreePlatform(self.handle) diff --git a/python/plugin.py b/python/plugin.py index e0054d86..c6cd9fc0 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -30,6 +30,8 @@ import filemetadata import binaryview import function import log +import lowlevelil +import mediumlevelil class PluginCommandContext(object): @@ -38,6 +40,7 @@ class PluginCommandContext(object): self.address = 0 self.length = 0 self.function = None + self.instruction = None class _PluginCommandMetaClass(type): @@ -118,6 +121,50 @@ class PluginCommand(object): log.log_error(traceback.format_exc()) @classmethod + def _low_level_il_function_action(cls, view, func, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + action(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _low_level_il_instruction_action(cls, view, func, instr, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + action(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _medium_level_il_function_action(cls, view, func, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + action(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _medium_level_il_instruction_action(cls, view, func, instr, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + action(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + + @classmethod def _default_is_valid(cls, view, is_valid): try: if is_valid is None: @@ -167,6 +214,62 @@ class PluginCommand(object): return False @classmethod + def _low_level_il_function_is_valid(cls, view, func, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _low_level_il_instruction_is_valid(cls, view, func, instr, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _medium_level_il_function_is_valid(cls, view, func, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _medium_level_il_instruction_is_valid(cls, view, func, instr, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod def register(cls, name, description, action, is_valid = None): """ ``register`` Register a plugin @@ -243,6 +346,82 @@ class PluginCommand(object): core.BNRegisterPluginCommandForFunction(name, description, action_obj, is_valid_obj, None) @classmethod + def register_for_low_level_il_function(cls, name, description, action, is_valid = None): + """ + ``register_for_low_level_il_function`` Register a plugin to be called with a low level IL function argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``LowLevelILFunction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_action(view, func, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_is_valid(view, func, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForLowLevelILFunction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_low_level_il_instruction(cls, name, description, action, is_valid = None): + """ + ``register_for_low_level_il_instruction`` Register a plugin to be called with a low level IL instruction argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``LowLevelILInstruction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_action(view, func, instr, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_is_valid(view, func, instr, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForLowLevelILInstruction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_medium_level_il_function(cls, name, description, action, is_valid = None): + """ + ``register_for_medium_level_il_function`` Register a plugin to be called with a medium level IL function argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``MediumLevelILFunction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_action(view, func, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_is_valid(view, func, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForMediumLevelILFunction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_medium_level_il_instruction(cls, name, description, action, is_valid = None): + """ + ``register_for_medium_level_il_instruction`` Register a plugin to be called with a medium level IL instruction argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``MediumLevelILInstruction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_action(view, func, instr, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_is_valid(view, func, instr, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForMediumLevelILInstruction(name, description, action_obj, is_valid_obj, None) + + @classmethod def get_valid_list(cls, context): """Dict of registered plugins""" commands = cls.list @@ -275,6 +454,36 @@ class PluginCommand(object): if not self.command.functionIsValid: return True return self.command.functionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand: + if context.function is None: + return False + if not self.command.lowLevelILFunctionIsValid: + return True + return self.command.lowLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand: + if context.instruction is None: + return False + if not isinstance(context.instruction, lowlevelil.LowLevelILInstruction): + return False + if not self.command.lowLevelILInstructionIsValid: + return True + return self.command.lowLevelILInstructionIsValid(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) + elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand: + if context.function is None: + return False + if not self.command.mediumLevelILFunctionIsValid: + return True + return self.command.mediumLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: + if context.instruction is None: + return False + if not isinstance(context.instruction, mediumlevelil.MediumLevelILInstruction): + return False + if not self.command.mediumLevelILInstructionIsValid: + return True + return self.command.mediumLevelILInstructionIsValid(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) return False def execute(self, context): @@ -288,6 +497,16 @@ class PluginCommand(object): self.command.rangeCommand(self.command.context, context.view.handle, context.address, context.length) elif self.command.type == PluginCommandType.FunctionPluginCommand: self.command.functionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand: + self.command.lowLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand: + self.command.lowLevelILInstructionCommand(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) + elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand: + self.command.mediumLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: + self.command.mediumLevelILInstructionCommand(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) def __repr__(self): return "<PluginCommand: %s>" % self.name diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index c92c249a..e7838748 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -540,7 +540,7 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_address"] = self.active_addr self.locals["here"] = self.active_addr self.locals["current_selection"] = (self.active_selection_begin, self.active_selection_end) - if self.active_func == None: + if self.active_func is None: self.locals["current_llil"] = None self.locals["current_mlil"] = None else: @@ -556,6 +556,8 @@ class PythonScriptingInstance(ScriptingInstance): elif self.locals["current_address"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["current_address"]): sys.stderr.write("Address 0x%x is not valid for the current view\n" % self.locals["current_address"]) + if self.active_view is not None: + self.active_view.update_analysis() except: traceback.print_exc() finally: diff --git a/python/types.py b/python/types.py index f5279047..42ed7ddd 100644 --- a/python/types.py +++ b/python/types.py @@ -641,7 +641,7 @@ class Type(object): return core.BNGenerateAutoDemangledTypeId(name) @classmethod - def get_auto_demanged_type_id_source(self): + def get_auto_demangled_type_id_source(self): return core.BNGetAutoDemangledTypeIdSource() def with_confidence(self, confidence): @@ -687,6 +687,21 @@ class SizeWithConfidence(object): return self.value +class RegisterStackAdjustmentWithConfidence(object): + def __init__(self, value, confidence = max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + def __int__(self): + return self.value + + class RegisterSet(object): def __init__(self, reg_list, confidence = max_confidence): self.regs = reg_list diff --git a/settings.cpp b/settings.cpp index 6b9c4e3a..b5899e38 100644 --- a/settings.cpp +++ b/settings.cpp @@ -51,6 +51,7 @@ std::vector<std::string> Setting::GetStringList(const std::string& pluginName, char** outBuffer = (char**)BNSettingGetStringList(pluginName.c_str(), name.c_str(), (const char**)buffer, &size); vector<string> result; + result.reserve(size); for (size_t i = 0; i < size; i++) result.emplace_back(outBuffer[i]); diff --git a/transform.cpp b/transform.cpp index 29a665d0..0a6fdfe6 100644 --- a/transform.cpp +++ b/transform.cpp @@ -157,6 +157,7 @@ vector<Ref<Transform>> Transform::GetTransformTypes() BNTransform** list = BNGetTransformTypeList(&count); vector<Ref<Transform>> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreTransform(list[i])); @@ -229,6 +230,7 @@ vector<TransformParameter> CoreTransform::GetParameters() const BNTransformParameterInfo* list = BNGetTransformParameterList(m_object, &count); vector<TransformParameter> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { TransformParameter param; @@ -188,6 +188,15 @@ size_t QualifiedName::size() const } +size_t QualifiedName::StringSize() const +{ + size_t size = 0; + for (auto& name : m_name) + size += name.size() + 2; + return size - 2; +} + + string QualifiedName::GetString() const { bool first = true; @@ -355,6 +364,7 @@ vector<FunctionParameter> Type::GetParameters() const BNFunctionParameter* types = BNGetTypeParameters(m_object, &count); vector<FunctionParameter> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { FunctionParameter param; @@ -474,11 +484,10 @@ vector<InstructionTextToken> Type::GetTokens(Platform* platform, uint8_t baseCon platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -492,11 +501,10 @@ vector<InstructionTextToken> Type::GetTokensBeforeName(Platform* platform, uint8 platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -510,11 +518,10 @@ vector<InstructionTextToken> Type::GetTokensAfterName(Platform* platform, uint8_ platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -575,19 +582,19 @@ Ref<Type> Type::NamedType(const QualifiedName& name, Type* type) Ref<Type> Type::NamedType(const string& id, const QualifiedName& name, Type* type) { BNQualifiedName nameObj = name.GetAPIObject(); - Type* result = new Type(BNCreateNamedTypeReferenceFromTypeAndId(id.c_str(), &nameObj, - type ? type->GetObject() : nullptr)); + BNType* coreObj = BNCreateNamedTypeReferenceFromTypeAndId(id.c_str(), &nameObj, + type ? type->GetObject() : nullptr); QualifiedName::FreeAPIObject(&nameObj); - return result; + return coreObj ? new Type(coreObj) : nullptr; } Ref<Type> Type::NamedType(BinaryView* view, const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); - Type* result = new Type(BNCreateNamedTypeReferenceFromType(view->GetObject(), &nameObj)); + BNType* coreObj = BNCreateNamedTypeReferenceFromType(view->GetObject(), &nameObj); QualifiedName::FreeAPIObject(&nameObj); - return result; + return coreObj ? new Type(coreObj) : nullptr; } @@ -882,6 +889,7 @@ vector<StructureMember> Structure::GetMembers() const BNStructureMember* members = BNGetStructureMembers(m_object, &count); vector<StructureMember> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { StructureMember member; @@ -1001,6 +1009,7 @@ vector<EnumerationMember> Enumeration::GetMembers() const BNEnumerationMember* members = BNGetEnumerationMembers(m_object, &count); vector<EnumerationMember> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { EnumerationMember member; @@ -53,6 +53,7 @@ vector<UpdateChannel> UpdateChannel::GetList() } vector<UpdateChannel> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { UpdateChannel channel; @@ -149,6 +150,7 @@ vector<UpdateVersion> UpdateVersion::GetChannelVersions(const string& channel) } vector<UpdateVersion> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { UpdateVersion version; |
