From 990cface5a0b9b814f423e45449a7d5f3cb6c19d Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 1 Dec 2016 17:22:22 -0500 Subject: Adding APIs to manipulate structures --- python/__init__.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/__init__.py b/python/__init__.py index 1751fefa..cc138009 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -576,6 +576,12 @@ class BinaryDataNotification: def string_removed(self, view, string_type, offset, length): pass + def type_defined(self, view, name, type): + pass + + def type_undefined(self, view, name, type): + pass + class UndoAction: name = None action_type = None @@ -671,6 +677,8 @@ class BinaryDataNotificationCallbacks(object): self._cb.dataVariableUpdated = self._cb.dataVariableUpdated.__class__(self._data_var_updated) self._cb.stringFound = self._cb.stringFound.__class__(self._string_found) self._cb.stringRemoved = self._cb.stringRemoved.__class__(self._string_removed) + self._cb.typeDefined = self._cb.typeDefined.__class__(self._type_defined) + self._cb.typeUndefined = self._cb.typeUndefined.__class__(self._type_undefined) def _register(self): core.BNRegisterDataNotification(self.view.handle, self._cb) @@ -753,6 +761,18 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) + def _type_defined(self, ctxt, name, type_obj): + try: + self.notify.type_defined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + except: + log_error(traceback.format_exc()) + + def _type_undefined(self, ctxt, name, type_obj): + try: + self.notify.type_undefined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + except: + log_error(traceback.format_exc()) + class _BinaryViewTypeMetaclass(type): @property def list(self): @@ -4447,14 +4467,22 @@ class Structure(object): @property def width(self): - """Structure width (read-only)""" + """Structure width""" return core.BNGetStructureWidth(self.handle) + @width.setter + def width(self, new_width): + core.BNSetStructureWidth(self.handle, new_width) + @property def alignment(self): - """Structure alignment (read-only)""" + """Structure alignment""" return core.BNGetStructureAlignment(self.handle) + @alignment.setter + def alignment(self, align): + core.BNSetStructureAlignment(self.handle, align) + @property def packed(self): return core.BNIsStructurePacked(self.handle) -- cgit v1.3.1 From 09a68bdd84d4789626f5c8b8631f61e7a41ca03d Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jan 2017 15:42:08 -0500 Subject: Use named type references for registered types, use qualified names for types --- architecture.cpp | 57 +++++++--- binaryninjaapi.h | 62 ++++++----- binaryninjacore.h | 71 ++++++++----- binaryview.cpp | 134 +++++++++++++++++++----- python/__init__.py | 290 ++++++++++++++++++++++++++++++++++++++------------- python/generator.cpp | 46 ++++---- type.cpp | 111 +++++++++----------- 7 files changed, 533 insertions(+), 238 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index e84b7f78..d0d87df4 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -746,9 +746,8 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map>& types, map>& variables, - map>& functions, string& errors, - const vector& includeDirs) + map, Ref>& types, map, Ref>& variables, + map, Ref>& functions, string& errors, const vector& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -762,26 +761,41 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file functions.clear(); bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size()); + &errorStr, includeDirList, includeDirs.size()); errors = errorStr; BNFreeString(errorStr); if (!ok) return false; for (size_t i = 0; i < result.typeCount; i++) - types[result.types[i].name] = new Type(BNNewTypeReference(result.types[i].type)); + { + vector name; + for (size_t j = 0; j < result.types[i].nameCount; j++) + name.push_back(result.types[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } for (size_t i = 0; i < result.variableCount; i++) - types[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + vector name; + for (size_t j = 0; j < result.variables[i].nameCount; j++) + name.push_back(result.variables[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } for (size_t i = 0; i < result.functionCount; i++) - types[result.functions[i].name] = new Type(BNNewTypeReference(result.functions[i].type)); + { + vector name; + for (size_t j = 0; j < result.functions[i].nameCount; j++) + name.push_back(result.functions[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, - map>& variables, map>& functions, - string& errors, const vector& includeDirs) +bool Architecture::ParseTypesFromSourceFile(const string& fileName, map, Ref>& types, + map, Ref>& variables, map, Ref>& functions, + string& errors, const vector& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -795,18 +809,33 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map name; + for (size_t j = 0; j < result.types[i].nameCount; j++) + name.push_back(result.types[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } for (size_t i = 0; i < result.variableCount; i++) - variables[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + vector name; + for (size_t j = 0; j < result.variables[i].nameCount; j++) + name.push_back(result.variables[i].name[j]); + variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } for (size_t i = 0; i < result.functionCount; i++) - functions[result.functions[i].name] = new Type(BNNewTypeReference(result.functions[i].type)); + { + vector name; + for (size_t j = 0; j < result.functions[i].nameCount; j++) + name.push_back(result.functions[i].name[j]); + functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 58f901ab..15c86a58 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -590,8 +590,8 @@ namespace BinaryNinja static void DataVariableUpdatedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void StringFoundCallback(void* ctxt, BNBinaryView* data, BNStringType type, uint64_t offset, size_t len); static void StringRemovedCallback(void* ctxt, BNBinaryView* data, BNStringType type, uint64_t offset, size_t len); - static void TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type); - static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type); + static void TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, BNType* type); + static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, BNType* type); public: BinaryDataNotification(); @@ -610,8 +610,8 @@ namespace BinaryNinja virtual void OnDataVariableUpdated(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnStringFound(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } virtual void OnStringRemoved(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } - virtual void OnTypeDefined(BinaryView* data, const std::string& name, Type* type) { (void)data; (void)name; (void)type; } - virtual void OnTypeUndefined(BinaryView* data, const std::string& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeDefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeUndefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } }; class FileAccessor @@ -755,7 +755,7 @@ namespace BinaryNinja uint64_t align, entrySize; }; - struct NameAndType; + struct QualifiedNameAndType; /*! BinaryView is the base class for creating views on binary data (e.g. ELF, PE, Mach-O). BinaryView should be subclassed to create a new BinaryView @@ -977,15 +977,21 @@ namespace BinaryNinja std::vector GetNextLinearDisassemblyLines(LinearDisassemblyPosition& pos, DisassemblySettings* settings); - bool ParseTypeString(const std::string& text, NameAndType& result, std::string& errors); + bool ParseTypeString(const std::string& text, QualifiedNameAndType& result, std::string& errors); - std::map> GetTypes(); + std::map, Ref> GetTypes(); Ref GetTypeByName(const std::string& name); + Ref GetTypeByName(const std::vector& name); bool IsTypeAutoDefined(const std::string& name); + bool IsTypeAutoDefined(const std::vector& name); void DefineType(const std::string& name, Ref type); + void DefineType(const std::vector& name, Ref type); void DefineUserType(const std::string& name, Ref type); + void DefineUserType(const std::vector& name, Ref type); void UndefineType(const std::string& name); + void UndefineType(const std::vector& name); void UndefineUserType(const std::string& name); + void UndefineUserType(const std::vector& name); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -1435,13 +1441,15 @@ namespace BinaryNinja void SetBinaryViewTypeConstant(const std::string& type, const std::string& name, uint64_t value); bool ParseTypesFromSource(const std::string& source, const std::string& fileName, - std::map>& types, std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); - bool ParseTypesFromSourceFile(const std::string& fileName, std::map>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + std::map, Ref>& types, + std::map, Ref>& variables, + std::map, Ref>& functions, std::string& errors, + const std::vector& includeDirs = std::vector()); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map, Ref>& types, + std::map, Ref>& variables, + std::map, Ref>& functions, std::string& errors, + const std::vector& includeDirs = std::vector()); void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); @@ -1504,7 +1512,7 @@ namespace BinaryNinja }; class Structure; - class UnknownType; + class NamedTypeReference; class Enumeration; struct NameAndType @@ -1513,6 +1521,12 @@ namespace BinaryNinja Ref type; }; + struct QualifiedNameAndType + { + std::vector name; + Ref type; + }; + class Type: public CoreRefCountObject { public: @@ -1532,7 +1546,7 @@ namespace BinaryNinja bool CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; - Ref GetUnknownType() const; + Ref GetNamedTypeReference() const; uint64_t GetElementCount() const; @@ -1554,7 +1568,8 @@ namespace BinaryNinja static Ref IntegerType(size_t width, bool sign, const std::string& altName = ""); static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); - static Ref UnknownNamedType(UnknownType* unknwn); + static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); + static Ref NamedType(const std::vector& name, Type* type); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); @@ -1565,10 +1580,14 @@ namespace BinaryNinja static std::string GetQualifiedName(const std::vector& names); }; - class UnknownType: public CoreRefCountObject + class NamedTypeReference: public CoreRefCountObject { public: - UnknownType(BNUnknownType* s, std::vector name = {}); + NamedTypeReference(BNNamedTypeReference* nt); + NamedTypeReference(BNNamedTypeReferenceClass cls, const std::vector& name = {}); + BNNamedTypeReferenceClass GetTypeClass() const; + void SetTypeClass(BNNamedTypeReferenceClass cls); std::vector GetName() const; void SetName(const std::vector& name); }; @@ -1586,8 +1605,6 @@ namespace BinaryNinja Structure(); Structure(BNStructure* s); - std::vector GetName() const; - void SetName(const std::vector& name); std::vector GetMembers() const; uint64_t GetWidth() const; void SetWidth(size_t width); @@ -1616,9 +1633,6 @@ namespace BinaryNinja public: Enumeration(BNEnumeration* e); - std::vector GetName() const; - void SetName(const std::vector& name); - std::vector GetMembers() const; void AddMember(const std::string& name); diff --git a/binaryninjacore.h b/binaryninjacore.h index b29a67a2..26f37536 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -94,7 +94,7 @@ extern "C" struct BNLowLevelILFunction; struct BNType; struct BNStructure; - struct BNUnknownType; + struct BNNamedTypeReference; struct BNEnumeration; struct BNCallingConvention; struct BNPlatform; @@ -371,7 +371,17 @@ extern "C" FunctionTypeClass = 8, VarArgsTypeClass = 9, ValueTypeClass = 10, - UnknownTypeClass = 11 + NamedTypeReferenceClass = 11 + }; + + enum BNNamedTypeReferenceClass + { + UnknownNamedTypeClass = 0, + TypedefNamedTypeClass = 1, + ClassNamedTypeClass = 2, + StructNamedTypeClass = 3, + UnionNamedTypeClass = 4, + EnumNamedTypeClass = 5 }; enum BNStructureType @@ -635,8 +645,8 @@ extern "C" void (*dataVariableUpdated)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*stringFound)(void* ctxt, BNBinaryView* view, BNStringType type, uint64_t offset, size_t len); void (*stringRemoved)(void* ctxt, BNBinaryView* view, BNStringType type, uint64_t offset, size_t len); - void (*typeDefined)(void* ctxt, BNBinaryView* view, const char* name, BNType* type); - void (*typeUndefined)(void* ctxt, BNBinaryView* view, const char* name, BNType* type); + void (*typeDefined)(void* ctxt, BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + void (*typeUndefined)(void* ctxt, BNBinaryView* view, const char** name, size_t nameCount, BNType* type); }; struct BNFileAccessor @@ -842,6 +852,13 @@ extern "C" BNType* type; }; + struct BNQualifiedNameAndType + { + char** name; + size_t nameCount; + BNType* type; + }; + struct BNStructureMember { BNType* type; @@ -864,9 +881,9 @@ extern "C" struct BNTypeParserResult { - BNNameAndType* types; - BNNameAndType* variables; - BNNameAndType* functions; + BNQualifiedNameAndType* types; + BNQualifiedNameAndType* variables; + BNQualifiedNameAndType* functions; size_t typeCount, variableCount, functionCount; }; @@ -1776,17 +1793,19 @@ extern "C" BINARYNINJACOREAPI void BNFreeDataVariables(BNDataVariable* vars, size_t count); BINARYNINJACOREAPI bool BNGetDataVariableAtAddress(BNBinaryView* view, uint64_t addr, BNDataVariable* var); - BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNNameAndType* result, char** errors); + BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, + BNQualifiedNameAndType* result, char** errors); BINARYNINJACOREAPI void BNFreeNameAndType(BNNameAndType* obj); + BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj); - BINARYNINJACOREAPI BNNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); - BINARYNINJACOREAPI void BNFreeTypeList(BNNameAndType* types, size_t count); - BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, const char* name, BNType* type); - BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, const char* name, BNType* type); - BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, const char* name); + BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); + BINARYNINJACOREAPI void BNFreeTypeList(BNQualifiedNameAndType* types, size_t count); + BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, const char** name, size_t nameCount); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -1968,6 +1987,7 @@ extern "C" BINARYNINJACOREAPI bool BNFunctionTypeCanReturn(BNType* type); BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type); BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); + BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, bool canReturn); @@ -1979,19 +1999,20 @@ extern "C" BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); - BINARYNINJACOREAPI BNType* BNCreateUnknownNamedType(BNUnknownType* ut); - BINARYNINJACOREAPI BNUnknownType* BNCreateUnknownType(void); - BINARYNINJACOREAPI void BNSetUnknownTypeName(BNUnknownType* ut, const char** name, size_t size); - BINARYNINJACOREAPI char** BNGetUnknownTypeName(BNUnknownType* ut, size_t* size); - BINARYNINJACOREAPI void BNFreeUnknownType(BNUnknownType* ut); - BINARYNINJACOREAPI BNUnknownType* BNNewUnknownTypeReference(BNUnknownType* ut); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI BNNamedTypeReference* BNCreateNamedType(void); + BINARYNINJACOREAPI void BNSetTypeReferenceClass(BNNamedTypeReference* nt, BNNamedTypeReferenceClass cls); + BINARYNINJACOREAPI BNNamedTypeReferenceClass BNGetTypeReferenceClass(BNNamedTypeReference* nt); + BINARYNINJACOREAPI void BNSetTypeReferenceName(BNNamedTypeReference* nt, const char** name, size_t size); + BINARYNINJACOREAPI char** BNGetTypeReferenceName(BNNamedTypeReference* nt, size_t* size); + BINARYNINJACOREAPI void BNFreeNamedTypeReference(BNNamedTypeReference* nt); + BINARYNINJACOREAPI BNNamedTypeReference* BNNewNamedTypeReference(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNStructure* BNCreateStructure(void); BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s); BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); - BINARYNINJACOREAPI char** BNGetStructureName(BNStructure* s, size_t* size); - BINARYNINJACOREAPI void BNSetStructureName(BNStructure* s, const char** names, size_t size); BINARYNINJACOREAPI BNStructureMember* BNGetStructureMembers(BNStructure* s, size_t* count); BINARYNINJACOREAPI void BNFreeStructureMemberList(BNStructureMember* members, size_t count); BINARYNINJACOREAPI uint64_t BNGetStructureWidth(BNStructure* s); @@ -2012,8 +2033,6 @@ extern "C" BINARYNINJACOREAPI BNEnumeration* BNNewEnumerationReference(BNEnumeration* e); BINARYNINJACOREAPI void BNFreeEnumeration(BNEnumeration* e); - BINARYNINJACOREAPI char** BNGetEnumerationName(BNEnumeration* e, size_t* size); - BINARYNINJACOREAPI void BNSetEnumerationName(BNEnumeration* e, const char** name, size_t size); BINARYNINJACOREAPI BNEnumerationMember* BNGetEnumerationMembers(BNEnumeration* e, size_t* count); BINARYNINJACOREAPI void BNFreeEnumerationMemberList(BNEnumerationMember* members, size_t count); diff --git a/binaryview.cpp b/binaryview.cpp index 154dfcf5..9fdd5748 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -129,21 +129,29 @@ void BinaryDataNotification::StringRemovedCallback(void* ctxt, BNBinaryView* obj } -void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type) +void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, + BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeDefined(view, name, typeObj); + vector nameList; + for (size_t i = 0; i < nameCount; i++) + nameList.push_back(name[i]); + notify->OnTypeDefined(view, nameList, typeObj); } -void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type) +void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, + BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeUndefined(view, name, typeObj); + vector nameList; + for (size_t i = 0; i < nameCount; i++) + nameList.push_back(name[i]); + notify->OnTypeUndefined(view, nameList, typeObj); } @@ -1447,9 +1455,9 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi } -bool BinaryView::ParseTypeString(const string& text, NameAndType& result, string& errors) +bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& result, string& errors) { - BNNameAndType nt; + BNQualifiedNameAndType nt; char* errorStr; if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr)) @@ -1459,22 +1467,28 @@ bool BinaryView::ParseTypeString(const string& text, NameAndType& result, string return false; } - result.name = nt.name; - result.type = new Type(nt.type); + for (size_t i = 0; i < nt.nameCount; i++) + result.name.push_back(nt.name[i]); + result.type = new Type(BNNewTypeReference(nt.type)); errors = ""; - BNFreeString(nt.name); + BNFreeQualifiedNameAndType(&nt); return true; } -map> BinaryView::GetTypes() +map, Ref> BinaryView::GetTypes() { size_t count; - BNNameAndType* types = BNGetAnalysisTypeList(m_object, &count); + BNQualifiedNameAndType* types = BNGetAnalysisTypeList(m_object, &count); - map> result; + map, Ref> result; for (size_t i = 0; i < count; i++) - result[types[i].name] = new Type(BNNewTypeReference(types[i].type)); + { + vector name; + for (size_t j = 0; j < types[i].nameCount; j++) + name.push_back(types[i].name[j]); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } BNFreeTypeList(types, count); return result; @@ -1483,40 +1497,112 @@ map> BinaryView::GetTypes() Ref BinaryView::GetTypeByName(const string& name) { - BNType* type = BNGetAnalysisTypeByName(m_object, name.c_str()); + const char* nameStr = name.c_str(); + BNType* type = BNGetAnalysisTypeByName(m_object, &nameStr, 1); + if (!type) + return nullptr; + return new Type(type); +} + + +Ref BinaryView::GetTypeByName(const vector& name) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + + BNType* type = BNGetAnalysisTypeByName(m_object, nameList, name.size()); + delete[] nameList; + if (!type) return nullptr; return new Type(type); } -bool BinaryView::IsTypeAutoDefined(const std::string& name) +bool BinaryView::IsTypeAutoDefined(const string& name) +{ + const char* nameStr = name.c_str(); + return BNIsAnalysisTypeAutoDefined(m_object, &nameStr, 1); +} + + +bool BinaryView::IsTypeAutoDefined(const vector& name) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + bool result = BNIsAnalysisTypeAutoDefined(m_object, nameList, name.size()); + delete[] nameList; + return result; +} + + +void BinaryView::DefineType(const string& name, Ref type) +{ + const char* nameStr = name.c_str(); + BNDefineAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineType(const vector& name, Ref type) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNDefineAnalysisType(m_object, nameList, name.size(), type->GetObject()); + delete[] nameList; +} + + +void BinaryView::DefineUserType(const string& name, Ref type) +{ + const char* nameStr = name.c_str(); + BNDefineUserAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineUserType(const vector& name, Ref type) { - return BNIsAnalysisTypeAutoDefined(m_object, name.c_str()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNDefineUserAnalysisType(m_object, nameList, name.size(), type->GetObject()); + delete[] nameList; } -void BinaryView::DefineType(const std::string& name, Ref type) +void BinaryView::UndefineType(const string& name) { - BNDefineAnalysisType(m_object, name.c_str(), type->GetObject()); + const char* nameStr = name.c_str(); + BNUndefineAnalysisType(m_object, &nameStr, 1); } -void BinaryView::DefineUserType(const std::string& name, Ref type) +void BinaryView::UndefineType(const vector& name) { - BNDefineUserAnalysisType(m_object, name.c_str(), type->GetObject()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNUndefineAnalysisType(m_object, nameList, name.size()); + delete[] nameList; } -void BinaryView::UndefineType(const std::string& name) +void BinaryView::UndefineUserType(const string& name) { - BNUndefineAnalysisType(m_object, name.c_str()); + const char* nameStr = name.c_str(); + BNUndefineUserAnalysisType(m_object, &nameStr, 1); } -void BinaryView::UndefineUserType(const std::string& name) +void BinaryView::UndefineUserType(const vector& name) { - BNUndefineUserAnalysisType(m_object, name.c_str()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNUndefineUserAnalysisType(m_object, nameList, name.size()); + delete[] nameList; } diff --git a/python/__init__.py b/python/__init__.py index cc138009..b5ced583 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -660,6 +660,70 @@ class StringReference(object): def __repr__(self): return "<%s: %#x, len %#x>" % (self.type, self.start, self.length) +class QualifiedName(object): + def __init__(self, name = []): + if isinstance(name, str): + self.name = [name] + else: + self.name = name + + def __str__(self): + return "::".join(self.name) + + def __repr__(self): + return repr(str(self)) + + def __len__(self): + return len(self.name) + + def __hash__(self): + return hash(str(self)) + + def __eq__(self, other): + if isinstance(other, str): + return str(self) == other + elif isinstance(other, list): + return self.name == other + elif isinstance(other, QualifiedName): + return self.name == other.name + return False + + def __ne__(self, other): + return not (self == other) + + def __lt__(self, other): + if isinstance(other, QualifiedName): + return self.name < other.name + return False + + def __le__(self, other): + if isinstance(other, QualifiedName): + return self.name <= other.name + return False + + def __gt__(self, other): + if isinstance(other, QualifiedName): + return self.name > other.name + return False + + def __ge__(self, other): + if isinstance(other, QualifiedName): + return self.name >= other.name + return False + + def __cmp__(self, other): + if self == other: + return 0 + if self < other: + return -1 + return 1 + + def __getitem__(self, key): + return self.name[key] + + def __iter__(self): + return iter(self.name) + class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): self.view = view @@ -761,15 +825,21 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) - def _type_defined(self, ctxt, name, type_obj): + def _type_defined(self, ctxt, name, name_count, type_obj): try: - self.notify.type_defined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + name_list = [] + for i in xrange(0, name_count): + name_list.append(name[i]) + self.notify.type_defined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) - def _type_undefined(self, ctxt, name, type_obj): + def _type_undefined(self, ctxt, name, name_count, type_obj): try: - self.notify.type_undefined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + name_list = [] + for i in xrange(0, name_count): + name_list.append(name[i]) + self.notify.type_undefined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) @@ -1394,7 +1464,10 @@ class BinaryView(object): type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} for i in xrange(0, count.value): - result[type_list[i].name] = Type(core.BNNewTypeReference(type_list[i].type)) + name = [] + for j in xrange(0, type_list[i].nameCount): + name.append(type_list[i].name[j]) + result[QualifiedName(name)] = Type(core.BNNewTypeReference(type_list[i].type)) core.BNFreeTypeList(type_list, count.value) return result @@ -3350,30 +3423,33 @@ class BinaryView(object): ``parse_type_string`` converts `C-style` string into a :py:Class:`Type`. :param str text: `C-style` string of type to create - :return: A tuple of a :py:Class:`Type` and string type name - :rtype: tuple(Type, str) + :return: A tuple of a :py:Class:`Type` and type name + :rtype: tuple(Type, QualifiedName) :Example: >>> bv.parse_type_string("int foo") (, 'foo') >>> """ - result = core.BNNameAndType() + result = core.BNQualifiedNameAndType() errors = ctypes.c_char_p() if not core.BNParseTypeString(self.handle, text, result, errors): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError, error_str type_obj = Type(core.BNNewTypeReference(result.type)) - name = result.name - core.BNFreeNameAndType(result) + name = [] + for i in xrange(0, result.nameCount): + name.append(result.name[i]) + name = QualifiedName(name) + core.BNFreeQualifiedNameAndType(result) return type_obj, name def get_type_by_name(self, name): """ ``get_type_by_name`` returns the defined type whose name corresponds with the provided ``name`` - :param str name: Type name to lookup + :param QualifiedName name: Type name to lookup :return: A :py:Class:`Type` or None if the type does not exist :rtype: Type or None :Example: @@ -3384,7 +3460,12 @@ class BinaryView(object): >>> """ - obj = core.BNGetAnalysisTypeByName(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + obj = core.BNGetAnalysisTypeByName(self.handle, name_list, len(name)) if not obj: return None return Type(obj) @@ -3394,7 +3475,7 @@ class BinaryView(object): ``is_type_auto_defined`` queries the user type list of name. If name is not in the *user* type list then the name is considered an *auto* type. - :param str name: Name of type to query + :param QualifiedName name: Name of type to query :return: True if the type is not a *user* type. False if the type is a *user* type. :Example: >>> bv.is_type_auto_defined("foo") @@ -3404,14 +3485,19 @@ class BinaryView(object): False >>> """ - return core.BNIsAnalysisTypeAutoDefined(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + return core.BNIsAnalysisTypeAutoDefined(self.handle, name_list, len(name)) def define_type(self, name, type_obj): """ ``define_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of types for the current :py:Class:`BinaryView`. - :param str name: Name of the type to be registered + :param QualifiedName name: Name of the type to be registered :param Type type_obj: Type object to be registered :rtype: None :Example: @@ -3421,14 +3507,19 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - core.BNDefineAnalysisType(self.handle, name, type_obj.handle) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNDefineAnalysisType(self.handle, name_list, len(name), type_obj.handle) def define_user_type(self, name, type_obj): """ ``define_user_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of user types for the current :py:Class:`BinaryView`. - :param str name: Name of the user type to be registered + :param QualifiedName name: Name of the user type to be registered :param Type type_obj: Type object to be registered :rtype: None :Example: @@ -3438,13 +3529,18 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNDefineUserAnalysisType(self.handle, name_list, len(name), type_obj.handle) def undefine_type(self, name): """ ``undefine_type`` removes a :py:Class:`Type` from the global list of types for the current :py:Class:`BinaryView` - :param str name: Name of type to be undefined + :param QualifiedName name: Name of type to be undefined :rtype: None :Example: @@ -3456,14 +3552,19 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - core.BNUndefineAnalysisType(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNUndefineAnalysisType(self.handle, name_list, len(name)) def undefine_user_type(self, name): """ ``undefine_user_type`` removes a :py:Class:`Type` from the global list of user types for the current :py:Class:`BinaryView` - :param str name: Name of user type to be undefined + :param QualifiedName name: Name of user type to be undefined :rtype: None :Example: @@ -3475,7 +3576,12 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - core.BNUndefineUserAnalysisType(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNUndefineUserAnalysisType(self.handle, name_list, len(name)) def find_next_data(self, start, data, flags = 0): """ @@ -4313,6 +4419,14 @@ class Type(object): return None return Enumeration(result) + @property + def named_type_reference(self): + """Reference to a named type (read-only)""" + result = core.BNGetTypeNamedTypeReference(self.handle) + if result is None: + return None + return NamedTypeReference(result) + @property def count(self): """Type count (read-only)""" @@ -4351,12 +4465,19 @@ class Type(object): return Type(core.BNCreateStructureType(structure_type.handle)) @classmethod - def unknown_type(self, unknown_type): - return Type(core.BNCreateUnknownType(unknown_type.handle)) + def named_type(self, named_type, width = 0, align = 1): + return Type(core.BNCreateNamedTypeReference(named_type.handle, width, align)) @classmethod - def unknown_type(self, s): - return Type(core.BNCreateUnknownType(s.handle)) + def named_type_from_type(self, name, t): + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + if t is not None: + t = t.handle + return Type(core.BNCreateNamedTypeReferenceFromType(name_list, len(name), t)) @classmethod def enumeration_type(self, arch, e, width = None): @@ -4394,28 +4515,60 @@ class Type(object): raise AttributeError, "attribute '%s' is read only" % name -class UnknownType(object): - def __init__(self, handle = None): +class NamedTypeReference(object): + def __init__(self, type_class = core.UnknownNamedTypeClass, name = None, handle = None): if handle is None: - self.handle = core.BNCreateUnknownType() + self.handle = core.BNCreateNamedType() + core.BNSetTypeReferenceClass(self.handle, type_class) + if name is not None: + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNSetTypeReferenceName(self.handle, name_list, len(name)) else: self.handle = handle def __del__(self): - core.BNFreeUnknownType(self.handle) + core.BNFreeNamedTypeReference(self.handle) + + @property + def type_class(self): + return core.BNGetTypeReferenceClass(self.handle) + + @type_class.setter + def type_class(self, value): + core.BNSetTypeReferenceClass(self.handle, value) @property def name(self): count = ctypes.c_ulonglong() - nameList = core.BNGetUnknownTypeName(self.handle, count) + nameList = core.BNGetTypeReferenceName(self.handle, count) result = [] for i in xrange(count.value): result.append(nameList[i]) - return get_qualified_name(result) + return QualifiedName(result) @name.setter def name(self, value): - core.BNSetUnknownTypeName(self.handle, value) + if isinstance(value, str): + value = [value] + name_list = (ctypes.c_char_p * len(value))() + for i in xrange(0, len(value)): + name_list[i] = value[i] + core.BNSetTypeReferenceName(self.handle, name_list, len(value)) + + def __repr__(self): + if self.type_class == core.TypedefNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.StructNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.UnionNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.EnumNamedTypeClass: + return "" % str(self.name) + return "" % str(self.name) class StructureMember(object): @@ -4440,19 +4593,6 @@ class Structure(object): def __del__(self): core.BNFreeStructure(self.handle) - @property - def name(self): - count = ctypes.c_ulonglong() - nameList = core.BNGetStructureName(self.handle, count) - result = [] - for i in xrange(count.value): - result.append(nameList[i]) - return get_qualified_name(result) - - @name.setter - def name(self, value): - core.BNSetStructureName(self.handle, value) - @property def members(self): """Structure member list (read-only)""" @@ -4538,14 +4678,6 @@ class Enumeration(object): def __del__(self): core.BNFreeEnumeration(self.handle) - @property - def name(self): - return core.BNGetEnumerationName(self.handle) - - @name.setter - def name(self, value): - core.BNSetEnumerationName(self.handle, value) - @property def members(self): """Enumeration member list (read-only)""" @@ -7423,8 +7555,8 @@ class Architecture(object): :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories - :return: a tuple of py:class:`TypeParserResult` and error string - :rtype: tuple(TypeParserResult,str) + :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult :Example: >>> arch.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') @@ -7444,18 +7576,27 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - return (None, error_str) + raise SyntaxError, error_str types = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = [] + for j in xrange(0, parse.types[i].nameCount): + name.append(parse.types[i].name[j]) + types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = [] + for j in xrange(0, parse.variables[i].nameCount): + name.append(parse.variables[i].name[j]) + variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - BNFreeTypeParserResult(parse) - return (TypeParserResult(types, variables, functions), error_str) + name = [] + for j in xrange(0, parse.functions[i].nameCount): + name.append(parse.functions[i].name[j]) + functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + core.BNFreeTypeParserResult(parse) + return TypeParserResult(types, variables, functions) def parse_types_from_source_file(self, filename, include_dirs = []): """ @@ -7464,8 +7605,8 @@ class Architecture(object): :param str filename: filename of file to be parsed :param list(str) include_dirs: optional list of string filename include directories - :return: a tuple of py:class:`TypeParserResult` and error string - :rtype: tuple(TypeParserResult, str) + :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult :Example: >>> file = "/Users/binja/tmp.c" @@ -7485,18 +7626,27 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - return (None, error_str) + raise SyntaxError, error_str types = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = [] + for j in xrange(0, parse.types[i].nameCount): + name.append(parse.types[i].name[j]) + types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = [] + for j in xrange(0, parse.variables[i].nameCount): + name.append(parse.variables[i].name[j]) + variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - BNFreeTypeParserResult(parse) - return (TypeParserResult(types, variables, functions), error_str) + name = [] + for j in xrange(0, parse.functions[i].nameCount): + name.append(parse.functions[i].name[j]) + functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + core.BNFreeTypeParserResult(parse) + return TypeParserResult(types, variables, functions) def register_calling_convention(self, cc): """ diff --git a/python/generator.cpp b/python/generator.cpp index 08485315..4c313fdd 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -97,11 +97,8 @@ void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallbac else fprintf(out, "ctypes.c_double"); break; - case StructureTypeClass: - fprintf(out, "%s", type->GetQualifiedName(type->GetStructure()->GetName()).c_str()); - break; - case EnumerationTypeClass: - fprintf(out, "%s", type->GetQualifiedName(type->GetEnumeration()->GetName()).c_str()); + case NamedTypeReferenceClass: + fprintf(out, "%s", type->GetQualifiedName(type->GetNamedTypeReference()->GetName()).c_str()); break; case PointerTypeClass: if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass)) @@ -156,7 +153,7 @@ int main(int argc, char* argv[]) Architecture::Register(new GeneratorArchitecture()); // Parse API header to get type and function information - map> types, vars, funcs; + map, Ref> types, vars, funcs; string errors; bool ok = Architecture::GetByName("generator")->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "%s", errors.c_str()); @@ -187,21 +184,25 @@ int main(int argc, char* argv[]) map enumMembers; for (auto& i : types) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; if (i.second->GetClass() == StructureTypeClass) { - fprintf(out, "class %s(ctypes.Structure):\n", i.first.c_str()); + fprintf(out, "class %s(ctypes.Structure):\n", name.c_str()); fprintf(out, " pass\n"); } else if (i.second->GetClass() == EnumerationTypeClass) { - fprintf(out, "%s = ctypes.c_int\n", i.first.c_str()); + fprintf(out, "%s = ctypes.c_int\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, "%s = %" PRId64 "\n", j.name.c_str(), j.value); - fprintf(out, "%s_names = {\n", i.first.c_str()); + fprintf(out, "%s_names = {\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, " %" PRId64 ": \"%s\",\n", j.value, j.name.c_str()); fprintf(out, "}\n"); - fprintf(out, "%s_by_name = {\n", i.first.c_str()); + fprintf(out, "%s_by_name = {\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, " \"%s\": %" PRId64 ",\n", j.name.c_str(), j.value); fprintf(out, "}\n"); @@ -211,7 +212,7 @@ int main(int argc, char* argv[]) else if ((i.second->GetClass() == BoolTypeClass) || (i.second->GetClass() == IntegerTypeClass) || (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass)) { - fprintf(out, "%s = ", i.first.c_str()); + fprintf(out, "%s = ", name.c_str()); OutputType(out, i.second); fprintf(out, "\n"); } @@ -225,9 +226,13 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Structure definitions\n"); for (auto& i : types) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; if ((i.second->GetClass() == StructureTypeClass) && (i.second->GetStructure()->GetMembers().size() != 0)) { - fprintf(out, "%s._fields_ = [\n", i.first.c_str()); + fprintf(out, "%s._fields_ = [\n", name.c_str()); for (auto& j : i.second->GetStructure()->GetMembers()) { fprintf(out, " (\"%s\", ", j.name.c_str()); @@ -241,6 +246,11 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Function definitions\n"); for (auto& i : funcs) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; + // Check for a string result, these will be automatically wrapped to free the string // memory and return a Python string bool stringResult = (i.second->GetChildType()->GetClass() == PointerTypeClass) && @@ -249,7 +259,7 @@ int main(int argc, char* argv[]) // Pointer returns will be automatically wrapped to return None on null pointer bool pointerResult = (i.second->GetChildType()->GetClass() == PointerTypeClass); bool callbackConvention = false; - if (i.first == "BNAllocString") + if (name == "BNAllocString") { // Don't perform automatic wrapping of string allocation, and return a void // pointer so that callback functions (which is the only valid use of BNAllocString) @@ -258,11 +268,11 @@ int main(int argc, char* argv[]) callbackConvention = true; } - string funcName = i.first; + string funcName = name; if (stringResult || pointerResult) funcName = string("_") + funcName; - fprintf(out, "%s = core.%s\n", funcName.c_str(), i.first.c_str()); + fprintf(out, "%s = core.%s\n", funcName.c_str(), name.c_str()); fprintf(out, "%s.restype = ", funcName.c_str()); OutputType(out, i.second->GetChildType(), true, callbackConvention); fprintf(out, "\n"); @@ -272,7 +282,7 @@ int main(int argc, char* argv[]) for (auto& j : i.second->GetParameters()) { fprintf(out, " "); - if (i.first == "BNFreeString") + if (name == "BNFreeString") { // BNFreeString expects a pointer to a string allocated by the core, so do not use // a c_char_p here, as that would be allocated by the Python runtime. This can @@ -291,7 +301,7 @@ int main(int argc, char* argv[]) if (stringResult) { // Emit wrapper to get Python string and free native memory - fprintf(out, "def %s(*args):\n", i.first.c_str()); + fprintf(out, "def %s(*args):\n", name.c_str()); fprintf(out, " result = %s(*args)\n", funcName.c_str()); fprintf(out, " string = ctypes.cast(result, ctypes.c_char_p).value\n"); fprintf(out, " BNFreeString(result)\n"); @@ -300,7 +310,7 @@ int main(int argc, char* argv[]) else if (pointerResult) { // Emit wrapper to return None on null pointer - fprintf(out, "def %s(*args):\n", i.first.c_str()); + fprintf(out, "def %s(*args):\n", name.c_str()); fprintf(out, " result = %s(*args)\n", funcName.c_str()); fprintf(out, " if not result:\n"); fprintf(out, " return None\n"); diff --git a/type.cpp b/type.cpp index c8cfdc33..0571f743 100644 --- a/type.cpp +++ b/type.cpp @@ -133,6 +133,15 @@ Ref Type::GetEnumeration() const } +Ref Type::GetNamedTypeReference() const +{ + BNNamedTypeReference* ref = BNGetTypeNamedTypeReference(m_object); + if (ref) + return new NamedTypeReference(ref); + return nullptr; +} + + uint64_t Type::GetElementCount() const { return BNGetTypeElementCount(m_object); @@ -307,9 +316,21 @@ Ref Type::StructureType(Structure* strct) } -Ref Type::UnknownNamedType(UnknownType* unknwn) +Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) { - return new Type(BNCreateUnknownNamedType(unknwn->GetObject())); + return new Type(BNCreateNamedTypeReference(ref->GetObject(), width, align)); +} + + +Ref Type::NamedType(const vector& name, Type* type) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(nameList, name.size(), + type ? type->GetObject() : nullptr)); + delete[] nameList; + return result; } @@ -355,35 +376,54 @@ void Type::SetFunctionCanReturn(bool canReturn) } -UnknownType::UnknownType(BNUnknownType* ut, vector names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) +{ + m_object = nt; +} + + +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const vector& names) { - m_object = ut; + m_object = BNCreateNamedType(); + BNSetTypeReferenceClass(m_object, cls); const char ** nameList = new const char*[names.size()]; for (size_t i = 0; i < names.size(); i++) { nameList[i] = names[i].c_str(); } - BNSetUnknownTypeName(ut, nameList, names.size()); + BNSetTypeReferenceName(m_object, nameList, names.size()); delete [] nameList; } -void UnknownType::SetName(const vector& names) +void NamedTypeReference::SetTypeClass(BNNamedTypeReferenceClass cls) +{ + BNSetTypeReferenceClass(m_object, cls); +} + + +BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const +{ + return BNGetTypeReferenceClass(m_object); +} + + +void NamedTypeReference::SetName(const vector& names) { const char ** nameList = new const char*[names.size()]; for (size_t i = 0; i < names.size(); i++) { nameList[i] = names[i].c_str(); } - BNSetUnknownTypeName(m_object, nameList, names.size()); + BNSetTypeReferenceName(m_object, nameList, names.size()); delete [] nameList; } -vector UnknownType::GetName() const +vector NamedTypeReference::GetName() const { size_t size; - char** name = BNGetUnknownTypeName(m_object, &size); + char** name = BNGetTypeReferenceName(m_object, &size); vector result; for (size_t i = 0; i < size; i++) { @@ -407,33 +447,6 @@ Structure::Structure(BNStructure* s) } -vector Structure::GetName() const -{ - size_t size; - char** name = BNGetStructureName(m_object, &size); - vector result; - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; - return result; -} - - -void Structure::SetName(const vector& names) -{ - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetStructureName(m_object, nameList, names.size()); - delete [] nameList; -} - - vector Structure::GetMembers() const { size_t count; @@ -532,32 +545,6 @@ Enumeration::Enumeration(BNEnumeration* e) } -vector Enumeration::GetName() const -{ - vector result; - size_t size; - char** name = BNGetEnumerationName(m_object, &size); - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; - return result; -} - -void Enumeration::SetName(const vector& names) -{ - const char **const nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetEnumerationName(m_object, nameList, names.size()); - delete [] nameList; -} - - vector Enumeration::GetMembers() const { size_t count; -- cgit v1.3.1 From 844e1aa5b4f89de2ffc1990824b094c553068642 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jan 2017 21:18:08 -0500 Subject: Create qualified name object --- architecture.cpp | 20 ++--- binaryninjaapi.h | 95 +++++++++++++++------- binaryview.cpp | 67 +++------------- demangle.cpp | 4 +- python/generator.cpp | 4 +- type.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++------- 6 files changed, 281 insertions(+), 127 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index d0d87df4..657d7bf0 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -746,8 +746,8 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map, Ref>& types, map, Ref>& variables, - map, Ref>& functions, string& errors, const vector& includeDirs) + map>& types, map>& variables, + map>& functions, string& errors, const vector& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -769,21 +769,21 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file for (size_t i = 0; i < result.typeCount; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < result.types[i].nameCount; j++) name.push_back(result.types[i].name[j]); types[name] = new Type(BNNewTypeReference(result.types[i].type)); } for (size_t i = 0; i < result.variableCount; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < result.variables[i].nameCount; j++) name.push_back(result.variables[i].name[j]); types[name] = new Type(BNNewTypeReference(result.variables[i].type)); } for (size_t i = 0; i < result.functionCount; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < result.functions[i].nameCount; j++) name.push_back(result.functions[i].name[j]); types[name] = new Type(BNNewTypeReference(result.functions[i].type)); @@ -793,8 +793,8 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file } -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map, Ref>& types, - map, Ref>& variables, map, Ref>& functions, +bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, + map>& variables, map>& functions, string& errors, const vector& includeDirs) { BNTypeParserResult result; @@ -817,21 +817,21 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map name; + QualifiedName name; for (size_t j = 0; j < result.types[i].nameCount; j++) name.push_back(result.types[i].name[j]); types[name] = new Type(BNNewTypeReference(result.types[i].type)); } for (size_t i = 0; i < result.variableCount; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < result.variables[i].nameCount; j++) name.push_back(result.variables[i].name[j]); variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); } for (size_t i = 0; i < result.functionCount; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < result.functions[i].nameCount; j++) name.push_back(result.functions[i].name[j]); functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 15c86a58..478cc090 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -277,6 +277,7 @@ namespace BinaryNinja class MainThreadAction; class MainThreadActionHandler; class InteractionHandler; + class QualifiedName; struct FormInputField; /*! Logs to the error console with the given BNLogLevel. @@ -368,7 +369,7 @@ namespace BinaryNinja bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, - std::vector& outVarName); + QualifiedName& outVarName); void RegisterMainThread(MainThreadActionHandler* handler); Ref ExecuteOnMainThread(const std::function& action); @@ -408,6 +409,47 @@ namespace BinaryNinja BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon); + class QualifiedName + { + std::vector m_name; + + public: + QualifiedName(); + QualifiedName(const std::string& name); + QualifiedName(const std::vector& name); + QualifiedName(const QualifiedName& name); + + QualifiedName& operator=(const std::string& name); + QualifiedName& operator=(const std::vector& name); + QualifiedName& operator=(const QualifiedName& name); + + bool operator==(const QualifiedName& other) const; + bool operator!=(const QualifiedName& other) const; + bool operator<(const QualifiedName& other) const; + + QualifiedName operator+(const QualifiedName& other) const; + + std::string& operator[](size_t i); + const std::string& operator[](size_t i) const; + std::vector::iterator begin(); + std::vector::iterator end(); + std::vector::const_iterator begin() const; + std::vector::const_iterator end() const; + std::string& front(); + const std::string& front() const; + std::string& back(); + const std::string& back() const; + void insert(std::vector::iterator loc, const std::string& name); + void insert(std::vector::iterator loc, std::vector::iterator b, + std::vector::iterator e); + void erase(std::vector::iterator i); + void clear(); + void push_back(const std::string& name); + size_t size() const; + + std::string GetString() const; + }; + class DataBuffer { BNDataBuffer* m_buffer; @@ -610,8 +652,8 @@ namespace BinaryNinja virtual void OnDataVariableUpdated(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnStringFound(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } virtual void OnStringRemoved(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } - virtual void OnTypeDefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } - virtual void OnTypeUndefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeDefined(BinaryView* data, const QualifiedName& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeUndefined(BinaryView* data, const QualifiedName& name, Type* type) { (void)data; (void)name; (void)type; } }; class FileAccessor @@ -979,19 +1021,13 @@ namespace BinaryNinja bool ParseTypeString(const std::string& text, QualifiedNameAndType& result, std::string& errors); - std::map, Ref> GetTypes(); - Ref GetTypeByName(const std::string& name); - Ref GetTypeByName(const std::vector& name); - bool IsTypeAutoDefined(const std::string& name); - bool IsTypeAutoDefined(const std::vector& name); - void DefineType(const std::string& name, Ref type); - void DefineType(const std::vector& name, Ref type); - void DefineUserType(const std::string& name, Ref type); - void DefineUserType(const std::vector& name, Ref type); - void UndefineType(const std::string& name); - void UndefineType(const std::vector& name); - void UndefineUserType(const std::string& name); - void UndefineUserType(const std::vector& name); + std::map> GetTypes(); + Ref GetTypeByName(const QualifiedName& name); + bool IsTypeAutoDefined(const QualifiedName& name); + void DefineType(const QualifiedName& name, Ref type); + void DefineUserType(const QualifiedName& name, Ref type); + void UndefineType(const QualifiedName& name); + void UndefineUserType(const QualifiedName& name); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -1441,14 +1477,14 @@ namespace BinaryNinja void SetBinaryViewTypeConstant(const std::string& type, const std::string& name, uint64_t value); bool ParseTypesFromSource(const std::string& source, const std::string& fileName, - std::map, Ref>& types, - std::map, Ref>& variables, - std::map, Ref>& functions, std::string& errors, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, const std::vector& includeDirs = std::vector()); bool ParseTypesFromSourceFile(const std::string& fileName, - std::map, Ref>& types, - std::map, Ref>& variables, - std::map, Ref>& functions, std::string& errors, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, const std::vector& includeDirs = std::vector()); void RegisterCallingConvention(CallingConvention* cc); @@ -1523,7 +1559,7 @@ namespace BinaryNinja struct QualifiedNameAndType { - std::vector name; + QualifiedName name; Ref type; }; @@ -1553,7 +1589,7 @@ namespace BinaryNinja void SetFunctionCanReturn(bool canReturn); std::string GetString() const; - std::string GetTypeAndName(const std::vector& name) const; + std::string GetTypeAndName(const QualifiedName& name) const; std::string GetStringBeforeName() const; std::string GetStringAfterName() const; @@ -1569,15 +1605,13 @@ namespace BinaryNinja static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); - static Ref NamedType(const std::vector& name, Type* type); + static Ref NamedType(const QualifiedName& name, Type* type); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); static Ref ArrayType(Type* type, uint64_t elem); static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, const std::vector& params, bool varArg = false); - - static std::string GetQualifiedName(const std::vector& names); }; class NamedTypeReference: public CoreRefCountObject& name = {}); + NamedTypeReference(BNNamedTypeReferenceClass cls = UnknownNamedTypeClass, + const QualifiedName& name = QualifiedName()); BNNamedTypeReferenceClass GetTypeClass() const; void SetTypeClass(BNNamedTypeReferenceClass cls); - std::vector GetName() const; - void SetName(const std::vector& name); + QualifiedName GetName() const; + void SetName(const QualifiedName& name); }; struct StructureMember diff --git a/binaryview.cpp b/binaryview.cpp index 9fdd5748..8394fc57 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -135,7 +135,7 @@ void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - vector nameList; + QualifiedName nameList; for (size_t i = 0; i < nameCount; i++) nameList.push_back(name[i]); notify->OnTypeDefined(view, nameList, typeObj); @@ -148,7 +148,7 @@ void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* dat BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - vector nameList; + QualifiedName nameList; for (size_t i = 0; i < nameCount; i++) nameList.push_back(name[i]); notify->OnTypeUndefined(view, nameList, typeObj); @@ -1476,15 +1476,15 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul } -map, Ref> BinaryView::GetTypes() +map> BinaryView::GetTypes() { size_t count; BNQualifiedNameAndType* types = BNGetAnalysisTypeList(m_object, &count); - map, Ref> result; + map> result; for (size_t i = 0; i < count; i++) { - vector name; + QualifiedName name; for (size_t j = 0; j < types[i].nameCount; j++) name.push_back(types[i].name[j]); result[name] = new Type(BNNewTypeReference(types[i].type)); @@ -1495,17 +1495,7 @@ map, Ref> BinaryView::GetTypes() } -Ref BinaryView::GetTypeByName(const string& name) -{ - const char* nameStr = name.c_str(); - BNType* type = BNGetAnalysisTypeByName(m_object, &nameStr, 1); - if (!type) - return nullptr; - return new Type(type); -} - - -Ref BinaryView::GetTypeByName(const vector& name) +Ref BinaryView::GetTypeByName(const QualifiedName& name) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -1520,14 +1510,7 @@ Ref BinaryView::GetTypeByName(const vector& name) } -bool BinaryView::IsTypeAutoDefined(const string& name) -{ - const char* nameStr = name.c_str(); - return BNIsAnalysisTypeAutoDefined(m_object, &nameStr, 1); -} - - -bool BinaryView::IsTypeAutoDefined(const vector& name) +bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -1538,14 +1521,7 @@ bool BinaryView::IsTypeAutoDefined(const vector& name) } -void BinaryView::DefineType(const string& name, Ref type) -{ - const char* nameStr = name.c_str(); - BNDefineAnalysisType(m_object, &nameStr, 1, type->GetObject()); -} - - -void BinaryView::DefineType(const vector& name, Ref type) +void BinaryView::DefineType(const QualifiedName& name, Ref type) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -1555,14 +1531,7 @@ void BinaryView::DefineType(const vector& name, Ref type) } -void BinaryView::DefineUserType(const string& name, Ref type) -{ - const char* nameStr = name.c_str(); - BNDefineUserAnalysisType(m_object, &nameStr, 1, type->GetObject()); -} - - -void BinaryView::DefineUserType(const vector& name, Ref type) +void BinaryView::DefineUserType(const QualifiedName& name, Ref type) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -1572,14 +1541,7 @@ void BinaryView::DefineUserType(const vector& name, Ref type) } -void BinaryView::UndefineType(const string& name) -{ - const char* nameStr = name.c_str(); - BNUndefineAnalysisType(m_object, &nameStr, 1); -} - - -void BinaryView::UndefineType(const vector& name) +void BinaryView::UndefineType(const QualifiedName& name) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -1589,14 +1551,7 @@ void BinaryView::UndefineType(const vector& name) } -void BinaryView::UndefineUserType(const string& name) -{ - const char* nameStr = name.c_str(); - BNUndefineUserAnalysisType(m_object, &nameStr, 1); -} - - -void BinaryView::UndefineUserType(const vector& name) +void BinaryView::UndefineUserType(const QualifiedName& name) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) diff --git a/demangle.cpp b/demangle.cpp index a12303ca..70a2fe08 100644 --- a/demangle.cpp +++ b/demangle.cpp @@ -6,7 +6,7 @@ using namespace std; bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, - std::vector& outVarName) + QualifiedName& outVarName) { BNType* localType = (*outType)->GetObject(); char** localVarName = nullptr; @@ -26,7 +26,7 @@ bool DemangleMS(Architecture* arch, bool DemangleGNU3(Architecture* arch, const std::string& mangledName, Type** outType, - std::vector& outVarName) + QualifiedName& outVarName) { BNType* localType = (*outType)->GetObject(); char** localVarName = nullptr; diff --git a/python/generator.cpp b/python/generator.cpp index 4c313fdd..485655c2 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -98,7 +98,7 @@ void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallbac fprintf(out, "ctypes.c_double"); break; case NamedTypeReferenceClass: - fprintf(out, "%s", type->GetQualifiedName(type->GetNamedTypeReference()->GetName()).c_str()); + fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str()); break; case PointerTypeClass: if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass)) @@ -153,7 +153,7 @@ int main(int argc, char* argv[]) Architecture::Register(new GeneratorArchitecture()); // Parse API header to get type and function information - map, Ref> types, vars, funcs; + map> types, vars, funcs; string errors; bool ok = Architecture::GetByName("generator")->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "%s", errors.c_str()); diff --git a/type.cpp b/type.cpp index 0571f743..ae8f04d3 100644 --- a/type.cpp +++ b/type.cpp @@ -24,6 +24,191 @@ using namespace BinaryNinja; using namespace std; +QualifiedName::QualifiedName() +{ +} + + +QualifiedName::QualifiedName(const string& name) +{ + m_name.push_back(name); +} + + +QualifiedName::QualifiedName(const vector& name): m_name(name) +{ +} + + +QualifiedName::QualifiedName(const QualifiedName& name): m_name(name.m_name) +{ +} + + +QualifiedName& QualifiedName::operator=(const string& name) +{ + m_name = vector{name}; + return *this; +} + + +QualifiedName& QualifiedName::operator=(const vector& name) +{ + m_name = name; + return *this; +} + + +QualifiedName& QualifiedName::operator=(const QualifiedName& name) +{ + m_name = name.m_name; + return *this; +} + + +bool QualifiedName::operator==(const QualifiedName& other) const +{ + return m_name == other.m_name; +} + + +bool QualifiedName::operator!=(const QualifiedName& other) const +{ + return m_name != other.m_name; +} + + +bool QualifiedName::operator<(const QualifiedName& other) const +{ + return m_name < other.m_name; +} + + +QualifiedName QualifiedName::operator+(const QualifiedName& other) const +{ + QualifiedName result(*this); + result.m_name.insert(result.m_name.end(), other.m_name.begin(), other.m_name.end()); + return result; +} + + +string& QualifiedName::operator[](size_t i) +{ + return m_name[i]; +} + + +const string& QualifiedName::operator[](size_t i) const +{ + return m_name[i]; +} + + +vector::iterator QualifiedName::begin() +{ + return m_name.begin(); +} + + +vector::iterator QualifiedName::end() +{ + return m_name.end(); +} + + +vector::const_iterator QualifiedName::begin() const +{ + return m_name.begin(); +} + + +vector::const_iterator QualifiedName::end() const +{ + return m_name.end(); +} + + +string& QualifiedName::front() +{ + return m_name.front(); +} + + +const string& QualifiedName::front() const +{ + return m_name.front(); +} + + +string& QualifiedName::back() +{ + return m_name.back(); +} + + +const string& QualifiedName::back() const +{ + return m_name.back(); +} + + +void QualifiedName::insert(vector::iterator loc, const string& name) +{ + m_name.insert(loc, name); +} + + +void QualifiedName::insert(vector::iterator loc, vector::iterator b, vector::iterator e) +{ + m_name.insert(loc, b, e); +} + + +void QualifiedName::erase(vector::iterator i) +{ + m_name.erase(i); +} + + +void QualifiedName::clear() +{ + m_name.clear(); +} + + +void QualifiedName::push_back(const string& name) +{ + m_name.push_back(name); +} + + +size_t QualifiedName::size() const +{ + return m_name.size(); +} + + +string QualifiedName::GetString() const +{ + bool first = true; + string out; + for (auto &name : m_name) + { + if (!first) + { + out += "::" + name; + } + else + { + out += name; + } + if (name.length() != 0) + first = false; + } + return out; +} + + Type::Type(BNType* type) { m_object = type; @@ -148,27 +333,6 @@ uint64_t Type::GetElementCount() const } -string Type::GetQualifiedName(const vector& names) -{ - bool first = true; - string out; - for (auto &name : names) - { - if (!first) - { - out += "::" + name; - } - else - { - out += name; - } - if (name.length() != 0) - first = false; - } - return out; -} - - string Type::GetString() const { char* str = BNGetTypeString(m_object); @@ -178,7 +342,7 @@ string Type::GetString() const } -string Type::GetTypeAndName(const vector& nameList) const +string Type::GetTypeAndName(const QualifiedName& nameList) const { const char ** str = new const char*[nameList.size()]; for (size_t i = 0; i < nameList.size(); i++) @@ -322,7 +486,7 @@ Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) } -Ref Type::NamedType(const vector& name, Type* type) +Ref Type::NamedType(const QualifiedName& name, Type* type) { const char** nameList = new const char*[name.size()]; for (size_t i = 0; i < name.size(); i++) @@ -382,7 +546,7 @@ NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) } -NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const vector& names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& names) { m_object = BNCreateNamedType(); BNSetTypeReferenceClass(m_object, cls); @@ -408,7 +572,7 @@ BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const } -void NamedTypeReference::SetName(const vector& names) +void NamedTypeReference::SetName(const QualifiedName& names) { const char ** nameList = new const char*[names.size()]; for (size_t i = 0; i < names.size(); i++) @@ -420,11 +584,11 @@ void NamedTypeReference::SetName(const vector& names) } -vector NamedTypeReference::GetName() const +QualifiedName NamedTypeReference::GetName() const { size_t size; char** name = BNGetTypeReferenceName(m_object, &size); - vector result; + QualifiedName result; for (size_t i = 0; i < size; i++) { result.push_back(name[i]); -- cgit v1.3.1 From 7e154a952fe5856b7cf650e2646ebc410b1fb506 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jan 2017 22:58:19 -0500 Subject: Add a qualified name object in the C API --- architecture.cpp | 24 ++------ binaryninjaapi.h | 8 ++- binaryninjacore.h | 34 ++++++----- binaryview.cpp | 72 ++++++++--------------- python/__init__.py | 166 ++++++++++++++++++++--------------------------------- type.cpp | 78 ++++++++++++++----------- 6 files changed, 161 insertions(+), 221 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index 657d7bf0..0e25fa85 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -769,23 +769,17 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file for (size_t i = 0; i < result.typeCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.types[i].nameCount; j++) - name.push_back(result.types[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); types[name] = new Type(BNNewTypeReference(result.types[i].type)); } for (size_t i = 0; i < result.variableCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.variables[i].nameCount; j++) - name.push_back(result.variables[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); types[name] = new Type(BNNewTypeReference(result.variables[i].type)); } for (size_t i = 0; i < result.functionCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.functions[i].nameCount; j++) - name.push_back(result.functions[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); types[name] = new Type(BNNewTypeReference(result.functions[i].type)); } BNFreeTypeParserResult(&result); @@ -817,23 +811,17 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - QualifiedName nameList; - for (size_t i = 0; i < nameCount; i++) - nameList.push_back(name[i]); - notify->OnTypeDefined(view, nameList, typeObj); + notify->OnTypeDefined(view, QualifiedName::FromAPIObject(name), typeObj); } -void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, - BNType* type) +void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - QualifiedName nameList; - for (size_t i = 0; i < nameCount; i++) - nameList.push_back(name[i]); - notify->OnTypeUndefined(view, nameList, typeObj); + notify->OnTypeUndefined(view, QualifiedName::FromAPIObject(name), typeObj); } @@ -1467,8 +1459,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul return false; } - for (size_t i = 0; i < nt.nameCount; i++) - result.name.push_back(nt.name[i]); + result.name = QualifiedName::FromAPIObject(&nt.name); result.type = new Type(BNNewTypeReference(nt.type)); errors = ""; BNFreeQualifiedNameAndType(&nt); @@ -1484,9 +1475,7 @@ map> BinaryView::GetTypes() map> result; for (size_t i = 0; i < count; i++) { - QualifiedName name; - for (size_t j = 0; j < types[i].nameCount; j++) - name.push_back(types[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); result[name] = new Type(BNNewTypeReference(types[i].type)); } @@ -1497,12 +1486,9 @@ map> BinaryView::GetTypes() Ref BinaryView::GetTypeByName(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - - BNType* type = BNGetAnalysisTypeByName(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetAnalysisTypeByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); if (!type) return nullptr; @@ -1512,52 +1498,42 @@ Ref BinaryView::GetTypeByName(const QualifiedName& name) bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - bool result = BNIsAnalysisTypeAutoDefined(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + bool result = BNIsAnalysisTypeAutoDefined(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); return result; } void BinaryView::DefineType(const QualifiedName& name, Ref type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNDefineAnalysisType(m_object, nameList, name.size(), type->GetObject()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNDefineAnalysisType(m_object, &nameObj, type->GetObject()); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::DefineUserType(const QualifiedName& name, Ref type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNDefineUserAnalysisType(m_object, nameList, name.size(), type->GetObject()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNDefineUserAnalysisType(m_object, &nameObj, type->GetObject()); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::UndefineType(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNUndefineAnalysisType(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNUndefineAnalysisType(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::UndefineUserType(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNUndefineUserAnalysisType(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNUndefineUserAnalysisType(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } diff --git a/python/__init__.py b/python/__init__.py index b5ced583..c2db468d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -664,6 +664,8 @@ class QualifiedName(object): def __init__(self, name = []): if isinstance(name, str): self.name = [name] + elif isinstance(name, QualifiedName): + self.name = name.name else: self.name = name @@ -724,6 +726,22 @@ class QualifiedName(object): def __iter__(self): return iter(self.name) + def _get_core_struct(self): + result = core.BNQualifiedName() + name_list = (ctypes.c_char_p * len(self.name))() + for i in xrange(0, len(self.name)): + name_list[i] = self.name[i] + result.name = name_list + result.nameCount = len(self.name) + return result + + @classmethod + def _from_core_struct(cls, name): + result = [] + for i in xrange(0, name.nameCount): + result.append(name.name[i]) + return QualifiedName(result) + class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): self.view = view @@ -825,21 +843,17 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) - def _type_defined(self, ctxt, name, name_count, type_obj): + def _type_defined(self, ctxt, name, type_obj): try: - name_list = [] - for i in xrange(0, name_count): - name_list.append(name[i]) - self.notify.type_defined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) + qualified_name = QualifiedName._from_core_struct(name[0]) + self.notify.type_defined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) - def _type_undefined(self, ctxt, name, name_count, type_obj): + def _type_undefined(self, ctxt, name, type_obj): try: - name_list = [] - for i in xrange(0, name_count): - name_list.append(name[i]) - self.notify.type_undefined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) + qualified_name = QualifiedName._from_core_struct(name[0]) + self.notify.type_undefined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) @@ -1464,10 +1478,8 @@ class BinaryView(object): type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} for i in xrange(0, count.value): - name = [] - for j in xrange(0, type_list[i].nameCount): - name.append(type_list[i].name[j]) - result[QualifiedName(name)] = Type(core.BNNewTypeReference(type_list[i].type)) + name = QualifiedName._from_core_struct(type_list[i].name) + result[name] = Type(core.BNNewTypeReference(type_list[i].type)) core.BNFreeTypeList(type_list, count.value) return result @@ -3438,10 +3450,7 @@ class BinaryView(object): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError, error_str type_obj = Type(core.BNNewTypeReference(result.type)) - name = [] - for i in xrange(0, result.nameCount): - name.append(result.name[i]) - name = QualifiedName(name) + name = QualifiedName._from_core_struct(result.name) core.BNFreeQualifiedNameAndType(result) return type_obj, name @@ -3460,12 +3469,8 @@ class BinaryView(object): >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - obj = core.BNGetAnalysisTypeByName(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + obj = core.BNGetAnalysisTypeByName(self.handle, name) if not obj: return None return Type(obj) @@ -3485,12 +3490,8 @@ class BinaryView(object): False >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - return core.BNIsAnalysisTypeAutoDefined(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + return core.BNIsAnalysisTypeAutoDefined(self.handle, name) def define_type(self, name, type_obj): """ @@ -3507,12 +3508,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNDefineAnalysisType(self.handle, name_list, len(name), type_obj.handle) + name = QualifiedName(name)._get_core_struct() + core.BNDefineAnalysisType(self.handle, name, type_obj.handle) def define_user_type(self, name, type_obj): """ @@ -3529,12 +3526,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNDefineUserAnalysisType(self.handle, name_list, len(name), type_obj.handle) + name = QualifiedName(name)._get_core_struct() + core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) def undefine_type(self, name): """ @@ -3552,12 +3545,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNUndefineAnalysisType(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNUndefineAnalysisType(self.handle, name) def undefine_user_type(self, name): """ @@ -3576,12 +3565,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNUndefineUserAnalysisType(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNUndefineUserAnalysisType(self.handle, name) def find_next_data(self, start, data, flags = 0): """ @@ -4470,14 +4455,10 @@ class Type(object): @classmethod def named_type_from_type(self, name, t): - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] + name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromType(name_list, len(name), t)) + return Type(core.BNCreateNamedTypeReferenceFromType(name, t)) @classmethod def enumeration_type(self, arch, e, width = None): @@ -4521,12 +4502,8 @@ class NamedTypeReference(object): self.handle = core.BNCreateNamedType() core.BNSetTypeReferenceClass(self.handle, type_class) if name is not None: - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNSetTypeReferenceName(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNSetTypeReferenceName(self.handle, name) else: self.handle = handle @@ -4544,20 +4521,15 @@ class NamedTypeReference(object): @property def name(self): count = ctypes.c_ulonglong() - nameList = core.BNGetTypeReferenceName(self.handle, count) - result = [] - for i in xrange(count.value): - result.append(nameList[i]) - return QualifiedName(result) + name = core.BNGetTypeReferenceName(self.handle, count) + result = QualifiedName._from_core_struct(name) + core.BNFreeQualifiedName(name) + return result @name.setter def name(self, value): - if isinstance(value, str): - value = [value] - name_list = (ctypes.c_char_p * len(value))() - for i in xrange(0, len(value)): - name_list[i] = value[i] - core.BNSetTypeReferenceName(self.handle, name_list, len(value)) + value = QualifiedName(value)._get_core_struct() + core.BNSetTypeReferenceName(self.handle, value) def __repr__(self): if self.type_class == core.TypedefNamedTypeClass: @@ -4646,8 +4618,6 @@ class Structure(object): raise AttributeError, "attribute '%s' is read only" % name def __repr__(self): - if len(self.name) > 0: - return "" % self.name return "" % self.width def append(self, t, name = ""): @@ -4696,8 +4666,6 @@ class Enumeration(object): raise AttributeError, "attribute '%s' is read only" % name def __repr__(self): - if len(self.name) > 0: - return "" % self.name return "" % repr(self.members) def append(self, name, value = None): @@ -7581,20 +7549,14 @@ class Architecture(object): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = [] - for j in xrange(0, parse.types[i].nameCount): - name.append(parse.types[i].name[j]) - types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = QualifiedName._from_core_struct(parse.types[i].name) + types[name] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - name = [] - for j in xrange(0, parse.variables[i].nameCount): - name.append(parse.variables[i].name[j]) - variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - name = [] - for j in xrange(0, parse.functions[i].nameCount): - name.append(parse.functions[i].name[j]) - functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + name = QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) return TypeParserResult(types, variables, functions) @@ -7631,20 +7593,14 @@ class Architecture(object): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = [] - for j in xrange(0, parse.types[i].nameCount): - name.append(parse.types[i].name[j]) - types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = QualifiedName._from_core_struct(parse.types[i].name) + types[name] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - name = [] - for j in xrange(0, parse.variables[i].nameCount): - name.append(parse.variables[i].name[j]) - variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - name = [] - for j in xrange(0, parse.functions[i].nameCount): - name.append(parse.functions[i].name[j]) - functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + name = QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) return TypeParserResult(types, variables, functions) diff --git a/type.cpp b/type.cpp index ae8f04d3..e71077e6 100644 --- a/type.cpp +++ b/type.cpp @@ -209,6 +209,34 @@ string QualifiedName::GetString() const } +BNQualifiedName QualifiedName::GetAPIObject() const +{ + BNQualifiedName result; + result.nameCount = m_name.size(); + result.name = new char*[m_name.size()]; + for (size_t i = 0; i < m_name.size(); i++) + result.name[i] = BNAllocString(m_name[i].c_str()); + return result; +} + + +void QualifiedName::FreeAPIObject(BNQualifiedName* name) +{ + for (size_t i = 0; i < name->nameCount; i++) + BNFreeString(name->name[i]); + delete[] name->name; +} + + +QualifiedName QualifiedName::FromAPIObject(BNQualifiedName* name) +{ + QualifiedName result; + for (size_t i = 0; i < name->nameCount; i++) + result.push_back(name->name[i]); + return result; +} + + Type::Type(BNType* type) { m_object = type; @@ -344,13 +372,9 @@ string Type::GetString() const string Type::GetTypeAndName(const QualifiedName& nameList) const { - const char ** str = new const char*[nameList.size()]; - for (size_t i = 0; i < nameList.size(); i++) - { - str[i] = nameList[i].c_str(); - } - char* outName = BNGetTypeAndName(m_object, str, nameList.size()); - delete [] str; + BNQualifiedName name = nameList.GetAPIObject(); + char* outName = BNGetTypeAndName(m_object, &name); + QualifiedName::FreeAPIObject(&name); return outName; } @@ -488,12 +512,9 @@ Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) Ref Type::NamedType(const QualifiedName& name, Type* type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - Type* result = new Type(BNCreateNamedTypeReferenceFromType(nameList, name.size(), - type ? type->GetObject() : nullptr)); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(&nameObj, type ? type->GetObject() : nullptr)); + QualifiedName::FreeAPIObject(&nameObj); return result; } @@ -550,13 +571,12 @@ NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const Qual { m_object = BNCreateNamedType(); BNSetTypeReferenceClass(m_object, cls); - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) + if (names.size() != 0) { - nameList[i] = names[i].c_str(); + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } - BNSetTypeReferenceName(m_object, nameList, names.size()); - delete [] nameList; } @@ -574,27 +594,17 @@ BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const void NamedTypeReference::SetName(const QualifiedName& names) { - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetTypeReferenceName(m_object, nameList, names.size()); - delete [] nameList; + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } QualifiedName NamedTypeReference::GetName() const { - size_t size; - char** name = BNGetTypeReferenceName(m_object, &size); - QualifiedName result; - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; + BNQualifiedName name = BNGetTypeReferenceName(m_object); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); return result; } -- cgit v1.3.1 From 1f6c09e54ab53403fe0236c46f69b896713abddc Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 16 Jan 2017 17:53:34 -0500 Subject: Fix lint issues --- python/architecture.py | 6 +++--- python/binaryview.py | 8 ++++---- python/types.py | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index d67f00a6..32d97b09 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -364,7 +364,7 @@ class Architecture(object): def __setattr__(self, name, value): if ((name == "name") or (name == "endianness") or (name == "address_size") or - (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length")): + (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length")): raise AttributeError("attribute '%s' is read only" % name) else: try: @@ -1610,7 +1610,7 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - raise SyntaxError, error_str + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} @@ -1654,7 +1654,7 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - raise SyntaxError, error_str + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} diff --git a/python/binaryview.py b/python/binaryview.py index 34be139d..cf30d78d 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -250,16 +250,16 @@ class BinaryDataNotificationCallbacks(object): def _type_defined(self, ctxt, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_defined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) + self.notify.type_defined(self.view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) except: - log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _type_undefined(self, ctxt, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_undefined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) + self.notify.type_undefined(self.view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) except: - log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) class _BinaryViewTypeMetaclass(type): diff --git a/python/types.py b/python/types.py index 757f88aa..0470ea73 100644 --- a/python/types.py +++ b/python/types.py @@ -24,7 +24,6 @@ import ctypes import _binaryninjacore as core from enums import SymbolType, TypeClass, NamedTypeReferenceClass import callingconvention -import demangle class QualifiedName(object): -- cgit v1.3.1 From ded271158000d7fa509f513b425d95390a7f2058 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 17 Jan 2017 18:44:51 -0500 Subject: Add missing Python APIs --- python/architecture.py | 6 ++++- python/basicblock.py | 4 +++- python/binaryview.py | 6 +++-- python/function.py | 19 ++++++++++++---- python/lowlevelil.py | 4 +++- python/types.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 90 insertions(+), 11 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 32d97b09..ea97f605 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -467,6 +467,8 @@ class Architecture(object): token_buf[i].value = tokens[i].value token_buf[i].size = tokens[i].size token_buf[i].operand = tokens[i].operand + token_buf[i].context = tokens[i].context + token_buf[i].address = tokens[i].address result[0] = token_buf ptr = ctypes.cast(token_buf, ctypes.c_void_p) self._pending_token_lists[ptr.value] = (ptr.value, token_buf) @@ -1148,7 +1150,9 @@ class Architecture(object): value = tokens[i].value size = tokens[i].size operand = tokens[i].operand - result.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) core.BNFreeInstructionText(tokens, count.value) return result, length.value diff --git a/python/basicblock.py b/python/basicblock.py index ae9889fc..ffbcd217 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -200,7 +200,9 @@ class BasicBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(function.DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result diff --git a/python/binaryview.py b/python/binaryview.py index cf30d78d..f8fe1fde 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1886,7 +1886,7 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, type.Type(var.type), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type), var.autoDiscovered) def get_function_at(self, addr, plat=None): """ @@ -2750,7 +2750,9 @@ class BinaryView(object): value = lines[i].contents.tokens[j].value size = lines[i].contents.tokens[j].size operand = lines[i].contents.tokens[j].operand - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].contents.tokens[j].context + address = lines[i].contents.tokens[j].address + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) contents = function.DisassemblyTextLine(addr, tokens) result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) diff --git a/python/function.py b/python/function.py index 7d03585c..5f9f475a 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,7 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext) import architecture import highlight import associateddatastore @@ -669,7 +669,9 @@ class Function(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(tokens) core.BNFreeInstructionTextLines(lines, count.value) return result @@ -916,7 +918,9 @@ class FunctionGraphBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -966,7 +970,9 @@ class FunctionGraphBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) yield DisassemblyTextLine(addr, tokens) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1237,12 +1243,15 @@ class InstructionTextToken(object): ========================== ============================================ """ - def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff): + def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, + context = InstructionTextTokenContext.NoTokenContext, address = 0): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value self.size = size self.operand = operand + self.context = InstructionTextTokenContext(context) + self.address = address def __str__(self): return self.text diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 419e8513..29b46b65 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -187,7 +187,9 @@ class LowLevelILInstruction(object): value = tokens[i].value size = tokens[i].size operand = tokens[i].operand - result.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) core.BNFreeInstructionText(tokens, count.value) return result diff --git a/python/types.py b/python/types.py index 0470ea73..1dd2157e 100644 --- a/python/types.py +++ b/python/types.py @@ -22,8 +22,9 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType import callingconvention +import function class QualifiedName(object): @@ -317,6 +318,56 @@ class Type(object): def get_string_after_name(self): return core.BNGetTypeStringAfterName(self.handle) + @property + def tokens(self): + """Type string as a list of tokens (read-only)""" + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokens(self.handle, count) + 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 + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + + def get_tokens_before_name(self): + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokensBeforeName(self.handle, count) + 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 + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + + def get_tokens_after_name(self): + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokensAfterName(self.handle, count) + 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 + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + @classmethod def void(cls): return Type(core.BNCreateVoidType()) @@ -518,6 +569,9 @@ class Structure(object): def remove(self, i): core.BNRemoveStructureMember(self.handle, i) + def replace(self, i, t, name = ""): + core.BNReplaceStructureMember(self.handle, i, t.handle, name) + class EnumerationMember(object): def __init__(self, name, value, default): @@ -565,6 +619,12 @@ class Enumeration(object): else: core.BNAddEnumerationMemberWithValue(self.handle, name, value) + def remove(self, i): + core.BNRemoveEnumerationMember(self.handle, i) + + def replace(self, i, name, value): + core.BNReplaceEnumerationMember(self.handle, i, name, value) + class TypeParserResult(object): def __init__(self, types, variables, functions): -- cgit v1.3.1 From c6ed1dd374515d0e23a9d627a7dfb659c7981d16 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 19 Jan 2017 21:15:32 -0500 Subject: Add API to find virtual address from file offset --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + binaryview.cpp | 6 ++++++ python/binaryview.py | 6 ++++++ 4 files changed, 14 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index afbff4da..4e3f3d57 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1050,6 +1050,7 @@ namespace BinaryNinja void RemoveUserSegment(uint64_t start, uint64_t length); std::vector GetSegments(); bool GetSegmentAt(uint64_t addr, Segment& result); + bool GetAddressForDataOffset(uint64_t offset, uint64_t& addr); void AddAutoSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "", uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "", diff --git a/binaryninjacore.h b/binaryninjacore.h index 02f753cf..7d3bc14c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1420,6 +1420,7 @@ extern "C" BINARYNINJACOREAPI BNSegment* BNGetSegments(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeSegmentList(BNSegment* segments); BINARYNINJACOREAPI bool BNGetSegmentAt(BNBinaryView* view, uint64_t addr, BNSegment* result); + BINARYNINJACOREAPI bool BNGetAddressForDataOffset(BNBinaryView* view, uint64_t offset, uint64_t* addr); BINARYNINJACOREAPI void BNAddAutoSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length, const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection, const char* infoSection, diff --git a/binaryview.cpp b/binaryview.cpp index bef23750..cc8bb733 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1645,6 +1645,12 @@ bool BinaryView::GetSegmentAt(uint64_t addr, Segment& result) } +bool BinaryView::GetAddressForDataOffset(uint64_t offset, uint64_t& addr) +{ + return BNGetAddressForDataOffset(m_object, offset, &addr); +} + + void BinaryView::AddAutoSection(const string& name, uint64_t start, uint64_t length, const string& type, uint64_t align, uint64_t entrySize, const string& linkedSection, const string& infoSection, uint64_t infoData) { diff --git a/python/binaryview.py b/python/binaryview.py index f8fe1fde..ba706fe5 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3052,6 +3052,12 @@ class BinaryView(object): segment.flags) return result + def get_address_for_data_offset(self, offset): + address = ctypes.c_ulonglong() + if not core.BNGetAddressForDataOffset(self.handle, offset, address): + return None + return address.value + def add_auto_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", info_section = "", info_data = 0): core.BNAddAutoSection(self.handle, name, start, length, type, align, entry_size, linked_section, -- cgit v1.3.1 From a43fb5d02a651a5d0ae92f06cb7282557bc045b3 Mon Sep 17 00:00:00 2001 From: Claude Hemberger Date: Sat, 28 Jan 2017 13:32:29 +0100 Subject: example documentation fix for BinaryWriter --- python/binaryview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 476f2be6..def04077 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3591,7 +3591,7 @@ class BinaryWriter(object): >>> hex(bw.offset) '0x100000008L' >>> bw.seek(0x100000000) - >>> hex(br.offset) + >>> hex(bw.offset) '0x100000000L' >>> """ @@ -3608,7 +3608,7 @@ class BinaryWriter(object): >>> hex(bw.offset) '0x100000008L' >>> bw.seek_relative(-8) - >>> hex(br.offset) + >>> hex(bw.offset) '0x100000000L' >>> """ -- cgit v1.3.1 From 8df9a34dd67c852626432c84a5007be3173c33e0 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 6 Feb 2017 22:27:42 -0500 Subject: Add type IDs for types to track across renames --- binaryninjaapi.cpp | 9 ++++ binaryninjaapi.h | 27 +++++++++-- binaryninjacore.h | 19 ++++++-- binaryview.cpp | 54 +++++++++++++++++++--- python/__init__.py | 4 ++ python/binaryview.py | 126 ++++++++++++++++++++++++++++++++++++++++++++------- python/types.py | 63 +++++++++++++++++++++++--- type.cpp | 90 +++++++++++++++++++++++++++++++++++- 8 files changed, 354 insertions(+), 38 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index e1dab528..099f35eb 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -237,3 +237,12 @@ void BinaryNinja::SetWorkerThreadCount(size_t count) { BNSetWorkerThreadCount(count); } + + +string BinaryNinja::GetUniqueIdentifierString() +{ + char* str = BNGetUniqueIdentifierString(); + string result = str; + BNFreeString(str); + return result; +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 4e3f3d57..92eeba30 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -409,6 +409,8 @@ namespace BinaryNinja BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon); + std::string GetUniqueIdentifierString(); + class QualifiedName { std::vector m_name; @@ -1027,11 +1029,15 @@ namespace BinaryNinja std::map> GetTypes(); Ref GetTypeByName(const QualifiedName& name); + Ref GetTypeById(const std::string& id); + std::string GetTypeId(const QualifiedName& name); + QualifiedName GetTypeNameById(const std::string& id); bool IsTypeAutoDefined(const QualifiedName& name); - void DefineType(const QualifiedName& name, Ref type); + QualifiedName DefineType(const std::string& id, const QualifiedName& defaultName, Ref type); void DefineUserType(const QualifiedName& name, Ref type); - void UndefineType(const QualifiedName& name); + void UndefineType(const std::string& id); void UndefineUserType(const QualifiedName& name); + void RenameType(const QualifiedName& oldName, const QualifiedName& newName); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -1611,12 +1617,18 @@ namespace BinaryNinja static Ref StructureType(Structure* strct); static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); static Ref NamedType(const QualifiedName& name, Type* type); + static Ref NamedType(const std::string& id, const QualifiedName& name, Type* type); + static Ref NamedType(BinaryView* view, const QualifiedName& name); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); static Ref ArrayType(Type* type, uint64_t elem); static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, const std::vector& params, bool varArg = false); + + static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); + static std::string GenerateAutoPlatformTypeId(const QualifiedName& name); + static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); }; class NamedTypeReference: public CoreRefCountObject GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const std::string& source, const QualifiedName& name); + static Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); + static Ref GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); }; struct StructureMember diff --git a/binaryninjacore.h b/binaryninjacore.h index 7d3bc14c..b454da64 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1234,6 +1234,8 @@ extern "C" BINARYNINJACOREAPI void BNRegisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); BINARYNINJACOREAPI void BNUnregisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); + BINARYNINJACOREAPI char* BNGetUniqueIdentifierString(void); + // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); @@ -1807,11 +1809,19 @@ extern "C" BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeTypeList(BNQualifiedNameAndType* types, size_t count); BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI BNType* BNGetAnalysisTypeById(BNBinaryView* view, const char* id); + BINARYNINJACOREAPI char* BNGetAnalysisTypeId(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI BNQualifiedName BNGetAnalysisTypeNameById(BNBinaryView* view, const char* id); BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, BNQualifiedName* name); - BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNQualifiedName BNDefineAnalysisType(BNBinaryView* view, const char* id, + BNQualifiedName* defaultName, BNType* type); BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name, BNType* type); - BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char* id); BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI void BNRenameAnalysisType(BNBinaryView* view, BNQualifiedName* oldName, BNQualifiedName* newName); + BINARYNINJACOREAPI char* BNGenerateAutoTypeId(const char* source, BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoDemangledTypeId(BNQualifiedName* name); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -2006,10 +2016,13 @@ extern "C" BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); - BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromTypeAndId(const char* id, BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(BNBinaryView* view, BNQualifiedName* name); BINARYNINJACOREAPI BNNamedTypeReference* BNCreateNamedType(void); BINARYNINJACOREAPI void BNSetTypeReferenceClass(BNNamedTypeReference* nt, BNNamedTypeReferenceClass cls); BINARYNINJACOREAPI BNNamedTypeReferenceClass BNGetTypeReferenceClass(BNNamedTypeReference* nt); + BINARYNINJACOREAPI void BNSetTypeReferenceId(BNNamedTypeReference* nt, const char* id); + BINARYNINJACOREAPI char* BNGetTypeReferenceId(BNNamedTypeReference* nt); BINARYNINJACOREAPI void BNSetTypeReferenceName(BNNamedTypeReference* nt, BNQualifiedName* name); BINARYNINJACOREAPI BNQualifiedName BNGetTypeReferenceName(BNNamedTypeReference* nt); BINARYNINJACOREAPI void BNFreeQualifiedName(BNQualifiedName* name); diff --git a/binaryview.cpp b/binaryview.cpp index cc8bb733..1b1574e1 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1496,6 +1496,35 @@ Ref BinaryView::GetTypeByName(const QualifiedName& name) } +Ref BinaryView::GetTypeById(const string& id) +{ + BNType* type = BNGetAnalysisTypeById(m_object, id.c_str()); + if (!type) + return nullptr; + return new Type(type); +} + + +QualifiedName BinaryView::GetTypeNameById(const string& id) +{ + BNQualifiedName name = BNGetAnalysisTypeNameById(m_object, id.c_str()); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); + return result; +} + + +string BinaryView::GetTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + char* id = BNGetAnalysisTypeId(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + string result = id; + BNFreeString(id); + return result; +} + + bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); @@ -1505,11 +1534,14 @@ bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) } -void BinaryView::DefineType(const QualifiedName& name, Ref type) +QualifiedName BinaryView::DefineType(const string& id, const QualifiedName& defaultName, Ref type) { - BNQualifiedName nameObj = name.GetAPIObject(); - BNDefineAnalysisType(m_object, &nameObj, type->GetObject()); + BNQualifiedName nameObj = defaultName.GetAPIObject(); + BNQualifiedName regName = BNDefineAnalysisType(m_object, id.c_str(), &nameObj, type->GetObject()); QualifiedName::FreeAPIObject(&nameObj); + QualifiedName result = QualifiedName::FromAPIObject(®Name); + BNFreeQualifiedName(®Name); + return result; } @@ -1521,11 +1553,9 @@ void BinaryView::DefineUserType(const QualifiedName& name, Ref type) } -void BinaryView::UndefineType(const QualifiedName& name) +void BinaryView::UndefineType(const string& id) { - BNQualifiedName nameObj = name.GetAPIObject(); - BNUndefineAnalysisType(m_object, &nameObj); - QualifiedName::FreeAPIObject(&nameObj); + BNUndefineAnalysisType(m_object, id.c_str()); } @@ -1537,6 +1567,16 @@ void BinaryView::UndefineUserType(const QualifiedName& name) } +void BinaryView::RenameType(const QualifiedName& oldName, const QualifiedName& newName) +{ + BNQualifiedName oldNameObj = oldName.GetAPIObject(); + BNQualifiedName newNameObj = newName.GetAPIObject(); + BNRenameAnalysisType(m_object, &oldNameObj, &newNameObj); + QualifiedName::FreeAPIObject(&oldNameObj); + QualifiedName::FreeAPIObject(&newNameObj); +} + + bool BinaryView::FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags) { return BNFindNextData(m_object, start, data.GetBufferObject(), &result, flags); diff --git a/python/__init__.py b/python/__init__.py index a1ea02f5..9b87aa47 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -51,6 +51,10 @@ def shutdown(): core.BNShutdown() +def get_unique_identifier(): + return core.BNGetUniqueIdentifierString() + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() diff --git a/python/binaryview.py b/python/binaryview.py index ba706fe5..2cdacb4c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -2881,7 +2881,7 @@ class BinaryView(object): :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> bv.define_user_type(name, type) >>> bv.get_type_by_name(name) >>> @@ -2892,6 +2892,71 @@ class BinaryView(object): return None return types.Type(obj) + def get_type_by_id(self, id): + """ + ``get_type_by_id`` returns the defined type whose unique identifier corresponds with the provided ``id`` + + :param str id: Unique identifier to lookup + :return: A :py:Class:`Type` or None if the type does not exist + :rtype: Type or None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) + >>> bv.get_type_by_id(type_id) + + >>> + """ + obj = core.BNGetAnalysisTypeById(self.handle, id) + if not obj: + return None + return types.Type(obj) + + def get_type_name_by_id(self, id): + """ + ``get_type_name_by_id`` returns the defined type name whose unique identifier corresponds with the provided ``id`` + + :param str id: Unique identifier to lookup + :return: A QualifiedName or None if the type does not exist + :rtype: QualifiedName or None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) + 'foo' + >>> bv.get_type_name_by_id(type_id) + 'foo' + >>> + """ + name = core.BNGetAnalysisTypeNameById(self.handle, id) + result = types.QualifiedName._from_core_struct(name) + core.BNFreeQualifiedName(name) + if len(result) == 0: + return None + return result + + def get_type_id(self, name): + """ + ``get_type_id`` returns the unique indentifier of the defined type whose name corresponds with the + provided ``name`` + + :param QualifiedName name: Type name to lookup + :return: The unique identifier of the type + :rtype: str + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> registered_name = bv.define_type(type_id, name, type) + >>> bv.get_type_id(registered_name) == type_id + True + >>> + """ + name = types.QualifiedName(name)._get_core_struct() + return core.BNGetAnalysisTypeId(self.handle, name) + def is_type_auto_defined(self, name): """ ``is_type_auto_defined`` queries the user type list of name. If name is not in the *user* type list then the name @@ -2910,23 +2975,28 @@ class BinaryView(object): name = types.QualifiedName(name)._get_core_struct() return core.BNIsAnalysisTypeAutoDefined(self.handle, name) - def define_type(self, name, type_obj): + def define_type(self, type_id, default_name, type_obj): """ ``define_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of types for - the current :py:Class:`BinaryView`. + the current :py:Class:`BinaryView`. This method should only be used for automatically generated types. - :param QualifiedName name: Name of the type to be registered + :param str type_id: Unique identifier for the automatically generated type + :param QualifiedName default_name: Name of the type to be registered :param Type type_obj: Type object to be registered - :rtype: None + :return: Registered name of the type. May not be the same as the requested name if the user has renamed types. + :rtype: QualifiedName :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) - >>> bv.get_type_by_name(name) + >>> registered_name = bv.define_type(Type.generate_auto_type_id("source", name), name, type) + >>> bv.get_type_by_name(registered_name) """ - name = types.QualifiedName(name)._get_core_struct() - core.BNDefineAnalysisType(self.handle, name, type_obj.handle) + name = types.QualifiedName(default_name)._get_core_struct() + reg_name = core.BNDefineAnalysisType(self.handle, type_id, name, type_obj.handle) + result = types.QualifiedName._from_core_struct(reg_name) + core.BNFreeQualifiedName(reg_name) + return result def define_user_type(self, name, type_obj): """ @@ -2946,24 +3016,24 @@ class BinaryView(object): name = types.QualifiedName(name)._get_core_struct() core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) - def undefine_type(self, name): + def undefine_type(self, type_id): """ ``undefine_type`` removes a :py:Class:`Type` from the global list of types for the current :py:Class:`BinaryView` - :param QualifiedName name: Name of type to be undefined + :param str type_id: Unique identifier of type to be undefined :rtype: None :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) >>> bv.get_type_by_name(name) - >>> bv.undefine_type(name) + >>> bv.undefine_type(type_id) >>> bv.get_type_by_name(name) >>> """ - name = types.QualifiedName(name)._get_core_struct() - core.BNUndefineAnalysisType(self.handle, name) + core.BNUndefineAnalysisType(self.handle, type_id) def undefine_user_type(self, name): """ @@ -2975,16 +3045,38 @@ class BinaryView(object): :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> bv.define_user_type(name, type) >>> bv.get_type_by_name(name) - >>> bv.undefine_type(name) + >>> bv.undefine_user_type(name) >>> bv.get_type_by_name(name) >>> """ name = types.QualifiedName(name)._get_core_struct() core.BNUndefineUserAnalysisType(self.handle, name) + def rename_type(self, old_name, new_name): + """ + ``rename_type`` renames a type in the global list of types for the current :py:Class:`BinaryView` + + :param QualifiedName old_name: Existing name of type to be renamed + :param QualifiedName new_name: New name of type to be renamed + :rtype: None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> bv.define_user_type(name, type) + >>> bv.get_type_by_name("foo") + + >>> bv.rename_type("foo", "bar") + >>> bv.get_type_by_name("bar") + + >>> + """ + old_name = types.QualifiedName(old_name)._get_core_struct() + new_name = types.QualifiedName(new_name)._get_core_struct() + core.BNRenameAnalysisType(self.handle, old_name, new_name) + def find_next_data(self, start, data, flags = 0): """ ``find_next_data`` searchs for the bytes in data starting at the virtual address ``start`` either, case-sensitive, diff --git a/python/types.py b/python/types.py index 1dd2157e..1cc02691 100644 --- a/python/types.py +++ b/python/types.py @@ -299,7 +299,7 @@ class Type(object): result = core.BNGetTypeNamedTypeReference(self.handle) if result is None: return None - return NamedTypeReference(result) + return NamedTypeReference(handle = result) @property def count(self): @@ -392,12 +392,24 @@ class Type(object): def named_type(self, named_type, width = 0, align = 1): return Type(core.BNCreateNamedTypeReference(named_type.handle, width, align)) + @classmethod + def named_type_from_type_and_id(self, type_id, name, t): + name = QualifiedName(name)._get_core_struct() + if t is not None: + t = t.handle + return Type(core.BNCreateNamedTypeReferenceFromTypeAndId(type_id, name, t)) + @classmethod def named_type_from_type(self, name, t): name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromType(name, t)) + return Type(core.BNCreateNamedTypeReferenceFromTypeAndId("", name, t)) + + @classmethod + def named_type_from_registered_type(self, view, name): + name = QualifiedName(name)._get_core_struct() + return Type(core.BNCreateNamedTypeReferenceFromType(view.handle, name)) @classmethod def enumeration_type(self, arch, e, width=None): @@ -428,6 +440,21 @@ class Type(object): return Type(core.BNCreateFunctionType(ret.handle, calling_convention, param_buf, len(params), variable_arguments)) + @classmethod + def generate_auto_type_id(self, source, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(source, name) + + @classmethod + def generate_auto_platform_type_id(self, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(name) + + @classmethod + def generate_auto_demangled_type_id(self, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(name) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -436,10 +463,12 @@ class Type(object): class NamedTypeReference(object): - def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, name = None, handle = None): + def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: self.handle = core.BNCreateNamedType() core.BNSetTypeReferenceClass(self.handle, type_class) + if type_id is not None: + core.BNSetTypeReferenceId(self.handle, type_id) if name is not None: name = QualifiedName(name)._get_core_struct() core.BNSetTypeReferenceName(self.handle, name) @@ -451,16 +480,23 @@ class NamedTypeReference(object): @property def type_class(self): - return core.BNGetTypeReferenceClass(self.handle) + return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle)) @type_class.setter def type_class(self, value): core.BNSetTypeReferenceClass(self.handle, value) + @property + def type_id(self): + return core.BNGetTypeReferenceId(self.handle) + + @type_id.setter + def type_id(self, value): + core.BNSetTypeReferenceId(self.handle, value) + @property def name(self): - count = ctypes.c_ulonglong() - name = core.BNGetTypeReferenceName(self.handle, count) + name = core.BNGetTypeReferenceName(self.handle) result = QualifiedName._from_core_struct(name) core.BNFreeQualifiedName(name) return result @@ -481,6 +517,21 @@ class NamedTypeReference(object): return "" % str(self.name) return "" % str(self.name) + @classmethod + def generate_auto_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + + @classmethod + def generate_auto_platform_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_platform_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + + @classmethod + def generate_auto_demangled_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_demangled_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + class StructureMember(object): def __init__(self, t, name, offset): diff --git a/type.cpp b/type.cpp index e71077e6..dd1fb8d6 100644 --- a/type.cpp +++ b/type.cpp @@ -511,9 +511,25 @@ Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) Ref Type::NamedType(const QualifiedName& name, Type* type) +{ + return NamedType("", name, type); +} + + +Ref Type::NamedType(const string& id, const QualifiedName& name, Type* type) { BNQualifiedName nameObj = name.GetAPIObject(); - Type* result = new Type(BNCreateNamedTypeReferenceFromType(&nameObj, type ? type->GetObject() : nullptr)); + Type* result = new Type(BNCreateNamedTypeReferenceFromTypeAndId(id.c_str(), &nameObj, + type ? type->GetObject() : nullptr)); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +Ref Type::NamedType(BinaryView* view, const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(view->GetObject(), &nameObj)); QualifiedName::FreeAPIObject(&nameObj); return result; } @@ -561,16 +577,47 @@ void Type::SetFunctionCanReturn(bool canReturn) } +string Type::GenerateAutoTypeId(const string& source, const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoTypeId(source.c_str(), &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +string Type::GenerateAutoPlatformTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoPlatformTypeId(&nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoDemangledTypeId(&nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; } -NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const string& id, const QualifiedName& names) { m_object = BNCreateNamedType(); BNSetTypeReferenceClass(m_object, cls); + if (id.size() != 0) + { + BNSetTypeReferenceId(m_object, id.c_str()); + } if (names.size() != 0) { BNQualifiedName nameObj = names.GetAPIObject(); @@ -592,6 +639,21 @@ BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const } +string NamedTypeReference::GetTypeId() const +{ + char* str = BNGetTypeReferenceId(m_object); + string result = str; + BNFreeString(str); + return result; +} + + +void NamedTypeReference::SetTypeId(const string& id) +{ + BNSetTypeReferenceId(m_object, id.c_str()); +} + + void NamedTypeReference::SetName(const QualifiedName& names) { BNQualifiedName nameObj = names.GetAPIObject(); @@ -609,6 +671,30 @@ QualifiedName NamedTypeReference::GetName() const } +Ref NamedTypeReference::GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const string& source, const QualifiedName& name) +{ + string id = Type::GenerateAutoTypeId(source, name); + return new NamedTypeReference(cls, id, name); +} + + +Ref NamedTypeReference::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoPlatformTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + +Ref NamedTypeReference::GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoDemangledTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + Structure::Structure() { m_object = BNCreateStructure(); -- cgit v1.3.1 From 898ec98d9858ddec7fb431ba304d996cec12ff68 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 9 Feb 2017 19:06:07 -0500 Subject: APIs for handling platform types --- architecture.cpp | 9 +++++---- binaryninjaapi.h | 17 ++++++++++++----- binaryninjacore.h | 16 ++++++++++------ binaryview.cpp | 6 ++++++ platform.cpp | 28 ++++++++++++++++++++++++++++ python/architecture.py | 12 ++++++++---- python/binaryview.py | 16 ++++++++++++++++ python/platform.py | 12 ++++++++++++ python/types.py | 18 ++++++------------ type.cpp | 26 +++++++++++--------------- 10 files changed, 114 insertions(+), 46 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index 0e25fa85..d72e7f42 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -747,7 +747,8 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, map>& types, map>& variables, - map>& functions, string& errors, const vector& includeDirs) + map>& functions, string& errors, const vector& includeDirs, + const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -761,7 +762,7 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file functions.clear(); bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size()); + &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); errors = errorStr; BNFreeString(errorStr); if (!ok) @@ -789,7 +790,7 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, map>& variables, map>& functions, - string& errors, const vector& includeDirs) + string& errors, const vector& includeDirs, const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -803,7 +804,7 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, std::map>& variables, std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); bool ParseTypesFromSourceFile(const std::string& fileName, std::map>& types, std::map>& variables, std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); @@ -1627,8 +1631,8 @@ namespace BinaryNinja const std::vector& params, bool varArg = false); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); - static std::string GenerateAutoPlatformTypeId(const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); + static std::string GetAutoDemangledTypeIdSource(); }; class NamedTypeReference: public CoreRefCountObject GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, const std::string& source, const QualifiedName& name); - static Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, - const QualifiedName& name); static Ref GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); }; @@ -2339,6 +2341,11 @@ namespace BinaryNinja Ref GetRelatedPlatform(Architecture* arch); void AddRelatedPlatform(Architecture* arch, Platform* platform); Ref GetAssociatedPlatformByAddress(uint64_t& addr); + + std::string GenerateAutoPlatformTypeId(const QualifiedName& name); + Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); + std::string GetAutoPlatformTypeIdSource(); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index b454da64..4b810002 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1820,8 +1820,12 @@ extern "C" BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name); BINARYNINJACOREAPI void BNRenameAnalysisType(BNBinaryView* view, BNQualifiedName* oldName, BNQualifiedName* newName); BINARYNINJACOREAPI char* BNGenerateAutoTypeId(const char* source, BNQualifiedName* name); - BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNPlatform* platform, BNQualifiedName* name); BINARYNINJACOREAPI char* BNGenerateAutoDemangledTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGetAutoPlatformTypeIdSource(BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetAutoDemangledTypeIdSource(void); + + BINARYNINJACOREAPI void BNRegisterPlatformTypes(BNBinaryView* view, BNPlatform* platform); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -2063,13 +2067,13 @@ extern "C" // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, - const char** includeDirs, size_t includeDirCount); + const char** includeDirs, size_t includeDirCount); BINARYNINJACOREAPI bool BNParseTypesFromSource(BNArchitecture* arch, const char* source, const char* fileName, - BNTypeParserResult* result, char** errors, - const char** includeDirs, size_t includeDirCount); + BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, + const char* autoTypeSource); BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNArchitecture* arch, const char* fileName, - BNTypeParserResult* result, char** errors, - const char** includeDirs, size_t includeDirCount); + BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, + const char* autoTypeSource); BINARYNINJACOREAPI void BNFreeTypeParserResult(BNTypeParserResult* result); // Updates diff --git a/binaryview.cpp b/binaryview.cpp index 1b1574e1..8edbc2bf 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1577,6 +1577,12 @@ void BinaryView::RenameType(const QualifiedName& oldName, const QualifiedName& n } +void BinaryView::RegisterPlatformTypes(Platform* platform) +{ + BNRegisterPlatformTypes(m_object, platform->GetObject()); +} + + bool BinaryView::FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags) { return BNFindNextData(m_object, start, data.GetBufferObject(), &result, flags); diff --git a/platform.cpp b/platform.cpp index 7a6571cc..3bf4c0a4 100644 --- a/platform.cpp +++ b/platform.cpp @@ -253,3 +253,31 @@ Ref Platform::GetAssociatedPlatformByAddress(uint64_t& addr) return nullptr; return new Platform(platform); } + + +string Platform::GenerateAutoPlatformTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + char* str = BNGenerateAutoPlatformTypeId(m_object, &nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; +} + + +Ref Platform::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = GenerateAutoPlatformTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + +string Platform::GetAutoPlatformTypeIdSource() +{ + char* str = BNGetAutoPlatformTypeIdSource(m_object); + string result = str; + BNFreeString(str); + return result; +} diff --git a/python/architecture.py b/python/architecture.py index ea97f605..4cd0c597 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1585,7 +1585,7 @@ class Architecture(object): """ core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) - def parse_types_from_source(self, source, filename=None, include_dirs=[]): + def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source`` parses the source string and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. @@ -1593,6 +1593,7 @@ class Architecture(object): :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -1610,7 +1611,8 @@ class Architecture(object): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() - result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, len(include_dirs)) + result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: @@ -1630,13 +1632,14 @@ class Architecture(object): core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions) - def parse_types_from_source_file(self, filename, include_dirs=[]): + def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str filename: filename of file to be parsed :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -1654,7 +1657,8 @@ class Architecture(object): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() - result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, len(include_dirs)) + result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: diff --git a/python/binaryview.py b/python/binaryview.py index 2cdacb4c..caa5d780 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3077,6 +3077,22 @@ class BinaryView(object): new_name = types.QualifiedName(new_name)._get_core_struct() core.BNRenameAnalysisType(self.handle, old_name, new_name) + def register_platform_types(self, platform): + """ + ``register_platform_types`` ensures that the platform-specific types for a :py:Class:`Platform` are available + for the current :py:Class:`BinaryView`. This is automatically performed when adding a new function or setting + the default platform. + + :param Platform platform: Platform containing types to be registered + :rtype: None + :Example: + + >>> platform = Platform["linux-x86"] + >>> bv.register_platform_types(platform) + >>> + """ + core.BNRegisterPlatformTypes(self.handle, platform.handle) + def find_next_data(self, start, data, flags = 0): """ ``find_next_data`` searchs for the bytes in data starting at the virtual address ``start`` either, case-sensitive, diff --git a/python/platform.py b/python/platform.py index 04dce587..5d90997d 100644 --- a/python/platform.py +++ b/python/platform.py @@ -25,6 +25,7 @@ import _binaryninjacore as core import startup import architecture import callingconvention +import types class _PlatformMetaClass(type): @@ -259,3 +260,14 @@ class Platform(object): new_addr.value = addr result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr) return Platform(None, handle = result), new_addr.value + + def generate_auto_platform_type_id(self, name): + name = types.QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoPlatformTypeId(self.handle, name) + + def generate_auto_platform_type_ref(self, type_class, name): + type_id = self.generate_auto_platform_type_id(name) + return types.NamedTypeReference(type_class, type_id, name) + + def get_auto_platform_type_id_source(self): + return core.BNGetAutoPlatformTypeIdSource(self.handle) diff --git a/python/types.py b/python/types.py index 1cc02691..f66625f8 100644 --- a/python/types.py +++ b/python/types.py @@ -446,14 +446,13 @@ class Type(object): return core.BNGenerateAutoTypeId(source, name) @classmethod - def generate_auto_platform_type_id(self, name): + def generate_auto_demangled_type_id(self, name): name = QualifiedName(name)._get_core_struct() - return core.BNGenerateAutoTypeId(name) + return core.BNGenerateAutoDemangledTypeId(name) @classmethod - def generate_auto_demangled_type_id(self, name): - name = QualifiedName(name)._get_core_struct() - return core.BNGenerateAutoTypeId(name) + def get_auto_demanged_type_id_source(self): + return core.BNGetAutoDemangledTypeIdSource() def __setattr__(self, name, value): try: @@ -523,13 +522,8 @@ class NamedTypeReference(object): return NamedTypeReference(type_class, type_id, name) @classmethod - def generate_auto_platform_type_ref(self, type_class, source, name): - type_id = Type.generate_auto_platform_type_id(source, name) - return NamedTypeReference(type_class, type_id, name) - - @classmethod - def generate_auto_demangled_type_ref(self, type_class, source, name): - type_id = Type.generate_auto_demangled_type_id(source, name) + def generate_auto_demangled_type_ref(self, type_class, name): + type_id = Type.generate_auto_demangled_type_id(name) return NamedTypeReference(type_class, type_id, name) diff --git a/type.cpp b/type.cpp index dd1fb8d6..66138001 100644 --- a/type.cpp +++ b/type.cpp @@ -580,26 +580,30 @@ void Type::SetFunctionCanReturn(bool canReturn) string Type::GenerateAutoTypeId(const string& source, const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoTypeId(source.c_str(), &nameObj); + char* str = BNGenerateAutoTypeId(source.c_str(), &nameObj); + string result = str; QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); return result; } -string Type::GenerateAutoPlatformTypeId(const QualifiedName& name) +string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoPlatformTypeId(&nameObj); + char* str = BNGenerateAutoDemangledTypeId(&nameObj); + string result = str; QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); return result; } -string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) +string Type::GetAutoDemangledTypeIdSource() { - BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoDemangledTypeId(&nameObj); - QualifiedName::FreeAPIObject(&nameObj); + char* str = BNGetAutoDemangledTypeIdSource(); + string result = str; + BNFreeString(str); return result; } @@ -679,14 +683,6 @@ Ref NamedTypeReference::GenerateAutoTypeReference(BNNamedTyp } -Ref NamedTypeReference::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, - const QualifiedName& name) -{ - string id = Type::GenerateAutoPlatformTypeId(name); - return new NamedTypeReference(cls, id, name); -} - - Ref NamedTypeReference::GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name) { -- cgit v1.3.1 From 3f08a3c209adba9de44f871e2a4cf358a71f59cd Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 9 Feb 2017 21:17:36 -0500 Subject: API for accessing platform-specific types and function definitions --- binaryninjaapi.h | 10 +++++ binaryninjacore.h | 18 ++++++++ platform.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ python/platform.py | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index ed9cedc5..4f3a0275 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2342,6 +2342,16 @@ namespace BinaryNinja void AddRelatedPlatform(Architecture* arch, Platform* platform); Ref GetAssociatedPlatformByAddress(uint64_t& addr); + std::map> GetTypes(); + std::map> GetVariables(); + std::map> GetFunctions(); + std::map GetSystemCalls(); + Ref GetTypeByName(const QualifiedName& name); + Ref GetVariableByName(const QualifiedName& name); + Ref GetFunctionByName(const QualifiedName& name); + std::string GetSystemCallName(uint32_t n); + Ref GetSystemCallType(uint32_t n); + std::string GenerateAutoPlatformTypeId(const QualifiedName& name); Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); diff --git a/binaryninjacore.h b/binaryninjacore.h index 4b810002..7c4b6db0 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1220,6 +1220,13 @@ extern "C" uint64_t end; }; + struct BNSystemCallInfo + { + uint32_t number; + BNQualifiedName name; + BNType* type; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -2202,6 +2209,17 @@ extern "C" BINARYNINJACOREAPI void BNAddRelatedPlatform(BNPlatform* platform, BNArchitecture* arch, BNPlatform* related); BINARYNINJACOREAPI BNPlatform* BNGetAssociatedPlatformByAddress(BNPlatform* platform, uint64_t* addr); + BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformTypes(BNPlatform* platform, size_t* count); + BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformVariables(BNPlatform* platform, size_t* count); + BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformFunctions(BNPlatform* platform, size_t* count); + BINARYNINJACOREAPI BNSystemCallInfo* BNGetPlatformSystemCalls(BNPlatform* platform, size_t* count); + BINARYNINJACOREAPI void BNFreeSystemCallList(BNSystemCallInfo* syscalls, size_t count); + BINARYNINJACOREAPI BNType* BNGetPlatformTypeByName(BNPlatform* platform, BNQualifiedName* name); + BINARYNINJACOREAPI BNType* BNGetPlatformVariableByName(BNPlatform* platform, BNQualifiedName* name); + BINARYNINJACOREAPI BNType* BNGetPlatformFunctionByName(BNPlatform* platform, BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGetPlatformSystemCallName(BNPlatform* platform, uint32_t number); + BINARYNINJACOREAPI BNType* BNGetPlatformSystemCallType(BNPlatform* platform, uint32_t number); + //Demangler BINARYNINJACOREAPI bool BNDemangleMS(BNArchitecture* arch, const char* mangledName, diff --git a/platform.cpp b/platform.cpp index 3bf4c0a4..afbcbbf3 100644 --- a/platform.cpp +++ b/platform.cpp @@ -255,6 +255,127 @@ Ref Platform::GetAssociatedPlatformByAddress(uint64_t& addr) } +map> Platform::GetTypes() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformTypes(m_object, &count); + + map> result; + for (size_t i = 0; i < count; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } + + BNFreeTypeList(types, count); + return result; +} + + +map> Platform::GetVariables() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformVariables(m_object, &count); + + map> result; + for (size_t i = 0; i < count; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } + + BNFreeTypeList(types, count); + return result; +} + + +map> Platform::GetFunctions() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformFunctions(m_object, &count); + + map> result; + for (size_t i = 0; i < count; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } + + BNFreeTypeList(types, count); + return result; +} + + +map Platform::GetSystemCalls() +{ + size_t count; + BNSystemCallInfo* calls = BNGetPlatformSystemCalls(m_object, &count); + + map result; + for (size_t i = 0; i < count; i++) + { + QualifiedNameAndType nt; + nt.name = QualifiedName::FromAPIObject(&calls[i].name); + nt.type = new Type(BNNewTypeReference(calls[i].type)); + result[calls[i].number] = nt; + } + + BNFreeSystemCallList(calls, count); + return result; +} + + +Ref Platform::GetTypeByName(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetPlatformTypeByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + if (!type) + return nullptr; + return new Type(type); +} + + +Ref Platform::GetVariableByName(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetPlatformVariableByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + if (!type) + return nullptr; + return new Type(type); +} + + +Ref Platform::GetFunctionByName(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetPlatformFunctionByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + if (!type) + return nullptr; + return new Type(type); +} + + +string Platform::GetSystemCallName(uint32_t n) +{ + char* str = BNGetPlatformSystemCallName(m_object, n); + string result = str; + BNFreeString(str); + return result; +} + + +Ref Platform::GetSystemCallType(uint32_t n) +{ + BNType* type = BNGetPlatformSystemCallType(m_object, n); + if (!type) + return nullptr; + return new Type(type); +} + + string Platform::GenerateAutoPlatformTypeId(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); diff --git a/python/platform.py b/python/platform.py index 5d90997d..ccc80476 100644 --- a/python/platform.py +++ b/python/platform.py @@ -216,6 +216,55 @@ class Platform(object): core.BNFreeCallingConventionList(cc, count.value) return result + @property + def types(self): + """List of platform-specific types (read-only)""" + count = ctypes.c_ulonglong(0) + type_list = core.BNGetPlatformTypes(self.handle, count) + result = {} + for i in xrange(0, count.value): + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + core.BNFreeTypeList(type_list, count.value) + return result + + @property + def variables(self): + """List of platform-specific variable definitions (read-only)""" + count = ctypes.c_ulonglong(0) + type_list = core.BNGetPlatformVariables(self.handle, count) + result = {} + for i in xrange(0, count.value): + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + core.BNFreeTypeList(type_list, count.value) + return result + + @property + def functions(self): + """List of platform-specific function definitions (read-only)""" + count = ctypes.c_ulonglong(0) + type_list = core.BNGetPlatformFunctions(self.handle, count) + result = {} + for i in xrange(0, count.value): + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + core.BNFreeTypeList(type_list, count.value) + return result + + @property + def system_calls(self): + """List of system calls for this platform (read-only)""" + count = ctypes.c_ulonglong(0) + call_list = core.BNGetPlatformSystemCalls(self.handle, count) + result = {} + for i in xrange(0, count.value): + name = types.QualifiedName._from_core_struct(call_list[i].name) + t = types.Type(core.BNNewTypeReference(call_list[i].type)) + result[call_list[i].number] = (name, t) + core.BNFreeSystemCallList(call_list, count.value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -261,6 +310,36 @@ class Platform(object): result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr) return Platform(None, handle = result), new_addr.value + def get_type_by_name(self, name): + name = types.QualifiedName(name)._get_core_struct() + obj = core.BNGetPlatformTypeByName(self.handle, name) + if not obj: + return None + return types.Type(obj) + + def get_variable_by_name(self, name): + name = types.QualifiedName(name)._get_core_struct() + obj = core.BNGetPlatformVariableByName(self.handle, name) + if not obj: + return None + return types.Type(obj) + + def get_function_by_name(self, name): + name = types.QualifiedName(name)._get_core_struct() + obj = core.BNGetPlatformFunctionByName(self.handle, name) + if not obj: + return None + return types.Type(obj) + + def get_system_call_name(self, number): + return core.BNGetPlatformSystemCallName(self.handle, number) + + def get_system_call_type(self, number): + obj = core.BNGetPlatformSystemCallType(self.handle, number) + if not obj: + return None + return types.Type(obj) + def generate_auto_platform_type_id(self, name): name = types.QualifiedName(name)._get_core_struct() return core.BNGenerateAutoPlatformTypeId(self.handle, name) -- cgit v1.3.1 From 57c08987ee10af0b52d5c3fd44739a3935f9efa7 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 16 Feb 2017 19:12:43 -0500 Subject: Basic blocks have incoming and outgoing edges with basic block references, use core object identity for equality --- basicblock.cpp | 30 +++++++++++++++++++++--- binaryninjaapi.h | 42 ++++++++++++++++++++++++++++++---- binaryninjacore.h | 7 +++--- python/architecture.py | 10 ++++++++ python/basicblock.py | 56 +++++++++++++++++++++++++++++++++------------ python/binaryview.py | 40 ++++++++++++++++++++++++++++++++ python/callingconvention.py | 10 ++++++++ python/filemetadata.py | 10 ++++++++ python/function.py | 30 ++++++++++++++++++++++++ python/lowlevelil.py | 10 ++++++++ python/platform.py | 10 ++++++++ python/transform.py | 10 ++++++++ python/types.py | 50 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 291 insertions(+), 24 deletions(-) (limited to 'python') diff --git a/basicblock.cpp b/basicblock.cpp index 4edcc568..153a7768 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -108,6 +108,12 @@ uint64_t BasicBlock::GetLength() const } +size_t BasicBlock::GetIndex() const +{ + return BNGetBasicBlockIndex(m_object); +} + + vector BasicBlock::GetOutgoingEdges() const { size_t count; @@ -118,12 +124,30 @@ vector BasicBlock::GetOutgoingEdges() const { BasicBlockEdge edge; edge.type = array[i].type; - edge.target = array[i].target; - edge.arch = array[i].arch ? new CoreArchitecture(array[i].arch) : nullptr; + edge.target = array[i].target ? new BasicBlock(BNNewBasicBlockReference(array[i].target)) : nullptr; + result.push_back(edge); + } + + BNFreeBasicBlockEdgeList(array, count); + return result; +} + + +vector BasicBlock::GetIncomingEdges() const +{ + size_t count; + BNBasicBlockEdge* array = BNGetBasicBlockIncomingEdges(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + BasicBlockEdge edge; + edge.type = array[i].type; + edge.target = array[i].target ? new BasicBlock(BNNewBasicBlockReference(array[i].target)) : nullptr; result.push_back(edge); } - BNFreeBasicBlockOutgoingEdgeList(array); + BNFreeBasicBlockEdgeList(array, count); return result; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 370a9ae2..7004501c 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -51,6 +51,8 @@ namespace BinaryNinja RefCountObject(): m_refs(0) {} virtual ~RefCountObject() {} + RefCountObject* GetObject() { return this; } + void AddRef() { #ifdef WIN32 @@ -101,7 +103,7 @@ namespace BinaryNinja CoreRefCountObject(): m_refs(0), m_object(nullptr) {} virtual ~CoreRefCountObject() {} - T* GetObject() { return m_object; } + T* GetObject() const { return m_object; } void AddRef() { @@ -158,7 +160,7 @@ namespace BinaryNinja StaticCoreRefCountObject(): m_refs(0), m_object(nullptr) {} virtual ~StaticCoreRefCountObject() {} - T* GetObject() { return m_object; } + T* GetObject() const { return m_object; } void AddRef() { @@ -246,6 +248,36 @@ namespace BinaryNinja return m_obj == NULL; } + bool operator==(const T* obj) const + { + return m_obj->GetObject() == obj->GetObject(); + } + + bool operator==(const Ref& obj) const + { + return m_obj->GetObject() == obj.m_obj->GetObject(); + } + + bool operator!=(const T* obj) const + { + return m_obj->GetObject() != obj->GetObject(); + } + + bool operator!=(const Ref& obj) const + { + return m_obj->GetObject() != obj.m_obj->GetObject(); + } + + bool operator<(const T* obj) const + { + return m_obj->GetObject() < obj->GetObject(); + } + + bool operator<(const Ref& obj) const + { + return m_obj->GetObject() < obj.m_obj->GetObject(); + } + T* GetPtr() const { return m_obj; @@ -1728,8 +1760,7 @@ namespace BinaryNinja struct BasicBlockEdge { BNBranchType type; - uint64_t target; - Ref arch; + Ref target; }; class BasicBlock: public CoreRefCountObject @@ -1744,7 +1775,10 @@ namespace BinaryNinja uint64_t GetEnd() const; uint64_t GetLength() const; + size_t GetIndex() const; + std::vector GetOutgoingEdges() const; + std::vector GetIncomingEdges() const; bool HasUndeterminedOutgoingEdges() const; void MarkRecentUse(); diff --git a/binaryninjacore.h b/binaryninjacore.h index b8531742..2d22bb3f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -793,8 +793,7 @@ extern "C" struct BNBasicBlockEdge { BNBranchType type; - uint64_t target; - BNArchitecture* arch; + BNBasicBlock* target; }; struct BNPoint @@ -1726,8 +1725,10 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetBasicBlockEnd(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockLength(BNBasicBlock* block); BINARYNINJACOREAPI BNBasicBlockEdge* BNGetBasicBlockOutgoingEdges(BNBasicBlock* block, size_t* count); - BINARYNINJACOREAPI void BNFreeBasicBlockOutgoingEdgeList(BNBasicBlockEdge* edges); + BINARYNINJACOREAPI BNBasicBlockEdge* BNGetBasicBlockIncomingEdges(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI void BNFreeBasicBlockEdgeList(BNBasicBlockEdge* edges, size_t count); BINARYNINJACOREAPI bool BNBasicBlockHasUndeterminedOutgoingEdges(BNBasicBlock* block); + BINARYNINJACOREAPI size_t BNGetBasicBlockIndex(BNBasicBlock* block); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); diff --git a/python/architecture.py b/python/architecture.py index 5bafe949..39e5e72d 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -333,6 +333,16 @@ class Architecture(object): self._pending_reg_lists = {} self._pending_token_lists = {} + def __eq__(self, value): + if not isinstance(value, Architecture): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Architecture): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def full_width_regs(self): """List of full width register strings (read-only)""" diff --git a/python/basicblock.py b/python/basicblock.py index f6dbd60d..ebacb311 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -29,19 +29,17 @@ import function class BasicBlockEdge(object): - def __init__(self, branch_type, target, arch): + def __init__(self, branch_type, target): self.type = branch_type - if self.type != BranchType.UnresolvedBranch: - self.target = target - self.arch = arch + self.target = target def __repr__(self): if self.type == BranchType.UnresolvedBranch: return "<%s>" % BranchType(self.type).name - elif self.arch: - return "<%s: %s@%#x>" % (self.type, self.arch.name, self.target) + elif self.target.arch: + return "<%s: %s@%#x>" % (BranchType(self.type).name, self.target.arch.name, self.target.start) else: - return "<%s: %#x>" % (self.type, self.target) + return "<%s: %#x>" % (BranchType(self.type).name, self.target.start) class BasicBlock(object): @@ -52,6 +50,16 @@ class BasicBlock(object): def __del__(self): core.BNFreeBasicBlock(self.handle) + def __eq__(self, value): + if not isinstance(value, BasicBlock): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, BasicBlock): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def function(self): """Basic block function (read-only)""" @@ -83,6 +91,11 @@ class BasicBlock(object): """Basic block length (read-only)""" return core.BNGetBasicBlockLength(self.handle) + @property + def index(self): + """Basic block index in list of blocks for the function (read-only)""" + return core.BNGetBasicBlockIndex(self.handle) + @property def outgoing_edges(self): """List of basic block outgoing edges (read-only)""" @@ -90,14 +103,29 @@ class BasicBlock(object): edges = core.BNGetBasicBlockOutgoingEdges(self.handle, count) result = [] for i in xrange(0, count.value): - branch_type = edges[i].type - target = edges[i].target - if edges[i].arch: - arch = architecture.Architecture(edges[i].arch) + branch_type = BranchType(edges[i].type) + if edges[i].target: + target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + else: + target = None + result.append(BasicBlockEdge(branch_type, target)) + core.BNFreeBasicBlockEdgeList(edges, count.value) + return result + + @property + def incoming_edges(self): + """List of basic block incoming edges (read-only)""" + count = ctypes.c_ulonglong(0) + edges = core.BNGetBasicBlockIncomingEdges(self.handle, count) + result = [] + for i in xrange(0, count.value): + branch_type = BranchType(edges[i].type) + if edges[i].target: + target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: - arch = None - result.append(BasicBlockEdge(branch_type, target, arch)) - core.BNFreeBasicBlockOutgoingEdgeList(edges) + target = None + result.append(BasicBlockEdge(branch_type, target)) + core.BNFreeBasicBlockEdgeList(edges, count.value) return result @property diff --git a/python/binaryview.py b/python/binaryview.py index 9753b653..dd37be69 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -299,6 +299,16 @@ class BinaryViewType(object): def __init__(self, handle): self.handle = core.handle_of_type(handle, core.BNBinaryViewType) + def __eq__(self, value): + if not isinstance(value, BinaryViewType): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, BinaryViewType): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def name(self): """BinaryView name (read-only)""" @@ -547,6 +557,16 @@ class BinaryView(object): self.notifications = {} self.next_address = None # Do NOT try to access view before init() is called, use placeholder + def __eq__(self, value): + if not isinstance(value, BinaryView): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, BinaryView): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @classmethod def register(cls): startup._init_plugins() @@ -3255,6 +3275,16 @@ class BinaryReader(object): def __del__(self): core.BNFreeBinaryReader(self.handle) + def __eq__(self, value): + if not isinstance(value, BinaryReader): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, BinaryReader): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def endianness(self): """ @@ -3562,6 +3592,16 @@ class BinaryWriter(object): def __del__(self): core.BNFreeBinaryWriter(self.handle) + def __eq__(self, value): + if not isinstance(value, BinaryWriter): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, BinaryWriter): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def endianness(self): """ diff --git a/python/callingconvention.py b/python/callingconvention.py index 5f4adeab..04ba711f 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -112,6 +112,16 @@ class CallingConvention(object): def __del__(self): core.BNFreeCallingConvention(self.handle) + def __eq__(self, value): + if not isinstance(value, CallingConvention): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, CallingConvention): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _get_caller_saved_regs(self, ctxt, count): try: regs = self.__class__.caller_saved_regs diff --git a/python/filemetadata.py b/python/filemetadata.py index f6593405..b489d5bb 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -93,6 +93,16 @@ class FileMetadata(object): core.BNSetFileMetadataNavigationHandler(self.handle, None) core.BNFreeFileMetadata(self.handle) + def __eq__(self, value): + if not isinstance(value, FileMetadata): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, FileMetadata): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @classmethod def _unregister(cls, f): handle = ctypes.cast(f, ctypes.c_void_p) diff --git a/python/function.py b/python/function.py index 3aeb8e22..4cdd6cc9 100644 --- a/python/function.py +++ b/python/function.py @@ -177,6 +177,16 @@ class Function(object): core.BNReleaseAdvancedFunctionAnalysisDataMultiple(self.handle, self._advanced_analysis_requests) core.BNFreeFunction(self.handle) + def __eq__(self, value): + if not isinstance(value, Function): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Function): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @classmethod def _unregister(cls, func): handle = ctypes.cast(func, ctypes.c_void_p) @@ -856,6 +866,16 @@ class FunctionGraphBlock(object): def __del__(self): core.BNFreeFunctionGraphBlock(self.handle) + def __eq__(self, value): + if not isinstance(value, FunctionGraphBlock): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, FunctionGraphBlock): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def basic_block(self): """Basic block associated with this part of the function graph (read-only)""" @@ -1030,6 +1050,16 @@ class FunctionGraph(object): self.abort() core.BNFreeFunctionGraph(self.handle) + def __eq__(self, value): + if not isinstance(value, FunctionGraph): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, FunctionGraph): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def function(self): """Function for a function graph (read-only)""" diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 29b46b65..c80fcd0d 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -253,6 +253,16 @@ class LowLevelILFunction(object): def __del__(self): core.BNFreeLowLevelILFunction(self.handle) + def __eq__(self, value): + if not isinstance(value, LowLevelILFunction): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, LowLevelILFunction): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def current_address(self): """Current IL Address (read/write)""" diff --git a/python/platform.py b/python/platform.py index ccc80476..139b7d5e 100644 --- a/python/platform.py +++ b/python/platform.py @@ -110,6 +110,16 @@ class Platform(object): def __del__(self): core.BNFreePlatform(self.handle) + def __eq__(self, value): + if not isinstance(value, Platform): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Platform): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def default_calling_convention(self): """ diff --git a/python/transform.py b/python/transform.py index 0c003738..40382c69 100644 --- a/python/transform.py +++ b/python/transform.py @@ -131,6 +131,16 @@ class Transform(object): def __repr__(self): return "" % self.name + def __eq__(self, value): + if not isinstance(value, Transform): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Transform): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _get_parameters(self, ctxt, count): try: count[0] = len(self.parameters) diff --git a/python/types.py b/python/types.py index 43aaa66f..ebaa36fc 100644 --- a/python/types.py +++ b/python/types.py @@ -139,6 +139,16 @@ class Symbol(object): def __del__(self): core.BNFreeSymbol(self.handle) + def __eq__(self, value): + if not isinstance(value, Symbol): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Symbol): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type(self): """Symbol type (read-only)""" @@ -194,6 +204,16 @@ class Type(object): def __del__(self): core.BNFreeType(self.handle) + def __eq__(self, value): + if not isinstance(value, Type): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Type): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type_class(self): """Type class (read-only)""" @@ -491,6 +511,16 @@ class NamedTypeReference(object): def __del__(self): core.BNFreeNamedTypeReference(self.handle) + def __eq__(self, value): + if not isinstance(value, NamedTypeReference): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, NamedTypeReference): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type_class(self): return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle)) @@ -564,6 +594,16 @@ class Structure(object): def __del__(self): core.BNFreeStructure(self.handle) + def __eq__(self, value): + if not isinstance(value, Structure): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Structure): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def members(self): """Structure member list (read-only)""" @@ -652,6 +692,16 @@ class Enumeration(object): def __del__(self): core.BNFreeEnumeration(self.handle) + def __eq__(self, value): + if not isinstance(value, Enumeration): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Enumeration): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def members(self): """Enumeration member list (read-only)""" -- cgit v1.3.1 From c46c3a9540f4d15eff8aa9660df69e374f7fd2f5 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 17 Feb 2017 23:22:17 -0500 Subject: Add dominator APIs --- basicblock.cpp | 37 +++++++++++++++++++++++++++++++++++++ binaryninjaapi.h | 7 +++++-- binaryninjacore.h | 6 ++++-- functiongraphblock.cpp | 3 +-- python/basicblock.py | 30 ++++++++++++++++++++++++++++++ python/function.py | 21 ++++++++++++--------- 6 files changed, 89 insertions(+), 15 deletions(-) (limited to 'python') diff --git a/basicblock.cpp b/basicblock.cpp index 153a7768..58fcb4aa 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -158,6 +158,43 @@ bool BasicBlock::HasUndeterminedOutgoingEdges() const } +set> BasicBlock::GetDominators() const +{ + size_t count; + BNBasicBlock** blocks = BNGetBasicBlockDominators(m_object, &count); + + set> result; + for (size_t i = 0; i < count; i++) + result.insert(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +set> BasicBlock::GetStrictDominators() const +{ + size_t count; + BNBasicBlock** blocks = BNGetBasicBlockStrictDominators(m_object, &count); + + set> result; + for (size_t i = 0; i < count; i++) + result.insert(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +Ref BasicBlock::GetImmediateDominator() const +{ + BNBasicBlock* result = BNGetBasicBlockImmediateDominator(m_object); + if (!result) + return nullptr; + return new BasicBlock(result); +} + + void BasicBlock::MarkRecentUse() { BNMarkBasicBlockAsRecentlyUsed(m_object); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7004501c..ea9d3972 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1781,6 +1781,10 @@ namespace BinaryNinja std::vector GetIncomingEdges() const; bool HasUndeterminedOutgoingEdges() const; + std::set> GetDominators() const; + std::set> GetStrictDominators() const; + Ref GetImmediateDominator() const; + void MarkRecentUse(); std::vector> GetAnnotations(); @@ -1970,8 +1974,7 @@ namespace BinaryNinja struct FunctionGraphEdge { BNBranchType type; - uint64_t target; - Ref arch; + Ref target; std::vector points; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 2d22bb3f..239d1002 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -805,8 +805,7 @@ extern "C" struct BNFunctionGraphEdge { BNBranchType type; - uint64_t target; - BNArchitecture* arch; + BNBasicBlock* target; BNPoint* points; size_t pointCount; }; @@ -1729,6 +1728,9 @@ extern "C" BINARYNINJACOREAPI void BNFreeBasicBlockEdgeList(BNBasicBlockEdge* edges, size_t count); BINARYNINJACOREAPI bool BNBasicBlockHasUndeterminedOutgoingEdges(BNBasicBlock* block); BINARYNINJACOREAPI size_t BNGetBasicBlockIndex(BNBasicBlock* block); + BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominators(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockStrictDominators(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI BNBasicBlock* BNGetBasicBlockImmediateDominator(BNBasicBlock* block); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index db69c25a..a37c0b49 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -128,8 +128,7 @@ const vector& FunctionGraphBlock::GetOutgoingEdges() { FunctionGraphEdge edge; edge.type = edges[i].type; - edge.target = edges[i].target; - edge.arch = edges[i].arch ? new CoreArchitecture(edges[i].arch) : nullptr; + edge.target = edges[i].target ? new BasicBlock(BNNewBasicBlockReference(edges[i].target)) : nullptr; edge.points.insert(edge.points.begin(), &edges[i].points[0], &edges[i].points[edges[i].pointCount]); result.push_back(edge); } diff --git a/python/basicblock.py b/python/basicblock.py index ebacb311..9d48d3cb 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -133,6 +133,36 @@ class BasicBlock(object): """Whether basic block has undetermined outgoing edges (read-only)""" return core.BNBasicBlockHasUndeterminedOutgoingEdges(self.handle) + @property + def dominators(self): + """List of dominators for this basic block (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetBasicBlockDominators(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def strict_dominators(self): + """List of strict dominators for this basic block (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetBasicBlockStrictDominators(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def immediate_dominator(self): + """Immediate dominator of this basic block (read-only)""" + result = core.BNGetBasicBlockImmediateDominator(self.handle) + if not result: + return None + return BasicBlock(self.view, result) + @property def annotations(self): """List of automatic annotations for the start of this block (read-only)""" diff --git a/python/function.py b/python/function.py index 4cdd6cc9..2f6788f6 100644 --- a/python/function.py +++ b/python/function.py @@ -847,16 +847,13 @@ class DisassemblyTextLine(object): class FunctionGraphEdge(object): - def __init__(self, branch_type, arch, target, points): + def __init__(self, branch_type, target, points): self.type = BranchType(branch_type) - self.arch = arch self.target = target self.points = points def __repr__(self): - if self.arch: - return "<%s: %s@%#x>" % (self.type.name, self.arch.name, self.target) - return "<%s: %#x>" % (self.type, self.target) + return "<%s: %s>" % (self.type.name, repr(self.target)) class FunctionGraphBlock(object): @@ -958,13 +955,19 @@ class FunctionGraphBlock(object): for i in xrange(0, count.value): branch_type = BranchType(edges[i].type) target = edges[i].target - arch = None - if edges[i].arch is not None: - arch = architecture.Architecture(edges[i].arch) + if target: + func = core.BNGetBasicBlockFunction(target) + if func is None: + core.BNFreeBasicBlock(target) + target = None + else: + target = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewBasicBlockReference(target)) + core.BNFreeFunction(func) points = [] for j in xrange(0, edges[i].pointCount): points.append((edges[i].points[j].x, edges[i].points[j].y)) - result.append(FunctionGraphEdge(branch_type, arch, target, points)) + result.append(FunctionGraphEdge(branch_type, target, points)) core.BNFreeFunctionGraphBlockOutgoingEdgeList(edges, count.value) return result -- cgit v1.3.1 From 96f6bc8a3099754bf79a05af7a1ec342f8030335 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sat, 18 Feb 2017 00:41:37 -0500 Subject: Add back edge property to block edges --- basicblock.cpp | 6 ++++++ binaryninjaapi.h | 2 ++ python/basicblock.py | 12 +++++++++--- python/examples/export_svg.py | 9 ++++++++- python/function.py | 10 ++++++++-- 5 files changed, 33 insertions(+), 6 deletions(-) (limited to 'python') diff --git a/basicblock.cpp b/basicblock.cpp index 58fcb4aa..d6423fa0 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -345,3 +345,9 @@ void BasicBlock::SetUserBasicBlockHighlight(uint8_t r, uint8_t g, uint8_t b, uin hc.alpha = alpha; SetUserBasicBlockHighlight(hc); } + + +bool BasicBlock::IsBackEdge(BasicBlock* source, BasicBlock* target) +{ + return source->GetDominators().count(target) != 0; +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index ea9d3972..6a23fd13 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1802,6 +1802,8 @@ namespace BinaryNinja void SetUserBasicBlockHighlight(BNHighlightStandardColor color, BNHighlightStandardColor mixColor, uint8_t mix, uint8_t alpha = 255); void SetUserBasicBlockHighlight(uint8_t r, uint8_t g, uint8_t b, uint8_t alpha = 255); + + static bool IsBackEdge(BasicBlock* source, BasicBlock* target); }; struct StackVariable diff --git a/python/basicblock.py b/python/basicblock.py index 9d48d3cb..e332cc3c 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -29,8 +29,9 @@ import function class BasicBlockEdge(object): - def __init__(self, branch_type, target): + def __init__(self, branch_type, source, target): self.type = branch_type + self.source = source self.target = target def __repr__(self): @@ -41,6 +42,11 @@ class BasicBlockEdge(object): else: return "<%s: %#x>" % (BranchType(self.type).name, self.target.start) + @property + def back_edge(self): + """Whether the edge is a back edge (end of a loop)""" + return self.target in self.source.dominators + class BasicBlock(object): def __init__(self, view, handle): @@ -108,7 +114,7 @@ class BasicBlock(object): target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None - result.append(BasicBlockEdge(branch_type, target)) + result.append(BasicBlockEdge(branch_type, self, target)) core.BNFreeBasicBlockEdgeList(edges, count.value) return result @@ -124,7 +130,7 @@ class BasicBlock(object): target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None - result.append(BasicBlockEdge(branch_type, target)) + result.append(BasicBlockEdge(branch_type, self, target)) core.BNFreeBasicBlockEdgeList(edges, count.value) return result diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 89bc41a1..95e2d62d 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -80,6 +80,10 @@ def render_svg(function): fill: none; stroke-width: 1px; } + .back_edge { + fill: none; + stroke-width: 2px; + } .UnconditionalBranch, .IndirectBranch { stroke: rgb(128, 198, 233); color: rgb(128, 198, 233); @@ -197,7 +201,10 @@ def render_svg(function): points += str(x * widthconst) + "," + str(y * heightconst) + " " x, y = edge.points[-1] points += str(x * widthconst) + "," + str(y * heightconst + 0) + " " - edges += ' \n'.format(type=BranchType(edge.type).name, points=points) + if edge.back_edge: + edges += ' \n'.format(type=BranchType(edge.type).name, points=points) + else: + edges += ' \n'.format(type=BranchType(edge.type).name, points=points) output += ' ' + edges + '\n' output += ' \n' output += '' diff --git a/python/function.py b/python/function.py index 2f6788f6..86c93bf7 100644 --- a/python/function.py +++ b/python/function.py @@ -847,14 +847,20 @@ class DisassemblyTextLine(object): class FunctionGraphEdge(object): - def __init__(self, branch_type, target, points): + def __init__(self, branch_type, source, target, points): self.type = BranchType(branch_type) + self.source = source self.target = target self.points = points def __repr__(self): return "<%s: %s>" % (self.type.name, repr(self.target)) + @property + def back_edge(self): + """Whether the edge is a back edge (end of a loop)""" + return self.target in self.source.basic_block.dominators + class FunctionGraphBlock(object): def __init__(self, handle): @@ -967,7 +973,7 @@ class FunctionGraphBlock(object): points = [] for j in xrange(0, edges[i].pointCount): points.append((edges[i].points[j].x, edges[i].points[j].y)) - result.append(FunctionGraphEdge(branch_type, target, points)) + result.append(FunctionGraphEdge(branch_type, self, target, points)) core.BNFreeFunctionGraphBlockOutgoingEdgeList(edges, count.value) return result -- cgit v1.3.1 From 33ae06ad9a4dfe1e78467ebf7f82a4c95f8945eb Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 20 Feb 2017 21:11:26 -0500 Subject: Add dominance frontier APIs --- basicblock.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ binaryninjaapi.h | 3 +++ binaryninjacore.h | 4 ++++ python/basicblock.py | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) (limited to 'python') diff --git a/basicblock.cpp b/basicblock.cpp index d6423fa0..d8ae0f65 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -195,6 +195,54 @@ Ref BasicBlock::GetImmediateDominator() const } +set> BasicBlock::GetDominatorTreeChildren() const +{ + size_t count; + BNBasicBlock** blocks = BNGetBasicBlockDominatorTreeChildren(m_object, &count); + + set> result; + for (size_t i = 0; i < count; i++) + result.insert(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +set> BasicBlock::GetDominanceFrontier() const +{ + size_t count; + BNBasicBlock** blocks = BNGetBasicBlockDominanceFrontier(m_object, &count); + + set> result; + for (size_t i = 0; i < count; i++) + result.insert(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +set> BasicBlock::GetIteratedDominanceFrontier(const set>& blocks) +{ + BNBasicBlock** blockSet = new BNBasicBlock*[blocks.size()]; + size_t i = 0; + for (auto& j : blocks) + blockSet[i++] = j->GetObject(); + + size_t count; + BNBasicBlock** resultBlocks = BNGetBasicBlockIteratedDominanceFrontier(blockSet, blocks.size(), &count); + delete[] blockSet; + + set> result; + for (size_t i = 0; i < count; i++) + result.insert(new BasicBlock(BNNewBasicBlockReference(resultBlocks[i]))); + + BNFreeBasicBlockList(resultBlocks, count); + return result; +} + + void BasicBlock::MarkRecentUse() { BNMarkBasicBlockAsRecentlyUsed(m_object); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 6a23fd13..6b69c95f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1784,6 +1784,9 @@ namespace BinaryNinja std::set> GetDominators() const; std::set> GetStrictDominators() const; Ref GetImmediateDominator() const; + std::set> GetDominatorTreeChildren() const; + std::set> GetDominanceFrontier() const; + static std::set> GetIteratedDominanceFrontier(const std::set>& blocks); void MarkRecentUse(); diff --git a/binaryninjacore.h b/binaryninjacore.h index 239d1002..d1c7f4d2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1731,6 +1731,10 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominators(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockStrictDominators(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI BNBasicBlock* BNGetBasicBlockImmediateDominator(BNBasicBlock* block); + BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominatorTreeChildren(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominanceFrontier(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockIteratedDominanceFrontier(BNBasicBlock** blocks, + size_t incomingCount, size_t* outputCount); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); diff --git a/python/basicblock.py b/python/basicblock.py index e332cc3c..9f256aa7 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -169,6 +169,28 @@ class BasicBlock(object): return None return BasicBlock(self.view, result) + @property + def dominator_tree_children(self): + """List of child blocks in the dominator tree for this basic block (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def dominance_frontier(self): + """Dominance frontier for this basic block (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + core.BNFreeBasicBlockList(blocks, count.value) + return result + @property def annotations(self): """List of automatic annotations for the start of this block (read-only)""" @@ -208,6 +230,21 @@ class BasicBlock(object): def highlight(self, value): self.set_user_highlight(value) + @classmethod + def get_iterated_dominance_frontier(self, blocks): + if len(blocks) == 0: + return [] + block_set = (ctypes.POINTER(core.BNBasicBlock) * len(blocks))() + for i in xrange(len(blocks)): + block_set[i] = blocks[i].handle + count = ctypes.c_ulonglong() + out_blocks = core.BNGetBasicBlockIteratedDominanceFrontier(block_set, len(blocks), count) + result = [] + for i in xrange(0, count.value): + result.append(BasicBlock(blocks[0].view, core.BNNewBasicBlockReference(out_blocks[i]))) + core.BNFreeBasicBlockList(out_blocks, count.value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) -- cgit v1.3.1 From c687ea8692ee553476280ee5b621e861b627fa80 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 22 Feb 2017 00:24:14 -0500 Subject: Add SSA form APIs --- binaryninjaapi.h | 1 + binaryninjacore.h | 49 ++++++++++++++++++++++++++++++++++------------- function.cpp | 6 ++++++ python/function.py | 5 +++++ python/lowlevelil.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 97 insertions(+), 18 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 6b69c95f..188471b3 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1887,6 +1887,7 @@ namespace BinaryNinja void SetCommentForAddress(uint64_t addr, const std::string& comment); Ref GetLowLevelIL() const; + Ref GetLowLevelILSSAForm() const; size_t GetLowLevelILForInstruction(Architecture* arch, uint64_t addr); std::vector GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr); RegisterValue GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg); diff --git a/binaryninjacore.h b/binaryninjacore.h index d1c7f4d2..c1e7d6f9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -238,17 +238,17 @@ extern "C" enum BNLowLevelILOperation { LLIL_NOP, - LLIL_SET_REG, - LLIL_SET_REG_SPLIT, - LLIL_SET_FLAG, - LLIL_LOAD, - LLIL_STORE, - LLIL_PUSH, - LLIL_POP, - LLIL_REG, + 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_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_CONST, - LLIL_FLAG, - LLIL_FLAG_BIT, + 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, LLIL_ADC, LLIL_SUB, @@ -285,7 +285,7 @@ extern "C" LLIL_NORET, LLIL_IF, LLIL_GOTO, - LLIL_FLAG_COND, + LLIL_FLAG_COND, // Valid only in Lifted IL LLIL_CMP_E, LLIL_CMP_NE, LLIL_CMP_SLT, @@ -303,7 +303,28 @@ extern "C" LLIL_TRAP, LLIL_UNDEF, LLIL_UNIMPL, - LLIL_UNIMPL_MEM + LLIL_UNIMPL_MEM, + + // The following instructions are only used in SSA form + LLIL_SET_REG_SSA, + LLIL_SET_REG_SSA_PARTIAL, + LLIL_SET_REG_SPLIT_SSA, + LLIL_REG_SPLIT_DEST_SSA, // Only valid within an LLIL_SET_REG_SPLIT_SSA instruction + LLIL_REG_SSA, + LLIL_REG_SSA_PARTIAL, + 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_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_REG_PHI, + LLIL_FLAG_PHI, + LLIL_MEM_PHI }; enum BNLowLevelILFlagCondition @@ -341,7 +362,8 @@ extern "C" { NormalFunctionGraph = 0, LowLevelILFunctionGraph = 1, - LiftedILFunctionGraph = 2 + LiftedILFunctionGraph = 2, + LowLevelILSSAFormFunctionGraph = 3 }; enum BNDisassemblyOption @@ -1672,6 +1694,7 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlocksStartingAtAddress(BNBinaryView* view, uint64_t addr, size_t* count); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelIL(BNFunction* func); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelILSSAForm(BNFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); diff --git a/function.cpp b/function.cpp index b1d008ee..d8a5a4a7 100644 --- a/function.cpp +++ b/function.cpp @@ -147,6 +147,12 @@ Ref Function::GetLowLevelIL() const } +Ref Function::GetLowLevelILSSAForm() const +{ + return new LowLevelILFunction(BNGetFunctionLowLevelILSSAForm(m_object)); +} + + size_t Function::GetLowLevelILForInstruction(Architecture* arch, uint64_t addr) { return BNGetLowLevelILForInstruction(m_object, arch->GetObject(), addr); diff --git a/python/function.py b/python/function.py index 86c93bf7..47099395 100644 --- a/python/function.py +++ b/python/function.py @@ -292,6 +292,11 @@ class Function(object): """Function low level IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelIL(self.handle), self) + @property + def low_level_il_ssa_form(self): + """Function low level IL in SSA form (read-only)""" + return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelILSSAForm(self.handle), self) + @property def lifted_il(self): """Function lifted IL (read-only)""" diff --git a/python/lowlevelil.py b/python/lowlevelil.py index c80fcd0d..3ce55793 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -110,7 +110,26 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_TRAP: [("value", "int")], LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], - LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")] + LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")], + LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")], + LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")], + LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")], + LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")], + LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], + 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"), ("index", "int"), ("src_memory", "int")], + LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("dest", "reg_ssa_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"), ("index", "int"), ("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")], + LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } def __init__(self, func, expr_index, instr_index=None): @@ -142,16 +161,41 @@ class LowLevelILInstruction(object): else: value = func.arch.get_reg_name(instr.operands[i]) elif operand_type == "flag": - value = func.arch.get_flag_name(instr.operands[i]) + if (instr.operands[i] & 0x80000000) != 0: + value = instr.operands[i] + else: + value = func.arch.get_flag_name(instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() - operands = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) value = [] for i in xrange(count.value): - value.append(operands[i]) - core.BNLowLevelILFreeOperandList(operands) + value.append(operand_list[i]) + 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) + value = [] + for i in xrange(count.value / 2): + reg = operand_list[i * 2] + reg_index = operand_list[(i * 2) + 1] + if (reg & 0x80000000) == 0: + reg = func.arch.get_reg_name(reg) + value.append((reg, reg_index)) + 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) + value = [] + for i in xrange(count.value / 2): + flag = operand_list[i * 2] + flag_index = operand_list[(i * 2) + 1] + if (flag & 0x80000000) == 0: + flag = func.arch.get_flag_name(flag) + value.append((flag, flag_index)) + core.BNLowLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value -- cgit v1.3.1 From 57088dfd10ebbc5361e1493c034dec8ed6730bdc Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Thu, 23 Feb 2017 02:20:55 -0500 Subject: add get_install_directory and savelastrun to the api --- binaryninjaapi.cpp | 11 +++++++++++ binaryninjaapi.h | 1 + binaryninjacore.h | 4 ++++ python/__init__.py | 9 +++++++++ 4 files changed, 25 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 6b303bcd..68cc2f43 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -59,6 +59,17 @@ void BinaryNinja::SetBundledPluginDirectory(const string& path) } +string BinaryNinja::GetInstallDirectory() +{ + char* path = BNGetInstallDirectory(); + if (!path) + return string(); + string result = path; + BNFreeString(path); + return result; +} + + string BinaryNinja::GetUserPluginDirectory() { char* path = BNGetUserPluginDirectory(); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 6b69c95f..b8b684be 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -376,6 +376,7 @@ namespace BinaryNinja void InitUserPlugins(); std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); + std::string GetInstallDirectory(); std::string GetUserPluginDirectory(); std::string GetPathRelativeToBundledPluginDirectory(const std::string& path); diff --git a/binaryninjacore.h b/binaryninjacore.h index d1c7f4d2..62889a4d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1247,10 +1247,14 @@ extern "C" // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); + BINARYNINJACOREAPI char* BNGetInstallDirectory(void); BINARYNINJACOREAPI char* BNGetBundledPluginDirectory(void); BINARYNINJACOREAPI void BNSetBundledPluginDirectory(const char* path); + BINARYNINJACOREAPI char* BNGetUserDirectory(void); BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void); + BINARYNINJACOREAPI void BNSaveLastRun(void); + BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetPathRelativeToUserPluginDirectory(const char* path); diff --git a/python/__init__.py b/python/__init__.py index b1f5cd08..dcbb8276 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -58,6 +58,15 @@ def get_unique_identifier(): return core.BNGetUniqueIdentifierString() +def get_install_directory(): + """ + ``get_install_directory`` returns a string pointing to the installed binary currently running + + .warning:: ONLY for use within the Binary Ninja UI, behavior is undefined and unreliable if run headlessly + """ + return core.BNGetInstallDirectory() + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() -- cgit v1.3.1 From dbe5606575f6b59b82eff2f9ab7b41990b57147e Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 23 Feb 2017 18:34:03 -0500 Subject: Instruction starts and SSA form are a property of IL functions --- binaryninjaapi.h | 6 ++++-- binaryninjacore.h | 8 ++++++-- function.cpp | 6 ------ lowlevelil.cpp | 19 +++++++++++++++++-- python/function.py | 5 ----- python/lowlevelil.py | 23 ++++++++++++++++++++++- 6 files changed, 49 insertions(+), 18 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 188471b3..9d81b198 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1887,7 +1887,6 @@ namespace BinaryNinja void SetCommentForAddress(uint64_t addr, const std::string& comment); Ref GetLowLevelIL() const; - Ref GetLowLevelILSSAForm() const; size_t GetLowLevelILForInstruction(Architecture* arch, uint64_t addr); std::vector GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr); RegisterValue GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg); @@ -2057,7 +2056,8 @@ namespace BinaryNinja LowLevelILFunction(BNLowLevelILFunction* func); uint64_t GetCurrentAddress() const; - void SetCurrentAddress(uint64_t addr); + void SetCurrentAddress(Architecture* arch, uint64_t addr); + size_t GetInstructionStart(Architecture* arch, uint64_t addr); void ClearIndirectBranches(); void SetIndirectBranches(const std::vector& branches); @@ -2158,6 +2158,8 @@ namespace BinaryNinja uint32_t GetTemporaryFlagCount(); std::vector> GetBasicBlocks() const; + + Ref GetSSAForm() const; }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index c1e7d6f9..e95f2bf3 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1694,7 +1694,6 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlocksStartingAtAddress(BNBinaryView* view, uint64_t addr, size_t* count); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelIL(BNFunction* func); - BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelILSSAForm(BNFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); @@ -1977,7 +1976,10 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); - BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, uint64_t addr); + BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNLowLevelILGetInstructionStart(BNLowLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, size_t count); @@ -2015,6 +2017,8 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetLowLevelILBasicBlockList(BNLowLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILSSAForm(BNLowLevelILFunction* func); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/function.cpp b/function.cpp index d8a5a4a7..b1d008ee 100644 --- a/function.cpp +++ b/function.cpp @@ -147,12 +147,6 @@ Ref Function::GetLowLevelIL() const } -Ref Function::GetLowLevelILSSAForm() const -{ - return new LowLevelILFunction(BNGetFunctionLowLevelILSSAForm(m_object)); -} - - size_t Function::GetLowLevelILForInstruction(Architecture* arch, uint64_t addr) { return BNGetLowLevelILForInstruction(m_object, arch->GetObject(), addr); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index bf3b980e..1a353b51 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -48,9 +48,15 @@ uint64_t LowLevelILFunction::GetCurrentAddress() const } -void LowLevelILFunction::SetCurrentAddress(uint64_t addr) +void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) { - BNLowLevelILSetCurrentAddress(m_object, addr); + BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) +{ + return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); } @@ -643,3 +649,12 @@ vector> LowLevelILFunction::GetBasicBlocks() const BNFreeBasicBlockList(blocks, count); return result; } + + +Ref LowLevelILFunction::GetSSAForm() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILSSAForm(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} diff --git a/python/function.py b/python/function.py index 47099395..86c93bf7 100644 --- a/python/function.py +++ b/python/function.py @@ -292,11 +292,6 @@ class Function(object): """Function low level IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelIL(self.handle), self) - @property - def low_level_il_ssa_form(self): - """Function low level IL in SSA form (read-only)""" - return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelILSSAForm(self.handle), self) - @property def lifted_il(self): """Function lifted IL (read-only)""" diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 3ce55793..390e4210 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -314,7 +314,12 @@ class LowLevelILFunction(object): @current_address.setter def current_address(self, value): - core.BNLowLevelILSetCurrentAddress(self.handle, value) + core.BNLowLevelILSetCurrentAddress(self.handle, self.arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self.arch + core.BNLowLevelILSetCurrentAddress(self.handle, arch.handle, value) @property def temp_reg_count(self): @@ -340,6 +345,14 @@ class LowLevelILFunction(object): core.BNFreeBasicBlockList(blocks, count.value) return result + @property + def ssa_form(self): + """Low level IL in SSA form (read-only)""" + result = core.BNGetLowLevelILSSAForm(self.handle) + if not result: + return None + return LowLevelILFunction(self.arch, result, self.source_function) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -373,6 +386,14 @@ class LowLevelILFunction(object): finally: core.BNFreeBasicBlockList(blocks, count.value) + def get_instruction_start(self, addr, arch = None): + if arch is None: + arch = self.arch + result = core.BNLowLevelILGetInstructionStart(self.handle, arch.handle, addr) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + def clear_indirect_branches(self): core.BNLowLevelILClearIndirectBranches(self.handle) -- cgit v1.3.1 From ba4bb6dbee0476d5c30d942ae978621af790d518 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 23 Feb 2017 22:56:47 -0500 Subject: Add APIs for definitions and uses of SSA variables --- binaryninjaapi.h | 10 +++++++ binaryninjacore.h | 12 ++++++++ lowlevelil.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ python/lowlevelil.py | 59 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9d81b198..9bdaf5f5 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2160,6 +2160,16 @@ namespace BinaryNinja std::vector> GetBasicBlocks() const; Ref GetSSAForm() const; + Ref GetNonSSAForm() const; + size_t GetSSAInstructionIndex(size_t instr) const; + size_t GetNonSSAInstructionIndex(size_t instr) const; + + size_t GetSSARegisterDefinition(uint32_t reg, size_t idx) const; + size_t GetSSAFlagDefinition(uint32_t flag, size_t idx) const; + size_t GetSSAMemoryDefinition(size_t idx) const; + std::set GetSSARegisterUses(uint32_t reg, size_t idx) const; + std::set GetSSAFlagUses(uint32_t flag, size_t idx) const; + std::set GetSSAMemoryUses(size_t idx) const; }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index e95f2bf3..f7fb2172 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2018,6 +2018,18 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetLowLevelILBasicBlockList(BNLowLevelILFunction* func, size_t* count); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILSSAForm(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILNonSSAForm(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); + + BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAMemoryDefinition(BNLowLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSARegisterUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, + size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAFlagUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, + size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t idx, size_t* count); // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 1a353b51..d09db62c 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -658,3 +658,84 @@ Ref LowLevelILFunction::GetSSAForm() const return nullptr; return new LowLevelILFunction(func); } + + +Ref LowLevelILFunction::GetNonSSAForm() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILNonSSAForm(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +size_t LowLevelILFunction::GetSSAInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t idx) const +{ + return BNGetLowLevelILSSARegisterDefinition(m_object, reg, idx); +} + + +size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t idx) const +{ + return BNGetLowLevelILSSAFlagDefinition(m_object, flag, idx); +} + + +size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +{ + return BNGetLowLevelILSSAMemoryDefinition(m_object, idx); +} + + +set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeLowLevelILInstructionList(instrs); + return result; +} + + +set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeLowLevelILInstructionList(instrs); + return result; +} + + +set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSAMemoryUses(m_object, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeLowLevelILInstructionList(instrs); + return result; +} diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 390e4210..564fef34 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -353,6 +353,14 @@ class LowLevelILFunction(object): return None return LowLevelILFunction(self.arch, result, self.source_function) + @property + def non_ssa_form(self): + """Low level IL in non-SSA (default) form (read-only)""" + result = core.BNGetLowLevelILNonSSAForm(self.handle) + if not result: + return None + return LowLevelILFunction(self.arch, result, self.source_function) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -1327,6 +1335,57 @@ class LowLevelILFunction(object): return None return LowLevelILLabel(label) + def get_ssa_instruction_index(self, instr): + return core.BNGetLowLevelILSSAInstructionIndex(self.handle, instr) + + def get_non_ssa_instruction_index(self, instr): + return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr) + + def get_ssa_reg_definition(self, reg, index): + result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_flag_definition(self, flag, index): + result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_memory_definition(self, index): + result = core.BNGetLowLevelILSSAMemoryDefinition(self.handle, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_reg_uses(self, reg, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeLowLevelILInstructionList(instrs) + return result + + def get_ssa_flag_uses(self, flag, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeLowLevelILInstructionList(instrs) + return result + + def get_ssa_memory_uses(self, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSAMemoryUses(self.handle, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeLowLevelILInstructionList(instrs) + return result + class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): -- cgit v1.3.1 From 57a3ea491d2d819ab5415d8d7bdf7e9e505808fc Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sat, 25 Feb 2017 00:25:36 -0500 Subject: Add APIs to access SSA-based data flow --- binaryninjaapi.h | 6 ++++++ binaryninjacore.h | 7 +++++++ function.cpp | 22 +++++++++++----------- lowlevelil.cpp | 21 +++++++++++++++++++++ python/lowlevelil.py | 22 ++++++++++++++++++++++ 5 files changed, 67 insertions(+), 11 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9bdaf5f5..9e8ce4c4 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1857,6 +1857,8 @@ namespace BinaryNinja int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive std::vector table; + + static RegisterValue FromAPIObject(BNRegisterValue& value); }; class FunctionGraph; @@ -2170,6 +2172,10 @@ namespace BinaryNinja std::set GetSSARegisterUses(uint32_t reg, size_t idx) const; std::set GetSSAFlagUses(uint32_t flag, size_t idx) const; std::set GetSSAMemoryUses(size_t idx) const; + + RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx); + RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); + RegisterValue GetSSAStackContents(size_t memoryIndex, int64_t offset, size_t size); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index f7fb2172..bb08c428 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2031,6 +2031,13 @@ extern "C" size_t* count); BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t idx, size_t* count); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSARegisterValue(BNLowLevelILFunction* func, + uint32_t reg, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAFlagValue(BNLowLevelILFunction* func, + uint32_t flag, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAStackContents(BNLowLevelILFunction* func, + size_t memoryIndex, int64_t offset, size_t size); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/function.cpp b/function.cpp index b1d008ee..fe119c9d 100644 --- a/function.cpp +++ b/function.cpp @@ -166,7 +166,7 @@ vector Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui } -static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value) +RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) { RegisterValue result; result.state = value.state; @@ -194,56 +194,56 @@ static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value) RegisterValue Function::GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAtInstruction(m_object, arch->GetObject(), addr, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAfterInstruction(m_object, arch->GetObject(), addr, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAtLowLevelILInstruction(m_object, i, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAfterLowLevelILInstruction(m_object, i, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAtInstruction(m_object, arch->GetObject(), addr, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAfterInstruction(m_object, arch->GetObject(), addr, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAtLowLevelILInstruction(m_object, i, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAfterLowLevelILInstruction(m_object, i, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } @@ -251,7 +251,7 @@ RegisterValue Function::GetParameterValueAtInstruction(Architecture* arch, uint6 { BNRegisterValue value = BNGetParameterValueAtInstruction(m_object, arch->GetObject(), addr, functionType ? functionType->GetObject() : nullptr, i); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } @@ -259,7 +259,7 @@ RegisterValue Function::GetParameterValueAtLowLevelILInstruction(size_t instr, T { BNRegisterValue value = BNGetParameterValueAtLowLevelILInstruction(m_object, instr, functionType ? functionType->GetObject() : nullptr, i); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index d09db62c..999e35ee 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -739,3 +739,24 @@ set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const BNFreeLowLevelILInstructionList(instrs); return result; } + + +RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t idx) +{ + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t idx) +{ + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetSSAStackContents(size_t memoryIndex, int64_t offset, size_t size) +{ + BNRegisterValue value = BNGetLowLevelILSSAStackContents(m_object, memoryIndex, offset, size); + return RegisterValue::FromAPIObject(value); +} diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 564fef34..6c664cb4 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1386,6 +1386,28 @@ class LowLevelILFunction(object): core.BNFreeLowLevelILInstructionList(instrs) return result + def get_ssa_reg_value(self, reg, index): + if isinstance(reg, str): + reg = self.arch.regs[reg].index + value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index) + result = function.RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_ssa_flag_value(self, flag, index): + if isinstance(flag, str): + flag = self.arch.get_flag_by_name(flag) + value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index) + result = function.RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_ssa_stack_contents(self, memory_index, offset, size): + value = core.BNGetLowLevelILSSAStackContents(self.handle, memory_index, offset, size) + result = function.RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): -- cgit v1.3.1 From afe6a3c1d97c1ac2fd3be04f710caa1424216edd Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 28 Feb 2017 19:01:47 -0500 Subject: Adding return address register value --- binaryninjacore.h | 3 ++- python/function.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjacore.h b/binaryninjacore.h index bb08c428..8536d56e 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -603,7 +603,8 @@ extern "C" SignedRangeValue, UnsignedRangeValue, LookupTableValue, - ComparisonResultValue + ComparisonResultValue, + ReturnAddressValue }; struct BNLookupTableEntry diff --git a/python/function.py b/python/function.py index 86c93bf7..07187080 100644 --- a/python/function.py +++ b/python/function.py @@ -101,6 +101,8 @@ class RegisterValue(object): return "" % ', '.join([repr(i) for i in self.table]) if self.type == RegisterValueType.OffsetFromUndeterminedValue: return "" % self.offset + if self.type == RegisterValueType.ReturnAddressValue: + return "" return "" -- cgit v1.3.1 From dc0f16fa9bbac0388bb844af8d9f6c3b72ec31e8 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 28 Feb 2017 20:23:20 -0500 Subject: Map expressions to SSA form and add API to query expression value --- binaryninjaapi.h | 4 ++++ binaryninjacore.h | 4 ++++ lowlevelil.cpp | 21 ++++++++++++++++++++- python/lowlevelil.py | 24 ++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9e8ce4c4..58ea890e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2165,6 +2165,8 @@ namespace BinaryNinja Ref GetNonSSAForm() const; size_t GetSSAInstructionIndex(size_t instr) const; size_t GetNonSSAInstructionIndex(size_t instr) const; + size_t GetSSAExprIndex(size_t instr) const; + size_t GetNonSSAExprIndex(size_t instr) const; size_t GetSSARegisterDefinition(uint32_t reg, size_t idx) const; size_t GetSSAFlagDefinition(uint32_t flag, size_t idx) const; @@ -2176,6 +2178,8 @@ namespace BinaryNinja RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx); RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); RegisterValue GetSSAStackContents(size_t memoryIndex, int64_t offset, size_t size); + + RegisterValue GetExprValue(size_t expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index 8536d56e..89302c64 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2022,6 +2022,8 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILNonSSAForm(BNLowLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAExprIndex(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAExprIndex(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); @@ -2039,6 +2041,8 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAStackContents(BNLowLevelILFunction* func, size_t memoryIndex, int64_t offset, size_t size); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 999e35ee..fecde9c8 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -671,7 +671,7 @@ Ref LowLevelILFunction::GetNonSSAForm() const size_t LowLevelILFunction::GetSSAInstructionIndex(size_t instr) const { - return BNGetLowLevelILNonSSAInstructionIndex(m_object, instr); + return BNGetLowLevelILSSAInstructionIndex(m_object, instr); } @@ -681,6 +681,18 @@ size_t LowLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const } +size_t LowLevelILFunction::GetSSAExprIndex(size_t expr) const +{ + return BNGetLowLevelILSSAExprIndex(m_object, expr); +} + + +size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const +{ + return BNGetLowLevelILNonSSAExprIndex(m_object, expr); +} + + size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t idx) const { return BNGetLowLevelILSSARegisterDefinition(m_object, reg, idx); @@ -760,3 +772,10 @@ RegisterValue LowLevelILFunction::GetSSAStackContents(size_t memoryIndex, int64_ BNRegisterValue value = BNGetLowLevelILSSAStackContents(m_object, memoryIndex, offset, size); return RegisterValue::FromAPIObject(value); } + + +RegisterValue LowLevelILFunction::GetExprValue(size_t expr) +{ + BNRegisterValue value = BNGetLowLevelILExprValue(m_object, expr); + return RegisterValue::FromAPIObject(value); +} diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 6c664cb4..6ed179c2 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -53,7 +53,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_PUSH: [("src", "expr")], LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], - LowLevelILOperation.LLIL_CONST: [("value", "int")], + LowLevelILOperation.LLIL_CONST: [("constant", "int")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], @@ -107,7 +107,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")], LowLevelILOperation.LLIL_SYSCALL: [], LowLevelILOperation.LLIL_BP: [], - LowLevelILOperation.LLIL_TRAP: [("value", "int")], + LowLevelILOperation.LLIL_TRAP: [("vector", "int")], LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], @@ -237,6 +237,26 @@ class LowLevelILInstruction(object): core.BNFreeInstructionText(tokens, count.value) return result + @property + def ssa_form(self): + """SSA form of expression (read-only)""" + return LowLevelILInstruction(self.function.ssa_form, + core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def non_ssa_form(self): + """Non-SSA form of expression (read-only)""" + return LowLevelILInstruction(self.function.non_ssa_form, + core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def value(self): + """Value of expression using static data flow analysis (read-only)""" + value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) -- cgit v1.3.1 From 94b38cee51eff16f1e79945806088c7ae60016d7 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 1 Mar 2017 03:45:51 -0500 Subject: Adding framework for medium level IL --- binaryninjaapi.h | 70 +++++++ binaryninjacore.h | 174 +++++++++++++++- function.cpp | 12 +- lowlevelil.cpp | 6 +- mediumlevelil.cpp | 378 ++++++++++++++++++++++++++++++++++ python/__init__.py | 1 + python/function.py | 20 +- python/lowlevelil.py | 8 +- python/mediumlevelil.py | 525 ++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1179 insertions(+), 15 deletions(-) create mode 100644 mediumlevelil.cpp create mode 100644 python/mediumlevelil.py (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 58ea890e..1367e7c1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1862,6 +1862,7 @@ namespace BinaryNinja }; class FunctionGraph; + class MediumLevelILFunction; class Function: public CoreRefCountObject { @@ -1913,6 +1914,8 @@ namespace BinaryNinja std::set GetFlagsReadByLiftedILInstruction(size_t i); std::set GetFlagsWrittenByLiftedILInstruction(size_t i); + Ref GetMediumLevelIL() const; + Ref GetType() const; void SetAutoType(Type* type); void SetUserType(Type* type); @@ -2182,6 +2185,73 @@ namespace BinaryNinja RegisterValue GetExprValue(size_t expr); }; + struct MediumLevelILLabel: public BNMediumLevelILLabel + { + MediumLevelILLabel(); + }; + + class MediumLevelILFunction: public CoreRefCountObject + { + public: + MediumLevelILFunction(Architecture* arch, Function* func = nullptr); + MediumLevelILFunction(BNMediumLevelILFunction* func); + + uint64_t GetCurrentAddress() const; + void SetCurrentAddress(Architecture* arch, uint64_t addr); + size_t GetInstructionStart(Architecture* arch, uint64_t addr); + + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddInstruction(ExprId expr); + + ExprId SetVar(size_t size, const BNILVariable& var, ExprId src); + ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src); + ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src); + ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex, ExprId src); + ExprId Var(size_t size, const BNILVariable& var); + ExprId VarField(size_t size, const BNILVariable& var, int64_t offset); + ExprId VarSSA(size_t size, const BNILVariable& var, size_t index); + ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex); + + ExprId Goto(BNMediumLevelILLabel& label); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + void MarkLabel(BNMediumLevelILLabel& label); + + std::vector GetOperandList(ExprId i, size_t listOperand); + ExprId AddLabelList(const std::vector& labels); + ExprId AddOperandList(const std::vector operands); + + BNILVariable GetVariable(ExprId i, size_t varOperand); + + BNMediumLevelILInstruction operator[](size_t i) const; + size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionCount() const; + + void Finalize(); + + bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); + bool GetInstructionText(Function* func, Architecture* arch, size_t i, + std::vector& tokens); + + std::vector> GetBasicBlocks() const; + + Ref GetSSAForm() const; + Ref GetNonSSAForm() const; + size_t GetSSAInstructionIndex(size_t instr) const; + size_t GetNonSSAInstructionIndex(size_t instr) const; + size_t GetSSAExprIndex(size_t instr) const; + size_t GetNonSSAExprIndex(size_t instr) const; + + size_t GetSSAVarDefinition(const BNILVariable& var, size_t idx) const; + size_t GetSSAMemoryDefinition(size_t idx) const; + std::set GetSSAVarUses(const BNILVariable& var, size_t idx) const; + std::set GetSSAMemoryUses(size_t idx) const; + + RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); + RegisterValue GetExprValue(size_t expr); + }; + class FunctionRecognizer { static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il); diff --git a/binaryninjacore.h b/binaryninjacore.h index 89302c64..aa9bb49b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,6 +92,7 @@ extern "C" struct BNSymbol; struct BNTemporaryFile; struct BNLowLevelILFunction; + struct BNMediumLevelILFunction; struct BNType; struct BNStructure; struct BNNamedTypeReference; @@ -363,7 +364,9 @@ extern "C" NormalFunctionGraph = 0, LowLevelILFunctionGraph = 1, LiftedILFunctionGraph = 2, - LowLevelILSSAFormFunctionGraph = 3 + LowLevelILSSAFormFunctionGraph = 3, + MediumLevelILFunctionGraph = 4, + MediumLevelILSSAFormFunctionGraph = 5 }; enum BNDisassemblyOption @@ -637,6 +640,115 @@ extern "C" bool autoDiscovered; }; + enum BNMediumLevelILOperation + { + MLIL_NOP, + MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA) + MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) + MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) + MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_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_CONST, + MLIL_ADD, + MLIL_ADC, + MLIL_SUB, + MLIL_SBB, + MLIL_AND, + MLIL_OR, + MLIL_XOR, + MLIL_LSL, + MLIL_LSR, + MLIL_ASR, + MLIL_ROL, + MLIL_RLC, + MLIL_ROR, + MLIL_RRC, + MLIL_MUL, + MLIL_MULU_DP, + MLIL_MULS_DP, + MLIL_DIVU, + MLIL_DIVU_DP, + MLIL_DIVS, + MLIL_DIVS_DP, + MLIL_MODU, + MLIL_MODU_DP, + MLIL_MODS, + MLIL_MODS_DP, + MLIL_NEG, + MLIL_NOT, + MLIL_SX, + MLIL_ZX, + MLIL_JUMP, + MLIL_JUMP_TO, + MLIL_CALL, + MLIL_RET, + MLIL_NORET, + MLIL_IF, + MLIL_GOTO, + MLIL_CMP_E, + MLIL_CMP_NE, + MLIL_CMP_SLT, + MLIL_CMP_ULT, + MLIL_CMP_SLE, + MLIL_CMP_ULE, + MLIL_CMP_SGE, + MLIL_CMP_UGE, + MLIL_CMP_SGT, + MLIL_CMP_UGT, + MLIL_TEST_BIT, + MLIL_BOOL_TO_INT, + MLIL_SYSCALL, + MLIL_BP, + MLIL_TRAP, + MLIL_UNDEF, + MLIL_UNIMPL, + MLIL_UNIMPL_MEM, + + // The following instructions are only used in SSA form + MLIL_SET_VAR_SSA, + MLIL_SET_VAR_SSA_FIELD, + MLIL_VAR_SSA, + MLIL_VAR_SSA_FIELD, + MLIL_CALL_SSA, + MLIL_SYSCALL_SSA, + MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + MLIL_LOAD_SSA, + MLIL_STORE_SSA, + MLIL_VAR_PHI, + MLIL_MEM_PHI + }; + + struct BNMediumLevelILInstruction + { + BNMediumLevelILOperation operation; + size_t size; + uint64_t operands[5]; + uint64_t address; + }; + + struct BNMediumLevelILLabel + { + bool resolved; + size_t ref; + size_t operand; + }; + + enum BNILVariableSourceType + { + RegisterVariableSourceType, + FlagVariableSourceType, + StackVariableSourceType + }; + + struct BNILVariable + { + BNILVariableSourceType type; + uint32_t index; + int64_t identifier; + }; + // Callbacks struct BNLogListener { @@ -1698,7 +1810,8 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); - BINARYNINJACOREAPI void BNFreeLowLevelILInstructionList(size_t* list); + BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch, @@ -2043,6 +2156,63 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + // Medium-level IL + BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, + size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, + BNMediumLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNMediumLevelILAddOperandList(BNMediumLevelILFunction* func, + uint64_t* operands, size_t count); + BINARYNINJACOREAPI uint64_t* BNMediumLevelILGetOperandList(BNMediumLevelILFunction* func, size_t expr, + size_t operand, size_t* count); + BINARYNINJACOREAPI void BNMediumLevelILFreeOperandList(uint64_t* operands); + + BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, + BNInstructionTextToken** tokens, size_t* count); + BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, + BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); + + BINARYNINJACOREAPI BNBasicBlock** BNGetMediumLevelILBasicBlockList(BNMediumLevelILFunction* func, size_t* count); + + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILNonSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t idx); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNILVariable* var, + size_t idx, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, + size_t idx, size_t* count); + + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/function.cpp b/function.cpp index fe119c9d..9faf68fa 100644 --- a/function.cpp +++ b/function.cpp @@ -161,7 +161,7 @@ vector Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui vector result; result.insert(result.end(), exits, &exits[count]); - BNFreeLowLevelILInstructionList(exits); + BNFreeILInstructionList(exits); return result; } @@ -343,7 +343,7 @@ set Function::GetLiftedILFlagUsesForDefinition(size_t i, uint32_t flag) set result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -355,7 +355,7 @@ set Function::GetLiftedILFlagDefinitionsForUse(size_t i, uint32_t flag) set result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -384,6 +384,12 @@ set Function::GetFlagsWrittenByLiftedILInstruction(size_t i) } +Ref Function::GetMediumLevelIL() const +{ + return new MediumLevelILFunction(BNGetFunctionMediumLevelIL(m_object)); +} + + Ref Function::GetType() const { return new Type(BNGetFunctionType(m_object)); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index fecde9c8..5a789981 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -720,7 +720,7 @@ set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) con for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -734,7 +734,7 @@ set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -748,7 +748,7 @@ set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp new file mode 100644 index 00000000..f6ad5bfd --- /dev/null +++ b/mediumlevelil.cpp @@ -0,0 +1,378 @@ +// Copyright (c) 2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +MediumLevelILLabel::MediumLevelILLabel() +{ + BNMediumLevelILInitLabel(this); +} + + +MediumLevelILFunction::MediumLevelILFunction(Architecture* arch, Function* func) +{ + m_object = BNCreateMediumLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr); +} + + +MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) +{ + m_object = func; +} + + +uint64_t MediumLevelILFunction::GetCurrentAddress() const +{ + return BNMediumLevelILGetCurrentAddress(m_object); +} + + +void MediumLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) +{ + BNMediumLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) +{ + return BNMediumLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddInstruction(size_t expr) +{ + return BNMediumLevelILAddInstruction(m_object, expr); +} + + +ExprId MediumLevelILFunction::SetVar(size_t size, const BNILVariable& var, ExprId src) +{ + return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, src); +} + + +ExprId MediumLevelILFunction::SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, size_t varIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + varIndex, src); +} + + +ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, + size_t varIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, varIndex, src); +} + + +ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var) +{ + return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); +} + + +ExprId MediumLevelILFunction::VarField(size_t size, const BNILVariable& var, int64_t offset) +{ + return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset); +} + + +ExprId MediumLevelILFunction::VarSSA(size_t size, const BNILVariable& var, size_t varIndex) +{ + return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex); +} + + +ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, + size_t varIndex) +{ + return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, varIndex); +} + + +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) +{ + return BNMediumLevelILGoto(m_object, &label); +} + + +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +{ + return BNMediumLevelILIf(m_object, operand, &t, &f); +} + + +void MediumLevelILFunction::MarkLabel(BNMediumLevelILLabel& label) +{ + BNMediumLevelILMarkLabel(m_object, &label); +} + + +vector MediumLevelILFunction::GetOperandList(ExprId expr, size_t listOperand) +{ + size_t count; + uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count); + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(operands[i]); + BNMediumLevelILFreeOperandList(operands); + return result; +} + + +ExprId MediumLevelILFunction::AddLabelList(const vector& labels) +{ + BNMediumLevelILLabel** labelList = new BNMediumLevelILLabel*[labels.size()]; + for (size_t i = 0; i < labels.size(); i++) + labelList[i] = labels[i]; + ExprId result = (ExprId)BNMediumLevelILAddLabelList(m_object, labelList, labels.size()); + delete[] labelList; + return result; +} + + +ExprId MediumLevelILFunction::AddOperandList(const vector operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +BNILVariable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) +{ + BNMediumLevelILInstruction instr = (*this)[i]; + BNILVariable result; + result.type = (BNILVariableSourceType)(instr.operands[varOperand] >> 32); + result.index = (uint32_t)instr.operands[varOperand]; + result.identifier = instr.operands[varOperand + 1]; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +{ + return BNGetMediumLevelILByIndex(m_object, i); +} + + +size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const +{ + return BNGetMediumLevelILIndexForInstruction(m_object, i); +} + + +size_t MediumLevelILFunction::GetInstructionCount() const +{ + return BNGetMediumLevelILInstructionCount(m_object); +} + + +void MediumLevelILFunction::Finalize() +{ + BNFinalizeMediumLevelILFunction(m_object); +} + + +bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILExprText(m_object, arch->GetObject(), expr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arch, size_t instr, + vector& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILInstructionText(m_object, func ? func->GetObject() : nullptr, arch->GetObject(), + instr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +vector> MediumLevelILFunction::GetBasicBlocks() const +{ + size_t count; + BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count); + + vector> result; + for (size_t i = 0; i < count; i++) + result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +Ref MediumLevelILFunction::GetSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +Ref MediumLevelILFunction::GetNonSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILNonSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +size_t MediumLevelILFunction::GetSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILNonSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetSSAVarDefinition(const BNILVariable& var, size_t idx) const +{ + return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx); +} + + +size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +{ + return BNGetMediumLevelILSSAMemoryDefinition(m_object, idx); +} + + +set MediumLevelILFunction::GetSSAVarUses(const BNILVariable& var, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +RegisterValue MediumLevelILFunction::GetSSAVarValue(const BNILVariable& var, size_t idx) +{ + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) +{ + BNRegisterValue value = BNGetMediumLevelILExprValue(m_object, expr); + return RegisterValue::FromAPIObject(value); +} diff --git a/python/__init__.py b/python/__init__.py index b1f5cd08..7502d205 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -32,6 +32,7 @@ from .basicblock import * from .function import * from .log import * from .lowlevelil import * +from .mediumlevelil import * from .types import * from .functionrecognizer import * from .update import * diff --git a/python/function.py b/python/function.py index 07187080..ed2a537c 100644 --- a/python/function.py +++ b/python/function.py @@ -33,6 +33,7 @@ import associateddatastore import types import basicblock import lowlevelil +import mediumlevelil import binaryview import log @@ -139,6 +140,14 @@ class StackVariableReference(object): return "" % (self.source_operand, self.name) +class ILVariable(object): + def __init__(self, func, var_type, index, identifier): + self.function = func + self.type = var_type + self.index = index + self.identifier = identifier + + class ConstantReference(object): def __init__(self, val, size): self.value = val @@ -299,6 +308,11 @@ class Function(object): """Function lifted IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) + @property + def medium_level_il(self): + """Function medium level IL (read-only)""" + return mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self) + @property def function_type(self): """Function type object""" @@ -398,7 +412,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(exits[i]) - core.BNFreeLowLevelILInstructionList(exits) + core.BNFreeILInstructionList(exits) return result def get_reg_value_at(self, addr, reg, arch=None): @@ -597,7 +611,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_lifted_il_flag_definitions_for_use(self, i, flag): @@ -608,7 +622,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_flags_read_by_lifted_il_instruction(self, i): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 6ed179c2..ed1cedd4 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -124,7 +124,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")], - LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("dest", "reg_ssa_list")], + LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_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"), ("index", "int"), ("src", "reg_ssa_list")], @@ -1385,7 +1385,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_flag_uses(self, flag, index): @@ -1394,7 +1394,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_memory_uses(self, index): @@ -1403,7 +1403,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_reg_value(self, reg, index): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py new file mode 100644 index 00000000..c4c4aa23 --- /dev/null +++ b/python/mediumlevelil.py @@ -0,0 +1,525 @@ +# Copyright (c) 2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType +import function +import basicblock + + +class MediumLevelILLabel(object): + def __init__(self, handle = None): + if handle is None: + self.handle = (core.BNMediumLevelILLabel * 1)() + core.BNMediumLevelILInitLabel(self.handle) + else: + self.handle = handle + + +class MediumLevelILInstruction(object): + """ + ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based + instructions. Tree-based instructions use infix notation with the left hand operand being the destination operand. + Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. MLIL ``eax = 0``). + """ + + ILOperations = { + MediumLevelILOperation.MLIL_NOP: [], + MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], + MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR: [("src", "var")], + MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_CONST: [("constant", "int")], + MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], + 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_DIVS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_NEG: [("src", "expr")], + MediumLevelILOperation.MLIL_NOT: [("src", "expr")], + MediumLevelILOperation.MLIL_SX: [("src", "expr")], + MediumLevelILOperation.MLIL_ZX: [("src", "expr")], + MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], + MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + MediumLevelILOperation.MLIL_CALL: [("dest", "expr")], + MediumLevelILOperation.MLIL_RET: [], + MediumLevelILOperation.MLIL_NORET: [], + MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], + MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], + MediumLevelILOperation.MLIL_CMP_E: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_NE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_SYSCALL: [], + MediumLevelILOperation.MLIL_BP: [], + MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], + MediumLevelILOperation.MLIL_UNDEF: [], + MediumLevelILOperation.MLIL_UNIMPL: [], + MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], + MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], + MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] + } + + def __init__(self, func, expr_index, instr_index=None): + instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) + self.function = func + self.expr_index = expr_index + self.instr_index = instr_index + self.operation = MediumLevelILOperation(instr.operation) + self.size = instr.size + self.address = instr.address + operands = MediumLevelILInstruction.ILOperations[instr.operation] + self.operands = [] + i = 0 + while i < len(operands): + name, operand_type = operands[i] + if operand_type == "int": + value = instr.operands[i] + elif operand_type == "expr": + value = MediumLevelILInstruction(func, instr.operands[i]) + elif operand_type == "var": + var_type = ILVariableSourceType(instr.operands[i] >> 32) + index = instr.operands[i] & 0xffffffff + identifier = instr.operands[i + 1] + i += 1 + value = function.ILVariable(self.function, var_type, index, identifier) + elif operand_type == "int_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + value = [] + for i in xrange(count.value): + value.append(operand_list[i]) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "var_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value / 3): + var_type = ILVariableSourceType(operand_list[j * 3] >> 32) + index = operand_list[j * 3] & 0xffffffff + identifier = operand_list[(j * 3) + 1] + var_index = operand_list[(j * 3) + 2] + value.append((function.ILVariable(self.function, var_type, index, identifier), var_index)) + core.BNMediumLevelILFreeOperandList(operand_list) + self.operands.append(value) + self.__dict__[name] = value + + def __str__(self): + tokens = self.tokens + if tokens is None: + return "invalid" + result = "" + for token in tokens: + result += token.text + return result + + def __repr__(self): + return "" % str(self) + + @property + def tokens(self): + """MLIL tokens (read-only)""" + count = ctypes.c_ulonglong() + tokens = ctypes.POINTER(core.BNInstructionTextToken)() + if (self.instr_index is not None) and (self.function.source_function is not None): + if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle, + self.function.arch.handle, self.instr_index, tokens, count): + return None + else: + if not core.BNGetMediumLevelILExprText(self.function.handle, self.function.arch.handle, + self.expr_index, tokens, count): + return None + 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 + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeInstructionText(tokens, count.value) + return result + + @property + def ssa_form(self): + """SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.ssa_form, + core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def non_ssa_form(self): + """Non-SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.non_ssa_form, + core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def value(self): + """Value of expression using static data flow analysis (read-only)""" + value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + +class MediumLevelILExpr(object): + """ + ``class MediumLevelILExpr`` hold the index of IL Expressions. + + .. note:: This class shouldn't be instantiated directly. Rather the helper members of MediumLevelILFunction should be \ + used instead. + """ + def __init__(self, index): + self.index = index + + +class MediumLevelILFunction(object): + """ + ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a function. MediumLevelILExpr + objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class + methods which return MediumLevelILExpr objects. + """ + def __init__(self, arch, handle = None, source_func = None): + self.arch = arch + self.source_function = source_func + if handle is not None: + self.handle = core.handle_of_type(handle, core.BNMediumLevelILFunction) + else: + func_handle = None + if self.source_function is not None: + func_handle = self.source_function.handle + self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle) + + def __del__(self): + core.BNFreeMediumLevelILFunction(self.handle) + + def __eq__(self, value): + if not isinstance(value, MediumLevelILFunction): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, MediumLevelILFunction): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + + @property + def current_address(self): + """Current IL Address (read/write)""" + return core.BNMediumLevelILGetCurrentAddress(self.handle) + + @current_address.setter + def current_address(self, value): + core.BNMediumLevelILSetCurrentAddress(self.handle, self.arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self.arch + core.BNMediumLevelILSetCurrentAddress(self.handle, arch.handle, value) + + @property + def basic_blocks(self): + """list of MediumLevelILBasicBlock objects (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + result = [] + view = None + if self.source_function is not None: + view = self.source_function.view + for i in xrange(0, count.value): + result.append(MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def ssa_form(self): + """Medium level IL in SSA form (read-only)""" + result = core.BNGetMediumLevelILSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def non_ssa_form(self): + """Medium level IL in non-SSA (default) form (read-only)""" + result = core.BNGetMediumLevelILNonSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + def __len__(self): + return int(core.BNGetMediumLevelILInstructionCount(self.handle)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, MediumLevelILExpr): + return MediumLevelILInstruction(self, i.index) + if (i < 0) or (i >= len(self)): + raise IndexError("index out of range") + return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + view = None + if self.source_function is not None: + view = self.source_function.view + try: + for i in xrange(0, count.value): + yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + + def get_instruction_start(self, addr, arch = None): + if arch is None: + arch = self.arch + result = core.BNMediumLevelILGetInstructionStart(self.handle, arch.handle, addr) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0): + if isinstance(operation, str): + operation = MediumLevelILOperation[operation] + elif isinstance(operation, MediumLevelILOperation): + operation = operation.value + return MediumLevelILExpr(core.BNMediumLevelILAddExpr(self.handle, operation, size, a, b, c, d, e)) + + def append(self, expr): + """ + ``append`` adds the MediumLevelILExpr ``expr`` to the current MediumLevelILFunction. + + :param MediumLevelILExpr expr: the MediumLevelILExpr to add to the current MediumLevelILFunction + :return: number of MediumLevelILExpr in the current function + :rtype: int + """ + return core.BNMediumLevelILAddInstruction(self.handle, expr.index) + + def goto(self, label): + """ + ``goto`` returns a goto expression which jumps to the provided MediumLevelILLabel. + + :param MediumLevelILLabel label: Label to jump to + :return: the MediumLevelILExpr that jumps to the provided label + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILGoto(self.handle, label.handle)) + + def if_expr(self, operand, t, f): + """ + ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the MediumLevelILLabel + ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. + + :param MediumLevelILExpr operand: comparison expression to evaluate. + :param MediumLevelILLabel t: Label for the true branch + :param MediumLevelILLabel f: Label for the false branch + :return: the MediumLevelILExpr for the if expression + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILIf(self.handle, operand.index, t.handle, f.handle)) + + def mark_label(self, label): + """ + ``mark_label`` assigns a MediumLevelILLabel to the current IL address. + + :param MediumLevelILLabel label: + :rtype: None + """ + core.BNMediumLevelILMarkLabel(self.handle, label.handle) + + def add_label_list(self, labels): + """ + ``add_label_list`` returns a label list expression for the given list of MediumLevelILLabel objects. + + :param list(MediumLevelILLabel) lables: the list of MediumLevelILLabel to get a label list expression from + :return: the label list expression + :rtype: MediumLevelILExpr + """ + label_list = (ctypes.POINTER(core.BNMediumLevelILLabel) * len(labels))() + for i in xrange(len(labels)): + label_list[i] = labels[i].handle + return MediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle, label_list, len(labels))) + + def add_operand_list(self, operands): + """ + ``add_operand_list`` returns an operand list expression for the given list of integer operands. + + :param list(int) operands: list of operand numbers + :return: an operand list expression + :rtype: MediumLevelILExpr + """ + operand_list = (ctypes.c_ulonglong * len(operands))() + for i in xrange(len(operands)): + operand_list[i] = operands[i] + return MediumLevelILExpr(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands))) + + def operand(self, n, expr): + """ + ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification. + + :param int n: + :param MediumLevelILExpr expr: + :return: returns the expression ``expr`` unmodified + :rtype: MediumLevelILExpr + """ + core.BNMediumLevelILSetExprSourceOperand(self.handle, expr.index, n) + return expr + + def finalize(self): + """ + ``finalize`` ends the function and computes the list of basic blocks. + + :rtype: None + """ + core.BNFinalizeMediumLevelILFunction(self.handle) + + def get_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr) + + def get_non_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) + + def get_ssa_var_definition(self, var, index): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_memory_definition(self, index): + result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_var_uses(self, var, index): + count = ctypes.c_ulonglong() + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_memory_uses(self, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_var_value(self, var, index): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) + result = function.RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + +class MediumLevelILBasicBlock(basicblock.BasicBlock): + def __init__(self, view, handle, owner): + super(MediumLevelILBasicBlock, self).__init__(view, handle) + self.il_function = owner + + def __iter__(self): + for idx in xrange(self.start, self.end): + yield self.il_function[idx] + + def __getitem__(self, idx): + size = self.end - self.start + if idx > size or idx < -size: + raise IndexError("list index is out of range") + if idx >= 0: + return self.il_function[idx + self.start] + else: + return self.il_function[self.end + idx] -- cgit v1.3.1 From 7aab4e4a3f8f2daadd1fbd00259da5b01090d84c Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 2 Mar 2017 00:37:46 -0500 Subject: Adding MLIL instructions, moving stack contents data flow to a later stage --- binaryninjaapi.h | 6 +++++- binaryninjacore.h | 7 +++++-- lowlevelil.cpp | 7 ------- mediumlevelil.cpp | 31 +++++++++++++++++++++++++++++++ python/lowlevelil.py | 6 ------ python/mediumlevelil.py | 5 ++++- 6 files changed, 45 insertions(+), 17 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 1367e7c1..e3ba4968 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2180,7 +2180,6 @@ namespace BinaryNinja RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx); RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); - RegisterValue GetSSAStackContents(size_t memoryIndex, int64_t offset, size_t size); RegisterValue GetExprValue(size_t expr); }; @@ -2207,12 +2206,17 @@ namespace BinaryNinja ExprId SetVar(size_t size, const BNILVariable& var, ExprId src); ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src); + ExprId SetVarSplit(size_t size, const BNILVariable& high, const BNILVariable& low, ExprId src); ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src); ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex, ExprId src); + ExprId SetVarSplitSSA(size_t size, const BNILVariable& high, size_t highIndex, + const BNILVariable& low, size_t lowIndex, ExprId src); ExprId Var(size_t size, const BNILVariable& var); ExprId VarField(size_t size, const BNILVariable& var, int64_t offset); ExprId VarSSA(size_t size, const BNILVariable& var, size_t index); ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex); + ExprId AddressOf(size_t size, const BNILVariable& var); + ExprId AddressOfField(size_t size, const BNILVariable& var, int64_t offset); ExprId Goto(BNMediumLevelILLabel& label); ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); diff --git a/binaryninjacore.h b/binaryninjacore.h index aa9bb49b..d35f806c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -645,10 +645,13 @@ extern "C" MLIL_NOP, MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA) MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) + MLIL_SET_VAR_SPLIT, // Not valid in SSA form (see MLIL_SET_VAR_SPLIT_SSA) MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_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_ADDRESS_OF, + MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_ADD, MLIL_ADC, @@ -708,6 +711,8 @@ extern "C" // The following instructions are only used in SSA form MLIL_SET_VAR_SSA, MLIL_SET_VAR_SSA_FIELD, + MLIL_SET_VAR_SPLIT_SSA, + MLIL_VAR_SPLIT_DEST_SSA, MLIL_VAR_SSA, MLIL_VAR_SSA_FIELD, MLIL_CALL_SSA, @@ -2151,8 +2156,6 @@ extern "C" uint32_t reg, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAFlagValue(BNLowLevelILFunction* func, uint32_t flag, size_t idx); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAStackContents(BNLowLevelILFunction* func, - size_t memoryIndex, int64_t offset, size_t size); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 5a789981..342effea 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -767,13 +767,6 @@ RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t idx) } -RegisterValue LowLevelILFunction::GetSSAStackContents(size_t memoryIndex, int64_t offset, size_t size) -{ - BNRegisterValue value = BNGetLowLevelILSSAStackContents(m_object, memoryIndex, offset, size); - return RegisterValue::FromAPIObject(value); -} - - RegisterValue LowLevelILFunction::GetExprValue(size_t expr) { BNRegisterValue value = BNGetLowLevelILExprValue(m_object, expr); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index f6ad5bfd..8c97db61 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -86,6 +86,13 @@ ExprId MediumLevelILFunction::SetVarField(size_t size, const BNILVariable& var, } +ExprId MediumLevelILFunction::SetVarSplit(size_t size, const BNILVariable& high, const BNILVariable& low, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SPLIT, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, high.identifier, + ((uint64_t)low.type << 32) | (uint64_t)low.index, low.identifier, src); +} + + ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, size_t varIndex, ExprId src) { return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, @@ -101,6 +108,17 @@ ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& va } +ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const BNILVariable& high, size_t highIndex, + const BNILVariable& low, size_t lowIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SPLIT_SSA, size, + AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, + high.identifier, highIndex), + AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)low.type << 32) | (uint64_t)low.index, + low.identifier, lowIndex), src); +} + + ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var) { return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); @@ -127,6 +145,19 @@ ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, } +ExprId MediumLevelILFunction::AddressOf(size_t size, const BNILVariable& var) +{ + return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); +} + + +ExprId MediumLevelILFunction::AddressOfField(size_t size, const BNILVariable& var, int64_t offset) +{ + return AddExpr(MLIL_ADDRESS_OF_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, + var.identifier, offset); +} + + ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) { return BNMediumLevelILGoto(m_object, &label); diff --git a/python/lowlevelil.py b/python/lowlevelil.py index ed1cedd4..40cb964c 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1422,12 +1422,6 @@ class LowLevelILFunction(object): core.BNFreeRegisterValue(value) return result - def get_ssa_stack_contents(self, memory_index, offset, size): - value = core.BNGetLowLevelILSSAStackContents(self.handle, memory_index, offset, size) - result = function.RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index c4c4aa23..839c45ce 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -47,6 +47,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_NOP: [], MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT: [("high", "var"), ("low", "var"), ("src", "expr")], MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR: [("src", "var")], @@ -108,12 +109,14 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SPLIT_DEST_SSA: [("dest", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")], MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], - MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], -- cgit v1.3.1 From a0132eed82d28d4408a2475847e1804a157b3dc1 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 4 Mar 2017 18:11:43 -0500 Subject: Adding repo manager APIs --- binaryninjaapi.cpp | 4 + binaryninjaapi.h | 83 +++++++++++ binaryninjacore.h | 117 +++++++++++++++- pluginmanager.cpp | 261 +++++++++++++++++++++++++++++++++++ python/__init__.py | 1 + python/pluginmanager.py | 359 ++++++++++++++++++++++++++++++++++++++++++++++++ python/startup.py | 1 + 7 files changed, 825 insertions(+), 1 deletion(-) create mode 100644 pluginmanager.cpp create mode 100644 python/pluginmanager.py (limited to 'python') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index e1dab528..1864e389 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -41,6 +41,10 @@ void BinaryNinja::InitUserPlugins() BNInitUserPlugins(); } +void BinaryNinja::InitRepoPlugins() +{ + BNInitRepoPlugins(); +} string BinaryNinja::GetBundledPluginDirectory() { diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a918fc42..0ba18f05 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -341,6 +341,7 @@ namespace BinaryNinja void InitCorePlugins(); void InitUserPlugins(); + void InitRepoPlugins(); std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); std::string GetUserPluginDirectory(); @@ -2425,4 +2426,86 @@ namespace BinaryNinja virtual BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon) = 0; }; + + typedef BNPluginOrigin PluginOrigin; + typedef BNPluginUpdateStatus PluginUpdateStatus; + typedef BNPluginType PluginType; + typedef BNRepositoryManifest RepositoryManifest; + + class RepoPlugin: public CoreRefCountObject + { + public: + RepoPlugin(const std::string& path, + bool installed, + bool enabled, + const std::string& api, + const std::string& author, + const std::string& description, + const std::string& license, + const std::string& licenseText, + const std::string& longdescription, + const std::string& minimimVersions, + const std::string& name, + const std::vector& pluginTypes, + const std::string& url, + const std::string& version); + RepoPlugin(BNRepoPlugin* plugin); + std::string GetPath() const; + bool IsInstalled() const; + std::string GetPluginDirectory() const; + void SetEnabled(bool enabled); + bool IsEnabled() const; + PluginUpdateStatus GetPluginUpdateStatus() const; + std::string GetApi() const; + std::string GetAuthor() const; + std::string GetDescription() const; + std::string GetLicense() const; + std::string GetLicenseText() const; + std::string GetLongdescription() const; + std::string GetMinimimVersions() const; + std::string GetName() const; + std::vector GetPluginTypes() const; + std::string GetUrl() const; + std::string GetVersion() const; + }; + + class Repository: public CoreRefCountObject + { + public: + Repository(const std::string& url, // URL of the git repository containing the plugins + const std::string& repoPath, // Name of the directory to store this repository within the repositories directory + const std::string& repoManifest="plugins", // Name of the of the inner directory and .json file + const std::string& localReference="master", + const std::string& remoteReference="origin"); + Repository(BNRepository* repository); + ~Repository(); + std::string GetUrl() const; + std::string GetRepoPath() const; + std::string GetLocalReference() const; + std::string GetRemoteReference() const; + std::vector> GetPlugins() const; + bool IsInitialized() const; + std::string GetPluginDirectory() const; + Ref GetPluginByPath(const std::string& pluginPath); + std::string GetFullPath() const; + }; + + class RepositoryManager: public CoreRefCountObject + { + bool m_core; + public: + RepositoryManager(std::vector>& repoInfo, const std::string& enabledPluginsPath); + RepositoryManager(BNRepositoryManager* repoManager); + RepositoryManager(); + ~RepositoryManager(); + bool CheckForUpdates(); + std::vector> GetRepositories(); + Ref GetRepositoryByPath(const std::string& repoName); + bool AddRepository(Ref repo); + bool EnablePlugin(const std::string& repoName, const std::string& pluginPath); + bool DisablePlugin(const std::string& repoName, const std::string& pluginPath); + bool InstallPlugin(const std::string& repoName, const std::string& pluginPath); + bool UninstallPlugin(const std::string& repoName, const std::string& pluginPath); + Ref GetDefaultRepository(); + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index b2ed7cd3..44ae666b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -45,6 +45,12 @@ #endif #endif +#ifdef WIN32 +#define PATH_SEP "\\" +#else +#define PATH_SEP "/" +#endif + #define BN_MAX_INSTRUCTION_LENGTH 256 #define BN_DEFAULT_NSTRUCTION_LENGTH 16 #define BN_DEFAULT_OPCODE_DISPLAY 8 @@ -104,6 +110,11 @@ extern "C" struct BNScriptingInstance; struct BNMainThreadAction; struct BNBackgroundTask; + struct BNRepository; + struct BNRepoPlugin; + struct BNRepositoryManager; + + typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx); //! Console log levels enum BNLogLevel @@ -567,6 +578,27 @@ extern "C" ComparisonResultValue }; + enum BNPluginOrigin + { + OfficialPluginOrigin, + CommunityPluginOrigin, + OtherPluginOrigin + }; + + enum BNPluginUpdateStatus + { + UpToDatePluginStatus, + UpdatesAvailablePluginStatus + }; + + enum BNPluginType + { + CorePluginType, + UiPluginType, + ArchitecturePluginType, + BinaryViewPluginType + }; + struct BNLookupTableEntry { int64_t* fromValues; @@ -1187,6 +1219,12 @@ extern "C" uint64_t end; }; + struct BNRepositoryManifest + { + const char* ManifestFile; + const char* RepoDirectory; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -1204,10 +1242,13 @@ extern "C" // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); + BINARYNINJACOREAPI void BNInitRepoPlugins(void); + BINARYNINJACOREAPI char* BNGetBundledPluginDirectory(void); BINARYNINJACOREAPI void BNSetBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void); - + BINARYNINJACOREAPI char* BNGetUserDirectory(void); + BINARYNINJACOREAPI char* BNGetRepositoriesDirectory(void); BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetPathRelativeToUserPluginDirectory(const char* path); @@ -2243,6 +2284,80 @@ extern "C" char*** outVarName, size_t* outVarNameElements); BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements); + + // Plugin repository APIs + BINARYNINJACOREAPI const char* BNPluginGetApi(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetAuthor(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetDescription(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLicense(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLicenseText(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLongdescription(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetMinimimVersions(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetName(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetUrl(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetVersion(BNRepoPlugin* p); + BINARYNINJACOREAPI void BNFreePluginTypes(BNPluginType* r); + BINARYNINJACOREAPI BNRepoPlugin* BNCreatePlugin(const char* path, + bool installed, + bool enabled, + const char* api, + const char* author, + const char* description, + const char* license, + const char* licenseText, + const char* longdescription, + const char* minimimVersions, + const char* name, + const BNPluginType* pluginTypes, + size_t pluginTypesSize, + const char* url, + const char* version); + BINARYNINJACOREAPI BNRepoPlugin* BNNewPluginReference(BNRepoPlugin* r); + BINARYNINJACOREAPI void BNFreePlugin(BNRepoPlugin* plugin); + BINARYNINJACOREAPI const char* BNPluginGetPath(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsInstalled(BNRepoPlugin* p); + BINARYNINJACOREAPI void BNPluginSetEnabled(BNRepoPlugin* p, bool enabled); + BINARYNINJACOREAPI bool BNPluginIsEnabled(BNRepoPlugin* p); + BINARYNINJACOREAPI BNPluginUpdateStatus BNPluginGetPluginUpdateStatus(BNRepoPlugin* p); + BINARYNINJACOREAPI BNPluginType* BNPluginGetPluginTypes(BNRepoPlugin* p, size_t* count); + BINARYNINJACOREAPI BNRepository* BNCreateRepository(const char* url, + const char* repoPath, + const char* localReference, + const char* remoteReference); + BINARYNINJACOREAPI BNRepository* BNNewRepositoryReference(BNRepository* r); + BINARYNINJACOREAPI void BNFreeRepository(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetUrl(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetRepoPath(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetLocalReference(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetRemoteReference(BNRepository* r); + BINARYNINJACOREAPI BNRepoPlugin** BNRepositoryGetPlugins(BNRepository* r, size_t* count); + BINARYNINJACOREAPI void BNFreeRepositoryPluginList(BNRepoPlugin** r); + BINARYNINJACOREAPI bool BNRepositoryIsInitialized(BNRepository* r); + BINARYNINJACOREAPI void BNRepositoryFreePluginDirectoryList(char** list, size_t count); + BINARYNINJACOREAPI BNRepoPlugin* BNRepositoryGetPluginByPath(BNRepository* r, const char* pluginPath); + BINARYNINJACOREAPI const char* BNRepositoryGetPluginsPath(BNRepository* r); + + BINARYNINJACOREAPI BNRepositoryManager* BNCreateRepositoryManager(BNRepository** repos, + size_t reposSize, + const char* enabledPluginsPath); + BINARYNINJACOREAPI BNRepositoryManager* BNNewRepositoryManagerReference(BNRepositoryManager* r); + BINARYNINJACOREAPI void BNFreeRepositoryManager(BNRepositoryManager* r); + BINARYNINJACOREAPI bool BNRepositoryManagerCheckForUpdates(BNRepositoryManager* r); + BINARYNINJACOREAPI BNRepository** BNRepositoryManagerGetRepositories(BNRepositoryManager* r, size_t* count); + BINARYNINJACOREAPI void BNFreeRepositoryManagerRepositoriesList(BNRepository** r); + BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, BNRepository* repo); + BINARYNINJACOREAPI bool BNRepositoryManagerEnablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerDisablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerInstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerUninstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerUpdatePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI BNRepository* BNRepositoryGetRepositoryByPath(BNRepositoryManager* r, const char* repoPath); + BINARYNINJACOREAPI BNRepositoryManager* BNGetRepositoryManager(); + + BINARYNINJACOREAPI BNRepository* BNRepositoryManagerGetDefaultRepository(BNRepositoryManager* r); + BINARYNINJACOREAPI void BNRegisterForPluginLoading(const char* pluginApiName, BNLoadPluginCallback cb, void* ctx); + BINARYNINJACOREAPI bool BNLoadPluginForApi(const char* pluginApiName, const char* repoPath, const char* pluginPath); + #ifdef __cplusplus } #endif diff --git a/pluginmanager.cpp b/pluginmanager.cpp new file mode 100644 index 00000000..24f6f09f --- /dev/null +++ b/pluginmanager.cpp @@ -0,0 +1,261 @@ +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + +#define RETURN_STRING(s) do { \ + char* contents = (char*)(s); \ + string result(contents); \ + BNFreeString(contents); \ + return result; \ +}while(0) + +RepoPlugin::RepoPlugin(const string& path, + bool installed, + bool enabled, + const string& api, + const string& author, + const string& description, + const string& license, + const string& licenseText, + const string& longdescription, + const string& minimimVersions, + const string& name, + const vector& pluginTypes, + const string& url, + const string& version) +{ + m_object = BNCreatePlugin(path.c_str(), + installed, + enabled, + api.c_str(), + author.c_str(), + description.c_str(), + license.c_str(), + licenseText.c_str(), + longdescription.c_str(), + minimimVersions.c_str(), + name.c_str(), + &pluginTypes[0], + pluginTypes.size(), + url.c_str(), + version.c_str()); +} + +RepoPlugin::RepoPlugin(BNRepoPlugin* plugin) +{ + m_object = plugin; +} + +string RepoPlugin::GetPath() const +{ + RETURN_STRING(BNPluginGetPath(m_object)); +} + +bool RepoPlugin::IsInstalled() const +{ + return BNPluginIsInstalled(m_object); +} + +void RepoPlugin::SetEnabled(bool enabled) +{ + return BNPluginSetEnabled(m_object, enabled); +} + +bool RepoPlugin::IsEnabled() const +{ + return BNPluginIsEnabled(m_object); +} + +PluginUpdateStatus RepoPlugin::GetPluginUpdateStatus() const +{ + return BNPluginGetPluginUpdateStatus(m_object); +} + +string RepoPlugin::GetApi() const +{ + RETURN_STRING(BNPluginGetApi(m_object)); +} + +string RepoPlugin::GetAuthor() const +{ + RETURN_STRING(BNPluginGetAuthor(m_object)); +} + +string RepoPlugin::GetDescription() const +{ + RETURN_STRING(BNPluginGetDescription(m_object)); +} + +string RepoPlugin::GetLicense() const +{ + RETURN_STRING(BNPluginGetLicense(m_object)); +} + +string RepoPlugin::GetLicenseText() const +{ + RETURN_STRING(BNPluginGetLicenseText(m_object)); +} + +string RepoPlugin::GetLongdescription() const +{ + RETURN_STRING(BNPluginGetLongdescription(m_object)); +} + +string RepoPlugin::GetMinimimVersions() const +{ + RETURN_STRING(BNPluginGetMinimimVersions(m_object)); +} + +string RepoPlugin::GetName() const +{ + RETURN_STRING(BNPluginGetName(m_object)); +} + +vector RepoPlugin::GetPluginTypes() const +{ + size_t count; + BNPluginType* pluginTypesPtr = BNPluginGetPluginTypes(m_object, &count); + vector pluginTypes; + for (size_t i = 0; i < count; i++) + { + pluginTypes.push_back((PluginType)pluginTypesPtr[i]); + } + BNFreePluginTypes(pluginTypesPtr); + return pluginTypes; +} + +string RepoPlugin::GetUrl() const +{ + RETURN_STRING(BNPluginGetUrl(m_object)); +} + +string RepoPlugin::GetVersion() const +{ + RETURN_STRING(BNPluginGetVersion(m_object)); +} + +Repository::Repository(const string& url, + const string& repoPath, + const string& repoManifest, + const string& localReference, + const string& remoteReference) +{ + m_object = BNCreateRepository(url.c_str(), + repoPath.c_str(), + localReference.c_str(), + remoteReference.c_str()); +} + +Repository::Repository(BNRepository* r) +{ + m_object = r; +} + +Repository::~Repository() +{ + BNFreeRepository(m_object); +} +string Repository::GetUrl() const +{ + RETURN_STRING(BNRepositoryGetUrl(m_object)); +} +string Repository::GetRepoPath() const +{ + RETURN_STRING(BNRepositoryGetRepoPath(m_object)); +} + +string Repository::GetLocalReference() const +{ + RETURN_STRING(BNRepositoryGetLocalReference(m_object)); +} + +string Repository::GetRemoteReference() const +{ + RETURN_STRING(BNRepositoryGetRemoteReference(m_object)); +} + +vector> Repository::GetPlugins() const +{ + vector> plugins; + size_t count = 0; + BNRepoPlugin** pluginsPtr = BNRepositoryGetPlugins(m_object, &count); + for (size_t i = 0; i < count; i++) + plugins.push_back(new RepoPlugin(BNNewPluginReference(pluginsPtr[i]))); + BNFreeRepositoryPluginList(pluginsPtr); + return plugins; +} + +bool Repository::IsInitialized() const +{ + return BNRepositoryIsInitialized(m_object); +} + +Ref Repository::GetPluginByPath(const string& pluginPath) +{ + return new RepoPlugin(BNNewPluginReference(BNRepositoryGetPluginByPath(m_object, pluginPath.c_str()))); +} + +string Repository::GetFullPath() const +{ + RETURN_STRING(BNRepositoryGetPluginsPath(m_object)); +} + +RepositoryManager::RepositoryManager(vector>& repoInfo, const string& enabledPluginsPath) + :m_core(false) +{ + BNRepository** buffer = new BNRepository*[repoInfo.size()]; + for (size_t i = 0; i < repoInfo.size(); i++) + buffer[i] = repoInfo[i]->m_object; + m_object = BNCreateRepositoryManager(buffer, repoInfo.size(), enabledPluginsPath.c_str()); + delete[] buffer; +} + +RepositoryManager::RepositoryManager(BNRepositoryManager* mgr) + :m_core(false) +{ + m_object = mgr; +} + +RepositoryManager::RepositoryManager() + :m_core(true) +{ + m_object = BNGetRepositoryManager(); +} + +RepositoryManager::~RepositoryManager() +{ + if (!m_core) + BNFreeRepositoryManager(m_object); +} + +bool RepositoryManager::CheckForUpdates() +{ + return BNRepositoryManagerCheckForUpdates(m_object); +} + +vector> RepositoryManager::GetRepositories() +{ + vector> repos; + size_t count = 0; + BNRepository** reposPtr = BNRepositoryManagerGetRepositories(m_object, &count); + for (size_t i = 0; i < count; i++) + repos.push_back(new Repository(BNNewRepositoryReference(reposPtr[i]))); + BNFreeRepositoryManagerRepositoriesList(reposPtr); + return repos; +} + +bool RepositoryManager::AddRepository(Ref repo) +{ + return BNRepositoryManagerAddRepository(m_object, repo->GetObject()); +} + +Ref RepositoryManager::GetRepositoryByPath(const std::string& repoPath) +{ + return new Repository(BNNewRepositoryReference(BNRepositoryGetRepositoryByPath(m_object, repoPath.c_str()))); +} + +Ref RepositoryManager::GetDefaultRepository() +{ + return new Repository(BNNewRepositoryReference(BNRepositoryManagerGetDefaultRepository(m_object))); +} diff --git a/python/__init__.py b/python/__init__.py index a1ea02f5..5df7c7f1 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -45,6 +45,7 @@ from .lineardisassembly import * from .undoaction import * from .highlight import * from .scriptingprovider import * +from .pluginmanager import * def shutdown(): diff --git a/python/pluginmanager.py b/python/pluginmanager.py new file mode 100644 index 00000000..348f13fb --- /dev/null +++ b/python/pluginmanager.py @@ -0,0 +1,359 @@ +# Copyright (c) 2015-2016 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from .enums import PluginType, PluginUpdateStatus +import startup + + +class RepoPlugin(object): + """ + ``Plugin`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. + """ + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNRepoPlugin) + + def __del__(self): + core.BNFreePlugin(self.handle) + + def __repr__(self): + return "<{} {}/{}>".format(self.path, "installed" if self.installed else "not-installed", "enabled" if self.enabled else "disabled") + + @property + def path(self): + """Relative path from the base of the repository to the actual plugin""" + return core.BNPluginGetPath(self.handle) + + @property + def installed(self): + """Boolean True if the plugin is installed, False otherwise""" + return core.BNPluginIsInstalled(self.handle) + + @property + def enabled(self): + """Boolean True if the plugin is currently enabled, False otherwise""" + return core.BNPluginIsEnabled(self.handle) + + @property + def api(self): + """string indicating the api used by the plugin""" + return core.BNPluginGetApi(self.handle) + + @property + def description(self): + """String short description of the plugin""" + return core.BNPluginGetDescription(self.handle) + + @property + def license(self): + """String short license description (ie MIT, BSD, GPLv2, etc)""" + return core.BNPluginGetLicense(self.handle) + + @property + def license_text(self): + """String complete license text for the given plugin""" + return core.BNPluginGetLicenseText(self.handle) + + @property + def long_description(self): + """String long description of the plugin""" + return core.BNPluginGetLongdescription(self.handle) + + @property + def minimum_version(self): + """String minimum version the plugin was tested on""" + return core.BNPluginGetMinimimVersions(self.handle) + + @property + def name(self): + """String name of the plugin""" + return core.BNPluginGetName(self.handle) + + @property + def plugin_types(self): + """List of PluginType enumeration objects indicating the plugin type(s)""" + result = [] + count = ctypes.c_ulonglong(0) + plugintypes = core.BNPluginGetPluginTypes(self.handle, count) + for i in xrange(count.value): + result.append(PluginType(plugintypes[i])) + core.BNFreePluginTypes(plugintypes) + return result + + @property + def url(self): + """String url of the plugin's git repository""" + return core.BNPluginGetUrl(self.handle) + + @property + def version(self): + """String version of the plugin""" + return core.BNPluginGetVersion(self.handle) + + @property + def update_status(self): + """PluginUpdateStatus enumeration indicating if the plugin is up to date or not""" + return PluginUpdateStatus(core.BNPluginGetPluginUpdateStatus(self.handle)) + + +class Repository(object): + """ + ``Repository`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. + """ + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNRepository) + + def __del__(self): + core.BNFreeRepository(self.handle) + + def __repr__(self): + return "<{} - {}/{}>".format(self.path, self.remote_reference, self.local_reference) + + @property + def url(self): + """String url of the git repository where the plugin repository's are stored""" + return core.BNRepositoryGetUrl(self.handle) + + @property + def path(self): + """String local path to store the given plugin repository""" + return core.BNRepositoryGetRepoPath(self.handle) + + @property + def local_reference(self): + """String for the local git reference (ie 'master')""" + return core.BNRepositoryGetLocalReference(self.handle) + + @property + def remote_reference(self): + """String for the remote git reference (ie 'origin')""" + return core.BNRepositoryGetRemoteReference(self.handle) + + @property + def plugins(self): + """List of Plugin objects contained within this repository""" + pluginlist = [] + count = ctypes.c_ulonglong(0) + result = core.BNRepositoryGetPlugins(self.handle, count) + for i in xrange(count.value): + pluginlist.append(RepoPlugin(handle=result[i])) + core.BNFreeRepositoryPluginList(result, count.value) + del result + return pluginlist + + @property + def initialized(self): + """Boolean True when the repository has been initialized""" + return core.BNRepositoryIsInitialized(self.handle) + + +class RepositoryManager(object): + def __init__(self, handle=None): + self.handle = core.BNGetRepositoryManager() + + def check_for_updates(self): + """Check for updates for all managed Repository objects""" + return core.BNRepositoryManagerCheckForUpdates(self.handle) + + @property + def repositories(self): + """List of Repository objects being managed""" + result = [] + count = ctypes.c_ulonglong(0) + repos = core.BNRepositoryManagerGetRepositories(self.handle, count) + for i in xrange(count.value): + result.append(Repository(handle=repos[i])) + core.BNFreeRepositoryManagerRepositoriesList(repos) + return result + + @property + def plugins(self): + """List of all RepoPlugins in each repository""" + plgs = {} + for repo in self.repositories: + plgs[repo.path] = repo.plugins + return plgs + + @property + def default_repository(self): + """Gets the default Repository""" + startup._init_plugins() + return Repository(handle=core.BNRepositoryManagerGetDefaultRepository(self.handle)) + + def enable_plugin(self, plugin, install=True, repo=None): + """ + ``enable_plugin`` Enables the installed plugin 'plugin', optionally installing the plugin if `install` is set to + True (default), and optionally using the non-default repository. + + :param str name: Name of the plugin to enable + :param Boolean install: Optionally install the repo, defaults to True. + :param str repo: Optional, specify a repository other than the default repository. + :return: Boolean value True if the plugin was successfully enabled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.enable_plugin('binaryninja-bookmarks') + True + >>> + """ + if install: + if not self.install_plugin(plugin, repo): + return False + + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerEnablePlugin(self.handle, repopath, pluginpath) + + def disable_plugin(self, plugin, repo=None): + """ + ``disable_plugin`` Disable the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to disable + :param Plugin or str plugin: Plugin to disable + :return: Boolean value True if the plugin was successfully disabled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.disable_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerDisablePlugin(self.handle, repopath, pluginpath) + + def install_plugin(self, plugin, repo=None): + """ + ``install_plugin`` install the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to install + :param Plugin or str plugin: Plugin to install + :return: Boolean value True if the plugin was successfully installed, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.install_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerInstallPlugin(self.handle, repopath, pluginpath) + + def uninstall_plugin(self, plugin, repo=None): + """ + ``uninstall_plugin`` uninstall the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to uninstall + :param Plugin or str plugin: Plugin to uninstall + :return: Boolean value True if the plugin was successfully uninstalled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.uninstall_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerUninstallPlugin(self.handle, repopath, pluginpath) + + def update_plugin(self, plugin, repo=None): + """ + ``update_plugin`` update the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to update + :param Plugin or str plugin: Plugin to update + :return: Boolean value True if the plugin was successfully updated, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.update_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerUpdatePlugin(self.handle, repopath, pluginpath) + + def add_repository(self, url=None, repopath=None, localreference="master", remotereference="origin"): + """ + ``add_repository`` adds a new plugin repository for the manager to track. + + :param str url: Url to the git repository where the plugins are stored. + :param str repopath: path to where the repository will be stored on disk locally + :param str localreference: Optional reference to the local tracking branch typically "master" + :param str remotereference: Optional reference to the remote tracking branch typically "origin" + :return: Boolean value True if the repository was successfully added, False otherwise. + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.add_repository(url="https://github.com/vector35/binaryninja-plugins.git", + repopath="myrepo", + repomanifest="plugins", + localreference="master", remotereference="origin") + True + >>> + """ + if not (isinstance(url, str) and isinstance(repopath, str) and + isinstance(localreference, str) and isinstance(remotereference, str)): + raise ValueError("Parameter is incorrect type") + repo = core.BNCreateRepository(url, repopath, localreference, remotereference) + + return core.BNRepositoryManagerAddRepository(self.handle, repo) diff --git a/python/startup.py b/python/startup.py index 809f185b..324cc690 100644 --- a/python/startup.py +++ b/python/startup.py @@ -30,5 +30,6 @@ def _init_plugins(): _plugin_init = True core.BNInitCorePlugins() core.BNInitUserPlugins() + core.BNInitRepoPlugins() if not core.BNIsLicenseValidated(): raise RuntimeError("License is not valid. Please supply a valid license.") -- cgit v1.3.1 From 3a95d0ae05e21775042176b8f688bafeb3f6d80f Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 7 Mar 2017 02:38:09 -0500 Subject: Add outputs and parameters for call and return, handle aliasing --- binaryninjaapi.h | 9 +++++++-- binaryninjacore.h | 25 ++++++++++++++++++------- mediumlevelil.cpp | 39 ++++++++++++++++++++++++++++++++++----- python/mediumlevelil.py | 36 +++++++++++++++++++++++++++++------- 4 files changed, 88 insertions(+), 21 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e3ba4968..f63deee1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2201,20 +2201,25 @@ namespace BinaryNinja size_t GetInstructionStart(Architecture* arch, uint64_t addr); ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, - ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0, ExprId f = 0); ExprId AddInstruction(ExprId expr); ExprId SetVar(size_t size, const BNILVariable& var, ExprId src); ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src); ExprId SetVarSplit(size_t size, const BNILVariable& high, const BNILVariable& low, ExprId src); ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src); - ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex, ExprId src); + ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, size_t varIndex, int64_t offset, ExprId src); ExprId SetVarSplitSSA(size_t size, const BNILVariable& high, size_t highIndex, const BNILVariable& low, size_t lowIndex, ExprId src); + ExprId SetVarAliased(size_t size, const BNILVariable& var, size_t destIndex, size_t srcIndex, ExprId src); + ExprId SetVarFieldAliased(size_t size, const BNILVariable& var, size_t destIndex, size_t srcIndex, + int64_t offset, ExprId src); ExprId Var(size_t size, const BNILVariable& var); ExprId VarField(size_t size, const BNILVariable& var, int64_t offset); ExprId VarSSA(size_t size, const BNILVariable& var, size_t index); ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex); + ExprId VarAliased(size_t size, const BNILVariable& var, size_t memIndex); + ExprId VarFieldAliased(size_t size, const BNILVariable& var, int64_t offset, size_t memIndex); ExprId AddressOf(size_t size, const BNILVariable& var); ExprId AddressOfField(size_t size, const BNILVariable& var, int64_t offset); diff --git a/binaryninjacore.h b/binaryninjacore.h index d35f806c..fe8382f9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -684,8 +684,11 @@ extern "C" MLIL_ZX, MLIL_JUMP, MLIL_JUMP_TO, - MLIL_CALL, - MLIL_RET, + MLIL_CALL, // Not valid in SSA form (see MLIL_CALL_SSA) + MLIL_CALL_UNTYPED, // Not valid in SSA form (see MLIL_CALL_UNTYPED_SSA) + MLIL_CALL_OUTPUT, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions + MLIL_CALL_PARAM, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions + MLIL_RET, // Not valid in SSA form (see MLIL_RET_SSA) MLIL_NORET, MLIL_IF, MLIL_GOTO, @@ -701,7 +704,8 @@ extern "C" MLIL_CMP_UGT, MLIL_TEST_BIT, MLIL_BOOL_TO_INT, - MLIL_SYSCALL, + 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_BP, MLIL_TRAP, MLIL_UNDEF, @@ -713,12 +717,19 @@ extern "C" MLIL_SET_VAR_SSA_FIELD, MLIL_SET_VAR_SPLIT_SSA, MLIL_VAR_SPLIT_DEST_SSA, + MLIL_SET_VAR_ALIASED, + MLIL_SET_VAR_ALIASED_FIELD, MLIL_VAR_SSA, MLIL_VAR_SSA_FIELD, + MLIL_VAR_ALIASED, + MLIL_VAR_ALIASED_FIELD, MLIL_CALL_SSA, + MLIL_CALL_UNTYPED_SSA, MLIL_SYSCALL_SSA, - MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions - MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + MLIL_SYSCALL_UNTYPED_SSA, + MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA family instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA family instructions + MLIL_RET_SSA, MLIL_LOAD_SSA, MLIL_STORE_SSA, MLIL_VAR_PHI, @@ -729,7 +740,7 @@ extern "C" { BNMediumLevelILOperation operation; size_t size; - uint64_t operands[5]; + uint64_t operands[6]; uint64_t address; }; @@ -2169,7 +2180,7 @@ extern "C" BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, - size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f); BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 8c97db61..f1f0bdd2 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -61,9 +61,9 @@ size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t a ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, - ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e, ExprId f) { - return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e, f); } @@ -100,11 +100,11 @@ ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, si } -ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, - size_t varIndex, ExprId src) +ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, size_t varIndex, + int64_t offset, ExprId src) { return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, - offset, varIndex, src); + varIndex, offset, src); } @@ -119,6 +119,22 @@ ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const BNILVariable& hi } +ExprId MediumLevelILFunction::SetVarAliased(size_t size, const BNILVariable& var, size_t destIndex, + size_t srcIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + destIndex, srcIndex, src); +} + + +ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const BNILVariable& var, size_t destIndex, + size_t srcIndex, int64_t offset, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + destIndex, srcIndex, offset, src); +} + + ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var) { return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); @@ -145,6 +161,19 @@ ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, } +ExprId MediumLevelILFunction::VarAliased(size_t size, const BNILVariable& var, size_t memIndex) +{ + return AddExpr(MLIL_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, memIndex); +} + + +ExprId MediumLevelILFunction::VarFieldAliased(size_t size, const BNILVariable& var, int64_t offset, size_t memIndex) +{ + return AddExpr(MLIL_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, memIndex); +} + + ExprId MediumLevelILFunction::AddressOf(size_t size, const BNILVariable& var) { return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 839c45ce..fa6371f8 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -84,8 +84,11 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ZX: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], - MediumLevelILOperation.MLIL_CALL: [("dest", "expr")], - MediumLevelILOperation.MLIL_RET: [], + MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "var_list")], + MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], + MediumLevelILOperation.MLIL_CALL_PARAM: [("src", "var_list")], + MediumLevelILOperation.MLIL_RET: [("src", "var_list")], MediumLevelILOperation.MLIL_NORET: [], MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], @@ -101,7 +104,8 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], - MediumLevelILOperation.MLIL_SYSCALL: [], + MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "var_list")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], MediumLevelILOperation.MLIL_UNDEF: [], @@ -110,11 +114,17 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], MediumLevelILOperation.MLIL_VAR_SPLIT_DEST_SSA: [("dest", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")], MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("param", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], @@ -134,8 +144,8 @@ class MediumLevelILInstruction(object): operands = MediumLevelILInstruction.ILOperations[instr.operation] self.operands = [] i = 0 - while i < len(operands): - name, operand_type = operands[i] + for operand in operands: + name, operand_type = operand if operand_type == "int": value = instr.operands[i] elif operand_type == "expr": @@ -150,8 +160,19 @@ class MediumLevelILInstruction(object): count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) value = [] - for i in xrange(count.value): - value.append(operand_list[i]) + for j in xrange(count.value): + value.append(operand_list[j]) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "var_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value / 2): + var_type = ILVariableSourceType(operand_list[j * 2] >> 32) + index = operand_list[j * 2] & 0xffffffff + identifier = operand_list[(j * 2) + 1] + value.append(function.ILVariable(self.function, var_type, index, identifier)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": count = ctypes.c_ulonglong() @@ -167,6 +188,7 @@ class MediumLevelILInstruction(object): core.BNMediumLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value + i += 1 def __str__(self): tokens = self.tokens -- cgit v1.3.1 From a51f7666462341f77e3223ff2b6ab218688dfa8c Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 7 Mar 2017 17:05:42 -0500 Subject: Use expression lists in call and return --- binaryninjacore.h | 1 - python/mediumlevelil.py | 24 +++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/binaryninjacore.h b/binaryninjacore.h index fe8382f9..1d5e10d8 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -729,7 +729,6 @@ extern "C" MLIL_SYSCALL_UNTYPED_SSA, MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA family instructions MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA family instructions - MLIL_RET_SSA, MLIL_LOAD_SSA, MLIL_STORE_SSA, MLIL_VAR_PHI, diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index fa6371f8..9f25ee97 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -52,6 +52,8 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], + MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], @@ -84,11 +86,11 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ZX: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], - MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "var_list")], + MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], MediumLevelILOperation.MLIL_CALL_PARAM: [("src", "var_list")], - MediumLevelILOperation.MLIL_RET: [("src", "var_list")], + MediumLevelILOperation.MLIL_RET: [("src", "expr_list")], MediumLevelILOperation.MLIL_NORET: [], MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], @@ -104,7 +106,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], - MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "var_list")], + MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "expr_list")], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], @@ -121,10 +123,10 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")], - MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")], - MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr"), ("stack", "expr")], - MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")], - MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("param", "expr"), ("stack", "expr")], + 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")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], @@ -186,6 +188,14 @@ class MediumLevelILInstruction(object): var_index = operand_list[(j * 3) + 2] value.append((function.ILVariable(self.function, var_type, index, identifier), var_index)) core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "expr_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value): + value.append(MediumLevelILInstruction(func, operand_list[j])) + core.BNMediumLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value i += 1 -- cgit v1.3.1 From 29be664b3c91d135b54ed34976357bb7d3413e94 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 10 Mar 2017 19:21:10 -0500 Subject: Mappings between low level IL and medium level IL --- binaryninjaapi.h | 14 ++++++++++++++ binaryninjacore.h | 26 ++++++++++++++++++++++--- lowlevelil.cpp | 36 ++++++++++++++++++++++++++++++++++ mediumlevelil.cpp | 39 +++++++++++++++++++++++++++++++++++++ python/lowlevelil.py | 45 +++++++++++++++++++++++++++++++++++++++++++ python/mediumlevelil.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f63deee1..ee342851 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2149,6 +2149,7 @@ namespace BinaryNinja BNLowLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionCount() const; + size_t GetExprCount() const; void AddLabelForAddress(Architecture* arch, ExprId addr); BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr); @@ -2182,6 +2183,11 @@ namespace BinaryNinja RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); RegisterValue GetExprValue(size_t expr); + + Ref GetMediumLevelIL() const; + Ref GetMappedMediumLevelIL() const; + size_t GetMappedMediumLevelILInstructionIndex(size_t instr) const; + size_t GetMappedMediumLevelILExprIndex(size_t expr) const; }; struct MediumLevelILLabel: public BNMediumLevelILLabel @@ -2236,6 +2242,7 @@ namespace BinaryNinja BNMediumLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionCount() const; + size_t GetExprCount() const; void Finalize(); @@ -2259,6 +2266,13 @@ namespace BinaryNinja RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); RegisterValue GetExprValue(size_t expr); + + size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; + size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; + + Ref GetLowLevelIL() const; + size_t GetLowLevelILInstructionIndex(size_t instr) const; + size_t GetLowLevelILExprIndex(size_t expr) const; }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index 1d5e10d8..66d5f010 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -60,6 +60,8 @@ #define BN_INVALID_OPERAND 0xffffffff +#define BN_INVALID_EXPR ((size_t)-1) + #define BN_DEFAULT_MIN_STRING_LENGTH 4 #define BN_MAX_STRING_LENGTH 128 @@ -366,7 +368,9 @@ extern "C" LiftedILFunctionGraph = 2, LowLevelILSSAFormFunctionGraph = 3, MediumLevelILFunctionGraph = 4, - MediumLevelILSSAFormFunctionGraph = 5 + MediumLevelILSSAFormFunctionGraph = 5, + MappedMediumLevelILFunctionGraph = 6, + MappedMediumLevelILSSAFormFunctionGraph = 7 }; enum BNDisassemblyOption @@ -727,8 +731,8 @@ extern "C" MLIL_CALL_UNTYPED_SSA, MLIL_SYSCALL_SSA, MLIL_SYSCALL_UNTYPED_SSA, - MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA family instructions - MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA family instructions + MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA family instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA family instructions MLIL_LOAD_SSA, MLIL_STORE_SSA, MLIL_VAR_PHI, @@ -2131,6 +2135,7 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func, @@ -2169,6 +2174,11 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMappedMediumLevelIL(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILExprIndex(BNLowLevelILFunction* func, size_t expr); + // Medium-level IL BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); @@ -2199,6 +2209,7 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); @@ -2226,6 +2237,15 @@ extern "C" const BNILVariable* var, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, + size_t instr); + + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 342effea..bd038b6e 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -553,6 +553,12 @@ size_t LowLevelILFunction::GetInstructionCount() const } +size_t LowLevelILFunction::GetExprCount() const +{ + return BNGetLowLevelILExprCount(m_object); +} + + void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr) { BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr); @@ -772,3 +778,33 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) BNRegisterValue value = BNGetLowLevelILExprValue(m_object, expr); return RegisterValue::FromAPIObject(value); } + + +Ref LowLevelILFunction::GetMediumLevelIL() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILForLowLevelIL(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +Ref LowLevelILFunction::GetMappedMediumLevelIL() const +{ + BNMediumLevelILFunction* func = BNGetMappedMediumLevelIL(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +size_t LowLevelILFunction::GetMappedMediumLevelILInstructionIndex(size_t instr) const +{ + return BNGetMappedMediumLevelILInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetMappedMediumLevelILExprIndex(size_t expr) const +{ + return BNGetMappedMediumLevelILExprIndex(m_object, expr); +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index f1f0bdd2..04b1cffd 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -268,6 +268,12 @@ size_t MediumLevelILFunction::GetInstructionCount() const } +size_t MediumLevelILFunction::GetExprCount() const +{ + return BNGetMediumLevelILExprCount(m_object); +} + + void MediumLevelILFunction::Finalize() { BNFinalizeMediumLevelILFunction(m_object); @@ -436,3 +442,36 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) BNRegisterValue value = BNGetMediumLevelILExprValue(m_object, expr); return RegisterValue::FromAPIObject(value); } + + +size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const +{ + return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr); +} + + +size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const +{ + return BNGetMediumLevelILSSAMemoryIndexAtILInstruction(m_object, instr); +} + + +Ref MediumLevelILFunction::GetLowLevelIL() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILForMediumLevelIL(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +size_t MediumLevelILFunction::GetLowLevelILInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const +{ + return BNGetLowLevelILExprIndex(m_object, expr); +} diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 40cb964c..462d4ade 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -25,6 +25,7 @@ import _binaryninjacore as core from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType import function import basicblock +import mediumlevelil class LowLevelILLabel(object): @@ -249,6 +250,14 @@ class LowLevelILInstruction(object): return LowLevelILInstruction(self.function.non_ssa_form, core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + @property + def mapped_medium_level_il(self): + """Gets the medium level IL expression corresponding to this expression""" + expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index) + if expr is None: + return None + return mediumlevelil.MediumLevelILInstruction(self.function.mapped_medium_level_il, expr) + @property def value(self): """Value of expression using static data flow analysis (read-only)""" @@ -381,6 +390,24 @@ class LowLevelILFunction(object): return None return LowLevelILFunction(self.arch, result, self.source_function) + @property + def medium_level_il(self): + """Medium level IL for this low level IL.""" + result = core.BNGetMediumLevelILForLowLevelIL(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def mapped_medium_level_il(self): + """Medium level IL with mappings between low level IL and medium level IL. Unused stores are not removed. + Typically, this should only be used to answer queries on assembly or low level IL where the query is + easier to perform on medium level IL.""" + result = core.BNGetMappedMediumLevelIL(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -1422,6 +1449,24 @@ class LowLevelILFunction(object): core.BNFreeRegisterValue(value) return result + def get_mapped_medium_level_il_instruction_index(self, instr): + med_il = self.mapped_medium_level_il + if med_il is None: + return None + result = core.BNGetMappedMediumLevelILInstructionIndex(self.handle, instr) + if result >= core.BNGetMediumLevelILInstructionCount(med_il.handle): + return None + return result + + def get_mapped_medium_level_il_expr_index(self, expr): + med_il = self.mapped_medium_level_il + if med_il is None: + return None + result = core.BNGetMappedMediumLevelILExprIndex(self.handle, expr) + if result >= core.BNGetMediumLevelILExprCount(med_il.handle): + return None + return result + class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 9f25ee97..00d7215f 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -25,6 +25,7 @@ import _binaryninjacore as core from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType import function import basicblock +import lowlevelil class MediumLevelILLabel(object): @@ -258,6 +259,14 @@ class MediumLevelILInstruction(object): core.BNFreeRegisterValue(value) return result + @property + def low_level_il(self): + """Low level IL form of this expression""" + expr = self.function.get_low_level_il_expr_index(self.expr_index) + if expr is None: + return None + return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -350,6 +359,14 @@ class MediumLevelILFunction(object): return None return MediumLevelILFunction(self.arch, result, self.source_function) + @property + def low_level_il(self): + """Low level IL for this function""" + result = core.BNGetLowLevelILForMediumLevelIL(self.handle) + if not result: + return None + return lowlevelil.LowLevelILFunction(self.arch, result, self.source_function) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -540,6 +557,40 @@ class MediumLevelILFunction(object): core.BNFreeRegisterValue(value) return result + def get_ssa_var_index_at_instruction(self, var, instr): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.handle, var_data, instr) + + def get_ssa_memory_index_at_instruction(self, instr): + return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.handle, instr) + + def get_low_level_il_instruction_index(self, instr): + low_il = self.low_level_il + if low_il is None: + return None + low_il = low_il.ssa_form + if low_il is None: + return None + result = core.BNGetLowLevelILInstructionIndex(self.handle, instr) + if result >= core.BNGetLowLevelILInstructionCount(low_il.handle): + return None + return result + + def get_low_level_il_expr_index(self, expr): + low_il = self.low_level_il + if low_il is None: + return None + low_il = low_il.ssa_form + if low_il is None: + return None + result = core.BNGetLowLevelILExprIndex(self.handle, expr) + if result >= core.BNGetLowLevelILExprCount(low_il.handle): + return None + return result + class MediumLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): -- cgit v1.3.1 From 42cb99079d4ff0a5aa49e7730bb73500d13f35dd Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 13 Mar 2017 23:03:41 -0400 Subject: Branch dependence APIs for path sensitive analysis --- binaryninjaapi.h | 3 +++ binaryninjacore.h | 19 +++++++++++++++++++ mediumlevelil.cpp | 20 ++++++++++++++++++++ python/mediumlevelil.py | 19 ++++++++++++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index ee342851..fb735a9d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2270,6 +2270,9 @@ namespace BinaryNinja size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; + BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; + std::map GetAllBranchDependenceAtInstruction(size_t instr) const; + Ref GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 66d5f010..7cc8b200 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1379,6 +1379,19 @@ extern "C" BNType* type; }; + enum BNILBranchDependence + { + NotBranchDependent, + TrueBranchDependent, + FalseBranchDependent + }; + + struct BNILBranchInstructionAndDependence + { + size_t branch; + BNILBranchDependence dependence; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -2242,6 +2255,12 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI BNILBranchDependence BNGetMediumLevelILBranchDependence(BNMediumLevelILFunction* func, + size_t curInstr, size_t branchInstr); + BINARYNINJACOREAPI BNILBranchInstructionAndDependence* BNGetAllMediumLevelILBranchDependence( + BNMediumLevelILFunction* func, size_t instr, size_t* count); + BINARYNINJACOREAPI void BNFreeILBranchDependenceList(BNILBranchInstructionAndDependence* branches); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr); BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 04b1cffd..dcd1fe8e 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -456,6 +456,26 @@ size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const } +BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const +{ + return BNGetMediumLevelILBranchDependence(m_object, curInstr, branchInstr); +} + + +map MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +{ + size_t count; + BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); + + map result; + for (size_t i = 0; i < count; i++) + result[deps[i].branch] = deps[i].dependence; + + BNFreeILBranchDependenceList(deps); + return result; +} + + Ref MediumLevelILFunction::GetLowLevelIL() const { BNLowLevelILFunction* func = BNGetLowLevelILForMediumLevelIL(m_object); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 00d7215f..8830e738 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType +from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType, ILBranchDependence import function import basicblock import lowlevelil @@ -259,6 +259,11 @@ class MediumLevelILInstruction(object): core.BNFreeRegisterValue(value) return result + @property + def branch_dependence(self): + """Set of branching instructions that must take the true or false path to reach this instruction""" + return self.function.get_all_branch_dependence_at_instruction(self.instr_index) + @property def low_level_il(self): """Low level IL form of this expression""" @@ -567,6 +572,18 @@ class MediumLevelILFunction(object): def get_ssa_memory_index_at_instruction(self, instr): return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.handle, instr) + def get_branch_dependence_at_instruction(self, cur_instr, branch_instr): + return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.handle, cur_instr, branch_instr)) + + def get_all_branch_dependence_at_instruction(self, instr): + count = ctypes.c_ulonglong() + deps = core.BNGetAllMediumLevelILBranchDependence(self.handle, instr, count) + result = {} + for i in xrange(0, count.value): + result[deps[i].branch] = ILBranchDependence(deps[i].dependence) + core.BNFreeILBranchDependenceList(deps) + return result + def get_low_level_il_instruction_index(self, instr): low_il = self.low_level_il if low_il is None: -- cgit v1.3.1 From fa8006024f68a3c924cce95b2ffb62880aa99bed Mon Sep 17 00:00:00 2001 From: Andrew Lamoureux Date: Wed, 15 Mar 2017 12:02:06 -0400 Subject: convenience function for bytes->IL new function: get_low_leveil_il_from_bytes() in Architecture example use: >>> arch.get_low_level_il_from_bytes('\xeb\xfe', 0x40DEAD) --- python/architecture.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 39e5e72d..079d3f5f 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1191,6 +1191,24 @@ class Architecture(object): core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle) return length.value + def get_low_level_il_from_bytes(self, data, addr): + """ + ``get_low_level_il_from_bytes`` converts the instruction in bytes to ``il`` at the given virtual address + + :param str data: the bytes of the instruction + :param int addr: virtual address of bytes in ``data`` + :return: the instruction + :rtype: LowLevelILInstruction + :Example: + + >>> arch.get_low_level_il_from_bytes('\xeb\xfe', 0x40DEAD) + + >>> + """ + func = lowlevelil.LowLevelILFunction(self) + self.get_instruction_low_level_il(data, addr, func) + return func[0] + def get_reg_name(self, reg): """ ``get_reg_name`` gets a register name from a register number. -- cgit v1.3.1 From da77a3011450e694a506c8d16ef084a28bc58214 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 15 Mar 2017 19:51:15 -0400 Subject: APIs for performing range analysis --- binaryninjaapi.h | 3 +++ binaryninjacore.h | 4 ++++ mediumlevelil.cpp | 20 ++++++++++++++++++++ python/mediumlevelil.py | 28 +++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index fb735a9d..3f39c827 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2241,6 +2241,7 @@ namespace BinaryNinja BNMediumLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionForExpr(size_t expr) const; size_t GetInstructionCount() const; size_t GetExprCount() const; @@ -2266,6 +2267,8 @@ namespace BinaryNinja RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); RegisterValue GetExprValue(size_t expr); + RegisterValue GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr); + RegisterValue GetPossibleExprValues(size_t expr); size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 7cc8b200..4905a73c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2221,6 +2221,7 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionForExpr(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); @@ -2249,6 +2250,9 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, const BNILVariable* var, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t idx, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, const BNILVariable* var, size_t instr); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index dcd1fe8e..51dd067d 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -262,6 +262,12 @@ size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const } +size_t MediumLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetMediumLevelILInstructionForExpr(m_object, expr); +} + + size_t MediumLevelILFunction::GetInstructionCount() const { return BNGetMediumLevelILInstructionCount(m_object); @@ -444,6 +450,20 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } +RegisterValue MediumLevelILFunction::GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleExprValues(size_t expr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleExprValues(m_object, expr); + return RegisterValue::FromAPIObject(value); +} + + size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const { return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8830e738..a63e1b31 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -140,7 +140,10 @@ class MediumLevelILInstruction(object): instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) self.function = func self.expr_index = expr_index - self.instr_index = instr_index + if instr_index is None: + self.instr_index = core.BNGetMediumLevelILInstructionForExpr(func.handle, expr_index) + else: + self.instr_index = instr_index self.operation = MediumLevelILOperation(instr.operation) self.size = instr.size self.address = instr.address @@ -218,7 +221,8 @@ class MediumLevelILInstruction(object): """MLIL tokens (read-only)""" count = ctypes.c_ulonglong() tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if (self.instr_index is not None) and (self.function.source_function is not None): + if ((self.instr_index is not None) and (self.function.source_function is not None) and + (self.expr_index == core.BNGetMediumLevelILIndexForInstruction(self.function.handle, self.instr_index))): if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle, self.function.arch.handle, self.instr_index, tokens, count): return None @@ -253,12 +257,20 @@ class MediumLevelILInstruction(object): @property def value(self): - """Value of expression using static data flow analysis (read-only)""" + """Value of expression if constant or a known value (read-only)""" value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) result = function.RegisterValue(self.function.arch, value) core.BNFreeRegisterValue(value) return result + @property + def possible_values(self): + """Possible values of expression using path-sensitive static data flow analysis (read-only)""" + value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + @property def branch_dependence(self): """Set of branching instructions that must take the true or false path to reach this instruction""" @@ -272,6 +284,16 @@ class MediumLevelILInstruction(object): return None return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) + def get_ssa_var_possible_values(self, var, index): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) -- cgit v1.3.1 From cec08b6240f775a831226d9f36ee7f96b369f285 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 16 Mar 2017 03:41:04 -0400 Subject: Adding APIs to query register and stack contents from IL --- binaryninjaapi.h | 34 +++++++++-- binaryninjacore.h | 63 ++++++++++++++++++-- function.cpp | 28 --------- lowlevelil.cpp | 91 +++++++++++++++++++++++++++++ mediumlevelil.cpp | 102 +++++++++++++++++++++++++++++++++ python/function.py | 42 -------------- python/lowlevelil.py | 98 ++++++++++++++++++++++++++++++- python/mediumlevelil.py | 149 ++++++++++++++++++++++++++++++++++++++++-------- 8 files changed, 503 insertions(+), 104 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 3f39c827..131d6a17 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1894,12 +1894,8 @@ namespace BinaryNinja std::vector GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr); RegisterValue GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg); RegisterValue GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg); - RegisterValue GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg); - RegisterValue GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg); RegisterValue GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size); RegisterValue GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size); - RegisterValue GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size); - RegisterValue GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size); RegisterValue GetParameterValueAtInstruction(Architecture* arch, uint64_t addr, Type* functionType, size_t i); RegisterValue GetParameterValueAtLowLevelILInstruction(size_t instr, Type* functionType, size_t i); std::vector GetRegistersReadByInstruction(Architecture* arch, uint64_t addr); @@ -2183,6 +2179,20 @@ namespace BinaryNinja RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); RegisterValue GetExprValue(size_t expr); + RegisterValue GetPossibleExprValues(size_t expr); + + RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); Ref GetMediumLevelIL() const; Ref GetMappedMediumLevelIL() const; @@ -2272,6 +2282,22 @@ namespace BinaryNinja size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; + BNILVariable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const; + BNILVariable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const; + BNILVariable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const; + + RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; std::map GetAllBranchDependenceAtInstruction(size_t instr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 4905a73c..eaba1a51 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1848,16 +1848,10 @@ extern "C" uint64_t addr, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); - BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg); - BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, size_t size); BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, size_t size); - BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtLowLevelILInstruction(BNFunction* func, size_t i, - int64_t offset, size_t size); - BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterLowLevelILInstruction(BNFunction* func, size_t i, - int64_t offset, size_t size); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNType* functionType, size_t i); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtLowLevelILInstruction(BNFunction* func, size_t instr, @@ -2186,6 +2180,32 @@ extern "C" uint32_t flag, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAtInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAfterInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleRegisterValuesAtInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleRegisterValuesAfterInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAtInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAfterInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleFlagValuesAtInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleFlagValuesAfterInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAtInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAfterInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleStackContentsAtInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleStackContentsAfterInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMappedMediumLevelIL(BNLowLevelILFunction* func); @@ -2258,6 +2278,37 @@ extern "C" const BNILVariable* var, size_t instr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForFlagAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t instr); + + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAfterInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleRegisterValuesAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAfterInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleFlagValuesAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleFlagValuesAfterInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAfterInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleStackContentsAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleStackContentsAfterInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNILBranchDependence BNGetMediumLevelILBranchDependence(BNMediumLevelILFunction* func, size_t curInstr, size_t branchInstr); diff --git a/function.cpp b/function.cpp index 9faf68fa..aa56f7af 100644 --- a/function.cpp +++ b/function.cpp @@ -205,20 +205,6 @@ RegisterValue Function::GetRegisterValueAfterInstruction(Architecture* arch, uin } -RegisterValue Function::GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg) -{ - BNRegisterValue value = BNGetRegisterValueAtLowLevelILInstruction(m_object, i, reg); - return RegisterValue::FromAPIObject(value); -} - - -RegisterValue Function::GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg) -{ - BNRegisterValue value = BNGetRegisterValueAfterLowLevelILInstruction(m_object, i, reg); - return RegisterValue::FromAPIObject(value); -} - - RegisterValue Function::GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAtInstruction(m_object, arch->GetObject(), addr, offset, size); @@ -233,20 +219,6 @@ RegisterValue Function::GetStackContentsAfterInstruction(Architecture* arch, uin } -RegisterValue Function::GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size) -{ - BNRegisterValue value = BNGetStackContentsAtLowLevelILInstruction(m_object, i, offset, size); - return RegisterValue::FromAPIObject(value); -} - - -RegisterValue Function::GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size) -{ - BNRegisterValue value = BNGetStackContentsAfterLowLevelILInstruction(m_object, i, offset, size); - return RegisterValue::FromAPIObject(value); -} - - RegisterValue Function::GetParameterValueAtInstruction(Architecture* arch, uint64_t addr, Type* functionType, size_t i) { BNRegisterValue value = BNGetParameterValueAtInstruction(m_object, arch->GetObject(), addr, diff --git a/lowlevelil.cpp b/lowlevelil.cpp index bd038b6e..54e26498 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -780,6 +780,97 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) } +RegisterValue LowLevelILFunction::GetPossibleExprValues(size_t expr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleExprValues(m_object, expr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILRegisterValueAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILFlagValueAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILFlagValueAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + Ref LowLevelILFunction::GetMediumLevelIL() const { BNMediumLevelILFunction* func = BNGetMediumLevelILForLowLevelIL(m_object); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 51dd067d..bb629e64 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -476,6 +476,108 @@ size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const } +BNILVariable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const +{ + return BNGetMediumLevelILVariableForRegisterAtInstruction(m_object, reg, instr); +} + + +BNILVariable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const +{ + return BNGetMediumLevelILVariableForFlagAtInstruction(m_object, flag, instr); +} + + +BNILVariable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const +{ + return BNGetMediumLevelILVariableForStackLocationAtInstruction(m_object, offset, instr); +} + + +RegisterValue MediumLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILRegisterValueAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILRegisterValueAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILFlagValueAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILFlagValueAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const { return BNGetMediumLevelILBranchDependence(m_object, curInstr, branchInstr); diff --git a/python/function.py b/python/function.py index ed2a537c..928597a7 100644 --- a/python/function.py +++ b/python/function.py @@ -459,36 +459,6 @@ class Function(object): core.BNFreeRegisterValue(value) return result - def get_reg_value_at_low_level_il_instruction(self, i, reg, arch=None): - """ - ``get_reg_value_at_low_level_il_instruction`` returns the value of the specified register ``reg`` at the il address - i - - :param int i: il address of instruction to query - :param Architecture arch: (optional) Architecture for the given function - :rtype: function.RegisterValue - :Example: - - >>> func.get_reg_value_at_low_level_il_instruction(15, 'rdi') - - """ - if arch is None: - arch = self.arch - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_after_low_level_il_instruction(self, i, reg): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAfterLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - def get_stack_contents_at(self, addr, offset, size, arch=None): """ ``get_stack_contents_at`` returns the RegisterValue for the item on the stack in the current function at the @@ -523,18 +493,6 @@ class Function(object): core.BNFreeRegisterValue(value) return result - def get_stack_contents_at_low_level_il_instruction(self, i, offset, size): - value = core.BNGetStackContentsAtLowLevelILInstruction(self.handle, i, offset, size) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_stack_contents_after_low_level_il_instruction(self, i, offset, size): - value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - def get_parameter_at(self, addr, func_type, i, arch=None): if arch is None: arch = self.arch diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 462d4ade..74b030d7 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -260,12 +260,108 @@ class LowLevelILInstruction(object): @property def value(self): - """Value of expression using static data flow analysis (read-only)""" + """Value of expression if constant or a known value (read-only)""" value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) result = function.RegisterValue(self.function.arch, value) core.BNFreeRegisterValue(value) return result + @property + def possible_values(self): + """Possible values of expression using path-sensitive static data flow analysis (read-only)""" + value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_reg_value(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_reg_value_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_reg_values(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_reg_values_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_flag_value(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_flag_value_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_flag_values(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_flag_values_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents(self, offset, size): + value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_after(self, offset, size): + value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_stack_contents(self, offset, size): + value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_stack_contents_after(self, offset, size): + value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index a63e1b31..6f482221 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -274,7 +274,13 @@ class MediumLevelILInstruction(object): @property def branch_dependence(self): """Set of branching instructions that must take the true or false path to reach this instruction""" - return self.function.get_all_branch_dependence_at_instruction(self.instr_index) + count = ctypes.c_ulonglong() + deps = core.BNGetAllMediumLevelILBranchDependence(self.function.handle, self.instr_index, count) + result = {} + for i in xrange(0, count.value): + result[deps[i].branch] = ILBranchDependence(deps[i].dependence) + core.BNFreeILBranchDependenceList(deps) + return result @property def low_level_il(self): @@ -284,6 +290,11 @@ class MediumLevelILInstruction(object): return None return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) + @property + def ssa_memory_index(self): + """Index of active memory contents in SSA form for this instruction""" + return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index) + def get_ssa_var_possible_values(self, var, index): var_data = core.BNILVariable() var_data.type = var.type @@ -294,6 +305,120 @@ class MediumLevelILInstruction(object): core.BNFreeRegisterValue(value) return result + def get_ssa_var_index(self, var): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index) + + def get_var_for_reg(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) + return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + + def get_var_for_flag(self, flag): + if isinstance(flag, str): + flag = self.function.arch.regs[flag].index + result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) + return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + + def get_var_for_stack_location(self, offset): + result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) + return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + + def get_reg_value(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_reg_value_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_reg_values(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_reg_values_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_flag_value(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_flag_value_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_flag_values(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_flag_values_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents(self, offset, size): + value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_after(self, offset, size): + value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_stack_contents(self, offset, size): + value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_possible_stack_contents_after(self, offset, size): + value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_branch_dependence(self, branch_instr): + return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.function.handle, self.instr_index, branch_instr)) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -584,28 +709,6 @@ class MediumLevelILFunction(object): core.BNFreeRegisterValue(value) return result - def get_ssa_var_index_at_instruction(self, var, instr): - var_data = core.BNILVariable() - var_data.type = var.type - var_data.index = var.index - var_data.identifier = var.identifier - return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.handle, var_data, instr) - - def get_ssa_memory_index_at_instruction(self, instr): - return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.handle, instr) - - def get_branch_dependence_at_instruction(self, cur_instr, branch_instr): - return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.handle, cur_instr, branch_instr)) - - def get_all_branch_dependence_at_instruction(self, instr): - count = ctypes.c_ulonglong() - deps = core.BNGetAllMediumLevelILBranchDependence(self.handle, instr, count) - result = {} - for i in xrange(0, count.value): - result[deps[i].branch] = ILBranchDependence(deps[i].dependence) - core.BNFreeILBranchDependenceList(deps) - return result - def get_low_level_il_instruction_index(self, instr): low_il = self.low_level_il if low_il is None: -- cgit v1.3.1 From a2992eb4a48dc38b60989f34f51812245a6239c4 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 16 Mar 2017 18:35:55 -0400 Subject: Switching to new data flow system --- binaryninjacore.h | 6 +----- python/function.py | 9 --------- 2 files changed, 1 insertion(+), 14 deletions(-) (limited to 'python') diff --git a/binaryninjacore.h b/binaryninjacore.h index eaba1a51..feea147d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -383,8 +383,7 @@ extern "C" GroupLinearDisassemblyFunctions = 64, // Debugging options - ShowBasicBlockRegisterState = 128, - ShowFlagUsage = 129 + ShowFlagUsage = 128 }; enum BNTypeClass @@ -602,15 +601,12 @@ extern "C" enum BNRegisterValueType { EntryValue, - OffsetFromEntryValue, ConstantValue, StackFrameOffset, UndeterminedValue, - OffsetFromUndeterminedValue, SignedRangeValue, UnsignedRangeValue, LookupTableValue, - ComparisonResultValue, ReturnAddressValue }; diff --git a/python/function.py b/python/function.py index 928597a7..a507534c 100644 --- a/python/function.py +++ b/python/function.py @@ -52,9 +52,6 @@ class RegisterValue(object): self.type = RegisterValueType(value.state) if value.state == RegisterValueType.EntryValue: self.reg = arch.get_reg_name(value.reg) - elif value.state == RegisterValueType.OffsetFromEntryValue: - self.reg = arch.get_reg_name(value.reg) - self.offset = value.value elif value.state == RegisterValueType.ConstantValue: self.value = value.value elif value.state == RegisterValueType.StackFrameOffset: @@ -82,14 +79,10 @@ class RegisterValue(object): from_list.append(value.table[i].fromValues[j]) self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue self.table.append(LookupTableEntry(from_list, value.table[i].toValue)) - elif value.state == RegisterValueType.OffsetFromUndeterminedValue: - self.offset = value.value def __repr__(self): if self.type == RegisterValueType.EntryValue: return "" % self.reg - if self.type == RegisterValueType.OffsetFromEntryValue: - return "" % (self.reg, self.offset) if self.type == RegisterValueType.ConstantValue: return "" % self.value if self.type == RegisterValueType.StackFrameOffset: @@ -100,8 +93,6 @@ class RegisterValue(object): return "" % (self.start, self.end, self.step) if self.type == RegisterValueType.LookupTableValue: return "" % ', '.join([repr(i) for i in self.table]) - if self.type == RegisterValueType.OffsetFromUndeterminedValue: - return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" return "" -- cgit v1.3.1 From b049ec1662df13d409d149d937fa3366c33b32a1 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Sun, 19 Mar 2017 01:19:38 -0400 Subject: change types in documentation for lowlevelil so the results will be clickable, resolves #583 --- python/function.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index 86c93bf7..e1c202f9 100644 --- a/python/function.py +++ b/python/function.py @@ -289,12 +289,12 @@ class Function(object): @property def low_level_il(self): - """Function low level IL (read-only)""" + """returns LowLevelILFunction used to represent Function low level IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelIL(self.handle), self) @property def lifted_il(self): - """Function lifted IL (read-only)""" + """returns LowLevelILFunction used to represent lifted IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) @property -- cgit v1.3.1 From b7509f379376a828b99cf71294b74d4f47ddbf91 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 22 Mar 2017 19:27:52 -0400 Subject: update documentation for get_instruction_low_level_il --- python/architecture.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 079d3f5f..d3778613 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1177,6 +1177,9 @@ class Architecture(object): ``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 -- cgit v1.3.1 From ddaf7506e1802cfd4f9c78bcfb14deb0180b04d8 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 22 Mar 2017 19:28:43 -0400 Subject: update basicblock.annotations to new argument order for function.get_block_annotations --- python/basicblock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index 9f256aa7..5bec391b 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -194,7 +194,7 @@ class BasicBlock(object): @property def annotations(self): """List of automatic annotations for the start of this block (read-only)""" - return self.function.get_block_annotations(self.arch, self.start) + return self.function.get_block_annotations(self.start, self.arch) @property def disassembly_text(self): -- cgit v1.3.1 From cb244a62fea649d6840b70b8e7fe7953eb3acc5a Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 22 Mar 2017 22:43:16 -0400 Subject: Adding new value object to hold disjoint sets --- binaryninjaapi.h | 46 +++++++++++++++----------- binaryninjacore.h | 60 +++++++++++++++++++++------------- function.cpp | 27 ++++++++++++---- lowlevelil.cpp | 42 ++++++++++++------------ mediumlevelil.cpp | 48 +++++++++++++-------------- python/function.py | 86 ++++++++++++++++++++++++++++++++++++------------- python/lowlevelil.py | 37 ++++++++------------- python/mediumlevelil.py | 37 ++++++++------------- 8 files changed, 223 insertions(+), 160 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 131d6a17..af0cf5ce 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1853,14 +1853,22 @@ namespace BinaryNinja struct RegisterValue { BNRegisterValueType state; - uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register - int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue - uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive - std::vector table; + int64_t value; static RegisterValue FromAPIObject(BNRegisterValue& value); }; + struct PossibleValueSet + { + BNRegisterValueType state; + int64_t value; + std::vector ranges; + std::set valueSet; + std::vector table; + + static PossibleValueSet FromAPIObject(BNPossibleValueSet& value); + }; + class FunctionGraph; class MediumLevelILFunction; @@ -2179,20 +2187,20 @@ namespace BinaryNinja RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); RegisterValue GetExprValue(size_t expr); - RegisterValue GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(size_t expr); RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); - RegisterValue GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); - RegisterValue GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); - RegisterValue GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); - RegisterValue GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); - RegisterValue GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); - RegisterValue GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); Ref GetMediumLevelIL() const; Ref GetMappedMediumLevelIL() const; @@ -2277,8 +2285,8 @@ namespace BinaryNinja RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); RegisterValue GetExprValue(size_t expr); - RegisterValue GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr); - RegisterValue GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr); + PossibleValueSet GetPossibleExprValues(size_t expr); size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; @@ -2288,16 +2296,16 @@ namespace BinaryNinja RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); - RegisterValue GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); - RegisterValue GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); - RegisterValue GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); - RegisterValue GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); - RegisterValue GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); - RegisterValue GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; std::map GetAllBranchDependenceAtInstruction(size_t instr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index feea147d..c43c9b21 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -600,14 +600,18 @@ extern "C" enum BNRegisterValueType { + UndeterminedValue, EntryValue, ConstantValue, StackFrameOffset, - UndeterminedValue, + ReturnAddressValue, + + // The following are only valid in BNPossibleValueSet SignedRangeValue, UnsignedRangeValue, LookupTableValue, - ReturnAddressValue + InSetOfValues, + NotInSetOfValues }; struct BNLookupTableEntry @@ -620,10 +624,22 @@ extern "C" struct BNRegisterValue { BNRegisterValueType state; - uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register - int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue - uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive - BNLookupTableEntry* table; // Number of entries in rangeEnd + int64_t value; + }; + + struct BNValueRange + { + uint64_t start, end, step; + }; + + struct BNPossibleValueSet + { + BNRegisterValueType state; + int64_t value; + BNValueRange* ranges; + int64_t* valueSet; + BNLookupTableEntry* table; + size_t count; }; struct BNRegisterOrConstant @@ -1852,7 +1868,7 @@ extern "C" uint64_t addr, BNType* functionType, size_t i); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtLowLevelILInstruction(BNFunction* func, size_t instr, BNType* functionType, size_t i); - BINARYNINJACOREAPI void BNFreeRegisterValue(BNRegisterValue* value); + BINARYNINJACOREAPI void BNFreePossibleValueSet(BNPossibleValueSet* value); BINARYNINJACOREAPI uint32_t* BNGetRegistersReadByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetRegistersWrittenByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, @@ -2176,31 +2192,31 @@ extern "C" uint32_t flag, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAtInstruction(BNLowLevelILFunction* func, uint32_t reg, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAfterInstruction(BNLowLevelILFunction* func, uint32_t reg, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleRegisterValuesAtInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAtInstruction(BNLowLevelILFunction* func, uint32_t reg, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleRegisterValuesAfterInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAfterInstruction(BNLowLevelILFunction* func, uint32_t reg, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAtInstruction(BNLowLevelILFunction* func, uint32_t flag, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAfterInstruction(BNLowLevelILFunction* func, uint32_t flag, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleFlagValuesAtInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAtInstruction(BNLowLevelILFunction* func, uint32_t flag, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleFlagValuesAfterInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAfterInstruction(BNLowLevelILFunction* func, uint32_t flag, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAtInstruction(BNLowLevelILFunction* func, int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAfterInstruction(BNLowLevelILFunction* func, int64_t offset, size_t len, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleStackContentsAtInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAtInstruction(BNLowLevelILFunction* func, int64_t offset, size_t len, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILPossibleStackContentsAfterInstruction(BNLowLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAfterInstruction(BNLowLevelILFunction* func, int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func); @@ -2266,9 +2282,9 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, const BNILVariable* var, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, const BNILVariable* var, size_t idx, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, const BNILVariable* var, size_t instr); @@ -2285,25 +2301,25 @@ extern "C" uint32_t reg, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAfterInstruction(BNMediumLevelILFunction* func, uint32_t reg, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleRegisterValuesAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAtInstruction(BNMediumLevelILFunction* func, uint32_t reg, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(BNMediumLevelILFunction* func, uint32_t reg, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAtInstruction(BNMediumLevelILFunction* func, uint32_t flag, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAfterInstruction(BNMediumLevelILFunction* func, uint32_t flag, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleFlagValuesAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAtInstruction(BNMediumLevelILFunction* func, uint32_t flag, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleFlagValuesAfterInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAfterInstruction(BNMediumLevelILFunction* func, uint32_t flag, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAtInstruction(BNMediumLevelILFunction* func, int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAfterInstruction(BNMediumLevelILFunction* func, int64_t offset, size_t len, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleStackContentsAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAtInstruction(BNMediumLevelILFunction* func, int64_t offset, size_t len, size_t instr); - BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILPossibleStackContentsAfterInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAfterInstruction(BNMediumLevelILFunction* func, int64_t offset, size_t len, size_t instr); BINARYNINJACOREAPI BNILBranchDependence BNGetMediumLevelILBranchDependence(BNMediumLevelILFunction* func, diff --git a/function.cpp b/function.cpp index aa56f7af..16ad1f1c 100644 --- a/function.cpp +++ b/function.cpp @@ -170,14 +170,19 @@ RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) { RegisterValue result; result.state = value.state; - result.reg = value.reg; result.value = value.value; - result.rangeStart = value.rangeStart; - result.rangeEnd = value.rangeEnd; - result.rangeStep = value.rangeStep; + return result; +} + + +PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value) +{ + PossibleValueSet result; + result.state = value.state; + result.value = value.value; if (value.state == LookupTableValue) { - for (size_t i = 0; i < (size_t)value.rangeEnd; i++) + for (size_t i = 0; i < value.count; i++) { LookupTableEntry entry; entry.fromValues.insert(entry.fromValues.end(), &value.table[i].fromValues[0], @@ -186,7 +191,17 @@ RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) result.table.push_back(entry); } } - BNFreeRegisterValue(&value); + else if ((value.state == SignedRangeValue) || (value.state == UnsignedRangeValue)) + { + for (size_t i = 0; i < value.count; i++) + result.ranges.push_back(value.ranges[i]); + } + else if ((value.state == InSetOfValues) || (value.state == NotInSetOfValues)) + { + for (size_t i = 0; i < value.count; i++) + result.valueSet.insert(value.valueSet[i]); + } + BNFreePossibleValueSet(&value); return result; } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 54e26498..9764445e 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -780,10 +780,10 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) } -RegisterValue LowLevelILFunction::GetPossibleExprValues(size_t expr) +PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) { - BNRegisterValue value = BNGetLowLevelILPossibleExprValues(m_object, expr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr); + return PossibleValueSet::FromAPIObject(value); } @@ -801,17 +801,17 @@ RegisterValue LowLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, } -RegisterValue LowLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); } @@ -829,17 +829,17 @@ RegisterValue LowLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, si } -RegisterValue LowLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); } @@ -857,17 +857,17 @@ RegisterValue LowLevelILFunction::GetStackContentsAfterInstruction(int32_t offse } -RegisterValue LowLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) { - BNRegisterValue value = BNGetLowLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index bb629e64..b0eb83a1 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -450,17 +450,17 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -RegisterValue MediumLevelILFunction::GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue MediumLevelILFunction::GetPossibleExprValues(size_t expr) +PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) { - BNRegisterValue value = BNGetMediumLevelILPossibleExprValues(m_object, expr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleExprValues(m_object, expr); + return PossibleValueSet::FromAPIObject(value); } @@ -508,17 +508,17 @@ RegisterValue MediumLevelILFunction::GetRegisterValueAfterInstruction(uint32_t r } -RegisterValue MediumLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue MediumLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); } @@ -536,17 +536,17 @@ RegisterValue MediumLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, } -RegisterValue MediumLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue MediumLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); } @@ -564,17 +564,17 @@ RegisterValue MediumLevelILFunction::GetStackContentsAfterInstruction(int32_t of } -RegisterValue MediumLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); } -RegisterValue MediumLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) { - BNRegisterValue value = BNGetMediumLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); - return RegisterValue::FromAPIObject(value); + BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); } diff --git a/python/function.py b/python/function.py index a507534c..51d61792 100644 --- a/python/function.py +++ b/python/function.py @@ -51,34 +51,78 @@ class RegisterValue(object): def __init__(self, arch, value): self.type = RegisterValueType(value.state) if value.state == RegisterValueType.EntryValue: - self.reg = arch.get_reg_name(value.reg) + self.reg = arch.get_reg_name(value.value) + elif value.state == RegisterValueType.ConstantValue: + self.value = value.value + elif value.state == RegisterValueType.StackFrameOffset: + self.offset = value.value + + def __repr__(self): + if self.type == RegisterValueType.EntryValue: + return "" % self.reg + if self.type == RegisterValueType.ConstantValue: + return "" % self.value + if self.type == RegisterValueType.StackFrameOffset: + return "" % self.offset + if self.type == RegisterValueType.ReturnAddressValue: + return "" + return "" + + +class ValueRange(object): + def __init__(self, start, end, step): + self.start = start + self.end = end + self.step = step + + def __repr__(self): + if self.step == 1: + return "" % (self.start, self.end) + return "" % (self.start, self.end, self.step) + + +class PossibleValueSet(object): + def __init__(self, arch, value): + self.type = RegisterValueType(value.state) + if value.state == RegisterValueType.EntryValue: + self.reg = arch.get_reg_name(value.value) elif value.state == RegisterValueType.ConstantValue: self.value = value.value elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value elif value.state == RegisterValueType.SignedRangeValue: self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep - if self.start & (1 << 63): - self.start |= ~((1 << 63) - 1) - if self.end & (1 << 63): - self.end |= ~((1 << 63) - 1) + self.ranges = [] + for i in xrange(0, value.count): + start = value.ranges[i].start + end = value.ranges[i].end + step = value.ranges[i].step + if start & (1 << 63): + start |= ~((1 << 63) - 1) + if end & (1 << 63): + end |= ~((1 << 63) - 1) + self.ranges.append(ValueRange(start, end, step)) elif value.state == RegisterValueType.UnsignedRangeValue: self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep + self.ranges = [] + for i in xrange(0, value.count): + start = value.ranges[i].start + end = value.ranges[i].end + step = value.ranges[i].step + self.ranges.append(ValueRange(start, end, step)) elif value.state == RegisterValueType.LookupTableValue: self.table = [] self.mapping = {} - for i in xrange(0, value.rangeEnd): + for i in xrange(0, value.count): from_list = [] for j in xrange(0, value.table[i].fromCount): from_list.append(value.table[i].fromValues[j]) self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue self.table.append(LookupTableEntry(from_list, value.table[i].toValue)) + elif (value.state == RegisterValueType.InSetOfValues) or (value.state == RegisterValueType.NotInSetOfValues): + self.values = set() + for i in xrange(0, value.count): + self.values.add(value.valueSet[i]) def __repr__(self): if self.type == RegisterValueType.EntryValue: @@ -87,12 +131,16 @@ class RegisterValue(object): return "" % self.value if self.type == RegisterValueType.StackFrameOffset: return "" % self.offset - if (self.type == RegisterValueType.SignedRangeValue) or (self.type == RegisterValueType.UnsignedRangeValue): - if self.step == 1: - return "" % (self.start, self.end) - return "" % (self.start, self.end, self.step) + if self.type == RegisterValueType.SignedRangeValue: + return "" % repr(self.ranges) + if self.type == RegisterValueType.UnsignedRangeValue: + return "" % repr(self.ranges) if self.type == RegisterValueType.LookupTableValue: return "" % ', '.join([repr(i) for i in self.table]) + if self.type == RegisterValueType.InSetOfValues: + return "" % repr(self.values) + if self.type == RegisterValueType.NotInSetOfValues: + return "" % repr(self.values) if self.type == RegisterValueType.ReturnAddressValue: return "" return "" @@ -425,7 +473,6 @@ class Function(object): reg = arch.regs[reg].index value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_reg_value_after(self, addr, reg, arch=None): @@ -447,7 +494,6 @@ class Function(object): reg = arch.regs[reg].index value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_stack_contents_at(self, addr, offset, size, arch=None): @@ -473,7 +519,6 @@ class Function(object): arch = self.arch value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_stack_contents_after(self, addr, offset, size, arch=None): @@ -481,7 +526,6 @@ class Function(object): arch = self.arch value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_parameter_at(self, addr, func_type, i, arch=None): @@ -491,7 +535,6 @@ class Function(object): func_type = func_type.handle value = core.BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_parameter_at_low_level_il_instruction(self, instr, func_type, i): @@ -499,7 +542,6 @@ class Function(object): func_type = func_type.handle value = core.BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type, i) result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_regs_read_by(self, addr, arch=None): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 74b030d7..a737d95e 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -263,15 +263,14 @@ class LowLevelILInstruction(object): """Value of expression if constant or a known value (read-only)""" value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result @property def possible_values(self): """Possible values of expression using path-sensitive static data flow analysis (read-only)""" value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_reg_value(self, reg): @@ -279,7 +278,6 @@ class LowLevelILInstruction(object): reg = self.function.arch.regs[reg].index value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_reg_value_after(self, reg): @@ -287,23 +285,22 @@ class LowLevelILInstruction(object): reg = self.function.arch.regs[reg].index value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_reg_values(self, reg): if isinstance(reg, str): reg = self.function.arch.regs[reg].index value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): if isinstance(reg, str): reg = self.function.arch.regs[reg].index value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): @@ -311,7 +308,6 @@ class LowLevelILInstruction(object): flag = self.function.arch.flags[flag].index value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_flag_value_after(self, flag): @@ -319,47 +315,44 @@ class LowLevelILInstruction(object): flag = self.function.arch.flags[flag].index value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_flag_values(self, flag): if isinstance(flag, str): flag = self.function.arch.flags[flag].index value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): if isinstance(flag, str): flag = self.function.arch.flags[flag].index value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset, size): value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_stack_contents_after(self, offset, size): value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_stack_contents(self, offset, size): value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_stack_contents_after(self, offset, size): value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def __setattr__(self, name, value): @@ -1534,7 +1527,6 @@ class LowLevelILFunction(object): reg = self.arch.regs[reg].index value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index) result = function.RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_ssa_flag_value(self, flag, index): @@ -1542,7 +1534,6 @@ class LowLevelILFunction(object): flag = self.arch.get_flag_by_name(flag) value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index) result = function.RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_mapped_medium_level_il_instruction_index(self, instr): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 6f482221..951ad591 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -260,15 +260,14 @@ class MediumLevelILInstruction(object): """Value of expression if constant or a known value (read-only)""" value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result @property def possible_values(self): """Possible values of expression using path-sensitive static data flow analysis (read-only)""" value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result @property @@ -302,7 +301,6 @@ class MediumLevelILInstruction(object): var_data.identifier = var.identifier value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_ssa_var_index(self, var): @@ -333,7 +331,6 @@ class MediumLevelILInstruction(object): reg = self.function.arch.regs[reg].index value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_reg_value_after(self, reg): @@ -341,23 +338,22 @@ class MediumLevelILInstruction(object): reg = self.function.arch.regs[reg].index value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_reg_values(self, reg): if isinstance(reg, str): reg = self.function.arch.regs[reg].index value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): if isinstance(reg, str): reg = self.function.arch.regs[reg].index value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): @@ -365,7 +361,6 @@ class MediumLevelILInstruction(object): flag = self.function.arch.flags[flag].index value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_flag_value_after(self, flag): @@ -373,47 +368,44 @@ class MediumLevelILInstruction(object): flag = self.function.arch.flags[flag].index value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_flag_values(self, flag): if isinstance(flag, str): flag = self.function.arch.flags[flag].index value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): if isinstance(flag, str): flag = self.function.arch.flags[flag].index value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset, size): value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_stack_contents_after(self, offset, size): value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) return result def get_possible_stack_contents(self, offset, size): value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_possible_stack_contents_after(self, offset, size): value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) - core.BNFreeRegisterValue(value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_branch_dependence(self, branch_instr): @@ -706,7 +698,6 @@ class MediumLevelILFunction(object): var_data.identifier = var.identifier value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) result = function.RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_low_level_il_instruction_index(self, instr): -- cgit v1.3.1 From bf57618db521f8677fd57cd9baa5d77acf025845 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sat, 25 Mar 2017 21:50:59 -0400 Subject: Fixing partial variable write instruction --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 951ad591..dff79fbd 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -115,7 +115,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], -- cgit v1.3.1 From e0f3069e8c01379ee6fca69c74ae98d8bf754535 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 28 Mar 2017 19:07:34 -0400 Subject: Cleanup of some of the plugin manager APIs --- binaryninjaapi.h | 28 ++++----------------- binaryninjacore.h | 36 ++++++++------------------ pluginmanager.cpp | 67 ++++++++----------------------------------------- python/pluginmanager.py | 34 +++++++++++++++++++------ 4 files changed, 53 insertions(+), 112 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 544c2e10..bab26345 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2591,22 +2591,6 @@ namespace BinaryNinja class RepoPlugin: public CoreRefCountObject { public: - RepoPlugin(const std::string& path, - bool installed, - bool enabled, - const std::string& api, - const std::string& author, - const std::string& description, - const std::string& license, - const std::string& licenseText, - const std::string& longdescription, - const std::string& minimimVersions, - const std::string& name, - const std::vector& pluginTypes, - const std::string& url, - const std::string& version, - const std::string& repoPath, - const std::string& gitModulesPath); RepoPlugin(BNRepoPlugin* plugin); std::string GetPath() const; bool IsInstalled() const; @@ -2630,11 +2614,6 @@ namespace BinaryNinja class Repository: public CoreRefCountObject { public: - Repository(const std::string& url, // URL of the git repository containing the plugins - const std::string& repoPath, // Name of the directory to store this repository within the repositories directory - const std::string& repoManifest="plugins", // Name of the of the inner directory and .json file - const std::string& localReference="master", - const std::string& remoteReference="origin"); Repository(BNRepository* repository); ~Repository(); std::string GetUrl() const; @@ -2652,14 +2631,17 @@ namespace BinaryNinja { bool m_core; public: - RepositoryManager(std::vector>& repoInfo, const std::string& enabledPluginsPath); + RepositoryManager(const std::string& enabledPluginsPath); RepositoryManager(BNRepositoryManager* repoManager); RepositoryManager(); ~RepositoryManager(); bool CheckForUpdates(); std::vector> GetRepositories(); Ref GetRepositoryByPath(const std::string& repoName); - bool AddRepository(Ref repo); + bool AddRepository(const std::string& url, + const std::string& repoPath, // Relative path within the repositories directory + const std::string& localReference="master", + const std::string& remoteReference="origin"); bool EnablePlugin(const std::string& repoName, const std::string& pluginPath); bool DisablePlugin(const std::string& repoName, const std::string& pluginPath); bool InstallPlugin(const std::string& repoName, const std::string& pluginPath); diff --git a/binaryninjacore.h b/binaryninjacore.h index 80fc715c..0b2375ef 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2403,23 +2403,6 @@ extern "C" BINARYNINJACOREAPI const char* BNPluginGetUrl(BNRepoPlugin* p); BINARYNINJACOREAPI const char* BNPluginGetVersion(BNRepoPlugin* p); BINARYNINJACOREAPI void BNFreePluginTypes(BNPluginType* r); - BINARYNINJACOREAPI BNRepoPlugin* BNCreatePlugin(const char* path, - bool installed, - bool enabled, - const char* api, - const char* author, - const char* description, - const char* license, - const char* licenseText, - const char* longdescription, - const char* minimimVersions, - const char* name, - const BNPluginType* pluginTypes, - size_t pluginTypesSize, - const char* url, - const char* version, - const char* repoPath, - const char* gitModulesPath); BINARYNINJACOREAPI BNRepoPlugin* BNNewPluginReference(BNRepoPlugin* r); BINARYNINJACOREAPI void BNFreePlugin(BNRepoPlugin* plugin); BINARYNINJACOREAPI const char* BNPluginGetPath(BNRepoPlugin* p); @@ -2428,10 +2411,11 @@ extern "C" BINARYNINJACOREAPI bool BNPluginIsEnabled(BNRepoPlugin* p); BINARYNINJACOREAPI BNPluginUpdateStatus BNPluginGetPluginUpdateStatus(BNRepoPlugin* p); BINARYNINJACOREAPI BNPluginType* BNPluginGetPluginTypes(BNRepoPlugin* p, size_t* count); - BINARYNINJACOREAPI BNRepository* BNCreateRepository(const char* url, - const char* repoPath, - const char* localReference, - const char* remoteReference); + BINARYNINJACOREAPI bool BNPluginEnable(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginDisable(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginInstall(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginUninstall(BNRepoPlugin* p); + BINARYNINJACOREAPI BNRepository* BNNewRepositoryReference(BNRepository* r); BINARYNINJACOREAPI void BNFreeRepository(BNRepository* r); BINARYNINJACOREAPI char* BNRepositoryGetUrl(BNRepository* r); @@ -2445,15 +2429,17 @@ extern "C" BINARYNINJACOREAPI BNRepoPlugin* BNRepositoryGetPluginByPath(BNRepository* r, const char* pluginPath); BINARYNINJACOREAPI const char* BNRepositoryGetPluginsPath(BNRepository* r); - BINARYNINJACOREAPI BNRepositoryManager* BNCreateRepositoryManager(BNRepository** repos, - size_t reposSize, - const char* enabledPluginsPath); + BINARYNINJACOREAPI BNRepositoryManager* BNCreateRepositoryManager(const char* enabledPluginsPath); BINARYNINJACOREAPI BNRepositoryManager* BNNewRepositoryManagerReference(BNRepositoryManager* r); BINARYNINJACOREAPI void BNFreeRepositoryManager(BNRepositoryManager* r); BINARYNINJACOREAPI bool BNRepositoryManagerCheckForUpdates(BNRepositoryManager* r); BINARYNINJACOREAPI BNRepository** BNRepositoryManagerGetRepositories(BNRepositoryManager* r, size_t* count); BINARYNINJACOREAPI void BNFreeRepositoryManagerRepositoriesList(BNRepository** r); - BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, BNRepository* repo); + BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, + const char* url, + const char* repoPath, + const char* localReference, + const char* remoteReference); BINARYNINJACOREAPI bool BNRepositoryManagerEnablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); BINARYNINJACOREAPI bool BNRepositoryManagerDisablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); BINARYNINJACOREAPI bool BNRepositoryManagerInstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); diff --git a/pluginmanager.cpp b/pluginmanager.cpp index ab2b23ee..95c8ea15 100644 --- a/pluginmanager.cpp +++ b/pluginmanager.cpp @@ -10,42 +10,6 @@ using namespace std; return result; \ }while(0) -RepoPlugin::RepoPlugin(const string& path, - bool installed, - bool enabled, - const string& api, - const string& author, - const string& description, - const string& license, - const string& licenseText, - const string& longdescription, - const string& minimimVersions, - const string& name, - const vector& pluginTypes, - const string& url, - const string& version, - const string& repoPath, - const string& gitModulesPath) -{ - m_object = BNCreatePlugin(path.c_str(), - installed, - enabled, - api.c_str(), - author.c_str(), - description.c_str(), - license.c_str(), - licenseText.c_str(), - longdescription.c_str(), - minimimVersions.c_str(), - name.c_str(), - &pluginTypes[0], - pluginTypes.size(), - url.c_str(), - version.c_str(), - repoPath.c_str(), - gitModulesPath.c_str()); -} - RepoPlugin::RepoPlugin(BNRepoPlugin* plugin) { m_object = plugin; @@ -139,18 +103,6 @@ string RepoPlugin::GetVersion() const RETURN_STRING(BNPluginGetVersion(m_object)); } -Repository::Repository(const string& url, - const string& repoPath, - const string& repoManifest, - const string& localReference, - const string& remoteReference) -{ - m_object = BNCreateRepository(url.c_str(), - repoPath.c_str(), - localReference.c_str(), - remoteReference.c_str()); -} - Repository::Repository(BNRepository* r) { m_object = r; @@ -205,14 +157,10 @@ string Repository::GetFullPath() const RETURN_STRING(BNRepositoryGetPluginsPath(m_object)); } -RepositoryManager::RepositoryManager(vector>& repoInfo, const string& enabledPluginsPath) +RepositoryManager::RepositoryManager(const string& enabledPluginsPath) :m_core(false) { - BNRepository** buffer = new BNRepository*[repoInfo.size()]; - for (size_t i = 0; i < repoInfo.size(); i++) - buffer[i] = repoInfo[i]->m_object; - m_object = BNCreateRepositoryManager(buffer, repoInfo.size(), enabledPluginsPath.c_str()); - delete[] buffer; + m_object = BNCreateRepositoryManager(enabledPluginsPath.c_str()); } RepositoryManager::RepositoryManager(BNRepositoryManager* mgr) @@ -249,9 +197,16 @@ vector> RepositoryManager::GetRepositories() return repos; } -bool RepositoryManager::AddRepository(Ref repo) +bool RepositoryManager::AddRepository(const std::string& url, + const std::string& repoPath, // Relative path within the repositories directory + const std::string& localReference, + const std::string& remoteReference) { - return BNRepositoryManagerAddRepository(m_object, repo->GetObject()); + return BNRepositoryManagerAddRepository(m_object, + url.c_str(), + repoPath.c_str(), + localReference.c_str(), + remoteReference.c_str()); } Ref RepositoryManager::GetRepositoryByPath(const std::string& repoPath) diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 348f13fb..766b9b53 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -28,7 +28,8 @@ import startup class RepoPlugin(object): """ - ``Plugin`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. + ``RepoPlugin` is mostly read-only, however you can install/uninstall enable/disable plugins. RepoPlugins are + created by parsing the plugins.json in a plugin repository. """ def __init__(self, handle): self.handle = core.handle_of_type(handle, core.BNRepoPlugin) @@ -49,11 +50,25 @@ class RepoPlugin(object): """Boolean True if the plugin is installed, False otherwise""" return core.BNPluginIsInstalled(self.handle) + @installed.setter + def installed(self, state): + if state: + return core.BNPluginInstall(self.handle) + else: + return core.BNPluginUninstall(self.handle) + @property def enabled(self): """Boolean True if the plugin is currently enabled, False otherwise""" return core.BNPluginIsEnabled(self.handle) + @enabled.setter + def enabled(self, state): + if state: + return core.BNPluginEnable(self.handle) + else: + return core.BNPluginDisable(self.handle) + @property def api(self): """string indicating the api used by the plugin""" @@ -151,7 +166,7 @@ class Repository(object): @property def plugins(self): - """List of Plugin objects contained within this repository""" + """List of RepoPlugin objects contained within this repository""" pluginlist = [] count = ctypes.c_ulonglong(0) result = core.BNRepositoryGetPlugins(self.handle, count) @@ -168,6 +183,10 @@ class Repository(object): class RepositoryManager(object): + """ + ``RepositoryManager`` Keeps track of all the repositories and keeps the enabled_plugins.json file coherent with + the plugins that are installed/unstalled enabled/disabled + """ def __init__(self, handle=None): self.handle = core.BNGetRepositoryManager() @@ -236,7 +255,7 @@ class RepositoryManager(object): ``disable_plugin`` Disable the specified plugin, pluginpath :param Repository or str repo: Repository containing the plugin to disable - :param Plugin or str plugin: Plugin to disable + :param RepoPlugin or str plugin: RepoPlugin to disable :return: Boolean value True if the plugin was successfully disabled, False otherwise :rtype: Boolean :Example: @@ -261,7 +280,7 @@ class RepositoryManager(object): ``install_plugin`` install the specified plugin, pluginpath :param Repository or str repo: Repository containing the plugin to install - :param Plugin or str plugin: Plugin to install + :param RepoPlugin or str plugin: RepoPlugin to install :return: Boolean value True if the plugin was successfully installed, False otherwise :rtype: Boolean :Example: @@ -286,7 +305,7 @@ class RepositoryManager(object): ``uninstall_plugin`` uninstall the specified plugin, pluginpath :param Repository or str repo: Repository containing the plugin to uninstall - :param Plugin or str plugin: Plugin to uninstall + :param RepoPlugin or str plugin: RepoPlugin to uninstall :return: Boolean value True if the plugin was successfully uninstalled, False otherwise :rtype: Boolean :Example: @@ -311,7 +330,7 @@ class RepositoryManager(object): ``update_plugin`` update the specified plugin, pluginpath :param Repository or str repo: Repository containing the plugin to update - :param Plugin or str plugin: Plugin to update + :param RepoPlugin or str plugin: RepoPlugin to update :return: Boolean value True if the plugin was successfully updated, False otherwise :rtype: Boolean :Example: @@ -354,6 +373,5 @@ class RepositoryManager(object): if not (isinstance(url, str) and isinstance(repopath, str) and isinstance(localreference, str) and isinstance(remotereference, str)): raise ValueError("Parameter is incorrect type") - repo = core.BNCreateRepository(url, repopath, localreference, remotereference) - return core.BNRepositoryManagerAddRepository(self.handle, repo) + return core.BNRepositoryManagerAddRepository(self.handle, url, repopath, localreference, remotereference) -- cgit v1.3.1 From ea621bf8ce15a477df3f11a8216f216dd5c31be5 Mon Sep 17 00:00:00 2001 From: lucasduffey Date: Sun, 2 Apr 2017 20:15:33 -0700 Subject: replaced BNHasExplicitlyDefinedType with BNFunctionHasExplicitlyDefinedType --- python/function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index e1c202f9..9e58c47d 100644 --- a/python/function.py +++ b/python/function.py @@ -258,7 +258,7 @@ class Function(object): @property def explicitly_defined_type(self): """Whether function has explicitly defined types (read-only)""" - return core.BNHasExplicitlyDefinedType(self.handle) + return core.BNFunctionHasExplicitlyDefinedType(self.handle) @property def needs_update(self): -- cgit v1.3.1 From de4d9adb89f2fe390d0e49b8c33a0e2328b36ed4 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 11 Apr 2017 11:42:19 -0400 Subject: fix example to point to community repo --- python/pluginmanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 766b9b53..37962114 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -363,7 +363,7 @@ class RepositoryManager(object): :Example: >>> mgr = RepositoryManager() - >>> mgr.add_repository(url="https://github.com/vector35/binaryninja-plugins.git", + >>> mgr.add_repository(url="https://github.com/vector35/community-plugins.git", repopath="myrepo", repomanifest="plugins", localreference="master", remotereference="origin") -- cgit v1.3.1 From 0ed147b61a1418915c1e243e05aa05e736b6a73f Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 17 Apr 2017 19:38:12 -0400 Subject: Use new variable system in functions --- binaryninjaapi.h | 81 ++++++++++++++++---------- binaryninjacore.h | 45 +++++++++------ function.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++---- mediumlevelil.cpp | 56 +++++++++--------- python/function.py | 39 +++++++++---- python/mediumlevelil.py | 30 +++++----- 6 files changed, 290 insertions(+), 112 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index af0cf5ce..c6ac8aa3 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1809,11 +1809,24 @@ namespace BinaryNinja static bool IsBackEdge(BasicBlock* source, BasicBlock* target); }; - struct StackVariable + struct Variable: public BNVariable { + Variable(); + Variable(BNVariableSourceType type, uint32_t index, uint64_t identifier); + Variable(const BNVariable& var); + + Variable& operator=(const Variable& var); + + bool operator==(const Variable& var) const; + bool operator!=(const Variable& var) const; + bool operator<(const Variable& var) const; + }; + + struct VariableNameAndType + { + Variable var; Ref type; std::string name; - int64_t offset; bool autoDefined; }; @@ -1928,12 +1941,20 @@ namespace BinaryNinja Ref CreateFunctionGraph(); - std::map GetStackLayout(); + std::map> GetStackLayout(); void CreateAutoStackVariable(int64_t offset, Ref type, const std::string& name); void CreateUserStackVariable(int64_t offset, Ref type, const std::string& name); void DeleteAutoStackVariable(int64_t offset); void DeleteUserStackVariable(int64_t offset); - bool GetStackVariableAtFrameOffset(int64_t offset, StackVariable& var); + bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var); + + std::map GetVariables(); + void CreateAutoVariable(const Variable& var, Ref type, const std::string& name, bool singleOnly = false); + void CreateUserVariable(const Variable& var, Ref type, const std::string& name, bool singleOnly = false); + void DeleteAutoVariable(const Variable& var); + void DeleteUserVariable(const Variable& var); + Ref GetVariableType(const Variable& var); + std::string GetVariableName(const Variable& var); void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches); void SetUserIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches); @@ -2228,24 +2249,24 @@ namespace BinaryNinja ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0, ExprId f = 0); ExprId AddInstruction(ExprId expr); - ExprId SetVar(size_t size, const BNILVariable& var, ExprId src); - ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src); - ExprId SetVarSplit(size_t size, const BNILVariable& high, const BNILVariable& low, ExprId src); - ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src); - ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, size_t varIndex, int64_t offset, ExprId src); - ExprId SetVarSplitSSA(size_t size, const BNILVariable& high, size_t highIndex, - const BNILVariable& low, size_t lowIndex, ExprId src); - ExprId SetVarAliased(size_t size, const BNILVariable& var, size_t destIndex, size_t srcIndex, ExprId src); - ExprId SetVarFieldAliased(size_t size, const BNILVariable& var, size_t destIndex, size_t srcIndex, + ExprId SetVar(size_t size, const Variable& var, ExprId src); + ExprId SetVarField(size_t size, const Variable& var, int64_t offset, ExprId src); + ExprId SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src); + ExprId SetVarSSA(size_t size, const Variable& var, size_t index, ExprId src); + ExprId SetVarFieldSSA(size_t size, const Variable& var, size_t varIndex, int64_t offset, ExprId src); + ExprId SetVarSplitSSA(size_t size, const Variable& high, size_t highIndex, + const Variable& low, size_t lowIndex, ExprId src); + ExprId SetVarAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, ExprId src); + ExprId SetVarFieldAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, int64_t offset, ExprId src); - ExprId Var(size_t size, const BNILVariable& var); - ExprId VarField(size_t size, const BNILVariable& var, int64_t offset); - ExprId VarSSA(size_t size, const BNILVariable& var, size_t index); - ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex); - ExprId VarAliased(size_t size, const BNILVariable& var, size_t memIndex); - ExprId VarFieldAliased(size_t size, const BNILVariable& var, int64_t offset, size_t memIndex); - ExprId AddressOf(size_t size, const BNILVariable& var); - ExprId AddressOfField(size_t size, const BNILVariable& var, int64_t offset); + ExprId Var(size_t size, const Variable& var); + ExprId VarField(size_t size, const Variable& var, int64_t offset); + ExprId VarSSA(size_t size, const Variable& var, size_t index); + ExprId VarFieldSSA(size_t size, const Variable& var, int64_t offset, size_t varIndex); + ExprId VarAliased(size_t size, const Variable& var, size_t memIndex); + ExprId VarFieldAliased(size_t size, const Variable& var, int64_t offset, size_t memIndex); + ExprId AddressOf(size_t size, const Variable& var); + ExprId AddressOfField(size_t size, const Variable& var, int64_t offset); ExprId Goto(BNMediumLevelILLabel& label); ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); @@ -2255,7 +2276,7 @@ namespace BinaryNinja ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); - BNILVariable GetVariable(ExprId i, size_t varOperand); + Variable GetVariable(ExprId i, size_t varOperand); BNMediumLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; @@ -2278,21 +2299,21 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSAVarDefinition(const BNILVariable& var, size_t idx) const; + size_t GetSSAVarDefinition(const Variable& var, size_t idx) const; size_t GetSSAMemoryDefinition(size_t idx) const; - std::set GetSSAVarUses(const BNILVariable& var, size_t idx) const; + std::set GetSSAVarUses(const Variable& var, size_t idx) const; std::set GetSSAMemoryUses(size_t idx) const; - RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); + RegisterValue GetSSAVarValue(const Variable& var, size_t idx); RegisterValue GetExprValue(size_t expr); - PossibleValueSet GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr); + PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr); PossibleValueSet GetPossibleExprValues(size_t expr); - size_t GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const; + size_t GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const; size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; - BNILVariable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const; - BNILVariable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const; - BNILVariable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const; + Variable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const; + Variable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const; + Variable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const; RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); diff --git a/binaryninjacore.h b/binaryninjacore.h index c43c9b21..68ea4069 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -766,16 +766,16 @@ extern "C" size_t operand; }; - enum BNILVariableSourceType + enum BNVariableSourceType { RegisterVariableSourceType, FlagVariableSourceType, StackVariableSourceType }; - struct BNILVariable + struct BNVariable { - BNILVariableSourceType type; + BNVariableSourceType type; uint32_t index; int64_t identifier; }; @@ -1129,11 +1129,11 @@ extern "C" uint32_t (*getFloatReturnValueRegister)(void* ctxt); }; - struct BNStackVariable + struct BNVariableNameAndType { + BNVariable var; BNType* type; char* name; - int64_t offset; bool autoDefined; }; @@ -1929,14 +1929,25 @@ extern "C" uint64_t len, size_t* count); BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings); - BINARYNINJACOREAPI BNStackVariable* BNGetStackLayout(BNFunction* func, size_t* count); - BINARYNINJACOREAPI void BNFreeStackLayout(BNStackVariable* vars, size_t count); + BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count); BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); BINARYNINJACOREAPI void BNDeleteAutoStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset); - BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, int64_t offset, BNStackVariable* var); - BINARYNINJACOREAPI void BNFreeStackVariable(BNStackVariable* var); + BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, BNArchitecture* arch, uint64_t addr, + int64_t offset, BNVariableNameAndType* var); + BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var); + + BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type, + const char* name, bool singleOnly); + BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type, + const char* name, bool singleOnly); + BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI void BNSetAutoIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source, BNArchitectureAndAddress* branches, size_t count); @@ -2272,29 +2283,29 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func, - const BNILVariable* var, size_t idx); + const BNVariable* var, size_t idx); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx); - BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNILVariable* var, + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNVariable* var, size_t idx, size_t* count); BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, size_t idx, size_t* count); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, - const BNILVariable* var, size_t idx); + const BNVariable* var, size_t idx); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, - const BNILVariable* var, size_t idx, size_t instr); + const BNVariable* var, size_t idx, size_t instr); BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, - const BNILVariable* var, size_t instr); + const BNVariable* var, size_t instr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, size_t instr); - BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func, uint32_t reg, size_t instr); - BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForFlagAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForFlagAtInstruction(BNMediumLevelILFunction* func, uint32_t flag, size_t instr); - BINARYNINJACOREAPI BNILVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(BNMediumLevelILFunction* func, int64_t offset, size_t instr); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAtInstruction(BNMediumLevelILFunction* func, diff --git a/function.cpp b/function.cpp index 16ad1f1c..c3402eea 100644 --- a/function.cpp +++ b/function.cpp @@ -24,6 +24,69 @@ using namespace BinaryNinja; using namespace std; +Variable::Variable() +{ + type = RegisterVariableSourceType; + index = 0; + identifier = 0; +} + + +Variable::Variable(BNVariableSourceType t, uint32_t i, uint64_t id) +{ + type = t; + index = i; + identifier = id; +} + + +Variable::Variable(const BNVariable& var) +{ + type = var.type; + index = var.index; + identifier = var.identifier; +} + + +Variable& Variable::operator=(const Variable& var) +{ + type = var.type; + index = var.index; + identifier = var.identifier; + return *this; +} + + +bool Variable::operator==(const Variable& var) const +{ + if (type != var.type) + return false; + if (index != var.index) + return false; + return identifier == var.identifier; +} + + +bool Variable::operator!=(const Variable& var) const +{ + return !((*this) == var); +} + + +bool Variable::operator<(const Variable& var) const +{ + if (type < var.type) + return true; + if (type > var.type) + return false; + if (index < var.index) + return true; + if (index > var.index) + return false; + return identifier < var.identifier; +} + + Function::Function(BNFunction* func) { m_object = func; @@ -414,23 +477,23 @@ Ref Function::CreateFunctionGraph() } -map Function::GetStackLayout() +map> Function::GetStackLayout() { size_t count; - BNStackVariable* vars = BNGetStackLayout(m_object, &count); + BNVariableNameAndType* vars = BNGetStackLayout(m_object, &count); - map result; + map> result; for (size_t i = 0; i < count; i++) { - StackVariable var; + VariableNameAndType var; var.name = vars[i].name; var.type = new Type(BNNewTypeReference(vars[i].type)); - var.offset = vars[i].offset; + var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; - result[vars[i].offset] = var; + result[vars[i].var.identifier].push_back(var); } - BNFreeStackLayout(vars, count); + BNFreeVariableList(vars, count); return result; } @@ -459,22 +522,86 @@ void Function::DeleteUserStackVariable(int64_t offset) } -bool Function::GetStackVariableAtFrameOffset(int64_t offset, StackVariable& result) +bool Function::GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, + int64_t offset, VariableNameAndType& result) { - BNStackVariable var; - if (!BNGetStackVariableAtFrameOffset(m_object, offset, &var)) + BNVariableNameAndType var; + if (!BNGetStackVariableAtFrameOffset(m_object, arch->GetObject(), addr, offset, &var)) return false; result.type = new Type(BNNewTypeReference(var.type)); result.name = var.name; - result.offset = var.offset; + result.var = var.var; result.autoDefined = var.autoDefined; - BNFreeStackVariable(&var); + BNFreeVariableNameAndType(&var); return true; } +map Function::GetVariables() +{ + size_t count; + BNVariableNameAndType* vars = BNGetFunctionVariables(m_object, &count); + + map result; + for (size_t i = 0; i < count; i++) + { + VariableNameAndType var; + var.name = vars[i].name; + var.type = new Type(BNNewTypeReference(vars[i].type)); + var.var = vars[i].var; + var.autoDefined = vars[i].autoDefined; + result[vars[i].var] = var; + } + + BNFreeVariableList(vars, count); + return result; +} + + +void Function::CreateAutoVariable(const Variable& var, Ref type, const string& name, bool singleOnly) +{ + BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), singleOnly); +} + + +void Function::CreateUserVariable(const Variable& var, Ref type, const string& name, bool singleOnly) +{ + BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), singleOnly); +} + + +void Function::DeleteAutoVariable(const Variable& var) +{ + BNDeleteAutoVariable(m_object, &var); +} + + +void Function::DeleteUserVariable(const Variable& var) +{ + BNDeleteAutoVariable(m_object, &var); +} + + +Ref Function::GetVariableType(const Variable& var) +{ + BNType* type = BNGetVariableType(m_object, &var); + if (!type) + return nullptr; + return new Type(type); +} + + +string Function::GetVariableName(const Variable& var) +{ + char* name = BNGetVariableName(m_object, &var); + string result = name; + BNFreeString(name); + return result; +} + + void Function::SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches) { BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index b0eb83a1..4ec5d69e 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -73,34 +73,34 @@ ExprId MediumLevelILFunction::AddInstruction(size_t expr) } -ExprId MediumLevelILFunction::SetVar(size_t size, const BNILVariable& var, ExprId src) +ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& var, ExprId src) { return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, src); } -ExprId MediumLevelILFunction::SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src) +ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& var, int64_t offset, ExprId src) { return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset, src); } -ExprId MediumLevelILFunction::SetVarSplit(size_t size, const BNILVariable& high, const BNILVariable& low, ExprId src) +ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src) { return AddExpr(MLIL_SET_VAR_SPLIT, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, high.identifier, ((uint64_t)low.type << 32) | (uint64_t)low.index, low.identifier, src); } -ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, size_t varIndex, ExprId src) +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const Variable& var, size_t varIndex, ExprId src) { return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex, src); } -ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, size_t varIndex, +ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const Variable& var, size_t varIndex, int64_t offset, ExprId src) { return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, @@ -108,8 +108,8 @@ ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& va } -ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const BNILVariable& high, size_t highIndex, - const BNILVariable& low, size_t lowIndex, ExprId src) +ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const Variable& high, size_t highIndex, + const Variable& low, size_t lowIndex, ExprId src) { return AddExpr(MLIL_SET_VAR_SPLIT_SSA, size, AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, @@ -119,7 +119,7 @@ ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const BNILVariable& hi } -ExprId MediumLevelILFunction::SetVarAliased(size_t size, const BNILVariable& var, size_t destIndex, +ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, ExprId src) { return AddExpr(MLIL_SET_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, @@ -127,7 +127,7 @@ ExprId MediumLevelILFunction::SetVarAliased(size_t size, const BNILVariable& var } -ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const BNILVariable& var, size_t destIndex, +ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, int64_t offset, ExprId src) { return AddExpr(MLIL_SET_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, @@ -135,25 +135,25 @@ ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const BNILVariable } -ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var) +ExprId MediumLevelILFunction::Var(size_t size, const Variable& var) { return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); } -ExprId MediumLevelILFunction::VarField(size_t size, const BNILVariable& var, int64_t offset) +ExprId MediumLevelILFunction::VarField(size_t size, const Variable& var, int64_t offset) { return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset); } -ExprId MediumLevelILFunction::VarSSA(size_t size, const BNILVariable& var, size_t varIndex) +ExprId MediumLevelILFunction::VarSSA(size_t size, const Variable& var, size_t varIndex) { return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex); } -ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, +ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const Variable& var, int64_t offset, size_t varIndex) { return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, @@ -161,26 +161,26 @@ ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, } -ExprId MediumLevelILFunction::VarAliased(size_t size, const BNILVariable& var, size_t memIndex) +ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& var, size_t memIndex) { return AddExpr(MLIL_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, memIndex); } -ExprId MediumLevelILFunction::VarFieldAliased(size_t size, const BNILVariable& var, int64_t offset, size_t memIndex) +ExprId MediumLevelILFunction::VarFieldAliased(size_t size, const Variable& var, int64_t offset, size_t memIndex) { return AddExpr(MLIL_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset, memIndex); } -ExprId MediumLevelILFunction::AddressOf(size_t size, const BNILVariable& var) +ExprId MediumLevelILFunction::AddressOf(size_t size, const Variable& var) { return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); } -ExprId MediumLevelILFunction::AddressOfField(size_t size, const BNILVariable& var, int64_t offset) +ExprId MediumLevelILFunction::AddressOfField(size_t size, const Variable& var, int64_t offset) { return AddExpr(MLIL_ADDRESS_OF_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset); @@ -239,11 +239,11 @@ ExprId MediumLevelILFunction::AddOperandList(const vector operands) } -BNILVariable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) +Variable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) { BNMediumLevelILInstruction instr = (*this)[i]; - BNILVariable result; - result.type = (BNILVariableSourceType)(instr.operands[varOperand] >> 32); + Variable result; + result.type = (BNVariableSourceType)(instr.operands[varOperand] >> 32); result.index = (uint32_t)instr.operands[varOperand]; result.identifier = instr.operands[varOperand + 1]; return result; @@ -396,7 +396,7 @@ size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t MediumLevelILFunction::GetSSAVarDefinition(const BNILVariable& var, size_t idx) const +size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t idx) const { return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx); } @@ -408,7 +408,7 @@ size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const } -set MediumLevelILFunction::GetSSAVarUses(const BNILVariable& var, size_t idx) const +set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t idx) const { size_t count; size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count); @@ -436,7 +436,7 @@ set MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const BNILVariable& var, size_t idx) +RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t idx) { BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx); return RegisterValue::FromAPIObject(value); @@ -450,7 +450,7 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const BNILVariable& var, size_t idx, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr) { BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); return PossibleValueSet::FromAPIObject(value); @@ -464,7 +464,7 @@ PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) } -size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const BNILVariable& var, size_t instr) const +size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const { return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr); } @@ -476,19 +476,19 @@ size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const } -BNILVariable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const +Variable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const { return BNGetMediumLevelILVariableForRegisterAtInstruction(m_object, reg, instr); } -BNILVariable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const +Variable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const { return BNGetMediumLevelILVariableForFlagAtInstruction(m_object, flag, instr); } -BNILVariable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const +Variable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const { return BNGetMediumLevelILVariableForStackLocationAtInstruction(m_object, offset, instr); } diff --git a/python/function.py b/python/function.py index 51d61792..74f4b0f8 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,7 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType) import architecture import highlight import associateddatastore @@ -146,14 +146,20 @@ class PossibleValueSet(object): return "" -class StackVariable(object): - def __init__(self, ofs, name, t): - self.offset = ofs +class VariableNameAndType(object): + def __init__(self, var, name, t): + self.var = var self.name = name self.type = t def __repr__(self): - return "" % (self.offset, self.type, self.name) + if self.var.type == VariableSourceType.StackVariableSourceType: + return "" % (self.var.identifier, self.type, self.name) + elif self.var.type == VariableSourceType.RegisterVariableSourceType: + return "" % (self.var.function.arch.get_reg_name(self.var.identifier), self.type, self.name) + elif self.var.type == VariableSourceType.FlagVariableSourceType: + return "" % (self.var.function.arch.get_flag_name(self.var.identifier), self.type, self.name) + return "" % (self.var, self.type, self.name) def __str__(self): return self.name @@ -179,7 +185,7 @@ class StackVariableReference(object): return "" % (self.source_operand, self.name) -class ILVariable(object): +class Variable(object): def __init__(self, func, var_type, index, identifier): self.function = func self.type = var_type @@ -363,14 +369,27 @@ class Function(object): @property def stack_layout(self): - """List of function stack (read-only)""" + """List of function stack variables (read-only)""" count = ctypes.c_ulonglong() v = core.BNGetStackLayout(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(StackVariable(v[i].offset, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) - result.sort(key = lambda x: x.offset) - core.BNFreeStackLayout(v, count.value) + var = Variable(self, v[i].var.type, v[i].var.index, v[i].var.identifier) + result.append(VariableNameAndType(var, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) + result.sort(key = lambda x: x.var.identifier) + core.BNFreeVariableList(v, count.value) + return result + + @property + def vars(self): + """List of function variables (read-only)""" + count = ctypes.c_ulonglong() + v = core.BNGetFunctionVariables(self.handle, count) + result = [] + for i in xrange(0, count.value): + var = Variable(self, v[i].var.type, v[i].var.index, v[i].var.identifier) + result.append(VariableNameAndType(var, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) + core.BNFreeVariableList(v, count.value) return result @property diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index dff79fbd..f827819f 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType, ILBranchDependence +from .enums import MediumLevelILOperation, InstructionTextTokenType, VariableSourceType, ILBranchDependence import function import basicblock import lowlevelil @@ -157,11 +157,11 @@ class MediumLevelILInstruction(object): elif operand_type == "expr": value = MediumLevelILInstruction(func, instr.operands[i]) elif operand_type == "var": - var_type = ILVariableSourceType(instr.operands[i] >> 32) + var_type = VariableSourceType(instr.operands[i] >> 32) index = instr.operands[i] & 0xffffffff identifier = instr.operands[i + 1] i += 1 - value = function.ILVariable(self.function, var_type, index, identifier) + value = function.Variable(self.function, var_type, index, identifier) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) @@ -175,10 +175,10 @@ class MediumLevelILInstruction(object): i += 1 value = [] for j in xrange(count.value / 2): - var_type = ILVariableSourceType(operand_list[j * 2] >> 32) + var_type = VariableSourceType(operand_list[j * 2] >> 32) index = operand_list[j * 2] & 0xffffffff identifier = operand_list[(j * 2) + 1] - value.append(function.ILVariable(self.function, var_type, index, identifier)) + value.append(function.Variable(self.function, var_type, index, identifier)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": count = ctypes.c_ulonglong() @@ -186,11 +186,11 @@ class MediumLevelILInstruction(object): i += 1 value = [] for j in xrange(count.value / 3): - var_type = ILVariableSourceType(operand_list[j * 3] >> 32) + var_type = VariableSourceType(operand_list[j * 3] >> 32) index = operand_list[j * 3] & 0xffffffff identifier = operand_list[(j * 3) + 1] var_index = operand_list[(j * 3) + 2] - value.append((function.ILVariable(self.function, var_type, index, identifier), var_index)) + value.append((function.Variable(self.function, var_type, index, identifier), var_index)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() @@ -295,7 +295,7 @@ class MediumLevelILInstruction(object): return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index) def get_ssa_var_possible_values(self, var, index): - var_data = core.BNILVariable() + var_data = core.BNVariable() var_data.type = var.type var_data.index = var.index var_data.identifier = var.identifier @@ -304,7 +304,7 @@ class MediumLevelILInstruction(object): return result def get_ssa_var_index(self, var): - var_data = core.BNILVariable() + var_data = core.BNVariable() var_data.type = var.type var_data.index = var.index var_data.identifier = var.identifier @@ -314,17 +314,17 @@ class MediumLevelILInstruction(object): if isinstance(reg, str): reg = self.function.arch.regs[reg].index result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) - return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.identifier) def get_var_for_flag(self, flag): if isinstance(flag, str): flag = self.function.arch.regs[flag].index result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) - return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.identifier) def get_var_for_stack_location(self, offset): result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) - return function.ILVariable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.identifier) def get_reg_value(self, reg): if isinstance(reg, str): @@ -654,7 +654,7 @@ class MediumLevelILFunction(object): return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) def get_ssa_var_definition(self, var, index): - var_data = core.BNILVariable() + var_data = core.BNVariable() var_data.type = var.type var_data.index = var.index var_data.identifier = var.identifier @@ -671,7 +671,7 @@ class MediumLevelILFunction(object): def get_ssa_var_uses(self, var, index): count = ctypes.c_ulonglong() - var_data = core.BNILVariable() + var_data = core.BNVariable() var_data.type = var.type var_data.index = var.index var_data.identifier = var.identifier @@ -692,7 +692,7 @@ class MediumLevelILFunction(object): return result def get_ssa_var_value(self, var, index): - var_data = core.BNILVariable() + var_data = core.BNVariable() var_data.type = var.type var_data.index = var.index var_data.identifier = var.identifier -- cgit v1.3.1 From d50d190f297afcb9621b39eb1d351e9eae96271b Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 20 Apr 2017 23:25:31 -0400 Subject: Renaming and adding variable identifiers --- binaryninjaapi.h | 11 ++++++--- binaryninjacore.h | 15 ++++++++---- function.cpp | 44 ++++++++++++++++++--------------- mediumlevelil.cpp | 38 ++++++++++++++--------------- python/function.py | 65 +++++++++++++++++++++++++++++-------------------- python/mediumlevelil.py | 38 ++++++++++++++--------------- 6 files changed, 118 insertions(+), 93 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index c6ac8aa3..0371c4ff 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1812,7 +1812,7 @@ namespace BinaryNinja struct Variable: public BNVariable { Variable(); - Variable(BNVariableSourceType type, uint32_t index, uint64_t identifier); + Variable(BNVariableSourceType type, uint32_t index, uint64_t storage); Variable(const BNVariable& var); Variable& operator=(const Variable& var); @@ -1820,6 +1820,9 @@ namespace BinaryNinja bool operator==(const Variable& var) const; bool operator!=(const Variable& var) const; bool operator<(const Variable& var) const; + + uint64_t ToIdentifier() const; + static Variable FromIdentifier(uint64_t id); }; struct VariableNameAndType @@ -1949,8 +1952,10 @@ namespace BinaryNinja bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var); std::map GetVariables(); - void CreateAutoVariable(const Variable& var, Ref type, const std::string& name, bool singleOnly = false); - void CreateUserVariable(const Variable& var, Ref type, const std::string& name, bool singleOnly = false); + void CreateAutoVariable(const Variable& var, Ref type, const std::string& name, + bool ignoreDisjointUses = false); + void CreateUserVariable(const Variable& var, Ref type, const std::string& name, + bool ignoreDisjointUses = false); void DeleteAutoVariable(const Variable& var); void DeleteUserVariable(const Variable& var); Ref GetVariableType(const Variable& var); diff --git a/binaryninjacore.h b/binaryninjacore.h index 68ea4069..1bd97cde 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -65,6 +65,9 @@ #define BN_DEFAULT_MIN_STRING_LENGTH 4 #define BN_MAX_STRING_LENGTH 128 +#define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL +#define BN_MAX_VARIABLE_INDEX 0xfffff + #ifdef __cplusplus extern "C" { @@ -768,16 +771,16 @@ extern "C" enum BNVariableSourceType { + StackVariableSourceType, RegisterVariableSourceType, - FlagVariableSourceType, - StackVariableSourceType + FlagVariableSourceType }; struct BNVariable { BNVariableSourceType type; uint32_t index; - int64_t identifier; + int64_t storage; }; // Callbacks @@ -1941,13 +1944,15 @@ extern "C" BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type, - const char* name, bool singleOnly); + const char* name, bool ignoreDisjointUses); BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type, - const char* name, bool singleOnly); + const char* name, bool ignoreDisjointUses); BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI uint64_t BNToVariableIdentifier(const BNVariable* var); + BINARYNINJACOREAPI BNVariable BNFromVariableIdentifier(uint64_t id); BINARYNINJACOREAPI void BNSetAutoIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source, BNArchitectureAndAddress* branches, size_t count); diff --git a/function.cpp b/function.cpp index c3402eea..b22f91dc 100644 --- a/function.cpp +++ b/function.cpp @@ -28,15 +28,15 @@ Variable::Variable() { type = RegisterVariableSourceType; index = 0; - identifier = 0; + storage = 0; } -Variable::Variable(BNVariableSourceType t, uint32_t i, uint64_t id) +Variable::Variable(BNVariableSourceType t, uint32_t i, uint64_t s) { type = t; index = i; - identifier = id; + storage = s; } @@ -44,7 +44,7 @@ Variable::Variable(const BNVariable& var) { type = var.type; index = var.index; - identifier = var.identifier; + storage = var.storage; } @@ -52,7 +52,7 @@ Variable& Variable::operator=(const Variable& var) { type = var.type; index = var.index; - identifier = var.identifier; + storage = var.storage; return *this; } @@ -63,7 +63,7 @@ bool Variable::operator==(const Variable& var) const return false; if (index != var.index) return false; - return identifier == var.identifier; + return storage == var.storage; } @@ -75,15 +75,19 @@ bool Variable::operator!=(const Variable& var) const bool Variable::operator<(const Variable& var) const { - if (type < var.type) - return true; - if (type > var.type) - return false; - if (index < var.index) - return true; - if (index > var.index) - return false; - return identifier < var.identifier; + return ToIdentifier() < var.ToIdentifier(); +} + + +uint64_t Variable::ToIdentifier() const +{ + return BNToVariableIdentifier(this); +} + + +Variable Variable::FromIdentifier(uint64_t id) +{ + return BNFromVariableIdentifier(id); } @@ -490,7 +494,7 @@ map> Function::GetStackLayout() var.type = new Type(BNNewTypeReference(vars[i].type)); var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; - result[vars[i].var.identifier].push_back(var); + result[vars[i].var.storage].push_back(var); } BNFreeVariableList(vars, count); @@ -560,15 +564,15 @@ map Function::GetVariables() } -void Function::CreateAutoVariable(const Variable& var, Ref type, const string& name, bool singleOnly) +void Function::CreateAutoVariable(const Variable& var, Ref type, const string& name, bool ignoreDisjointUses) { - BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), singleOnly); + BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); } -void Function::CreateUserVariable(const Variable& var, Ref type, const string& name, bool singleOnly) +void Function::CreateUserVariable(const Variable& var, Ref type, const string& name, bool ignoreDisjointUses) { - BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), singleOnly); + BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 4ec5d69e..0b420a82 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -75,27 +75,27 @@ ExprId MediumLevelILFunction::AddInstruction(size_t expr) ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& var, ExprId src) { - return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, src); + return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, src); } ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& var, int64_t offset, ExprId src) { - return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, offset, src); } ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src) { - return AddExpr(MLIL_SET_VAR_SPLIT, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, high.identifier, - ((uint64_t)low.type << 32) | (uint64_t)low.index, low.identifier, src); + return AddExpr(MLIL_SET_VAR_SPLIT, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, high.storage, + ((uint64_t)low.type << 32) | (uint64_t)low.index, low.storage, src); } ExprId MediumLevelILFunction::SetVarSSA(size_t size, const Variable& var, size_t varIndex, ExprId src) { - return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, varIndex, src); } @@ -103,7 +103,7 @@ ExprId MediumLevelILFunction::SetVarSSA(size_t size, const Variable& var, size_t ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const Variable& var, size_t varIndex, int64_t offset, ExprId src) { - return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, varIndex, offset, src); } @@ -113,16 +113,16 @@ ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const Variable& high, { return AddExpr(MLIL_SET_VAR_SPLIT_SSA, size, AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, - high.identifier, highIndex), + high.storage, highIndex), AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)low.type << 32) | (uint64_t)low.index, - low.identifier, lowIndex), src); + low.storage, lowIndex), src); } ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, ExprId src) { - return AddExpr(MLIL_SET_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_SET_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, destIndex, srcIndex, src); } @@ -130,60 +130,60 @@ ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& var, si ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, int64_t offset, ExprId src) { - return AddExpr(MLIL_SET_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_SET_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, destIndex, srcIndex, offset, src); } ExprId MediumLevelILFunction::Var(size_t size, const Variable& var) { - return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); + return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage); } ExprId MediumLevelILFunction::VarField(size_t size, const Variable& var, int64_t offset) { - return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset); + return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, offset); } ExprId MediumLevelILFunction::VarSSA(size_t size, const Variable& var, size_t varIndex) { - return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex); + return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, varIndex); } ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const Variable& var, int64_t offset, size_t varIndex) { - return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, offset, varIndex); } ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& var, size_t memIndex) { - return AddExpr(MLIL_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, memIndex); + return AddExpr(MLIL_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, memIndex); } ExprId MediumLevelILFunction::VarFieldAliased(size_t size, const Variable& var, int64_t offset, size_t memIndex) { - return AddExpr(MLIL_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + return AddExpr(MLIL_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, offset, memIndex); } ExprId MediumLevelILFunction::AddressOf(size_t size, const Variable& var) { - return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); + return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage); } ExprId MediumLevelILFunction::AddressOfField(size_t size, const Variable& var, int64_t offset) { return AddExpr(MLIL_ADDRESS_OF_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, - var.identifier, offset); + var.storage, offset); } @@ -245,7 +245,7 @@ Variable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) Variable result; result.type = (BNVariableSourceType)(instr.operands[varOperand] >> 32); result.index = (uint32_t)instr.operands[varOperand]; - result.identifier = instr.operands[varOperand + 1]; + result.storage = instr.operands[varOperand + 1]; return result; } diff --git a/python/function.py b/python/function.py index 74f4b0f8..bca67a44 100644 --- a/python/function.py +++ b/python/function.py @@ -146,25 +146,6 @@ class PossibleValueSet(object): return "" -class VariableNameAndType(object): - def __init__(self, var, name, t): - self.var = var - self.name = name - self.type = t - - def __repr__(self): - if self.var.type == VariableSourceType.StackVariableSourceType: - return "" % (self.var.identifier, self.type, self.name) - elif self.var.type == VariableSourceType.RegisterVariableSourceType: - return "" % (self.var.function.arch.get_reg_name(self.var.identifier), self.type, self.name) - elif self.var.type == VariableSourceType.FlagVariableSourceType: - return "" % (self.var.function.arch.get_flag_name(self.var.identifier), self.type, self.name) - return "" % (self.var, self.type, self.name) - - def __str__(self): - return self.name - - class StackVariableReference(object): def __init__(self, src_operand, t, name, start_ofs, ref_ofs): self.source_operand = src_operand @@ -186,11 +167,40 @@ class StackVariableReference(object): class Variable(object): - def __init__(self, func, var_type, index, identifier): + def __init__(self, func, source_type, index, storage, name = None, var_type = None): self.function = func - self.type = var_type + self.source_type = source_type self.index = index - self.identifier = identifier + self.storage = storage + + var = core.BNVariable() + var.type = source_type + var.index = index + 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 = core.BNGetVariableType(func.handle, var) + if var_type: + var_type = types.Type(var_type) + + self.name = name + self.type = var_type + + @classmethod + def from_identifier(self, func, identifier): + var = core.BNFromVariableIdentifier(identifier) + return Variable(func, VariableSourceType(var.type), var.index, var.storage) + + def __repr__(self): + if self.type is None: + return "" % self.name + return "" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name()) + + def __str__(self): + return self.name class ConstantReference(object): @@ -374,9 +384,9 @@ class Function(object): v = core.BNGetStackLayout(self.handle, count) result = [] for i in xrange(0, count.value): - var = Variable(self, v[i].var.type, v[i].var.index, v[i].var.identifier) - result.append(VariableNameAndType(var, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) - result.sort(key = lambda x: x.var.identifier) + 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)))) + result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -387,8 +397,9 @@ class Function(object): v = core.BNGetFunctionVariables(self.handle, count) result = [] for i in xrange(0, count.value): - var = Variable(self, v[i].var.type, v[i].var.index, v[i].var.identifier) - result.append(VariableNameAndType(var, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) + 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)))) + result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index f827819f..e959e480 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -159,9 +159,9 @@ class MediumLevelILInstruction(object): elif operand_type == "var": var_type = VariableSourceType(instr.operands[i] >> 32) index = instr.operands[i] & 0xffffffff - identifier = instr.operands[i + 1] + storage = instr.operands[i + 1] i += 1 - value = function.Variable(self.function, var_type, index, identifier) + value = function.Variable(self.function.source_function, var_type, index, storage) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) @@ -177,8 +177,8 @@ class MediumLevelILInstruction(object): for j in xrange(count.value / 2): var_type = VariableSourceType(operand_list[j * 2] >> 32) index = operand_list[j * 2] & 0xffffffff - identifier = operand_list[(j * 2) + 1] - value.append(function.Variable(self.function, var_type, index, identifier)) + storage = operand_list[(j * 2) + 1] + value.append(function.Variable(self.function.source_function, var_type, index, storage)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": count = ctypes.c_ulonglong() @@ -188,9 +188,9 @@ class MediumLevelILInstruction(object): for j in xrange(count.value / 3): var_type = VariableSourceType(operand_list[j * 3] >> 32) index = operand_list[j * 3] & 0xffffffff - identifier = operand_list[(j * 3) + 1] + storage = operand_list[(j * 3) + 1] var_index = operand_list[(j * 3) + 2] - value.append((function.Variable(self.function, var_type, index, identifier), var_index)) + value.append((function.Variable(self.function.source_function, var_type, index, storage), var_index)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() @@ -296,35 +296,35 @@ class MediumLevelILInstruction(object): def get_ssa_var_possible_values(self, var, index): var_data = core.BNVariable() - var_data.type = var.type + var_data.type = var.source_type var_data.index = var.index - var_data.identifier = var.identifier + var_data.storage = var.storage value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_ssa_var_index(self, var): var_data = core.BNVariable() - var_data.type = var.type + var_data.type = var.source_type var_data.index = var.index - var_data.identifier = var.identifier + var_data.storage = var.storage return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index) def get_var_for_reg(self, reg): if isinstance(reg, str): reg = self.function.arch.regs[reg].index result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_flag(self, flag): if isinstance(flag, str): flag = self.function.arch.regs[flag].index result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_stack_location(self, offset): result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.identifier) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_reg_value(self, reg): if isinstance(reg, str): @@ -655,9 +655,9 @@ class MediumLevelILFunction(object): def get_ssa_var_definition(self, var, index): var_data = core.BNVariable() - var_data.type = var.type + var_data.type = var.source_type var_data.index = var.index - var_data.identifier = var.identifier + var_data.storage = var.storage result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) if result >= core.BNGetMediumLevelILInstructionCount(self.handle): return None @@ -672,9 +672,9 @@ class MediumLevelILFunction(object): def get_ssa_var_uses(self, var, index): count = ctypes.c_ulonglong() var_data = core.BNVariable() - var_data.type = var.type + var_data.type = var.source_type var_data.index = var.index - var_data.identifier = var.identifier + var_data.storage = var.storage instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) result = [] for i in xrange(0, count.value): @@ -693,9 +693,9 @@ class MediumLevelILFunction(object): def get_ssa_var_value(self, var, index): var_data = core.BNVariable() - var_data.type = var.type + var_data.type = var.source_type var_data.index = var.index - var_data.identifier = var.identifier + var_data.storage = var.storage value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) result = function.RegisterValue(self.arch, value) return result -- cgit v1.3.1 From e673afe4b958b5f8f808ff8457d0664ccecce93a Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 21 Apr 2017 01:41:34 -0400 Subject: Using variable identifiers in MLIL --- binaryninjaapi.h | 23 +-------- binaryninjacore.h | 5 +- mediumlevelil.cpp | 129 +----------------------------------------------- python/mediumlevelil.py | 27 ++++------ 4 files changed, 14 insertions(+), 170 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 0371c4ff..072bfb5a 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2251,28 +2251,9 @@ namespace BinaryNinja size_t GetInstructionStart(Architecture* arch, uint64_t addr); ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, - ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0, ExprId f = 0); + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); ExprId AddInstruction(ExprId expr); - ExprId SetVar(size_t size, const Variable& var, ExprId src); - ExprId SetVarField(size_t size, const Variable& var, int64_t offset, ExprId src); - ExprId SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src); - ExprId SetVarSSA(size_t size, const Variable& var, size_t index, ExprId src); - ExprId SetVarFieldSSA(size_t size, const Variable& var, size_t varIndex, int64_t offset, ExprId src); - ExprId SetVarSplitSSA(size_t size, const Variable& high, size_t highIndex, - const Variable& low, size_t lowIndex, ExprId src); - ExprId SetVarAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, ExprId src); - ExprId SetVarFieldAliased(size_t size, const Variable& var, size_t destIndex, size_t srcIndex, - int64_t offset, ExprId src); - ExprId Var(size_t size, const Variable& var); - ExprId VarField(size_t size, const Variable& var, int64_t offset); - ExprId VarSSA(size_t size, const Variable& var, size_t index); - ExprId VarFieldSSA(size_t size, const Variable& var, int64_t offset, size_t varIndex); - ExprId VarAliased(size_t size, const Variable& var, size_t memIndex); - ExprId VarFieldAliased(size_t size, const Variable& var, int64_t offset, size_t memIndex); - ExprId AddressOf(size_t size, const Variable& var); - ExprId AddressOfField(size_t size, const Variable& var, int64_t offset); - ExprId Goto(BNMediumLevelILLabel& label); ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); void MarkLabel(BNMediumLevelILLabel& label); @@ -2281,8 +2262,6 @@ namespace BinaryNinja ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); - Variable GetVariable(ExprId i, size_t varOperand); - BNMediumLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionForExpr(size_t expr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 1bd97cde..21592772 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -735,7 +735,6 @@ extern "C" MLIL_SET_VAR_SSA, MLIL_SET_VAR_SSA_FIELD, MLIL_SET_VAR_SPLIT_SSA, - MLIL_VAR_SPLIT_DEST_SSA, MLIL_SET_VAR_ALIASED, MLIL_SET_VAR_ALIASED_FIELD, MLIL_VAR_SSA, @@ -758,7 +757,7 @@ extern "C" { BNMediumLevelILOperation operation; size_t size; - uint64_t operands[6]; + uint64_t operands[5]; uint64_t address; }; @@ -2250,7 +2249,7 @@ extern "C" BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, - size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f); + size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 0b420a82..868f3f75 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -61,9 +61,9 @@ size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t a ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, - ExprId a, ExprId b, ExprId c, ExprId d, ExprId e, ExprId f) + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { - return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e, f); + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); } @@ -73,120 +73,6 @@ ExprId MediumLevelILFunction::AddInstruction(size_t expr) } -ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& var, ExprId src) -{ - return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, src); -} - - -ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& var, int64_t offset, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - offset, src); -} - - -ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_SPLIT, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, high.storage, - ((uint64_t)low.type << 32) | (uint64_t)low.index, low.storage, src); -} - - -ExprId MediumLevelILFunction::SetVarSSA(size_t size, const Variable& var, size_t varIndex, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - varIndex, src); -} - - -ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const Variable& var, size_t varIndex, - int64_t offset, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - varIndex, offset, src); -} - - -ExprId MediumLevelILFunction::SetVarSplitSSA(size_t size, const Variable& high, size_t highIndex, - const Variable& low, size_t lowIndex, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_SPLIT_SSA, size, - AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)high.type << 32) | (uint64_t)high.index, - high.storage, highIndex), - AddExpr(MLIL_VAR_SPLIT_DEST_SSA, size, ((uint64_t)low.type << 32) | (uint64_t)low.index, - low.storage, lowIndex), src); -} - - -ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& var, size_t destIndex, - size_t srcIndex, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - destIndex, srcIndex, src); -} - - -ExprId MediumLevelILFunction::SetVarFieldAliased(size_t size, const Variable& var, size_t destIndex, - size_t srcIndex, int64_t offset, ExprId src) -{ - return AddExpr(MLIL_SET_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - destIndex, srcIndex, offset, src); -} - - -ExprId MediumLevelILFunction::Var(size_t size, const Variable& var) -{ - return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage); -} - - -ExprId MediumLevelILFunction::VarField(size_t size, const Variable& var, int64_t offset) -{ - return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, offset); -} - - -ExprId MediumLevelILFunction::VarSSA(size_t size, const Variable& var, size_t varIndex) -{ - return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, varIndex); -} - - -ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const Variable& var, int64_t offset, - size_t varIndex) -{ - return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - offset, varIndex); -} - - -ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& var, size_t memIndex) -{ - return AddExpr(MLIL_VAR_ALIASED, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, memIndex); -} - - -ExprId MediumLevelILFunction::VarFieldAliased(size_t size, const Variable& var, int64_t offset, size_t memIndex) -{ - return AddExpr(MLIL_VAR_ALIASED_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage, - offset, memIndex); -} - - -ExprId MediumLevelILFunction::AddressOf(size_t size, const Variable& var) -{ - return AddExpr(MLIL_ADDRESS_OF, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.storage); -} - - -ExprId MediumLevelILFunction::AddressOfField(size_t size, const Variable& var, int64_t offset) -{ - return AddExpr(MLIL_ADDRESS_OF_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, - var.storage, offset); -} - - ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) { return BNMediumLevelILGoto(m_object, &label); @@ -239,17 +125,6 @@ ExprId MediumLevelILFunction::AddOperandList(const vector operands) } -Variable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) -{ - BNMediumLevelILInstruction instr = (*this)[i]; - Variable result; - result.type = (BNVariableSourceType)(instr.operands[varOperand] >> 32); - result.index = (uint32_t)instr.operands[varOperand]; - result.storage = instr.operands[varOperand + 1]; - return result; -} - - BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const { return BNGetMediumLevelILByIndex(m_object, i); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index e959e480..316e45b7 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from .enums import MediumLevelILOperation, InstructionTextTokenType, VariableSourceType, ILBranchDependence +from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence import function import basicblock import lowlevelil @@ -119,7 +119,6 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], - MediumLevelILOperation.MLIL_VAR_SPLIT_DEST_SSA: [("dest", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], @@ -157,11 +156,7 @@ class MediumLevelILInstruction(object): elif operand_type == "expr": value = MediumLevelILInstruction(func, instr.operands[i]) elif operand_type == "var": - var_type = VariableSourceType(instr.operands[i] >> 32) - index = instr.operands[i] & 0xffffffff - storage = instr.operands[i + 1] - i += 1 - value = function.Variable(self.function.source_function, var_type, index, storage) + value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) @@ -174,23 +169,19 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): - var_type = VariableSourceType(operand_list[j * 2] >> 32) - index = operand_list[j * 2] & 0xffffffff - storage = operand_list[(j * 2) + 1] - value.append(function.Variable(self.function.source_function, var_type, index, storage)) + for j in operand_list: + value.append(function.Variable.from_identifier(self.function.source_function, j)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 3): - var_type = VariableSourceType(operand_list[j * 3] >> 32) - index = operand_list[j * 3] & 0xffffffff - storage = operand_list[(j * 3) + 1] - var_index = operand_list[(j * 3) + 2] - value.append((function.Variable(self.function.source_function, var_type, index, storage), var_index)) + for j in xrange(count.value / 2): + var_id = operand_list[j * 2] + var_index = operand_list[(j * 2) + 2] + value.append((function.Variable.from_identifier(self.function.source_function, + var_id), var_index)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() -- cgit v1.3.1 From 095d7a42a0d2858b4240fbd041d8c22a01c7e571 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 21 Apr 2017 22:08:06 -0400 Subject: Allowing rename of all types of variables --- binaryninjaapi.h | 2 +- binaryninjacore.h | 10 +++++----- function.cpp | 4 ++-- python/function.py | 24 +++++++++++++----------- python/mediumlevelil.py | 4 ++-- 5 files changed, 23 insertions(+), 21 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 072bfb5a..8df46775 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1838,7 +1838,7 @@ namespace BinaryNinja uint32_t sourceOperand; Ref type; std::string name; - int64_t startingOffset; + Variable var; int64_t referencedOffset; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 21592772..69b45c28 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -188,7 +188,7 @@ extern "C" // not be used directly by the architecture plugins CodeSymbolToken = 64, DataSymbolToken = 65, - StackVariableToken = 66, + LocalVariableToken = 66, ImportToken = 67, AddressDisplayToken = 68 }; @@ -196,7 +196,7 @@ extern "C" enum BNInstructionTextTokenContext { NoTokenContext = 0, - StackVariableTokenContext = 1, + LocalVariableTokenContext = 1, DataVariableTokenContext = 2, FunctionReturnTokenContext = 3, ArgumentTokenContext = 4 @@ -212,8 +212,8 @@ extern "C" FunctionHeaderStartLineType, FunctionHeaderEndLineType, FunctionContinuationLineType, - StackVariableLineType, - StackVariableListEndLineType, + LocalVariableLineType, + LocalVariableListEndLineType, FunctionEndLineType, NoteStartLineType, NoteLineType, @@ -1144,7 +1144,7 @@ extern "C" uint32_t sourceOperand; BNType* type; char* name; - int64_t startingOffset; + uint64_t varIdentifier; int64_t referencedOffset; }; diff --git a/function.cpp b/function.cpp index b22f91dc..d4f91db1 100644 --- a/function.cpp +++ b/function.cpp @@ -355,7 +355,7 @@ vector Function::GetStackVariablesReferencedByInstructio ref.sourceOperand = refs[i].sourceOperand; ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr; ref.name = refs[i].name; - ref.startingOffset = refs[i].startingOffset; + ref.var = Variable::FromIdentifier(refs[i].varIdentifier); ref.referencedOffset = refs[i].referencedOffset; result.push_back(ref); } @@ -584,7 +584,7 @@ void Function::DeleteAutoVariable(const Variable& var) void Function::DeleteUserVariable(const Variable& var) { - BNDeleteAutoVariable(m_object, &var); + BNDeleteUserVariable(m_object, &var); } diff --git a/python/function.py b/python/function.py index bca67a44..04187cbe 100644 --- a/python/function.py +++ b/python/function.py @@ -147,29 +147,29 @@ class PossibleValueSet(object): class StackVariableReference(object): - def __init__(self, src_operand, t, name, start_ofs, ref_ofs): + def __init__(self, src_operand, t, name, var, ref_ofs): self.source_operand = src_operand self.type = t self.name = name - self.starting_offset = start_ofs + self.var = var self.referenced_offset = ref_ofs if self.source_operand == 0xffffffff: self.source_operand = None def __repr__(self): if self.source_operand is None: - if self.referenced_offset != self.starting_offset: - return "" % (self.name, self.referenced_offset - self.starting_offset) + if self.referenced_offset != self.var.storage: + return "" % (self.name, self.referenced_offset - self.var.storage) return "" % self.name - if self.referenced_offset != self.starting_offset: - return "" % (self.source_operand, self.name, self.referenced_offset) + if self.referenced_offset != self.var.storage: + return "" % (self.source_operand, self.name, self.var.storage) return "" % (self.source_operand, self.name) class Variable(object): def __init__(self, func, source_type, index, storage, name = None, var_type = None): self.function = func - self.source_type = source_type + self.source_type = VariableSourceType(source_type) self.index = index self.storage = storage @@ -190,9 +190,9 @@ class Variable(object): self.type = var_type @classmethod - def from_identifier(self, func, identifier): + def from_identifier(self, func, identifier, name = None, var_type = None): var = core.BNFromVariableIdentifier(identifier) - return Variable(func, VariableSourceType(var.type), var.index, var.storage) + return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type) def __repr__(self): if self.type is None: @@ -603,8 +603,10 @@ class Function(object): refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(StackVariableReference(refs[i].sourceOperand, types.Type(core.BNNewTypeReference(refs[i].type)), - refs[i].name, refs[i].startingOffset, refs[i].referencedOffset)) + var_type = types.Type(core.BNNewTypeReference(refs[i].type)) + result.append(StackVariableReference(refs[i].sourceOperand, var_type, + refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type), + refs[i].referencedOffset)) core.BNFreeStackVariableReferenceList(refs, count.value) return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 316e45b7..bc7a5c89 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -169,8 +169,8 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in operand_list: - value.append(function.Variable.from_identifier(self.function.source_function, j)) + for j in xrange(count.value): + value.append(function.Variable.from_identifier(self.function.source_function, operand_list[j])) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": count = ctypes.c_ulonglong() -- cgit v1.3.1 From 66c7accacdbc73ed4edb7e9bada54085a3272426 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 21 Apr 2017 22:45:19 -0400 Subject: Add Python variable creation APIs --- python/function.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'python') diff --git a/python/function.py b/python/function.py index 04187cbe..b3533f92 100644 --- a/python/function.py +++ b/python/function.py @@ -841,6 +841,57 @@ class Function(object): color = highlight.HighlightColor(color) core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct()) + def create_auto_stack_var(self, offset, var_type, name): + core.BNCreateAutoStackVariable(self.handle, offset, var_type.handle, name) + + def create_user_stack_var(self, offset, var_type, name): + core.BNCreateUserStackVariable(self.handle, offset, var_type.handle, name) + + def delete_auto_stack_var(self, offset): + core.BNDeleteAutoStackVariable(self.handle, offset) + + def delete_user_stack_var(self, offset): + core.BNDeleteUserStackVariable(self.handle, offset) + + def create_auto_var(self, var, var_type, name, ignore_disjoint_uses = False): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNCreateAutoVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + + def create_user_var(self, var, var_type, name, ignore_disjoint_uses = False): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNCreateUserVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + + def delete_auto_var(self, var): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNDeleteAutoVariable(self.handle, var_data) + + def delete_user_var(self, var): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNDeleteUserVariable(self.handle, var_data) + + def get_stack_var_at_frame_offset(self, offset, addr, arch=None): + if arch is None: + arch = self.arch + found_var = core.BNVariableNameAndType() + if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var): + return None + result = Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage, + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type))) + core.BNFreeVariableNameAndType(found_var) + return result + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): -- cgit v1.3.1 From ae147a96b2c0b9540113a2a1598c8f6c720534fb Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Sat, 22 Apr 2017 09:43:52 -0400 Subject: Type check ssa functions (#657) * Changed Function.get_low_level_il_at and Function.get_lifted_il_at to return a LowLevelILInstruction instead of an instruction index. * Added type check to get_ssa_* functions --- python/function.py | 10 +++++----- python/lowlevelil.py | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index 18856ff2..0ee55f32 100644 --- a/python/function.py +++ b/python/function.py @@ -458,20 +458,20 @@ class Function(object): def get_low_level_il_at(self, addr, arch=None): """ - ``get_low_level_il_at`` gets the LowLevelIL instruction address corresponding to the given virtual address + ``get_low_level_il_at`` gets the LowLevelILInstruction corresponding to the given virtual address :param int addr: virtual address of the function to be queried :param Architecture arch: (optional) Architecture for the given function - :rtype: int + :rtype: LowLevelILInstruction :Example: >>> func = bv.functions[0] >>> func.get_low_level_il_at(func.start) - 0L + """ if arch is None: arch = self.arch - return core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr) + return self.low_level_il[core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)] def get_low_level_il_exits_at(self, addr, arch=None): if arch is None: @@ -624,7 +624,7 @@ class Function(object): def get_lifted_il_at(self, addr, arch=None): if arch is None: arch = self.arch - return core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr) + return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)] def get_lifted_il_flag_uses_for_definition(self, i, flag): if isinstance(flag, str): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index a737d95e..3634cca2 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1478,12 +1478,16 @@ class LowLevelILFunction(object): return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr) def get_ssa_reg_definition(self, reg, index): + if isinstance(reg, str): + reg = self.arch.regs[reg].index result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None return result def get_ssa_flag_definition(self, flag, index): + if isinstance(flag, str): + flag = self.arch.get_flag_by_name(flag) result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None @@ -1496,6 +1500,8 @@ class LowLevelILFunction(object): return result def get_ssa_reg_uses(self, reg, index): + if isinstance(reg, str): + reg = self.arch.regs[reg].index count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count) result = [] @@ -1505,6 +1511,8 @@ class LowLevelILFunction(object): return result def get_ssa_flag_uses(self, flag, index): + if isinstance(flag, str): + flag = self.arch.get_flag_by_name(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count) result = [] -- cgit v1.3.1 From 83011a9ed7aee1dd64692aef874350ce0db289b0 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 25 Apr 2017 17:51:46 -0400 Subject: function.platform now correctly returns the functions platform --- python/function.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index 0ee55f32..d54cf25a 100644 --- a/python/function.py +++ b/python/function.py @@ -28,6 +28,7 @@ from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTok HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType) import architecture +import platform import highlight import associateddatastore import types @@ -293,10 +294,10 @@ class Function(object): @property def platform(self): """Function platform (read-only)""" - platform = core.BNGetFunctionPlatform(self.handle) - if platform is None: + plat = core.BNGetFunctionPlatform(self.handle) + if plat is None: return None - return platform.Platform(None, handle = platform) + return platform.Platform(None, handle = plat) @property def start(self): -- cgit v1.3.1 From 6ef07eaf6f26b41fa9c10b9cacf02f6893b0017a Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 25 Apr 2017 19:05:39 -0400 Subject: Fix invalid index in phi list --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index bc7a5c89..f205714e 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -179,7 +179,7 @@ class MediumLevelILInstruction(object): value = [] for j in xrange(count.value / 2): var_id = operand_list[j * 2] - var_index = operand_list[(j * 2) + 2] + var_index = operand_list[(j * 2) + 1] value.append((function.Variable.from_identifier(self.function.source_function, var_id), var_index)) core.BNMediumLevelILFreeOperandList(operand_list) -- cgit v1.3.1 From 448097c6eca321519f2de88619afa804ad6d4ef9 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 27 Apr 2017 00:40:07 -0400 Subject: Adding an API for performance debugging --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 9 +++++++++ function.cpp | 13 +++++++++++++ python/function.py | 10 ++++++++++ 4 files changed, 34 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index ab84afc4..8812e7c9 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1997,6 +1997,8 @@ namespace BinaryNinja void RequestAdvancedAnalysisData(); void ReleaseAdvancedAnalysisData(); void ReleaseAdvancedAnalysisData(size_t count); + + std::map GetAnalysisPerformanceInfo(); }; class AdvancedFunctionAnalysisDataRequestor diff --git a/binaryninjacore.h b/binaryninjacore.h index 7e9a034f..dcd9941c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1456,6 +1456,12 @@ extern "C" BNILBranchDependence dependence; }; + struct BNPerformanceInfo + { + char* name; + double seconds; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -2101,6 +2107,9 @@ extern "C" BINARYNINJACOREAPI void BNSetAutoBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color); BINARYNINJACOREAPI void BNSetUserBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color); + BINARYNINJACOREAPI BNPerformanceInfo* BNGetFunctionAnalysisPerformanceInfo(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNFreeAnalysisPerformanceInfo(BNPerformanceInfo* info, size_t count); + // Disassembly settings BINARYNINJACOREAPI BNDisassemblySettings* BNCreateDisassemblySettings(void); BINARYNINJACOREAPI BNDisassemblySettings* BNNewDisassemblySettingsReference(BNDisassemblySettings* settings); diff --git a/function.cpp b/function.cpp index d4f91db1..194153a8 100644 --- a/function.cpp +++ b/function.cpp @@ -861,6 +861,19 @@ void Function::ReleaseAdvancedAnalysisData() } +map Function::GetAnalysisPerformanceInfo() +{ + size_t count; + BNPerformanceInfo* info = BNGetFunctionAnalysisPerformanceInfo(m_object, &count); + + map result; + for (size_t i = 0; i < count; i++) + result[info[i].name] = info[i].seconds; + BNFreeAnalysisPerformanceInfo(info, count); + return result; +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/python/function.py b/python/function.py index d54cf25a..2a0176c9 100644 --- a/python/function.py +++ b/python/function.py @@ -426,6 +426,16 @@ class Function(object): else: return Function._associated_data[handle.value] + @property + def analysis_performance_info(self): + count = ctypes.c_ulonglong() + info = core.BNGetFunctionAnalysisPerformanceInfo(self.handle, count) + result = {} + for i in xrange(0, count.value): + result[info[i].name] = info[i].seconds + core.BNFreeAnalysisPerformanceInfo(info, count.value) + return result + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) -- cgit v1.3.1 From 62a96d238dcfe93542f495c0a303baf2d4b3e046 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 2 May 2017 21:30:09 -0400 Subject: Make plugin loading errors show up in error console --- python/log.py | 5 ----- python/scriptingprovider.py | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/python/log.py b/python/log.py index 45adb4aa..f09b94a1 100644 --- a/python/log.py +++ b/python/log.py @@ -23,11 +23,6 @@ import _binaryninjacore as core -def redirect_output_to_log(): - global _output_to_log - _output_to_log = True - - def log(level, text): """ ``log`` writes messages to the log console for the given log level. diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 71402b1b..1fe5d1e3 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -38,6 +38,11 @@ import log _output_to_log = False +def redirect_output_to_log(): + global _output_to_log + _output_to_log = True + + class _ThreadActionContext(object): _actions = [] -- cgit v1.3.1 From 597a190065ed23553c8351905803b6b5699c18cd Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 2 May 2017 22:16:52 -0400 Subject: add method to query log output state --- python/examples/bin_info.py | 1 - python/log.py | 13 +++++++++++++ python/scriptingprovider.py | 11 +---------- 3 files changed, 14 insertions(+), 11 deletions(-) (limited to 'python') diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py index 4c4ab8fd..495fb5b5 100644 --- a/python/examples/bin_info.py +++ b/python/examples/bin_info.py @@ -38,7 +38,6 @@ def get_bininfo(bv): sys.exit(1) bv = BinaryViewType.get_view_of_file(filename) - log.redirect_output_to_log() log.log_to_stdout(True) contents = "## %s ##\n" % bv.file.filename diff --git a/python/log.py b/python/log.py index f09b94a1..850772f1 100644 --- a/python/log.py +++ b/python/log.py @@ -23,6 +23,19 @@ import _binaryninjacore as core +_output_to_log = False + + +def redirect_output_to_log(): + global _output_to_log + _output_to_log = True + + +def is_output_redirected_to_log(): + global _output_to_log + return _output_to_log + + def log(level, text): """ ``log`` writes messages to the log console for the given log level. diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 1fe5d1e3..859f262e 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -35,13 +35,6 @@ import basicblock import startup import log -_output_to_log = False - - -def redirect_output_to_log(): - global _output_to_log - _output_to_log = True - class _ThreadActionContext(object): _actions = [] @@ -384,14 +377,12 @@ class _PythonScriptingInstanceOutput(object): return self.write('\n'.join(lines)) def write(self, data): - global _output_to_log - interpreter = None if "value" in dir(PythonScriptingInstance._interpreter): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: - if _output_to_log: + if log.is_output_redirected_to_log(): self.buffer += data while True: i = self.buffer.find('\n') -- cgit v1.3.1 From 362b82012d980f06c98b54b8032c4912ff5c8893 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 2 May 2017 18:11:21 -0400 Subject: Renaming SSA index to version, more uniform register and variable representation in IL --- binaryninjaapi.h | 32 +++---- binaryninjacore.h | 36 ++++---- lowlevelil.cpp | 32 +++---- mediumlevelil.cpp | 32 +++---- python/architecture.py | 14 +++ python/function.py | 12 +-- python/lowlevelil.py | 229 ++++++++++++++++++++++++++++++++---------------- python/mediumlevelil.py | 220 +++++++++++++++++++++++++++++++++------------- 8 files changed, 396 insertions(+), 211 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8812e7c9..41beb852 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2206,15 +2206,15 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSARegisterDefinition(uint32_t reg, size_t idx) const; - size_t GetSSAFlagDefinition(uint32_t flag, size_t idx) const; - size_t GetSSAMemoryDefinition(size_t idx) const; - std::set GetSSARegisterUses(uint32_t reg, size_t idx) const; - std::set GetSSAFlagUses(uint32_t flag, size_t idx) const; - std::set GetSSAMemoryUses(size_t idx) const; + size_t GetSSARegisterDefinition(uint32_t reg, size_t version) const; + size_t GetSSAFlagDefinition(uint32_t flag, size_t version) const; + size_t GetSSAMemoryDefinition(size_t version) const; + std::set GetSSARegisterUses(uint32_t reg, size_t version) const; + std::set GetSSAFlagUses(uint32_t flag, size_t version) const; + std::set GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx); - RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); + RegisterValue GetSSARegisterValue(uint32_t reg, size_t version); + RegisterValue GetSSAFlagValue(uint32_t flag, size_t version); RegisterValue GetExprValue(size_t expr); PossibleValueSet GetPossibleExprValues(size_t expr); @@ -2287,18 +2287,18 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSAVarDefinition(const Variable& var, size_t idx) const; - size_t GetSSAMemoryDefinition(size_t idx) const; - std::set GetSSAVarUses(const Variable& var, size_t idx) const; - std::set GetSSAMemoryUses(size_t idx) const; + size_t GetSSAVarDefinition(const Variable& var, size_t version) const; + size_t GetSSAMemoryDefinition(size_t version) const; + std::set GetSSAVarUses(const Variable& var, size_t version) const; + std::set GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSAVarValue(const Variable& var, size_t idx); + RegisterValue GetSSAVarValue(const Variable& var, size_t version); RegisterValue GetExprValue(size_t expr); - PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr); + PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); PossibleValueSet GetPossibleExprValues(size_t expr); - size_t GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const; - size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; + size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const; + size_t GetSSAMemoryVersionAtInstruction(size_t instr) const; Variable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const; Variable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const; Variable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index dcd9941c..730cbe8d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2257,19 +2257,21 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILSSAExprIndex(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAExprIndex(BNLowLevelILFunction* func, size_t expr); - BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); - BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); - BINARYNINJACOREAPI size_t BNGetLowLevelILSSAMemoryDefinition(BNLowLevelILFunction* func, size_t idx); - BINARYNINJACOREAPI size_t* BNGetLowLevelILSSARegisterUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, + BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, + uint32_t reg, size_t version); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, + uint32_t reg, size_t version); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAMemoryDefinition(BNLowLevelILFunction* func, size_t version); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSARegisterUses(BNLowLevelILFunction* func, + uint32_t reg, size_t version, size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAFlagUses(BNLowLevelILFunction* func, uint32_t reg, size_t version, size_t* count); - BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAFlagUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, - size_t* count); - BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t idx, size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t version, size_t* count); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSARegisterValue(BNLowLevelILFunction* func, - uint32_t reg, size_t idx); + uint32_t reg, size_t version); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAFlagValue(BNLowLevelILFunction* func, - uint32_t flag, size_t idx); + uint32_t flag, size_t version); BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr); @@ -2352,23 +2354,23 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func, - const BNVariable* var, size_t idx); - BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx); + const BNVariable* var, size_t version); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t version); BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNVariable* var, - size_t idx, size_t* count); + size_t version, size_t* count); BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, - size_t idx, size_t* count); + size_t version, size_t* count); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, - const BNVariable* var, size_t idx); + const BNVariable* var, size_t version); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, - const BNVariable* var, size_t idx, size_t instr); + const BNVariable* var, size_t version, size_t instr); BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); - BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarVersionAtILInstruction(BNMediumLevelILFunction* func, const BNVariable* var, size_t instr); - BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryVersionAtILInstruction(BNMediumLevelILFunction* func, size_t instr); BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func, uint32_t reg, size_t instr); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 9764445e..d266c2c9 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -699,28 +699,28 @@ size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t idx) const +size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t version) const { - return BNGetLowLevelILSSARegisterDefinition(m_object, reg, idx); + return BNGetLowLevelILSSARegisterDefinition(m_object, reg, version); } -size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t idx) const +size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t version) const { - return BNGetLowLevelILSSAFlagDefinition(m_object, flag, idx); + return BNGetLowLevelILSSAFlagDefinition(m_object, flag, version); } -size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t version) const { - return BNGetLowLevelILSSAMemoryDefinition(m_object, idx); + return BNGetLowLevelILSSAMemoryDefinition(m_object, version); } -set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) const +set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) const { size_t count; - size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, idx, &count); + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, version, &count); set result; for (size_t i = 0; i < count; i++) @@ -731,10 +731,10 @@ set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) con } -set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const +set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t version) const { size_t count; - size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, idx, &count); + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, version, &count); set result; for (size_t i = 0; i < count; i++) @@ -745,10 +745,10 @@ set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const } -set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const +set LowLevelILFunction::GetSSAMemoryUses(size_t version) const { size_t count; - size_t* instrs = BNGetLowLevelILSSAMemoryUses(m_object, idx, &count); + size_t* instrs = BNGetLowLevelILSSAMemoryUses(m_object, version, &count); set result; for (size_t i = 0; i < count; i++) @@ -759,16 +759,16 @@ set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const } -RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t idx) +RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t version) { - BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, idx); + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, version); return RegisterValue::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t idx) +RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t version) { - BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, idx); + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, version); return RegisterValue::FromAPIObject(value); } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 868f3f75..75c99a54 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -271,22 +271,22 @@ size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t idx) const +size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t version) const { - return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx); + return BNGetMediumLevelILSSAVarDefinition(m_object, &var, version); } -size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t version) const { - return BNGetMediumLevelILSSAMemoryDefinition(m_object, idx); + return BNGetMediumLevelILSSAMemoryDefinition(m_object, version); } -set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t idx) const +set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t version) const { size_t count; - size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count); + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, version, &count); set result; for (size_t i = 0; i < count; i++) @@ -297,10 +297,10 @@ set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t idx } -set MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const +set MediumLevelILFunction::GetSSAMemoryUses(size_t version) const { size_t count; - size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, idx, &count); + size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, version, &count); set result; for (size_t i = 0; i < count; i++) @@ -311,9 +311,9 @@ set MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t idx) +RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) { - BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx); + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); return RegisterValue::FromAPIObject(value); } @@ -325,9 +325,9 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr) +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr) { - BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, version, instr); return PossibleValueSet::FromAPIObject(value); } @@ -339,15 +339,15 @@ PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) } -size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const +size_t MediumLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const { - return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr); + return BNGetMediumLevelILSSAVarVersionAtILInstruction(m_object, &var, instr); } -size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const +size_t MediumLevelILFunction::GetSSAMemoryVersionAtInstruction(size_t instr) const { - return BNGetMediumLevelILSSAMemoryIndexAtILInstruction(m_object, instr); + return BNGetMediumLevelILSSAMemoryVersionAtILInstruction(m_object, instr); } diff --git a/python/architecture.py b/python/architecture.py index d3778613..60c8a1dd 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1232,6 +1232,20 @@ class Architecture(object): """ return core.BNGetArchitectureFlagName(self.handle, flag) + def get_reg_index(self, reg): + if isinstance(reg, str): + return self.regs[reg].index + elif isinstance(reg, lowlevelil.ILRegister): + return reg.index + return reg + + def get_flag_index(self, flag): + if isinstance(flag, str): + return self._flags[flag] + elif isinstance(flag, lowlevelil.ILFlag): + return flag.index + return flag + def get_flag_write_type_name(self, write_type): """ ``get_flag_write_type_name`` gets the flag write type name for the given flag. diff --git a/python/function.py b/python/function.py index 2a0176c9..509d9b3b 100644 --- a/python/function.py +++ b/python/function.py @@ -510,8 +510,7 @@ class Function(object): """ if arch is None: arch = self.arch - if isinstance(reg, str): - reg = arch.regs[reg].index + reg = arch.get_reg_index(reg) value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) return result @@ -531,8 +530,7 @@ class Function(object): """ if arch is None: arch = self.arch - if isinstance(reg, str): - reg = arch.regs[reg].index + reg = arch.get_reg_index(reg) value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) return result @@ -638,8 +636,7 @@ class Function(object): return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)] def get_lifted_il_flag_uses_for_definition(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] + flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count) result = [] @@ -649,8 +646,7 @@ class Function(object): return result def get_lifted_il_flag_definitions_for_use(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] + flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagDefinitionsForUse(self.handle, i, flag, count) result = [] diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 3634cca2..21f43db3 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -37,6 +37,73 @@ class LowLevelILLabel(object): self.handle = handle +class ILRegister(object): + def __init__(self, arch, reg): + self.arch = arch + self.index = reg + self.temp = (self.index & 0x80000000) != 0 + if self.temp: + self.name = "temp%d" % (self.index & 0x7fffffff) + else: + self.name = self.arch.get_reg_name(self.index) + + @property + def info(self): + return self.arch.regs[self.name] + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + +class ILFlag(object): + def __init__(self, arch, flag): + self.arch = arch + self.index = flag + self.temp = (self.index & 0x80000000) != 0 + if self.temp: + self.name = "cond:%d" % (self.index & 0x7fffffff) + else: + self.name = self.arch.get_flag_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + +class SSARegister(object): + def __init__(self, reg, version): + self.reg = reg + self.version = version + + def __repr__(self): + return "" % (repr(self.reg), self.version) + + +class SSAFlag(object): + def __init__(self, flag, version): + self.flag = flag + self.version = version + + def __repr__(self): + return "" % (repr(self.flag), self.version) + + +class LowLevelILOperationAndSize(object): + def __init__(self, operation, size): + self.operation = operation + self.size = size + + def __repr__(self): + if self.size == 0: + return "<%s>" % self.operation.name + return "<%s %d>" % (self.operation.name, self.size) + + class LowLevelILInstruction(object): """ ``class LowLevelILInstruction`` Low Level Intermediate Language Instructions are infinite length tree-based @@ -112,24 +179,24 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], - LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")], - LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "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_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")], - LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")], - LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")], - LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")], - LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")], - LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")], + LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")], + LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")], + LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "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")], LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], 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"), ("index", "int"), ("src_memory", "int")], + LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")], LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_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"), ("index", "int"), ("src", "reg_ssa_list")], - LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")], + LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")], LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -150,27 +217,31 @@ class LowLevelILInstruction(object): self.source_operand = None operands = LowLevelILInstruction.ILOperations[instr.operation] self.operands = [] - for i in xrange(0, len(operands)): - name, operand_type = operands[i] + i = 0 + for operand in operands: + name, operand_type = operand if operand_type == "int": value = instr.operands[i] elif operand_type == "expr": value = LowLevelILInstruction(func, instr.operands[i]) elif operand_type == "reg": - if (instr.operands[i] & 0x80000000) != 0: - value = instr.operands[i] - else: - value = func.arch.get_reg_name(instr.operands[i]) + value = ILRegister(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 == "flag": - if (instr.operands[i] & 0x80000000) != 0: - value = instr.operands[i] - else: - value = func.arch.get_flag_name(instr.operands[i]) + 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 == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 value = [] for i in xrange(count.value): value.append(operand_list[i]) @@ -178,27 +249,26 @@ class LowLevelILInstruction(object): 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_index = operand_list[(i * 2) + 1] - if (reg & 0x80000000) == 0: - reg = func.arch.get_reg_name(reg) - value.append((reg, reg_index)) + reg_version = operand_list[(i * 2) + 1] + value.append(SSARegister(ILRegister(func.arch, reg), 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_index = operand_list[(i * 2) + 1] - if (flag & 0x80000000) == 0: - flag = func.arch.get_flag_name(flag) - value.append((flag, flag_index)) + flag_version = operand_list[(i * 2) + 1] + value.append(SSAFlag(ILFlag(func.arch, flag), flag_version)) core.BNLowLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value + i += 1 def __str__(self): tokens = self.tokens @@ -273,61 +343,76 @@ class LowLevelILInstruction(object): core.BNFreePossibleValueSet(value) return result + @property + def prefix_operands(self): + """All operands in the expression tree in prefix order""" + result = [LowLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: + if isinstance(operand, LowLevelILInstruction): + result += operand.prefix_operands + else: + result.append(operand) + return result + + @property + def postfix_operands(self): + """All operands in the expression tree in postfix order""" + result = [] + for operand in self.operands: + if isinstance(operand, LowLevelILInstruction): + result += operand.postfix_operands + else: + result.append(operand) + result.append(LowLevelILOperationAndSize(self.operation, self.size)) + return result + def get_reg_value(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_reg_value_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_reg_values(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_flag_value_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_flag_values(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) @@ -589,8 +674,7 @@ class LowLevelILFunction(object): :return: The expression ``reg = value`` :rtype: LowLevelILExpr """ - if isinstance(reg, str): - reg = self.arch.regs[reg].index + reg = self.arch.get_reg_index(reg) return self.expr(LowLevelILOperation.LLIL_SET_REG, reg, value.index, size = size, flags = flags) def set_reg_split(self, size, hi, lo, value, flags = 0): @@ -606,10 +690,8 @@ class LowLevelILFunction(object): :return: The expression ``hi:lo = value`` :rtype: LowLevelILExpr """ - if isinstance(hi, str): - hi = self.arch.regs[hi].index - if isinstance(lo, str): - lo = self.arch.regs[lo].index + hi = self.arch.get_reg_index(hi) + 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_flag(self, flag, value): @@ -676,8 +758,7 @@ class LowLevelILFunction(object): :return: A register expression for the given string :rtype: LowLevelILExpr """ - if isinstance(reg, str): - reg = self.arch.regs[reg].index + reg = self.arch.get_reg_index(reg) return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size) def const(self, size, value): @@ -1477,18 +1558,16 @@ class LowLevelILFunction(object): def get_non_ssa_instruction_index(self, instr): return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr) - def get_ssa_reg_definition(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index) + def get_ssa_reg_definition(self, reg_ssa): + reg = self.arch.get_reg_index(reg_ssa.reg) + result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, reg_ssa.version) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None return result - def get_ssa_flag_definition(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) - result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index) + def get_ssa_flag_definition(self, flag_ssa): + flag = self.arch.get_flag_index(flag_ssa.flag) + result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, flag_ssa.version) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None return result @@ -1499,22 +1578,20 @@ class LowLevelILFunction(object): return None return result - def get_ssa_reg_uses(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index + def get_ssa_reg_uses(self, reg_ssa): + reg = self.arch.get_reg_index(reg_ssa.reg) count = ctypes.c_ulonglong() - instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count) + instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, reg_ssa.version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_flag_uses(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) + def get_ssa_flag_uses(self, flag_ssa): + flag = self.arch.get_flag_index(flag_ssa.flag) count = ctypes.c_ulonglong() - instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count) + instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, flag_ssa.version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) @@ -1530,17 +1607,15 @@ class LowLevelILFunction(object): core.BNFreeILInstructionList(instrs) return result - def get_ssa_reg_value(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index) + def get_ssa_reg_value(self, reg_ssa): + reg = self.arch.get_reg_index(reg_ssa.reg) + value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, reg_ssa.version) result = function.RegisterValue(self.arch, value) return result - def get_ssa_flag_value(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) - value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index) + def get_ssa_flag_value(self, flag_ssa): + flag = self.arch.get_flag_index(flag_ssa.flag) + value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, flag_ssa.version) result = function.RegisterValue(self.arch, value) return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index f205714e..e8c5b0f3 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -28,6 +28,15 @@ import basicblock import lowlevelil +class SSAVariable(object): + def __init__(self, var, version): + self.var = var + self.version = version + + def __repr__(self): + return "" % (repr(self.var), self.version) + + class MediumLevelILLabel(object): def __init__(self, handle = None): if handle is None: @@ -37,6 +46,17 @@ class MediumLevelILLabel(object): self.handle = handle +class MediumLevelILOperationAndSize(object): + def __init__(self, operation, size): + self.operation = operation + self.size = size + + def __repr__(self): + if self.size == 0: + return "<%s>" % self.operation.name + return "<%s %d>" % (self.operation.name, self.size) + + class MediumLevelILInstruction(object): """ ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based @@ -114,15 +134,15 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNDEF: [], MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "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", "expr"), ("low", "expr"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], - MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], - MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], - MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], - MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], + 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_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")], @@ -131,7 +151,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -157,6 +177,19 @@ class MediumLevelILInstruction(object): value = MediumLevelILInstruction(func, instr.operands[i]) elif operand_type == "var": value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + elif operand_type == "var_ssa": + var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + version = instr.operands[i + 1] + i += 1 + value = SSAVariable(var, version) + elif operand_type == "var_ssa_dest_and_src": + var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + dest_version = instr.operands[i + 1] + src_version = instr.operands[i + 2] + i += 2 + self.operands.append(SSAVariable(var, dest_version)) + self.dest = SSAVariable(var, dest_version) + value = SSAVariable(var, src_version) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) @@ -179,9 +212,9 @@ class MediumLevelILInstruction(object): value = [] for j in xrange(count.value / 2): var_id = operand_list[j * 2] - var_index = operand_list[(j * 2) + 1] - value.append((function.Variable.from_identifier(self.function.source_function, - var_id), var_index)) + var_version = operand_list[(j * 2) + 1] + value.append(SSAVariable(function.Variable.from_identifier(self.function.source_function, + var_id), var_version)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() @@ -281,35 +314,108 @@ class MediumLevelILInstruction(object): return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) @property - def ssa_memory_index(self): - """Index of active memory contents in SSA form for this instruction""" - return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index) + def ssa_memory_version(self): + """Version of active memory contents in SSA form for this instruction""" + return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index) + + @property + def prefix_operands(self): + """All operands in the expression tree in prefix order""" + result = [MediumLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: + if isinstance(operand, MediumLevelILInstruction): + result += operand.prefix_operands + else: + result.append(operand) + return result + + @property + def postfix_operands(self): + """All operands in the expression tree in postfix order""" + result = [] + for operand in self.operands: + if isinstance(operand, MediumLevelILInstruction): + result += operand.postfix_operands + else: + result.append(operand) + result.append(MediumLevelILOperationAndSize(self.operation, self.size)) + return result + + @property + def vars_written(self): + """List of variables written by instruction""" + if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_SSA, MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_ALIASED, MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD, + MediumLevelILOperation.MLIL_VAR_PHI]: + return [self.dest] + elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]: + return [self.high, self.low] + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL]: + return self.output + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, + MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, + MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + return self.output.vars_written + elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: + return self.dest + return [] + + @property + def vars_read(self): + """List of variables read by instruction""" + if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SSA, + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA, MediumLevelILOperation.MLIL_SET_VAR_ALIASED]: + return self.src.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]: + return [self.prev] + self.src.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, + MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA]: + result = [] + for param in self.params: + result += param.vars_read + return result + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + return self.params.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_CALL_PARAM, MediumLevelILOperation.MLIL_CALL_PARAM_SSA, + MediumLevelILOperation.MLIL_VAR_PHI]: + return self.src + elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: + return [] + result = [] + for operand in self.operands: + if (isinstance(operand, function.Variable)) or (isinstance(operand, SSAVariable)): + result.append(operand) + elif isinstance(operand, MediumLevelILInstruction): + result += operand.vars_read + return result - def get_ssa_var_possible_values(self, var, index): + def get_ssa_var_possible_values(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result - def get_ssa_var_index(self, var): + def get_ssa_var_version(self, var): var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index) + return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index) def get_var_for_reg(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_flag(self, flag): - if isinstance(flag, str): - flag = self.function.arch.regs[flag].index + flag = self.function.arch.get_flag_index(flag) result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) return function.Variable(self.function.source_function, result.type, result.index, result.storage) @@ -318,60 +424,52 @@ class MediumLevelILInstruction(object): return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_reg_value(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_reg_value_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_reg_values(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_flag_value_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_flag_values(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) @@ -644,50 +742,50 @@ class MediumLevelILFunction(object): def get_non_ssa_instruction_index(self, instr): return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) - def get_ssa_var_definition(self, var, index): + def get_ssa_var_definition(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version) if result >= core.BNGetMediumLevelILInstructionCount(self.handle): return None return result - def get_ssa_memory_definition(self, index): - result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index) + def get_ssa_memory_definition(self, version): + result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, version) if result >= core.BNGetMediumLevelILInstructionCount(self.handle): return None return result - def get_ssa_var_uses(self, var, index): + def get_ssa_var_uses(self, ssa_var): count = ctypes.c_ulonglong() var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_memory_uses(self, index): + def get_ssa_memory_uses(self, version): count = ctypes.c_ulonglong() - instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count) + instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_var_value(self, var, index): + def get_ssa_var_value(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, ssa_var.version) result = function.RegisterValue(self.arch, value) return result -- cgit v1.3.1 From 04474d6ae818ddfa9978ffac6f1cdcaae56a87b5 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 2 May 2017 21:41:20 -0400 Subject: Fix NES plugin for new IL API --- python/examples/nes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/examples/nes.py b/python/examples/nes.py index 4122cde0..813b91c9 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -201,11 +201,11 @@ def indirect_load(il, value): def load_zero_page_16(il, value): if il[value].operation == LowLevelILOperation.LLIL_CONST: - if il[value].value == 0xff: + if il[value].constant == 0xff: lo = il.zero_extend(2, il.load(1, il.const(2, 0xff))) hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const(2, 0)), il.const(2, 8))) return il.or_expr(2, lo, hi) - return il.load(2, il.const(2, il[value].value)) + return il.load(2, il.const(2, il[value].constant)) il.append(il.set_reg(1, LLIL_TEMP(0), value)) value = il.reg(1, LLIL_TEMP(0)) lo_addr = value @@ -244,7 +244,7 @@ OperandIL = [ def cond_branch(il, cond, dest): t = None if il[dest].operation == LowLevelILOperation.LLIL_CONST: - t = il.get_label_for_address(Architecture['6502'], il[dest].value) + t = il.get_label_for_address(Architecture['6502'], il[dest].constant) if t is None: t = LowLevelILLabel() indirect = True @@ -262,7 +262,7 @@ def cond_branch(il, cond, dest): def jump(il, dest): label = None if il[dest].operation == LowLevelILOperation.LLIL_CONST: - label = il.get_label_for_address(Architecture['6502'], il[dest].value) + label = il.get_label_for_address(Architecture['6502'], il[dest].constant) if label is None: il.append(il.jump(dest)) else: -- cgit v1.3.1 From 26c8f70fd837baec98bcf2aac89ae658c5590013 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 3 May 2017 23:37:30 -0400 Subject: Adding IL instruction for truncating result to smaller value --- binaryninjaapi.h | 5 +++-- binaryninjacore.h | 2 ++ lowlevelil.cpp | 14 ++++++++++---- python/lowlevelil.py | 16 ++++++++++++++-- python/mediumlevelil.py | 1 + 5 files changed, 30 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 41beb852..a179a810 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2144,8 +2144,9 @@ namespace BinaryNinja ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); ExprId Neg(size_t size, ExprId a, uint32_t flags = 0); ExprId Not(size_t size, ExprId a, uint32_t flags = 0); - ExprId SignExtend(size_t size, ExprId a); - ExprId ZeroExtend(size_t size, ExprId a); + ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0); + ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0); + ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0); ExprId Jump(ExprId dest); ExprId Call(ExprId dest); ExprId Return(size_t dest); diff --git a/binaryninjacore.h b/binaryninjacore.h index 730cbe8d..abb53a7b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -313,6 +313,7 @@ extern "C" LLIL_NOT, LLIL_SX, LLIL_ZX, + LLIL_LOW_PART, LLIL_JUMP, LLIL_JUMP_TO, LLIL_CALL, @@ -751,6 +752,7 @@ extern "C" MLIL_NOT, MLIL_SX, MLIL_ZX, + MLIL_LOW_PART, MLIL_JUMP, MLIL_JUMP_TO, MLIL_CALL, // Not valid in SSA form (see MLIL_CALL_SSA) diff --git a/lowlevelil.cpp b/lowlevelil.cpp index d266c2c9..0b2837f1 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -326,15 +326,21 @@ ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags) } -ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a) +ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags) { - return AddExpr(LLIL_SX, size, 0, a); + return AddExpr(LLIL_SX, size, flags, a); } -ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a) +ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags) { - return AddExpr(LLIL_ZX, size, 0, a); + return AddExpr(LLIL_ZX, size, flags, a); +} + + +ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags) +{ + return AddExpr(LLIL_LOW_PART, size, flags, a); } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 21f43db3..fd713b44 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -153,6 +153,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_SX: [("src", "expr")], LowLevelILOperation.LLIL_ZX: [("src", "expr")], + LowLevelILOperation.LLIL_LOW_PART: [("src", "expr")], LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], @@ -1188,7 +1189,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SX, value.index, size=size, flags=flags) - def zero_extend(self, size, value): + def zero_extend(self, size, value, flags=None): """ ``zero_extend`` zero-extends the expression in ``value`` to ``size`` bytes @@ -1197,7 +1198,18 @@ class LowLevelILFunction(object): :return: The expression ``sx.(value)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size) + return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags) + + def low_part(self, size, value, flags=None): + """ + ``low_part`` truncates ``value`` to ``size`` bytes + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to zero extend + :return: The expression ``(value).`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_LOW_PART, value.index, size=size, flags=flags) def jump(self, dest): """ diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index e8c5b0f3..cef8d83e 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -105,6 +105,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_NOT: [("src", "expr")], MediumLevelILOperation.MLIL_SX: [("src", "expr")], MediumLevelILOperation.MLIL_ZX: [("src", "expr")], + MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], -- cgit v1.3.1 From 7cc163fa72b3ea342a9b061ae8988887edbf198f Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 4 May 2017 19:28:27 -0400 Subject: Initial support for concrete flags computation --- architecture.cpp | 20 ++++++++++++++------ binaryninjaapi.h | 10 ++++++++-- binaryninjacore.h | 7 +++++-- lowlevelil.cpp | 39 +++++++++++++++++++++++++++++++++++++++ python/architecture.py | 42 ++++++++++++++++++++++++++++++------------ python/examples/nes.py | 9 +++++++++ 6 files changed, 105 insertions(+), 22 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index d72e7f42..02f2a88f 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -598,22 +598,30 @@ vector Architecture::GetFlagsWrittenByFlagWriteType(uint32_t) size_t Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, flag, operands, + (void)flagWriteType; + BNFlagRole role = GetFlagRole(flag); + return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } -size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) +size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, + BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, flag, operands, + return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } -ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition, LowLevelILFunction& il) +ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +{ + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); +} + + +ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) { - return il.Unimplemented(); + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a179a810..068653b3 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1440,9 +1440,10 @@ namespace BinaryNinja virtual std::vector GetFlagsWrittenByFlagWriteType(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, 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 BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); @@ -2179,6 +2180,11 @@ namespace BinaryNinja ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); + ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); + ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); + ExprId GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, + BNRegisterOrConstant* operands, size_t operandCount); + ExprId Operand(uint32_t n, ExprId expr); BNLowLevelILInstruction operator[](size_t i) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index abb53a7b..8838ca97 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -334,6 +334,7 @@ extern "C" LLIL_CMP_UGT, LLIL_TEST_BIT, LLIL_BOOL_TO_INT, + LLIL_ADD_OVERFLOW, LLIL_SYSCALL, LLIL_BP, LLIL_TRAP, @@ -775,6 +776,7 @@ extern "C" MLIL_CMP_UGT, MLIL_TEST_BIT, MLIL_BOOL_TO_INT, + 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_BP, @@ -1830,10 +1832,11 @@ extern "C" 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, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, - BNLowLevelILFunction* il); + size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il); + BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, + 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); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 0b2837f1..875f0083 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -534,6 +534,45 @@ ExprId LowLevelILFunction::AddOperandList(const vector operands) } +ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) +{ + if (operand.constant) + return AddExpr(LLIL_CONST, size, 0, operand.value); + return AddExpr(LLIL_REG, size, 0, operand.reg); +} + + +ExprId LowLevelILFunction::GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) +{ + if (operand.constant) + return AddExpr(LLIL_CONST, size, 0, -(int64_t)operand.value); + return AddExpr(LLIL_NEG, size, 0, AddExpr(LLIL_REG, size, 0, operand.reg)); +} + + +ExprId LowLevelILFunction::GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, + BNRegisterOrConstant* operands, size_t operandCount) +{ + if (operandCount == 0) + return AddExpr(op, size, 0); + if (operandCount == 1) + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size)); + if (operandCount == 2) + { + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size)); + } + if (operandCount == 3) + { + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size), GetExprForRegisterOrConstant(operands[2], size)); + } + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size), GetExprForRegisterOrConstant(operands[2], size), + GetExprForRegisterOrConstant(operands[3], size)); +} + + ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) { BNLowLevelILSetExprSourceOperand(m_object, expr, n); diff --git a/python/architecture.py b/python/architecture.py index 60c8a1dd..236ef90b 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -651,11 +651,11 @@ class Architecture(object): operand_list = [] for i in xrange(operand_count): if operands[i].constant: - operand_list.append(("const", operands[i].value)) + operand_list.append(operands[i].value) elif lowlevelil.LLIL_REG_IS_TEMP(operands[i].reg): - operand_list.append(("reg", operands[i].reg)) + operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) else: - operand_list.append(("reg", self._regs_by_index[operands[i].reg])) + 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, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except (KeyError, OSError): @@ -915,7 +915,10 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + flag = self.get_flag_index(flag) + if flag not in self._flag_roles: + return il.unimplemented() + 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): @@ -927,7 +930,7 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + return self.get_default_flag_condition_low_level_il(cond, il) @abc.abstractmethod def perform_assemble(self, code, addr): @@ -1276,7 +1279,7 @@ class Architecture(object): """ return self._flag_write_types[write_type] - def get_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: :param int size: @@ -1286,22 +1289,26 @@ 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._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + 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], operand_list, len(operand_list), il.handle)) + self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle)) - def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_default_flag_write_low_level_il(self, op, size, role, operands, il): """ :param LowLevelILOperation op: :param int size: - :param str write_type: + :param FlagRole role: :param list(str or int) operands: a list of either items that are either string register names or constant \ integer values :param LowLevelILFunction il: @@ -1311,12 +1318,15 @@ class Architecture(object): for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + 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.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], operand_list, len(operand_list), il.handle)) + role, operand_list, len(operand_list), il.handle)) def get_flag_condition_low_level_il(self, cond, il): """ @@ -1326,6 +1336,14 @@ class Architecture(object): """ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_default_flag_condition_low_level_il(self, cond, il): + """ + :param LowLevelILFlagCondition cond: + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_modified_regs_on_write(self, reg): """ ``get_modified_regs_on_write`` returns a list of register names that are modified when ``reg`` is written. diff --git a/python/examples/nes.py b/python/examples/nes.py index 813b91c9..0018b956 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -469,6 +469,15 @@ class M6502(Architecture): return length + def perform_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) + def perform_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 -- cgit v1.3.1 From 7bc394fc4490920bac688234f5c4c23901ab84c7 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 5 May 2017 17:57:06 -0400 Subject: Adding carry flag operand to IL instructions that need it --- binaryninjaapi.h | 9 +++++---- lowlevelil.cpp | 29 +++++++++++++++++++++-------- python/lowlevelil.py | 36 ++++++++++++++++++++---------------- 3 files changed, 46 insertions(+), 28 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 068653b3..b5ca60b4 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2119,9 +2119,9 @@ namespace BinaryNinja ExprId Flag(uint32_t reg); ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex); ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId AddCarry(size_t size, ExprId a, ExprId b, uint32_t flags = 0); + ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId SubBorrow(size_t size, ExprId a, ExprId b, uint32_t flags = 0); + ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0); @@ -2129,9 +2129,9 @@ namespace BinaryNinja ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, uint32_t flags = 0); + ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, uint32_t flags = 0); + ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); @@ -2182,6 +2182,7 @@ namespace BinaryNinja ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); + ExprId GetExprForFlagOrConstant(const BNRegisterOrConstant& operand); ExprId GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, BNRegisterOrConstant* operands, size_t operandCount); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 875f0083..ffb447ab 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -170,9 +170,9 @@ ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags) } -ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, uint32_t flags) +ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) { - return AddExpr(LLIL_ADC, size, flags, a, b); + return AddExpr(LLIL_ADC, size, flags, a, b, carry); } @@ -182,9 +182,9 @@ ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags) } -ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, uint32_t flags) +ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) { - return AddExpr(LLIL_SBB, size, flags, a, b); + return AddExpr(LLIL_SBB, size, flags, a, b, carry); } @@ -230,9 +230,9 @@ ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t } -ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, uint32_t flags) +ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) { - return AddExpr(LLIL_RLC, size, flags, a, b); + return AddExpr(LLIL_RLC, size, flags, a, b, carry); } @@ -242,9 +242,9 @@ ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t } -ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, uint32_t flags) +ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) { - return AddExpr(LLIL_RRC, size, flags, a, b); + return AddExpr(LLIL_RRC, size, flags, a, b, carry); } @@ -550,6 +550,14 @@ ExprId LowLevelILFunction::GetNegExprForRegisterOrConstant(const BNRegisterOrCon } +ExprId LowLevelILFunction::GetExprForFlagOrConstant(const BNRegisterOrConstant& operand) +{ + if (operand.constant) + return AddExpr(LLIL_CONST, 0, 0, operand.value); + return AddExpr(LLIL_FLAG, 0, 0, operand.reg); +} + + ExprId LowLevelILFunction::GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, BNRegisterOrConstant* operands, size_t operandCount) { @@ -564,6 +572,11 @@ ExprId LowLevelILFunction::GetExprForRegisterOrConstantOperation(BNLowLevelILOpe } if (operandCount == 3) { + if ((op == LLIL_ADC) || (op == LLIL_SBB) || (op == LLIL_RLC) || (op == LLIL_RRC)) + { + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size), GetExprForFlagOrConstant(operands[2])); + } return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), GetExprForRegisterOrConstant(operands[1], size), GetExprForRegisterOrConstant(operands[2], size)); } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index fd713b44..cb4c9b69 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -125,9 +125,9 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_SUB: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_AND: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_OR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_XOR: [("left", "expr"), ("right", "expr")], @@ -135,9 +135,9 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_LSR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ASR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ROL: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_ROR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_MUL: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], @@ -809,7 +809,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ADD, a.index, b.index, size=size, flags=flags) - def add_carry(self, size, a, b, flags=None): + def add_carry(self, size, a, b, carry, flags=None): """ ``add_carry`` adds with carry expression ``a`` to expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -817,11 +817,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: flags to set - :return: The expression ``adc.{}(a, b)`` + :return: The expression ``adc.{}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, carry.index, size=size, flags=flags) def sub(self, size, a, b, flags=None): """ @@ -837,7 +838,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SUB, a.index, b.index, size=size, flags=flags) - def sub_borrow(self, size, a, b, flags=None): + def sub_borrow(self, size, a, b, carry, flags=None): """ ``sub_borrow`` subtracts with borrow expression ``b`` from expression ``a`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -845,11 +846,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: flags to set - :return: The expression ``sbc.{}(a, b)`` + :return: The expression ``sbb.{}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, carry.index, size=size, flags=flags) def and_expr(self, size, a, b, flags=None): """ @@ -949,7 +951,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ROL, a.index, b.index, size=size, flags=flags) - def rotate_left_carry(self, size, a, b, flags=None): + def rotate_left_carry(self, size, a, b, carry, flags=None): """ ``rotate_left_carry`` bitwise rotates left with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -957,11 +959,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: optional, flags to set - :return: The expression ``rcl.{}(a, b)`` + :return: The expression ``rlc.{}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, carry.index, size=size, flags=flags) def rotate_right(self, size, a, b, flags=None): """ @@ -977,7 +980,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ROR, a.index, b.index, size=size, flags=flags) - def rotate_right_carry(self, size, a, b, flags=None): + def rotate_right_carry(self, size, a, b, carry, flags=None): """ ``rotate_right_carry`` bitwise rotates right with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -985,11 +988,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: optional, flags to set - :return: The expression ``rcr.{}(a, b)`` + :return: The expression ``rrc.{}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, carry.index, size=size, flags=flags) def mult(self, size, a, b, flags=None): """ -- cgit v1.3.1 From 48691ea74855a919245ea5dc173ef7f9a82c47a7 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 9 May 2017 22:25:48 -0400 Subject: style tweaks and banner at the bottom of svgs --- python/examples/export_svg.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 95e2d62d..7814c9fd 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,6 +1,7 @@ # from binaryninja import * import os import webbrowser +import time try: from urllib import pathname2url # Python 2.x except: @@ -34,7 +35,7 @@ def save_svg(bv, function): outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename) if outputfile is None: return - content = render_svg(function) + content = render_svg(function, origname) output = open(outputfile, 'w') output.write(content) output.close() @@ -54,7 +55,7 @@ def instruction_data_flow(function, address): return 'Opcode: {bytes}'.format(bytes=padded) -def render_svg(function): +def render_svg(function, origname): graph = function.create_graph() graph.layout_and_wait() heightconst = 15 @@ -67,7 +68,13 @@ def render_svg(function): @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro); body { background-color: rgb(42, 42, 42); + color: rgb(220, 220, 220); + font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace; } + a, a:visited { + color: rgb(200, 200, 200); + font-weight: bold; + } svg { background-color: rgb(42, 42, 42); display: block; @@ -101,7 +108,7 @@ def render_svg(function): fill: currentColor; } text { - font-family: 'Source Code Pro'; + font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace; font-size: 9pt; fill: rgb(224, 224, 224); } @@ -207,7 +214,10 @@ def render_svg(function): edges += ' \n'.format(type=BranchType(edge.type).name, points=points) output += ' ' + edges + '\n' output += ' \n' - output += '' + output += '' + + output += '

This CFG generated by Binary Ninja from {filename} on {timestring}.

'.format(filename = origname, timestring = time.strftime("%c")) + output += '' return output -- cgit v1.3.1 From eaeecf37a582894dd614e2ac4e56c35575af95a0 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 9 May 2017 23:03:17 -0400 Subject: add warnings for duplicate symbols --- python/binaryview.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 042c08f5..09537a16 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -2145,6 +2145,8 @@ class BinaryView(object): """ ``define_auto_symbol`` adds a symbol to the internal list of automatically discovered Symbol objects. + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :rtype: None """ @@ -2154,6 +2156,8 @@ class BinaryView(object): """ ``define_auto_symbol_and_var_or_function`` + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :param SymbolType sym_type: Type of symbol being defined :param Platform plat: (optional) platform @@ -2180,6 +2184,8 @@ class BinaryView(object): """ ``define_user_symbol`` adds a symbol to the internal list of user added Symbol objects. + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :rtype: None """ -- cgit v1.3.1 From 12d16ae11dd2c0524a36c59c5b025c38edb4135b Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 10 May 2017 01:40:53 -0400 Subject: add documentation for show_message_box and fix default button parameter --- python/interaction.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/interaction.py b/python/interaction.py index 6d640d17..b479e922 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -23,7 +23,7 @@ import traceback # Binary Ninja components import _binaryninjacore as core -from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonResult +from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult import binaryview import log @@ -517,5 +517,17 @@ def get_form_input(fields, title): return True -def show_message_box(title, text, buttons = MessageBoxButtonResult.OKButton, icon = MessageBoxIcon.InformationIcon): +def show_message_box(title, text, buttons = MessageBoxButtonSet.OKButtonSet, icon = MessageBoxIcon.InformationIcon): + """ + ``show_message_box`` Displays a configurable message box in the UI, or prompts on the console as appropriate + retrieves a list of all Symbol objects of the provided symbol type in the optionally + provided range. + + :param str title: Text title for the message box. + :param str text: Text for the main body of the message box. + :param MessageBoxButtonSet buttons: One of :py:class:`MessageBoxButtonSet` + :param MessageBoxIcon icon: One of :py:class:`MessageBoxIcon` + :return: Which button was selected + :rtype: MessageBoxButtonResult + """ return core.BNShowMessageBox(title, text, buttons, icon) -- cgit v1.3.1 From 2111f1f77241c938b30bd3cf2851919094429dd6 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sun, 14 May 2017 09:41:28 -0400 Subject: Expose some core API's for the demangling and type creation --- binaryninjaapi.h | 20 +++++++++++ binaryninjacore.h | 16 ++++++++- demangle.cpp | 16 ++++++--- python/demangle.py | 4 +-- type.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b5ca60b4..5fb78367 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -407,6 +407,10 @@ namespace BinaryNinja const std::string& mangledName, Type** outType, QualifiedName& outVarName); + bool DemangleGNU3(Architecture* arch, + const std::string& mangledName, + Type** outType, + QualifiedName& outVarName); void RegisterMainThread(MainThreadActionHandler* handler); Ref ExecuteOnMainThread(const std::function& action); @@ -1624,6 +1628,7 @@ namespace BinaryNinja BNTypeClass GetClass() const; uint64_t GetWidth() const; size_t GetAlignment() const; + QualifiedName GetTypeName() const; bool IsSigned() const; bool IsConst() const; bool IsVolatile() const; @@ -1636,6 +1641,13 @@ namespace BinaryNinja Ref GetStructure() const; Ref GetEnumeration() const; Ref GetNamedTypeReference() const; + BNMemberScope GetScope() const; + void SetScope(BNMemberScope scope); + BNMemberAccess GetAccess() const; + void SetAccess(BNMemberAccess access); + void SetConst(bool cnst); + void SetVolatile(bool vltl); + void SetTypeName(const QualifiedName& name); uint64_t GetElementCount() const; @@ -1664,6 +1676,8 @@ namespace BinaryNinja static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); + static Ref PointerType(size_t width, Type* type, bool cnst = false, bool vltl = false, + BNReferenceType refType = PointerReferenceType); static Ref ArrayType(Type* type, uint64_t elem); static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, const std::vector& params, bool varArg = false); @@ -1671,6 +1685,8 @@ namespace BinaryNinja static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); static std::string GetAutoDemangledTypeIdSource(); + static std::string GenerateAutoDebugTypeId(const QualifiedName& name); + static std::string GetAutoDebugTypeIdSource(); }; class NamedTypeReference: public CoreRefCountObject GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); + static Ref GenerateAutoDebugTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); }; struct StructureMember @@ -1705,6 +1723,7 @@ namespace BinaryNinja public: Structure(); Structure(BNStructure* s); + Structure(BNStructureType type, bool isUnion = false, bool packed = false); std::vector GetMembers() const; uint64_t GetWidth() const; @@ -1732,6 +1751,7 @@ namespace BinaryNinja class Enumeration: public CoreRefCountObject { public: + Enumeration(); Enumeration(BNEnumeration* e); std::vector GetMembers() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 8838ca97..c6a79cf5 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -457,7 +457,8 @@ extern "C" NoScope, StaticScope, VirtualScope, - ThunkScope + ThunkScope, + FriendScope }; enum BNMemberAccess @@ -2097,6 +2098,8 @@ extern "C" BINARYNINJACOREAPI char* BNGenerateAutoDemangledTypeId(BNQualifiedName* name); BINARYNINJACOREAPI char* BNGetAutoPlatformTypeIdSource(BNPlatform* platform); BINARYNINJACOREAPI char* BNGetAutoDemangledTypeIdSource(void); + BINARYNINJACOREAPI char* BNGenerateAutoDebugTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGetAutoDebugTypeIdSource(void); BINARYNINJACOREAPI void BNRegisterPlatformTypes(BNBinaryView* view, BNPlatform* platform); @@ -2428,6 +2431,8 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateEnumerationType(BNArchitecture* arch, BNEnumeration* e, size_t width, bool isSigned); BINARYNINJACOREAPI BNType* BNCreatePointerType(BNArchitecture* arch, BNType* type, bool cnst, bool vltl, BNReferenceType refType); + BINARYNINJACOREAPI BNType* BNCreatePointerTypeOfWidth(size_t width, BNType* type, bool cnst, bool vltl, + BNReferenceType refType); BINARYNINJACOREAPI BNType* BNCreateArrayType(BNType* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNType* returnValue, BNCallingConvention* callingConvention, BNNameAndType* params, size_t paramCount, bool varArg); @@ -2436,6 +2441,8 @@ extern "C" BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); BINARYNINJACOREAPI void BNFreeType(BNType* type); + BINARYNINJACOREAPI BNQualifiedName BNTypeGetTypeName(BNType* nt); + BINARYNINJACOREAPI void BNTypeSetTypeName(BNType* type, BNQualifiedName* name); BINARYNINJACOREAPI BNTypeClass BNGetTypeClass(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeWidth(BNType* type); BINARYNINJACOREAPI size_t BNGetTypeAlignment(BNType* type); @@ -2454,6 +2461,12 @@ extern "C" BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, bool canReturn); + BINARYNINJACOREAPI BNMemberScope BNTypeGetMemberScope(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScope scope); + BINARYNINJACOREAPI BNMemberAccess BNTypeGetMemberAccess(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccess access); + BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, bool cnst); + BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, bool vltl); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); @@ -2478,6 +2491,7 @@ extern "C" BINARYNINJACOREAPI BNNamedTypeReference* BNNewNamedTypeReference(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNStructure* BNCreateStructure(void); + BINARYNINJACOREAPI BNStructure* BNCreateStructureWithOptions(BNStructureType type, bool isUnion, bool packed); BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s); BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); diff --git a/demangle.cpp b/demangle.cpp index 70a2fe08..677998d2 100644 --- a/demangle.cpp +++ b/demangle.cpp @@ -1,18 +1,22 @@ #include "binaryninjaapi.h" -using namespace BinaryNinja; using namespace std; +namespace BinaryNinja +{ bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName) { - BNType* localType = (*outType)->GetObject(); + BNType* localType = nullptr; char** localVarName = nullptr; size_t localSize = 0; if (!BNDemangleMS(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize)) return false; + if (!localType) + return false; + *outType = new Type(localType); for (size_t i = 0; i < localSize; i++) { outVarName.push_back(localVarName[i]); @@ -23,16 +27,19 @@ bool DemangleMS(Architecture* arch, } -bool DemangleGNU3(Architecture* arch, +bool DemangleGNU3(Ref arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName) { - BNType* localType = (*outType)->GetObject(); + BNType* localType; char** localVarName = nullptr; size_t localSize = 0; if (!BNDemangleGNU3(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize)) return false; + if (!localType) + return false; + *outType = new Type(localType); for (size_t i = 0; i < localSize; i++) { outVarName.push_back(localVarName[i]); @@ -41,3 +48,4 @@ bool DemangleGNU3(Architecture* arch, delete [] localVarName; return true; } +} \ No newline at end of file diff --git a/python/demangle.py b/python/demangle.py index ed38674a..2a17cdfd 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -48,8 +48,8 @@ def demangle_ms(arch, mangled_name): :param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes. :param str mangled_name: a mangled Microsoft Visual Studio C++ name - :return: returns a Type object for the mangled name - :rtype: Type + :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error + :rtype: Tuple :Example: >>> demangle_ms(Architecture["x86_64"], "?testf@Foobar@@SA?AW4foo@1@W421@@Z") diff --git a/type.cpp b/type.cpp index 66138001..32da27d2 100644 --- a/type.cpp +++ b/type.cpp @@ -279,6 +279,42 @@ bool Type::IsFloat() const } +BNMemberScope Type::GetScope() const +{ + return BNTypeGetMemberScope(m_object); +} + + +void Type::SetScope(BNMemberScope scope) +{ + return BNTypeSetMemberScope(m_object, scope); +} + + +BNMemberAccess Type::GetAccess() const +{ + return BNTypeGetMemberAccess(m_object); +} + + +void Type::SetAccess(BNMemberAccess access) +{ + return BNTypeSetMemberAccess(m_object, access); +} + + +void Type::SetConst(bool cnst) +{ + BNTypeSetConst(m_object, cnst); +} + + +void Type::SetVolatile(bool vltl) +{ + BNTypeSetVolatile(m_object, vltl); +} + + Ref Type::GetChildType() const { BNType* type = BNGetChildType(m_object); @@ -547,6 +583,12 @@ Ref Type::PointerType(Architecture* arch, Type* type, bool cnst, bool vltl } +Ref Type::PointerType(size_t width, Type* type, bool cnst, bool vltl, BNReferenceType refType) +{ + return new Type(BNCreatePointerTypeOfWidth(width, type->GetObject(), cnst, vltl, refType)); +} + + Ref Type::ArrayType(Type* type, uint64_t elem) { return new Type(BNCreateArrayType(type->GetObject(), elem)); @@ -608,6 +650,43 @@ string Type::GetAutoDemangledTypeIdSource() } +string Type::GenerateAutoDebugTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + char* str = BNGenerateAutoDebugTypeId(&nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; +} + + +string Type::GetAutoDebugTypeIdSource() +{ + char* str = BNGetAutoDebugTypeIdSource(); + string result = str; + BNFreeString(str); + return result; +} + + +QualifiedName Type::GetTypeName() const +{ + BNQualifiedName name = BNTypeGetTypeName(m_object); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); + return result; +} + + +void Type::SetTypeName(const QualifiedName& names) +{ + BNQualifiedName nameObj = names.GetAPIObject(); + BNTypeSetTypeName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; @@ -691,12 +770,26 @@ Ref NamedTypeReference::GenerateAutoDemangledTypeReference(B } +Ref NamedTypeReference::GenerateAutoDebugTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoDebugTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + Structure::Structure() { m_object = BNCreateStructure(); } +Structure::Structure(BNStructureType type, bool isUnion, bool packed) +{ + m_object = BNCreateStructureWithOptions(type, isUnion, packed); +} + + Structure::Structure(BNStructure* s) { m_object = s; @@ -801,6 +894,12 @@ Enumeration::Enumeration(BNEnumeration* e) } +Enumeration::Enumeration() +{ + m_object = BNCreateEnumeration(); +} + + vector Enumeration::GetMembers() const { size_t count; -- cgit v1.3.1 From d6c63268eb98fb0801d1c825e1aa4f72c1e1d99c Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 15 May 2017 23:58:48 -0400 Subject: Adding a constant expression with pointer hint for improved types --- binaryninjaapi.h | 1 + binaryninjacore.h | 6 +++++- lowlevelil.cpp | 6 ++++++ python/examples/nes.py | 34 +++++++++++++++++----------------- python/lowlevelil.py | 12 ++++++++++++ python/mediumlevelil.py | 1 + 6 files changed, 42 insertions(+), 18 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5fb78367..783f6345 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2136,6 +2136,7 @@ namespace BinaryNinja ExprId Pop(size_t size); ExprId Register(size_t size, uint32_t reg); ExprId Const(size_t size, uint64_t val); + ExprId ConstPointer(size_t size, uint64_t val); ExprId Flag(uint32_t reg); ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex); ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0); diff --git a/binaryninjacore.h b/binaryninjacore.h index c6a79cf5..949f5997 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -282,6 +282,7 @@ extern "C" LLIL_POP, // Not valid in SSA form (expanded) LLIL_REG, // Not valid in SSA form (see LLIL_REG_SSA) LLIL_CONST, + LLIL_CONST_PTR, 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, @@ -598,7 +599,8 @@ extern "C" UnsignedDecimalDisplayType, SignedHexadecimalDisplayType, UnsignedHexadecimalDisplayType, - CharacterConstantDisplayType + CharacterConstantDisplayType, + PointerDisplayType }; struct BNLowLevelILInstruction @@ -638,6 +640,7 @@ extern "C" UndeterminedValue, EntryValue, ConstantValue, + ConstantPointerValue, StackFrameOffset, ReturnAddressValue, @@ -725,6 +728,7 @@ extern "C" MLIL_ADDRESS_OF, MLIL_ADDRESS_OF_FIELD, MLIL_CONST, + MLIL_CONST_PTR, MLIL_ADD, MLIL_ADC, MLIL_SUB, diff --git a/lowlevelil.cpp b/lowlevelil.cpp index ffb447ab..178d3709 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -152,6 +152,12 @@ ExprId LowLevelILFunction::Const(size_t size, uint64_t val) } +ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val) +{ + return AddExpr(LLIL_CONST_PTR, size, 0, val); +} + + ExprId LowLevelILFunction::Flag(uint32_t reg) { return AddExpr(LLIL_FLAG, 0, 0, reg); diff --git a/python/examples/nes.py b/python/examples/nes.py index 0018b956..47f98b43 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -191,21 +191,21 @@ OperandTokens = [ def indirect_load(il, value): if (value & 0xff) == 0xff: - lo_addr = il.const(2, value) - hi_addr = il.const(2, (value & 0xff00) | ((value + 1) & 0xff)) + lo_addr = il.const_pointer(2, value) + hi_addr = il.const_pointer(2, (value & 0xff00) | ((value + 1) & 0xff)) lo = il.zero_extend(2, il.load(1, lo_addr)) hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8)) return il.or_expr(2, lo, hi) - return il.load(2, il.const(2, value)) + return il.load(2, il.const_pointer(2, value)) def load_zero_page_16(il, value): if il[value].operation == LowLevelILOperation.LLIL_CONST: if il[value].constant == 0xff: - lo = il.zero_extend(2, il.load(1, il.const(2, 0xff))) - hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const(2, 0)), il.const(2, 8))) + lo = il.zero_extend(2, il.load(1, il.const_pointer(2, 0xff))) + hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const_pointer(2, 0)), il.const(2, 8))) return il.or_expr(2, lo, hi) - return il.load(2, il.const(2, il[value].constant)) + return il.load(2, il.const_pointer(2, il[value].constant)) il.append(il.set_reg(1, LLIL_TEMP(0), value)) value = il.reg(1, LLIL_TEMP(0)) lo_addr = value @@ -217,23 +217,23 @@ def load_zero_page_16(il, value): OperandIL = [ lambda il, value: None, # NONE - lambda il, value: il.load(1, il.const(2, value)), # ABS + lambda il, value: il.load(1, il.const_pointer(2, value)), # ABS lambda il, value: il.const(2, value), # ABS_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x")))), # ABS_X lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x"))), # ABS_X_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y")))), # ABS_Y lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y"))), # ABS_Y_DEST lambda il, value: il.reg(1, "a"), # ACCUM - lambda il, value: il.const(2, value), # ADDR + lambda il, value: il.const_pointer(2, value), # ADDR lambda il, value: il.const(1, value), # IMMED lambda il, value: indirect_load(il, value), # IND lambda il, value: il.load(1, load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x")))), # IND_X lambda il, value: load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x"))), # IND_X_DEST lambda il, value: il.load(1, il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y"))), # IND_Y lambda il, value: il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y")), # IND_Y_DEST - lambda il, value: il.const(2, value), # REL - lambda il, value: il.load(1, il.const(2, value)), # ZERO - lambda il, value: il.const(2, value), # ZERO_DEST + lambda il, value: il.const_pointer(2, value), # REL + lambda il, value: il.load(1, il.const_pointer(2, value)), # ZERO + lambda il, value: il.const_pointer(2, value), # ZERO_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x")))), # ZERO_X lambda il, value: il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x"))), # ZERO_X_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "y")))), # ZERO_Y @@ -300,7 +300,7 @@ def rti(il): InstructionIL = { - "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, flags = "*")), + "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")), "asl": lambda il, operand: il.store(1, operand, il.shift_left(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "asl@": lambda il, operand: il.set_reg(1, "a", il.shift_left(1, operand, il.const(1, 1), flags = "czs")), "and": lambda il, operand: il.set_reg(1, "a", il.and_expr(1, il.reg(1, "a"), operand, flags = "zs")), @@ -341,13 +341,13 @@ InstructionIL = { "php": lambda il, operand: il.push(1, get_p_value(il)), "pla": lambda il, operand: il.set_reg(1, "a", il.pop(1), flags = "zs"), "plp": lambda il, operand: set_p_value(il, il.pop(1)), - "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), - "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), - "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), - "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), + "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")), + "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")), + "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")), + "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")), "rti": lambda il, operand: rti(il), "rts": lambda il, operand: il.ret(il.add(2, il.pop(2), il.const(2, 1))), - "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, flags = "*")), + "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")), "sec": lambda il, operand: il.set_flag("c", il.const(0, 1)), "sed": lambda il, operand: il.set_flag("d", il.const(0, 1)), "sei": lambda il, operand: il.set_flag("i", il.const(0, 1)), diff --git a/python/lowlevelil.py b/python/lowlevelil.py index cb4c9b69..5b133abd 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -122,6 +122,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], LowLevelILOperation.LLIL_CONST: [("constant", "int")], + LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], @@ -773,6 +774,17 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CONST, value, size=size) + def const_pointer(self, size, value): + """ + ``const_pointer`` returns an expression for the constant pointer ``value`` with size ``size`` + + :param int size: the size of the pointer in bytes + :param int value: address referenced by pointer + :return: A constant expression of given value and size + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size) + def flag(self, reg): """ ``flag`` returns a flag expression for the given flag name. diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index cef8d83e..4aacad00 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -76,6 +76,7 @@ class MediumLevelILInstruction(object): 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_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], -- cgit v1.3.1 From 55ca41ccd9b2cd91f4d806a0fc75797b6c8c5735 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 16 May 2017 17:35:49 -0400 Subject: Adding pointer information to constant reference list --- binaryninjacore.h | 1 + python/function.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/binaryninjacore.h b/binaryninjacore.h index 949f5997..dbd78f8b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1292,6 +1292,7 @@ extern "C" { int64_t value; size_t size; + bool pointer, intermediate; }; enum BNHighlightColorStyle diff --git a/python/function.py b/python/function.py index 509d9b3b..f32f6ad6 100644 --- a/python/function.py +++ b/python/function.py @@ -205,11 +205,15 @@ class Variable(object): class ConstantReference(object): - def __init__(self, val, size): + def __init__(self, val, size, ptr, intermediate): self.value = val self.size = size + self.pointer = ptr + self.intermediate = intermediate def __repr__(self): + if self.pointer: + return "" % self.value if self.size == 0: return "" % self.value return "" % (self.value, self.size) @@ -626,7 +630,7 @@ class Function(object): refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(ConstantReference(refs[i].value, refs[i].size)) + result.append(ConstantReference(refs[i].value, refs[i].size, refs[i].pointer, refs[i].intermediate)) core.BNFreeConstantReferenceList(refs) return result -- cgit v1.3.1 From abf7ebaf7f7d00b7ce6dc3055e0d511e8b8cf117 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 17 May 2017 21:02:21 -0400 Subject: BinaryView doc string fixes Noticed `create_database` had the wrong function name in the docstring. Was able to grep a few more occurrences. There may be more. --- python/binaryview.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 09537a16..ff954b17 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -641,7 +641,7 @@ class BinaryView(object): @classmethod def set_default_session_data(cls, name, value): """ - ```set_default_session_data``` saves a variable to the BinaryView. + ``set_default_session_data`` saves a variable to the BinaryView. :param name: name of the variable to be saved :param value: value of the variable to be saved @@ -1329,7 +1329,7 @@ class BinaryView(object): def perform_is_offset_executable(self, addr): """ - ``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is executable. + ``perform_is_offset_executable`` implements a check if a virtual address ``addr`` is executable. .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide data without overriding this method. @@ -1410,7 +1410,7 @@ class BinaryView(object): def create_database(self, filename, progress_func=None): """ - ``perform_get_database`` writes the current database (.bndb) file out to the specified file. + ``create_database`` writes the current database (.bndb) file out to the specified file. :param str filename: path and filename to write the bndb to, this string `should` have ".bndb" appended to it. :param callable() progress_func: optional function to be called with the current progress and total count. @@ -1851,7 +1851,7 @@ class BinaryView(object): def define_user_data_var(self, addr, var_type): """ - ``define_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``. + ``define_user_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``. :param int addr: virtual address to define the given data variable :param binaryninja.Type var_type: type to be defined at the given virtual address @@ -1881,7 +1881,7 @@ class BinaryView(object): def undefine_user_data_var(self, addr): """ - ``undefine_data_var`` removes the user data variable at the virtual address ``addr``. + ``undefine_user_data_var`` removes the user data variable at the virtual address ``addr``. :param int addr: virtual address to define the data variable to be removed :rtype: None -- cgit v1.3.1 From aac1ebc6c004fc908c72d7dbee96d48d79440df4 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Fri, 19 May 2017 12:08:21 -0400 Subject: update copyright year --- LICENSE.txt | 2 +- architecture.cpp | 2 +- basicblock.cpp | 2 +- binaryninjaapi.cpp | 2 +- binaryninjaapi.h | 2 +- binaryninjacore.h | 2 +- binaryreader.cpp | 2 +- binaryview.cpp | 2 +- binaryviewtype.cpp | 2 +- binarywriter.cpp | 2 +- callingconvention.cpp | 2 +- databuffer.cpp | 2 +- fileaccessor.cpp | 2 +- filemetadata.cpp | 2 +- function.cpp | 2 +- functiongraph.cpp | 2 +- functiongraphblock.cpp | 2 +- functionrecognizer.cpp | 2 +- log.cpp | 2 +- lowlevelil.cpp | 2 +- platform.cpp | 2 +- plugin.cpp | 2 +- python/__init__.py | 2 +- python/architecture.py | 2 +- python/associateddatastore.py | 2 +- python/basicblock.py | 2 +- python/binaryview.py | 2 +- python/callingconvention.py | 2 +- python/databuffer.py | 2 +- python/demangle.py | 2 +- python/examples/angr_plugin.py | 2 +- python/examples/bin_info.py | 2 +- python/examples/breakpoint.py | 2 +- python/examples/instruction_iterator.py | 2 +- python/examples/jump_table.py | 2 +- python/examples/nds.py | 2 +- python/examples/nes.py | 2 +- python/examples/nsf.py | 2 +- python/examples/print_syscalls.py | 2 +- python/examples/version_switcher.py | 2 +- python/fileaccessor.py | 2 +- python/filemetadata.py | 2 +- python/function.py | 2 +- python/functionrecognizer.py | 2 +- python/generator.cpp | 2 +- python/highlight.py | 2 +- python/interaction.py | 2 +- python/lineardisassembly.py | 2 +- python/log.py | 2 +- python/lowlevelil.py | 2 +- python/mainthread.py | 2 +- python/platform.py | 2 +- python/plugin.py | 2 +- python/pluginmanager.py | 2 +- python/scriptingprovider.py | 2 +- python/startup.py | 2 +- python/transform.py | 2 +- python/types.py | 2 +- python/undoaction.py | 2 +- python/update.py | 2 +- tempfile.cpp | 2 +- transform.cpp | 2 +- type.cpp | 2 +- update.cpp | 2 +- 64 files changed, 64 insertions(+), 64 deletions(-) (limited to 'python') diff --git a/LICENSE.txt b/LICENSE.txt index 625bc6c9..ef8398a2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015-2016 Vector 35 LLC +Copyright (c) 2015-2017 Vector 35 LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/architecture.cpp b/architecture.cpp index 02f2a88f..eb70b16c 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/basicblock.cpp b/basicblock.cpp index d8ae0f65..7eb37c57 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 661892e3..c425df88 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 783f6345..d27ab5fa 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjacore.h b/binaryninjacore.h index dbd78f8b..23014782 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryreader.cpp b/binaryreader.cpp index 5c8a0dc6..ad4859ff 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryview.cpp b/binaryview.cpp index 8edbc2bf..b18b065b 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index e7feb68c..e23838f6 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binarywriter.cpp b/binarywriter.cpp index efac9d9e..a7426346 100644 --- a/binarywriter.cpp +++ b/binarywriter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/callingconvention.cpp b/callingconvention.cpp index 770daf78..fb5ed73f 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/databuffer.cpp b/databuffer.cpp index 72788e8c..f2031842 100644 --- a/databuffer.cpp +++ b/databuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/fileaccessor.cpp b/fileaccessor.cpp index 1fa69746..29fb45ae 100644 --- a/fileaccessor.cpp +++ b/fileaccessor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/filemetadata.cpp b/filemetadata.cpp index b3764167..dc08fe30 100644 --- a/filemetadata.cpp +++ b/filemetadata.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/function.cpp b/function.cpp index 194153a8..b570499c 100644 --- a/function.cpp +++ b/function.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functiongraph.cpp b/functiongraph.cpp index 30e2e165..7e5ec079 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index a37c0b49..99ce2e08 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functionrecognizer.cpp b/functionrecognizer.cpp index 45e19faf..32c7245c 100644 --- a/functionrecognizer.cpp +++ b/functionrecognizer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/log.cpp b/log.cpp index edeed17d..dd15559f 100644 --- a/log.cpp +++ b/log.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 178d3709..c48b5b92 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/platform.cpp b/platform.cpp index afbcbbf3..2a095da2 100644 --- a/platform.cpp +++ b/platform.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/plugin.cpp b/plugin.cpp index 9f51e989..e8dd881d 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/python/__init__.py b/python/__init__.py index c7c5f768..4f58a6db 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/architecture.py b/python/architecture.py index 236ef90b..34f2ca35 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/associateddatastore.py b/python/associateddatastore.py index 6b5e688e..c9b35ee0 100644 --- a/python/associateddatastore.py +++ b/python/associateddatastore.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/basicblock.py b/python/basicblock.py index 5bec391b..3dc5b050 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/binaryview.py b/python/binaryview.py index 09537a16..5a03b800 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/callingconvention.py b/python/callingconvention.py index 04ba711f..4c87eef6 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/databuffer.py b/python/databuffer.py index 6b3423da..3f9e4ce5 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/demangle.py b/python/demangle.py index 2a17cdfd..11673263 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py index 90217d65..c84373be 100644 --- a/python/examples/angr_plugin.py +++ b/python/examples/angr_plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py index 495fb5b5..17a96685 100644 --- a/python/examples/bin_info.py +++ b/python/examples/bin_info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py index b1297e26..a2801511 100644 --- a/python/examples/breakpoint.py +++ b/python/examples/breakpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py index 7ff2d692..f55e1c1b 100644 --- a/python/examples/instruction_iterator.py +++ b/python/examples/instruction_iterator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py index 439e2ab6..419cc188 100644 --- a/python/examples/jump_table.py +++ b/python/examples/jump_table.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nds.py b/python/examples/nds.py index ff137b4b..34d8a292 100644 --- a/python/examples/nds.py +++ b/python/examples/nds.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nes.py b/python/examples/nes.py index 47f98b43..e55a90b7 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nsf.py b/python/examples/nsf.py index b1bac3a8..b0164065 100644 --- a/python/examples/nsf.py +++ b/python/examples/nsf.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py index 2af4d38d..d995ad1e 100644 --- a/python/examples/print_syscalls.py +++ b/python/examples/print_syscalls.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py index 9d5bbf05..3e1cab40 100644 --- a/python/examples/version_switcher.py +++ b/python/examples/version_switcher.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 8fec43a1..2c1f1d19 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/filemetadata.py b/python/filemetadata.py index b489d5bb..4bfc0214 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/function.py b/python/function.py index f32f6ad6..0352ee58 100644 --- a/python/function.py +++ b/python/function.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 960aee2f..8514a2ee 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/generator.cpp b/python/generator.cpp index 1c0e7b16..6f19db66 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/python/highlight.py b/python/highlight.py index 6af1cf95..96bc543d 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/interaction.py b/python/interaction.py index b479e922..60607692 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 9b88b78a..5ef8d623 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/log.py b/python/log.py index 850772f1..f7144183 100644 --- a/python/log.py +++ b/python/log.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 5b133abd..d1a76a2a 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/mainthread.py b/python/mainthread.py index 220f0b64..3e12bd65 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/platform.py b/python/platform.py index 139b7d5e..9ba7625f 100644 --- a/python/platform.py +++ b/python/platform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/plugin.py b/python/plugin.py index 2632b5a9..f038d122 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 37962114..c0f70260 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 859f262e..94616d59 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/startup.py b/python/startup.py index 324cc690..0abc47cb 100644 --- a/python/startup.py +++ b/python/startup.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/transform.py b/python/transform.py index 40382c69..59d719e7 100644 --- a/python/transform.py +++ b/python/transform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/types.py b/python/types.py index ebaa36fc..1e566f68 100644 --- a/python/types.py +++ b/python/types.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/undoaction.py b/python/undoaction.py index 9f742e00..7e3c76a0 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/update.py b/python/update.py index 6417e4a0..be6962d7 100644 --- a/python/update.py +++ b/python/update.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/tempfile.cpp b/tempfile.cpp index 4683bbcd..a8ee32d4 100644 --- a/tempfile.cpp +++ b/tempfile.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/transform.cpp b/transform.cpp index d7ec44b9..29a665d0 100644 --- a/transform.cpp +++ b/transform.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/type.cpp b/type.cpp index 32da27d2..5dd00cbd 100644 --- a/type.cpp +++ b/type.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/update.cpp b/update.cpp index 9d9a2216..135fee5e 100644 --- a/update.cpp +++ b/update.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to -- cgit v1.3.1 From 18c3e2e49ceef496d272f6bcbf81b0d768f29acb Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Thu, 25 May 2017 17:21:12 -0400 Subject: fix enum link in documentation --- python/function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index 0352ee58..34511cfa 100644 --- a/python/function.py +++ b/python/function.py @@ -753,7 +753,7 @@ class Function(object): :param int instr_addr: :param int value: :param int operand: - :param IntegerDisplayTypeEnum display_type: + :param enums.IntegerDisplayType display_type: :param Architecture arch: (optional) """ if arch is None: -- cgit v1.3.1 From d7cb0b3acc0621aa69061d0d1199ac33c664e58f Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 25 May 2017 19:51:45 -0400 Subject: Modify how structures are created in the type system, expose additional structure APIs --- binaryninjaapi.h | 6 +++--- binaryninjacore.h | 5 +++-- python/types.py | 12 ++++++++---- type.cpp | 14 ++++++++++---- 4 files changed, 24 insertions(+), 13 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index d27ab5fa..5ea6d909 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1723,7 +1723,7 @@ namespace BinaryNinja public: Structure(); Structure(BNStructure* s); - Structure(BNStructureType type, bool isUnion = false, bool packed = false); + Structure(BNStructureType type, bool packed = false); std::vector GetMembers() const; uint64_t GetWidth() const; @@ -1733,8 +1733,8 @@ namespace BinaryNinja bool IsPacked() const; void SetPacked(bool packed); bool IsUnion() const; - void SetUnion(bool u); - + void SetStructureType(BNStructureType type); + BNStructureType GetStructureType() const; void AddMember(Type* type, const std::string& name); void AddMemberAtOffset(Type* type, const std::string& name, uint64_t offset); void RemoveMember(size_t idx); diff --git a/binaryninjacore.h b/binaryninjacore.h index 23014782..8880747c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2496,7 +2496,7 @@ extern "C" BINARYNINJACOREAPI BNNamedTypeReference* BNNewNamedTypeReference(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNStructure* BNCreateStructure(void); - BINARYNINJACOREAPI BNStructure* BNCreateStructureWithOptions(BNStructureType type, bool isUnion, bool packed); + BINARYNINJACOREAPI BNStructure* BNCreateStructureWithOptions(BNStructureType type, bool packed); BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s); BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); @@ -2509,7 +2509,8 @@ extern "C" BINARYNINJACOREAPI bool BNIsStructurePacked(BNStructure* s); BINARYNINJACOREAPI void BNSetStructurePacked(BNStructure* s, bool packed); BINARYNINJACOREAPI bool BNIsStructureUnion(BNStructure* s); - BINARYNINJACOREAPI void BNSetStructureUnion(BNStructure* s, bool u); + BINARYNINJACOREAPI void BNSetStructureType(BNStructure* s, BNStructureType type); + BINARYNINJACOREAPI BNStructureType BNGetStructureType(BNStructure* s); BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNType* type, const char* name); BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNType* type, const char* name, uint64_t offset); diff --git a/python/types.py b/python/types.py index 1e566f68..f8e416f4 100644 --- a/python/types.py +++ b/python/types.py @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType import callingconvention import function @@ -646,9 +646,13 @@ class Structure(object): def union(self): return core.BNIsStructureUnion(self.handle) - @union.setter - def union(self, value): - core.BNSetStructureUnion(self.handle, value) + @property + def type(self): + return StructureType(core.BNGetStructureType(self.handle)) + + @type.setter + def type(self, value): + core.BNSetStructureType(self.handle, value) def __setattr__(self, name, value): try: diff --git a/type.cpp b/type.cpp index 5dd00cbd..6e55bb69 100644 --- a/type.cpp +++ b/type.cpp @@ -784,9 +784,9 @@ Structure::Structure() } -Structure::Structure(BNStructureType type, bool isUnion, bool packed) +Structure::Structure(BNStructureType type, bool packed) { - m_object = BNCreateStructureWithOptions(type, isUnion, packed); + m_object = BNCreateStructureWithOptions(type, packed); } @@ -858,9 +858,15 @@ bool Structure::IsUnion() const } -void Structure::SetUnion(bool u) +void Structure::SetStructureType(BNStructureType t) { - BNSetStructureUnion(m_object, u); + BNSetStructureType(m_object, t); +} + + +BNStructureType Structure::GetStructureType() const +{ + return BNGetStructureType(m_object); } -- cgit v1.3.1 From 36525b7ee9a8ee3eb95a8ba5ec490c05874bde8d Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 31 May 2017 15:52:17 -0400 Subject: Make branches types always use the enumeration not the name --- python/architecture.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 34f2ca35..504f67ce 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1128,13 +1128,12 @@ class Architecture(object): result.length = info.length result.branch_delay = info.branchDelay for i in xrange(0, info.branchCount): - branch_type = BranchType(info.branchType[i]).name target = info.branchTarget[i] if info.branchArch[i]: arch = Architecture(info.branchArch[i]) else: arch = None - result.add_branch(branch_type, target, arch) + result.add_branch(BranchType(info.branchType[i]), target, arch) return result def get_instruction_text(self, data, addr): -- cgit v1.3.1 From 74a7c69b0a16ae55659a8824d90aacc058321319 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 31 May 2017 16:25:00 -0400 Subject: Fixing BinaryDataNotificationCallbacks --- python/binaryview.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 8165c592..c0ac0abc 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -210,27 +210,27 @@ class BinaryDataNotificationCallbacks(object): def _data_var_added(self, ctxt, view, var): try: - address = var.address - var_type = types.Type(core.BNNewTypeReference(var.type)) - auto_discovered = var.autoDiscovered + address = var[0].address + var_type = types.Type(core.BNNewTypeReference(var[0].type)) + auto_discovered = var[0].autoDiscovered self.notify.data_var_added(self.view, DataVariable(address, var_type, auto_discovered)) except: log.log_error(traceback.format_exc()) def _data_var_removed(self, ctxt, view, var): try: - address = var.address - var_type = types.Type(core.BNNewTypeReference(var.type)) - auto_discovered = var.autoDiscovered + address = var[0].address + var_type = types.Type(core.BNNewTypeReference(var[0].type)) + auto_discovered = var[0].autoDiscovered self.notify.data_var_removed(self.view, DataVariable(address, var_type, auto_discovered)) except: log.log_error(traceback.format_exc()) def _data_var_updated(self, ctxt, view, var): try: - address = var.address - var_type = types.Type(core.BNNewTypeReference(var.type)) - auto_discovered = var.autoDiscovered + address = var[0].address + var_type = types.Type(core.BNNewTypeReference(var[0].type)) + auto_discovered = var[0].autoDiscovered self.notify.data_var_updated(self.view, DataVariable(address, var_type, auto_discovered)) except: log.log_error(traceback.format_exc()) @@ -247,17 +247,17 @@ class BinaryDataNotificationCallbacks(object): except: log.log_error(traceback.format_exc()) - def _type_defined(self, ctxt, name, type_obj): + def _type_defined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_defined(self.view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_defined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) except: log.log_error(traceback.format_exc()) - def _type_undefined(self, ctxt, name, type_obj): + def _type_undefined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_undefined(self.view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_undefined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) except: log.log_error(traceback.format_exc()) -- cgit v1.3.1 From 26c2df9ace8ce372ad14e114edd0c2713c033f67 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 31 May 2017 16:28:52 -0400 Subject: Example implementing notification callbacks --- python/examples/notification_callbacks.py | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 python/examples/notification_callbacks.py (limited to 'python') diff --git a/python/examples/notification_callbacks.py b/python/examples/notification_callbacks.py new file mode 100644 index 00000000..b7c9cde9 --- /dev/null +++ b/python/examples/notification_callbacks.py @@ -0,0 +1,51 @@ +from binaryninja import BinaryDataNotification, PluginCommand, log_info +import inspect + +def reg_notif(view): + demo_notification = DemoNotification(view) + view.register_notification(demo_notification) + +class DemoNotification(BinaryDataNotification): + def __init__(self, view): + self.view = view + + def data_written(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def data_inserted(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def data_removed(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def function_added(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def function_removed(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def function_updated(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def data_var_added(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def data_var_updated(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def data_var_removed(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def string_found(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def string_removed(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def type_defined(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + + def type_undefined(self, *args): + log_info(inspect.stack()[0][3] + str(args)) + +PluginCommand.register("Register Notification", "", reg_notif) -- cgit v1.3.1 From c48c3a7597f6bb7b8064107f1fbf908464276f11 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 1 Jun 2017 23:10:31 -0400 Subject: Use enumeration types for Endianness and ImplicitRegisterExtend --- python/architecture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 504f67ce..2eb3c717 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -128,7 +128,7 @@ class Architecture(object): 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)).name + 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__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle) @@ -146,7 +146,7 @@ class Architecture(object): 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).name, regs[i]) + ImplicitRegisterExtend(info.extend), regs[i]) core.BNFreeRegisterList(regs) count = ctypes.c_ulonglong() -- cgit v1.3.1 From 4de25b0c1eecb50f137f2623793d1dea0081e8a0 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 6 Jun 2017 12:49:11 -0400 Subject: Adding missing X_ADD_OVERFLOW ILOperation --- python/lowlevelil.py | 1 + python/mediumlevelil.py | 1 + 2 files changed, 2 insertions(+) (limited to 'python') diff --git a/python/lowlevelil.py b/python/lowlevelil.py index d1a76a2a..dfa7aaf6 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -175,6 +175,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")], + LowLevelILOperation.LLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SYSCALL: [], LowLevelILOperation.LLIL_BP: [], LowLevelILOperation.LLIL_TRAP: [("vector", "int")], diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 4aacad00..1274bd9b 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -129,6 +129,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "expr_list")], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], -- cgit v1.3.1 From f0d1697cd7e49fb3889106f03e724d633e660a5f Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 7 Jun 2017 17:30:27 -0400 Subject: Allow ILRegister's to be compared properly --- python/lowlevelil.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'python') diff --git a/python/lowlevelil.py b/python/lowlevelil.py index dfa7aaf6..c359a79c 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -57,6 +57,9 @@ class ILRegister(object): def __repr__(self): return self.name + def __eq__(self, other): + return self.info == other.info + class ILFlag(object): def __init__(self, arch, flag): -- cgit v1.3.1