From ec2d882e1a165b703e8fedaa81246dcdd91f50f3 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 15 Aug 2017 00:24:03 -0400 Subject: Add APIs to access and update portions of the function type, and added new APIs for global registers and implicit incoming state in calling conventions --- callingconvention.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'callingconvention.cpp') diff --git a/callingconvention.cpp b/callingconvention.cpp index fb5ed73f..b0783ad6 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -44,6 +44,10 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback; cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback; cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback; + cc.getGlobalPointerRegister = GetGlobalPointerRegisterCallback; + cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback; + cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback; + cc.getIncomingFlagValue = GetIncomingFlagValueCallback; AddRefForRegistration(); m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc); @@ -137,6 +141,46 @@ uint32_t CallingConvention::GetFloatReturnValueRegisterCallback(void* ctxt) } +uint32_t CallingConvention::GetGlobalPointerRegisterCallback(void* ctxt) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + return cc->GetGlobalPointerRegister(); +} + + +uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + vector regs = cc->GetImplicitlyDefinedRegisters(); + *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; +} + + +BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); +} + + +BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); +} + + Ref CallingConvention::GetArchitecture() const { return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object)); @@ -194,6 +238,30 @@ uint32_t CallingConvention::GetFloatReturnValueRegister() } +uint32_t CallingConvention::GetGlobalPointerRegister() +{ + return BN_INVALID_REGISTER; +} + + +vector CallingConvention::GetImplicitlyDefinedRegisters() +{ + return vector(); +} + + +RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + +RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc) { } @@ -260,3 +328,32 @@ uint32_t CoreCallingConvention::GetFloatReturnValueRegister() { return BNGetFloatReturnValueRegister(m_object); } + + +uint32_t CoreCallingConvention::GetGlobalPointerRegister() +{ + return BNGetGlobalPointerRegister(m_object); +} + + +vector CoreCallingConvention::GetImplicitlyDefinedRegisters() +{ + size_t count; + uint32_t* regs = BNGetImplicitlyDefinedRegisters(m_object, &count); + vector result; + result.insert(result.end(), regs, ®s[count]); + BNFreeRegisterList(regs); + return result; +} + + +RegisterValue CoreCallingConvention::GetIncomingRegisterValue(uint32_t reg, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingRegisterValue(m_object, reg, func ? func->GetObject() : nullptr)); +} + + +RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr)); +} -- cgit v1.3.1 From e40b46fdf8b76acb5ca2d0a062b0b8ac2ca99a16 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 22:53:10 -0400 Subject: Work around limitations in ctypes --- binaryninjaapi.h | 4 ++-- binaryninjacore.h | 4 ++-- callingconvention.cpp | 8 ++++---- python/callingconvention.py | 16 ++++++++++------ 4 files changed, 18 insertions(+), 14 deletions(-) (limited to 'callingconvention.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8a09529e..a1b31089 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3075,8 +3075,8 @@ namespace BinaryNinja static uint32_t GetGlobalPointerRegisterCallback(void* ctxt); static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count); - static BNRegisterValue GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func); - static BNRegisterValue GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func); + static void GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + static void GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); public: Ref GetArchitecture() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index b69d79f9..5c6619b2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1250,8 +1250,8 @@ extern "C" uint32_t (*getGlobalPointerRegister)(void* ctxt); uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count); - BNRegisterValue (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func); - BNRegisterValue (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func); + void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + void (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func, BNRegisterValue* result); }; struct BNVariableNameAndType diff --git a/callingconvention.cpp b/callingconvention.cpp index b0783ad6..0a7d349c 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -161,23 +161,23 @@ uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, s } -BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +void CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) { CallingConvention* cc = (CallingConvention*)ctxt; Ref funcObj; if (func) funcObj = new Function(BNNewFunctionReference(func)); - return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); + *result = cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); } -BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +void CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) { CallingConvention* cc = (CallingConvention*)ctxt; Ref funcObj; if (func) funcObj = new Function(BNNewFunctionReference(func)); - return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); + *result = cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); } diff --git a/python/callingconvention.py b/python/callingconvention.py index 609c71b0..bd8bbeee 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -267,25 +267,29 @@ class CallingConvention(object): count[0] = 0 return None - def _get_incoming_reg_value(self, ctxt, reg, func): + def _get_incoming_reg_value(self, ctxt, reg, func, result): try: func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) reg_name = self.arch.get_reg_name(reg) - return self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() + api_obj = self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - return function.RegisterValue()._to_api_object() + api_obj = function.RegisterValue()._to_api_object() + result[0].state = api_obj.state + result[0].value = api_obj.value - def _get_incoming_flag_value(self, ctxt, reg, func): + def _get_incoming_flag_value(self, ctxt, reg, func, result): try: func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) reg_name = self.arch.get_reg_name(reg) - return self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() + api_obj = self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - return function.RegisterValue()._to_api_object() + api_obj = function.RegisterValue()._to_api_object() + result[0].state = api_obj.state + result[0].value = api_obj.value def __repr__(self): return "" % (self.arch.name, self.name) -- cgit v1.3.1 From 0d88336e22cf85a917729fe0f814c1e63736fca0 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 23 Aug 2017 01:04:47 -0400 Subject: Added APIs for clobbered registers, global pointers, and function exit data flow info --- binaryninjaapi.h | 13 ++++++++ binaryninjacore.h | 36 ++++++++++++++++++++- callingconvention.cpp | 20 ++++++++++++ function.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ mediumlevelil.cpp | 26 +++++++++++---- python/binaryview.py | 6 ++++ python/callingconvention.py | 10 ++++++ python/function.py | 79 ++++++++++++++++++++++++++++++++++++++++++++- python/types.py | 37 +++++++++++++++++++++ 9 files changed, 297 insertions(+), 9 deletions(-) (limited to 'callingconvention.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e16679cc..f5f51908 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2185,6 +2185,8 @@ namespace BinaryNinja Confidence> GetCallingConvention() const; Confidence> GetParameterVariables() const; Confidence HasVariableArguments() const; + Confidence GetStackAdjustment() const; + Confidence> GetClobberedRegisters() const; void SetAutoType(Type* type); void SetAutoReturnType(const Confidence>& type); @@ -2192,6 +2194,8 @@ namespace BinaryNinja void SetAutoParameterVariables(const Confidence>& vars); void SetAutoHasVariableArguments(const Confidence& varArgs); void SetAutoCanReturn(const Confidence& returns); + void SetAutoStackAdjustment(const Confidence& stackAdjust); + void SetAutoClobberedRegisters(const Confidence>& clobbered); void SetUserType(Type* type); void SetReturnType(const Confidence>& type); @@ -2199,6 +2203,8 @@ namespace BinaryNinja void SetParameterVariables(const Confidence>& vars); void SetHasVariableArguments(const Confidence& varArgs); void SetCanReturn(const Confidence& returns); + void SetStackAdjustment(const Confidence& stackAdjust); + void SetClobberedRegisters(const Confidence>& clobbered); void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); @@ -2260,6 +2266,9 @@ namespace BinaryNinja std::map GetAnalysisPerformanceInfo(); std::vector GetTypeTokens(DisassemblySettings* settings = nullptr); + + Confidence GetGlobalPointerValue() const; + Confidence GetRegisterValueAtExit(uint32_t reg) const; }; class AdvancedFunctionAnalysisDataRequestor @@ -2856,6 +2865,7 @@ namespace BinaryNinja void Finalize(); void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true, + const std::set& knownNotAliases = std::set(), const std::set& knownAliases = std::set()); bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); @@ -3069,6 +3079,7 @@ namespace BinaryNinja static bool AreArgumentRegistersSharedIndexCallback(void* ctxt); static bool IsStackReservedForArgumentRegistersCallback(void* ctxt); + static bool IsStackAdjustedOnReturnCallback(void* ctxt); static uint32_t GetIntegerReturnValueRegisterCallback(void* ctxt); static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt); @@ -3089,6 +3100,7 @@ namespace BinaryNinja virtual std::vector GetFloatArgumentRegisters(); virtual bool AreArgumentRegistersSharedIndex(); virtual bool IsStackReservedForArgumentRegisters(); + virtual bool IsStackAdjustedOnReturn(); virtual uint32_t GetIntegerReturnValueRegister() = 0; virtual uint32_t GetHighIntegerReturnValueRegister(); @@ -3111,6 +3123,7 @@ namespace BinaryNinja virtual std::vector GetFloatArgumentRegisters() override; virtual bool AreArgumentRegistersSharedIndex() override; virtual bool IsStackReservedForArgumentRegisters() override; + virtual bool IsStackAdjustedOnReturn() override; virtual uint32_t GetIntegerReturnValueRegister() override; virtual uint32_t GetHighIntegerReturnValueRegister() override; diff --git a/binaryninjacore.h b/binaryninjacore.h index 0ee5c4d7..6ba7fda4 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -694,6 +694,12 @@ extern "C" int64_t value; }; + struct BNRegisterValueWithConfidence + { + BNRegisterValue value; + uint8_t confidence; + }; + struct BNValueRange { uint64_t start, end, step; @@ -1113,6 +1119,12 @@ extern "C" uint8_t confidence; }; + struct BNSizeWithConfidence + { + size_t value; + uint8_t confidence; + }; + struct BNMemberScopeWithConfidence { BNMemberScope value; @@ -1132,6 +1144,13 @@ extern "C" uint8_t confidence; }; + struct BNRegisterSetWithConfidence + { + uint32_t* regs; + size_t count; + uint8_t confidence; + }; + struct BNFunctionParameter { char* name; @@ -1243,6 +1262,7 @@ extern "C" bool (*areArgumentRegistersSharedIndex)(void* ctxt); bool (*isStackReservedForArgumentRegisters)(void* ctxt); + bool (*isStackAdjustedOnReturn)(void* ctxt); uint32_t (*getIntegerReturnValueRegister)(void* ctxt); uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt); @@ -1806,6 +1826,8 @@ extern "C" BINARYNINJACOREAPI BNAddressRange* BNGetAllocatedRanges(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeAddressRanges(BNAddressRange* ranges); + BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetGlobalPointerValue(BNBinaryView* view); + // Raw binary data view BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataView(BNFileMetadata* file); BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataViewFromBuffer(BNFileMetadata* file, BNDataBuffer* buf); @@ -2073,18 +2095,25 @@ extern "C" BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func); BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func); + BINARYNINJACOREAPI BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func); + BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func); + BINARYNINJACOREAPI void BNFreeClobberedRegisters(BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetAutoFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); 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 BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); 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 BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym); BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type); @@ -2093,6 +2122,9 @@ extern "C" BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetFunctionTypeTokens(BNFunction* func, BNDisassemblySettings* settings, size_t* count); + BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionGlobalPointerValue(BNFunction* func); + BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionRegisterValueAtExit(BNFunction* func, uint32_t reg); + BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block); @@ -2492,7 +2524,8 @@ extern "C" BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func, - bool analyzeConditionals, bool handleAliases, BNVariable* knownAliases, size_t knownAliasCount); + bool analyzeConditionals, bool handleAliases, BNVariable* knownNotAliases, size_t knownNotAliasCount, + BNVariable* knownAliases, size_t knownAliasCount); BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func, BNMediumLevelILFunction* src); @@ -2795,6 +2828,7 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetFloatArgumentRegisters(BNCallingConvention* cc, size_t* count); BINARYNINJACOREAPI bool BNAreArgumentRegistersSharedIndex(BNCallingConvention* cc); BINARYNINJACOREAPI bool BNIsStackReservedForArgumentRegisters(BNCallingConvention* cc); + BINARYNINJACOREAPI bool BNIsStackAdjustedOnReturn(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetIntegerReturnValueRegister(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc); diff --git a/callingconvention.cpp b/callingconvention.cpp index 0a7d349c..945ba25f 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -41,6 +41,7 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.freeRegisterList = FreeRegisterListCallback; cc.areArgumentRegistersSharedIndex = AreArgumentRegistersSharedIndexCallback; cc.isStackReservedForArgumentRegisters = IsStackReservedForArgumentRegistersCallback; + cc.isStackAdjustedOnReturn = IsStackAdjustedOnReturnCallback; cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback; cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback; cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback; @@ -120,6 +121,13 @@ bool CallingConvention::IsStackReservedForArgumentRegistersCallback(void* ctxt) } +bool CallingConvention::IsStackAdjustedOnReturnCallback(void* ctxt) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + return cc->IsStackAdjustedOnReturn(); +} + + uint32_t CallingConvention::GetIntegerReturnValueRegisterCallback(void* ctxt) { CallingConvention* cc = (CallingConvention*)ctxt; @@ -226,6 +234,12 @@ bool CallingConvention::IsStackReservedForArgumentRegisters() } +bool CallingConvention::IsStackAdjustedOnReturn() +{ + return false; +} + + uint32_t CallingConvention::GetHighIntegerReturnValueRegister() { return BN_INVALID_REGISTER; @@ -312,6 +326,12 @@ bool CoreCallingConvention::IsStackReservedForArgumentRegisters() } +bool CoreCallingConvention::IsStackAdjustedOnReturn() +{ + return BNIsStackAdjustedOnReturn(m_object); +} + + uint32_t CoreCallingConvention::GetIntegerReturnValueRegister() { return BNGetIntegerReturnValueRegister(m_object); diff --git a/function.cpp b/function.cpp index 976d73d2..550691d0 100644 --- a/function.cpp +++ b/function.cpp @@ -508,6 +508,25 @@ Confidence Function::HasVariableArguments() const } +Confidence Function::GetStackAdjustment() const +{ + BNSizeWithConfidence sc = BNGetFunctionStackAdjustment(m_object); + return Confidence(sc.value, sc.confidence); +} + + +Confidence> Function::GetClobberedRegisters() const +{ + BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object); + set regSet; + for (size_t i = 0; i < regs.count; i++) + regSet.insert(regs.regs[i]); + Confidence> result(regSet, regs.confidence); + BNFreeClobberedRegisters(®s); + return result; +} + + void Function::SetAutoType(Type* type) { BNSetFunctionAutoType(m_object, type->GetObject()); @@ -568,6 +587,29 @@ void Function::SetAutoCanReturn(const Confidence& returns) } +void Function::SetAutoStackAdjustment(const Confidence& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetAutoFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetAutoClobberedRegisters(const Confidence>& clobbered) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[clobbered.GetValue().size()]; + regs.count = clobbered.GetValue().size(); + size_t i = 0; + for (auto reg : clobbered.GetValue()) + regs.regs[i++] = reg; + regs.confidence = clobbered.GetConfidence(); + BNSetAutoFunctionClobberedRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::SetUserType(Type* type) { BNSetFunctionUserType(m_object, type->GetObject()); @@ -628,6 +670,29 @@ void Function::SetCanReturn(const Confidence& returns) } +void Function::SetStackAdjustment(const Confidence& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetUserFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetClobberedRegisters(const Confidence>& clobbered) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[clobbered.GetValue().size()]; + regs.count = clobbered.GetValue().size(); + size_t i = 0; + for (auto reg : clobbered.GetValue()) + regs.regs[i++] = reg; + regs.confidence = clobbered.GetConfidence(); + BNSetUserFunctionClobberedRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::ApplyImportedTypes(Symbol* sym) { BNApplyImportedTypes(m_object, sym->GetObject()); @@ -1014,6 +1079,20 @@ void Function::SetUserInstructionHighlight(Architecture* arch, uint64_t addr, ui } +Confidence Function::GetGlobalPointerValue() const +{ + BNRegisterValueWithConfidence value = BNGetFunctionGlobalPointerValue(m_object); + return Confidence(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + +Confidence Function::GetRegisterValueAtExit(uint32_t reg) const +{ + BNRegisterValueWithConfidence value = BNGetFunctionRegisterValueAtExit(m_object, reg); + return Confidence(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + void Function::Reanalyze() { BNReanalyzeFunction(m_object); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index f978f681..04a7341f 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -302,19 +302,31 @@ void MediumLevelILFunction::Finalize() void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases, - const set& knownAliases) + const set& knownNotAliases, const set& knownAliases) { - BNVariable* vars = new BNVariable[knownAliases.size()]; + BNVariable* knownNotAlias = new BNVariable[knownNotAliases.size()]; + BNVariable* knownAlias = new BNVariable[knownAliases.size()]; + size_t i = 0; + for (auto& j : knownNotAliases) + { + knownNotAlias[i].type = j.type; + knownNotAlias[i].index = j.index; + knownNotAlias[i].storage = j.storage; + } + + i = 0; for (auto& j : knownAliases) { - vars[i].type = j.type; - vars[i].index = j.index; - vars[i].storage = j.storage; + knownAlias[i].type = j.type; + knownAlias[i].index = j.index; + knownAlias[i].storage = j.storage; } - BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size()); - delete[] vars; + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, knownNotAlias, knownNotAliases.size(), + knownAlias, knownAliases.size()); + delete[] knownNotAlias; + delete[] knownAlias; } diff --git a/python/binaryview.py b/python/binaryview.py index d977de50..bf8a87e0 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -927,6 +927,12 @@ class BinaryView(object): else: return BinaryView._associated_data[handle.value] + @property + def global_pointer_value(self): + """Discovered value of the global pointer register, if the binary uses one (read-only)""" + result = core.BNGetGlobalPointerValue(self.handle) + return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + def __len__(self): return int(core.BNGetViewLength(self.handle)) diff --git a/python/callingconvention.py b/python/callingconvention.py index bd8bbeee..e72475c9 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -37,6 +37,7 @@ class CallingConvention(object): float_arg_regs = [] arg_regs_share_index = False stack_reserved_for_arg_regs = False + stack_adjusted_on_return = False int_return_reg = None high_int_return_reg = None float_return_reg = None @@ -59,6 +60,7 @@ class CallingConvention(object): self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) self._cb.areArgumentRegistersSharedIndex = self._cb.areArgumentRegistersSharedIndex.__class__(self._arg_regs_share_index) self._cb.isStackReservedForArgumentRegisters = self._cb.isStackReservedForArgumentRegisters.__class__(self._stack_reserved_for_arg_regs) + self._cb.isStackAdjustedOnReturn = self._cb.isStackAdjustedOnReturn.__class__(self._stack_adjusted_on_return) self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg) self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg) self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg) @@ -74,6 +76,7 @@ class CallingConvention(object): 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) + self.__dict__["stack_adjusted_on_return"] = core.BNIsStackAdjustedOnReturn(self.handle) count = ctypes.c_ulonglong() regs = core.BNGetCallerSavedRegisters(self.handle, count) @@ -218,6 +221,13 @@ class CallingConvention(object): log.log_error(traceback.format_exc()) return False + def _stack_adjusted_on_return(self, ctxt): + try: + return self.__class__.stack_adjusted_on_return + except: + log.log_error(traceback.format_exc()) + return False + def _get_int_return_reg(self, ctxt): try: return self.arch.regs[self.__class__.int_return_reg].index diff --git a/python/function.py b/python/function.py index 55151e16..553b156f 100644 --- a/python/function.py +++ b/python/function.py @@ -50,11 +50,12 @@ class LookupTableEntry(object): class RegisterValue(object): - def __init__(self, arch = None, value = None): + def __init__(self, arch = None, value = None, confidence = types.max_confidence): 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: @@ -63,8 +64,10 @@ class RegisterValue(object): self.reg = value.value elif (value.state == RegisterValueType.ConstantValue) or (value.state == RegisterValueType.ConstantPointerValue): self.value = value.value + self.is_constant = True elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value + self.confidence = confidence def __repr__(self): if self.type == RegisterValueType.EntryValue: @@ -280,6 +283,9 @@ class ParameterVariables(object): def __getitem__(self, idx): return self.vars[idx] + def __len__(self): + return len(self.vars) + def with_confidence(self, confidence): return ParameterVariables(list(self.vars), confidence = confidence) @@ -598,6 +604,52 @@ class Function(object): bc.confidence = types.max_confidence core.BNSetUserFunctionHasVariableArguments(self.handle, bc) + @property + def stack_adjustment(self): + """Number of bytes removed from the stack after return""" + result = core.BNGetFunctionStackAdjustment(self.handle) + return types.SizeWithConfidence(result.value, confidence = result.confidence) + + @stack_adjustment.setter + def stack_adjustment(self, value): + sc = core.BNSizeWithConfidence() + sc.value = int(value) + if hasattr(value, 'confidence'): + sc.confidence = value.confidence + else: + sc.confidence = types.max_confidence + core.BNSetUserFunctionStackAdjustment(self.handle, sc) + + @property + def clobbered_regs(self): + """Registers that are modified by this function""" + result = core.BNGetFunctionClobberedRegisters(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.BNFreeClobberedRegisters(result) + return regs + + @clobbered_regs.setter + def clobbered_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.BNSetUserFunctionClobberedRegisters(self.handle, regs) + + @property + def global_pointer_value(self): + """Discovered value of the global pointer register, if the function uses one (read-only)""" + result = core.BNGetFunctionGlobalPointerValue(self.handle) + return RegisterValue(self.arch, result.value, confidence = result.confidence) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -963,6 +1015,27 @@ class Function(object): bc.confidence = types.max_confidence core.BNSetAutoFunctionCanReturn(self.handle, bc) + def set_auto_stack_adjustment(self, value): + sc = core.BNSizeWithConfidence() + sc.value = int(value) + if hasattr(value, 'confidence'): + sc.confidence = value.confidence + else: + sc.confidence = types.max_confidence + core.BNSetAutoFunctionStackAdjustment(self.handle, sc) + + def set_auto_clobbered_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.BNSetAutoFunctionClobberedRegisters(self.handle, regs) + def get_int_display_type(self, instr_addr, value, operand, arch=None): if arch is None: arch = self.arch @@ -1160,6 +1233,10 @@ class Function(object): core.BNFreeDisassemblyTextLines(lines, count.value) return result + def get_reg_value_at_exit(self, reg): + result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg)) + return RegisterValue(self.arch, result.value, confidence = result.confidence) + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): diff --git a/python/types.py b/python/types.py index fd2ee27e..bf4a7b74 100644 --- a/python/types.py +++ b/python/types.py @@ -650,6 +650,43 @@ class BoolWithConfidence(object): return self.value +class SizeWithConfidence(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 + self.confidence = confidence + + def __repr__(self): + return repr(self.regs) + + def __iter__(self): + for reg in self.regs: + yield reg + + def __getitem__(self, idx): + return self.regs[idx] + + def __len__(self): + return len(self.regs) + + def with_confidence(self, confidence): + return RegisterSet(list(self.regs), confidence = confidence) + + class ReferenceTypeWithConfidence(object): def __init__(self, value, confidence = max_confidence): self.value = value -- cgit v1.3.1