diff options
| -rw-r--r-- | architecture.cpp | 61 | ||||
| -rw-r--r-- | basicblock.cpp | 2 | ||||
| -rw-r--r-- | binaryninjaapi.cpp | 9 | ||||
| -rw-r--r-- | binaryninjaapi.h | 173 | ||||
| -rw-r--r-- | binaryninjacore.h | 167 | ||||
| -rw-r--r-- | binaryview.cpp | 135 | ||||
| -rw-r--r-- | demangle.cpp | 4 | ||||
| -rw-r--r-- | function.cpp | 4 | ||||
| -rw-r--r-- | functiongraphblock.cpp | 2 | ||||
| -rw-r--r-- | lowlevelil.cpp | 8 | ||||
| -rw-r--r-- | platform.cpp | 149 | ||||
| -rw-r--r-- | python/__init__.py | 4 | ||||
| -rw-r--r-- | python/architecture.py | 54 | ||||
| -rw-r--r-- | python/basicblock.py | 4 | ||||
| -rw-r--r-- | python/binaryview.py | 199 | ||||
| -rw-r--r-- | python/function.py | 19 | ||||
| -rw-r--r-- | python/generator.cpp | 56 | ||||
| -rw-r--r-- | python/lowlevelil.py | 4 | ||||
| -rw-r--r-- | python/platform.py | 91 | ||||
| -rw-r--r-- | python/types.py | 292 | ||||
| -rw-r--r-- | type.cpp | 547 |
21 files changed, 1655 insertions, 329 deletions
diff --git a/architecture.cpp b/architecture.cpp index 3c7d9af8..d72e7f42 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -52,7 +52,14 @@ InstructionTextToken::InstructionTextToken(): type(TextToken), value(0) InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, const std::string& txt, uint64_t val, - size_t s, size_t o) : type(t), text(txt), value(val), size(s), operand(o) + size_t s, size_t o) : type(t), text(txt), value(val), size(s), operand(o), context(NoTokenContext), address(0) +{ +} + + +InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, BNInstructionTextTokenContext ctxt, + const string& txt, uint64_t a, uint64_t val, size_t s, size_t o): + type(t), text(txt), value(val), size(s), operand(o), context(ctxt), address(a) { } @@ -153,6 +160,8 @@ bool Architecture::GetInstructionTextCallback(void* ctxt, const uint8_t* data, u (*result)[i].value = tokens[i].value; (*result)[i].size = tokens[i].size; (*result)[i].operand = tokens[i].operand; + (*result)[i].context = tokens[i].context; + (*result)[i].address = tokens[i].address; } return true; } @@ -737,9 +746,9 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map<string, Ref<Type>>& types, map<string, Ref<Type>>& variables, - map<string, Ref<Type>>& functions, string& errors, - const vector<string>& includeDirs) + map<QualifiedName, Ref<Type>>& types, map<QualifiedName, Ref<Type>>& variables, + map<QualifiedName, Ref<Type>>& functions, string& errors, const vector<string>& includeDirs, + const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -753,26 +762,35 @@ 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) return false; for (size_t i = 0; i < result.typeCount; i++) - types[result.types[i].name] = new Type(BNNewTypeReference(result.types[i].type)); + { + 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++) - types[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + 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++) - types[result.functions[i].name] = new Type(BNNewTypeReference(result.functions[i].type)); + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + types[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<string, Ref<Type>>& types, - map<string, Ref<Type>>& variables, map<string, Ref<Type>>& functions, - string& errors, const vector<string>& includeDirs) +bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<QualifiedName, Ref<Type>>& types, + map<QualifiedName, Ref<Type>>& variables, map<QualifiedName, Ref<Type>>& functions, + string& errors, const vector<string>& includeDirs, const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -786,18 +804,27 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<string, functions.clear(); bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, - includeDirList, includeDirs.size()); + includeDirList, includeDirs.size(), autoTypeSource.c_str()); 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)); + { + 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++) - variables[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); + 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)); + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } @@ -954,8 +981,8 @@ bool CoreArchitecture::GetInstructionText(const uint8_t* data, uint64_t addr, si for (size_t i = 0; i < count; i++) { - result.push_back(InstructionTextToken(tokens[i].type, tokens[i].text, tokens[i].value, - tokens[i].size, tokens[i].operand)); + result.push_back(InstructionTextToken(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, + tokens[i].value, tokens[i].size, tokens[i].operand)); } BNFreeInstructionText(tokens, count); diff --git a/basicblock.cpp b/basicblock.cpp index 93a279a1..4edcc568 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -164,6 +164,8 @@ vector<DisassemblyTextLine> BasicBlock::GetDisassemblyText(DisassemblySettings* token.value = lines[i].tokens[j].value; token.size = lines[i].tokens[j].size; token.operand = lines[i].tokens[j].operand; + token.context = lines[i].tokens[j].context; + token.address = lines[i].tokens[j].address; line.tokens.push_back(token); } result.push_back(line); diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 483d7393..6b303bcd 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -257,3 +257,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 204cd2d8..370a9ae2 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. @@ -371,7 +372,7 @@ namespace BinaryNinja bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, - std::vector<std::string>& outVarName); + QualifiedName& outVarName); void RegisterMainThread(MainThreadActionHandler* handler); Ref<MainThreadAction> ExecuteOnMainThread(const std::function<void()>& action); @@ -411,6 +412,53 @@ 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<std::string> m_name; + + public: + QualifiedName(); + QualifiedName(const std::string& name); + QualifiedName(const std::vector<std::string>& name); + QualifiedName(const QualifiedName& name); + + QualifiedName& operator=(const std::string& name); + QualifiedName& operator=(const std::vector<std::string>& 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<std::string>::iterator begin(); + std::vector<std::string>::iterator end(); + std::vector<std::string>::const_iterator begin() const; + std::vector<std::string>::const_iterator end() const; + std::string& front(); + const std::string& front() const; + std::string& back(); + const std::string& back() const; + void insert(std::vector<std::string>::iterator loc, const std::string& name); + void insert(std::vector<std::string>::iterator loc, std::vector<std::string>::iterator b, + std::vector<std::string>::iterator e); + void erase(std::vector<std::string>::iterator i); + void clear(); + void push_back(const std::string& name); + size_t size() const; + + std::string GetString() const; + + BNQualifiedName GetAPIObject() const; + static void FreeAPIObject(BNQualifiedName* name); + static QualifiedName FromAPIObject(BNQualifiedName* name); + }; + class DataBuffer { BNDataBuffer* m_buffer; @@ -593,6 +641,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, BNQualifiedName* name, BNType* type); + static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type); public: BinaryDataNotification(); @@ -611,6 +661,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 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 @@ -682,10 +734,15 @@ namespace BinaryNinja std::string text; uint64_t value; size_t size, operand; + BNInstructionTextTokenContext context; + uint64_t address; InstructionTextToken(); InstructionTextToken(BNInstructionTextTokenType type, const std::string& text, uint64_t value = 0, size_t size = 0, size_t operand = BN_INVALID_OPERAND); + InstructionTextToken(BNInstructionTextTokenType type, BNInstructionTextTokenContext context, + const std::string& text, uint64_t address, uint64_t value = 0, size_t size = 0, + size_t operand = BN_INVALID_OPERAND); }; struct DisassemblyTextLine @@ -749,7 +806,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 @@ -971,15 +1028,21 @@ namespace BinaryNinja std::vector<LinearDisassemblyLine> 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<QualifiedName, Ref<Type>> GetTypes(); + Ref<Type> GetTypeByName(const QualifiedName& name); + Ref<Type> GetTypeById(const std::string& id); + std::string GetTypeId(const QualifiedName& name); + QualifiedName GetTypeNameById(const std::string& id); + bool IsTypeAutoDefined(const QualifiedName& name); + QualifiedName DefineType(const std::string& id, const QualifiedName& defaultName, Ref<Type> type); + void DefineUserType(const QualifiedName& name, Ref<Type> type); + void UndefineType(const std::string& id); + void UndefineUserType(const QualifiedName& name); + void RenameType(const QualifiedName& oldName, const QualifiedName& newName); - std::map<std::string, Ref<Type>> GetTypes(); - Ref<Type> GetTypeByName(const std::string& name); - bool IsTypeAutoDefined(const std::string& name); - void DefineType(const std::string& name, Ref<Type> type); - void DefineUserType(const std::string& name, Ref<Type> type); - void UndefineType(const std::string& name); - void UndefineUserType(const std::string& name); + void RegisterPlatformTypes(Platform* platform); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -998,6 +1061,7 @@ namespace BinaryNinja void RemoveUserSegment(uint64_t start, uint64_t length); std::vector<Segment> 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 = "", @@ -1429,13 +1493,17 @@ 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<std::string, Ref<Type>>& types, std::map<std::string, Ref<Type>>& variables, - std::map<std::string, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>()); - bool ParseTypesFromSourceFile(const std::string& fileName, std::map<std::string, Ref<Type>>& types, - std::map<std::string, Ref<Type>>& variables, - std::map<std::string, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>()); + std::map<QualifiedName, Ref<Type>>& types, + std::map<QualifiedName, Ref<Type>>& variables, + std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>(), + const std::string& autoTypeSource = ""); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map<QualifiedName, Ref<Type>>& types, + std::map<QualifiedName, Ref<Type>>& variables, + std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>(), + const std::string& autoTypeSource = ""); void RegisterCallingConvention(CallingConvention* cc); std::vector<Ref<CallingConvention>> GetCallingConventions(); @@ -1498,7 +1566,7 @@ namespace BinaryNinja }; class Structure; - class UnknownType; + class NamedTypeReference; class Enumeration; struct NameAndType @@ -1507,6 +1575,12 @@ namespace BinaryNinja Ref<Type> type; }; + struct QualifiedNameAndType + { + QualifiedName name; + Ref<Type> type; + }; + class Type: public CoreRefCountObject<BNType, BNNewTypeReference, BNFreeType> { public: @@ -1526,17 +1600,21 @@ namespace BinaryNinja bool CanReturn() const; Ref<Structure> GetStructure() const; Ref<Enumeration> GetEnumeration() const; - Ref<UnknownType> GetUnknownType() const; + Ref<NamedTypeReference> GetNamedTypeReference() const; uint64_t GetElementCount() const; void SetFunctionCanReturn(bool canReturn); std::string GetString() const; - std::string GetTypeAndName(const std::vector<std::string>& name) const; + std::string GetTypeAndName(const QualifiedName& name) const; std::string GetStringBeforeName() const; std::string GetStringAfterName() const; + std::vector<InstructionTextToken> GetTokens() const; + std::vector<InstructionTextToken> GetTokensBeforeName() const; + std::vector<InstructionTextToken> GetTokensAfterName() const; + Ref<Type> Duplicate() const; static Ref<Type> VoidType(); @@ -1544,7 +1622,10 @@ namespace BinaryNinja static Ref<Type> IntegerType(size_t width, bool sign, const std::string& altName = ""); static Ref<Type> FloatType(size_t width, const std::string& typeName = ""); static Ref<Type> StructureType(Structure* strct); - static Ref<Type> UnknownNamedType(UnknownType* unknwn); + static Ref<Type> NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); + static Ref<Type> NamedType(const QualifiedName& name, Type* type); + static Ref<Type> NamedType(const std::string& id, const QualifiedName& name, Type* type); + static Ref<Type> NamedType(BinaryView* view, const QualifiedName& name); static Ref<Type> EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref<Type> PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); @@ -1552,15 +1633,29 @@ namespace BinaryNinja static Ref<Type> FunctionType(Type* returnValue, CallingConvention* callingConvention, const std::vector<NameAndType>& params, bool varArg = false); - static std::string GetQualifiedName(const std::vector<std::string>& names); + static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); + static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); + static std::string GetAutoDemangledTypeIdSource(); }; - class UnknownType: public CoreRefCountObject<BNUnknownType, BNNewUnknownTypeReference, BNFreeUnknownType> + class NamedTypeReference: public CoreRefCountObject<BNNamedTypeReference, BNNewNamedTypeReference, + BNFreeNamedTypeReference> { public: - UnknownType(BNUnknownType* s, std::vector<std::string> name = {}); - std::vector<std::string> GetName() const; - void SetName(const std::vector<std::string>& name); + NamedTypeReference(BNNamedTypeReference* nt); + NamedTypeReference(BNNamedTypeReferenceClass cls = UnknownNamedTypeClass, const std::string& id = "", + const QualifiedName& name = QualifiedName()); + BNNamedTypeReferenceClass GetTypeClass() const; + void SetTypeClass(BNNamedTypeReferenceClass cls); + std::string GetTypeId() const; + void SetTypeId(const std::string& id); + QualifiedName GetName() const; + void SetName(const QualifiedName& name); + + static Ref<NamedTypeReference> GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const std::string& source, const QualifiedName& name); + static Ref<NamedTypeReference> GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); }; struct StructureMember @@ -1573,13 +1668,14 @@ namespace BinaryNinja class Structure: public CoreRefCountObject<BNStructure, BNNewStructureReference, BNFreeStructure> { public: + Structure(); Structure(BNStructure* s); - std::vector<std::string> GetName() const; - void SetName(const std::vector<std::string>& name); std::vector<StructureMember> GetMembers() const; uint64_t GetWidth() const; + void SetWidth(size_t width); size_t GetAlignment() const; + void SetAlignment(size_t align); bool IsPacked() const; void SetPacked(bool packed); bool IsUnion() const; @@ -1588,6 +1684,7 @@ namespace BinaryNinja void AddMember(Type* type, const std::string& name); void AddMemberAtOffset(Type* type, const std::string& name, uint64_t offset); void RemoveMember(size_t idx); + void ReplaceMember(size_t idx, Type* type, const std::string& name); }; struct EnumerationMember @@ -1602,13 +1699,12 @@ namespace BinaryNinja public: Enumeration(BNEnumeration* e); - std::vector<std::string> GetName() const; - void SetName(const std::vector<std::string>& name); - std::vector<EnumerationMember> GetMembers() const; void AddMember(const std::string& name); void AddMemberWithValue(const std::string& name, uint64_t value); + void RemoveMember(size_t idx); + void ReplaceMember(size_t idx, const std::string& name, uint64_t value); }; class DisassemblySettings: public CoreRefCountObject<BNDisassemblySettings, @@ -2248,6 +2344,21 @@ namespace BinaryNinja Ref<Platform> GetRelatedPlatform(Architecture* arch); void AddRelatedPlatform(Architecture* arch, Platform* platform); Ref<Platform> GetAssociatedPlatformByAddress(uint64_t& addr); + + std::map<QualifiedName, Ref<Type>> GetTypes(); + std::map<QualifiedName, Ref<Type>> GetVariables(); + std::map<QualifiedName, Ref<Type>> GetFunctions(); + std::map<uint32_t, QualifiedNameAndType> GetSystemCalls(); + Ref<Type> GetTypeByName(const QualifiedName& name); + Ref<Type> GetVariableByName(const QualifiedName& name); + Ref<Type> GetFunctionByName(const QualifiedName& name); + std::string GetSystemCallName(uint32_t n); + Ref<Type> GetSystemCallType(uint32_t n); + + std::string GenerateAutoPlatformTypeId(const QualifiedName& name); + Ref<NamedTypeReference> GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); + std::string GetAutoPlatformTypeIdSource(); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index 1ee71402..b8531742 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; @@ -166,19 +166,17 @@ extern "C" FloatingPointToken = 8, AnnotationToken = 9, CodeRelativeAddressToken = 10, - StackVariableTypeToken = 11, - DataVariableTypeToken = 12, - FunctionReturnTypeToken = 13, - FunctionAttributeToken = 14, - ArgumentTypeToken = 15, - ArgumentNameToken = 16, - HexDumpByteValueToken = 17, - HexDumpSkippedByteToken = 18, - HexDumpInvalidByteToken = 19, - HexDumpTextToken = 20, - OpcodeToken = 21, - StringToken = 22, - CharacterConstantToken = 23, + ArgumentNameToken = 11, + HexDumpByteValueToken = 12, + HexDumpSkippedByteToken = 13, + HexDumpInvalidByteToken = 14, + HexDumpTextToken = 15, + OpcodeToken = 16, + StringToken = 17, + CharacterConstantToken = 18, + KeywordToken = 19, + TypeNameToken = 20, + FieldNameToken = 21, // The following are output by the analysis system automatically, these should // not be used directly by the architecture plugins @@ -189,6 +187,15 @@ extern "C" AddressDisplayToken = 68 }; + enum BNInstructionTextTokenContext + { + NoTokenContext = 0, + StackVariableTokenContext = 1, + DataVariableTokenContext = 2, + FunctionReturnTokenContext = 3, + ArgumentTokenContext = 4 + }; + enum BNLinearDisassemblyLineType { BlankLineType, @@ -364,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 @@ -614,6 +631,12 @@ extern "C" bool (*navigate)(void* ctxt, const char* view, uint64_t offset); }; + struct BNQualifiedName + { + char** name; + size_t nameCount; + }; + struct BNBinaryDataNotification { void* context; @@ -628,6 +651,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, BNQualifiedName* name, BNType* type); + void (*typeUndefined)(void* ctxt, BNBinaryView* view, BNQualifiedName* name, BNType* type); }; struct BNFileAccessor @@ -708,6 +733,8 @@ extern "C" char* text; uint64_t value; size_t size, operand; + BNInstructionTextTokenContext context; + uint64_t address; }; struct BNInstructionTextLine @@ -831,6 +858,12 @@ extern "C" BNType* type; }; + struct BNQualifiedNameAndType + { + BNQualifiedName name; + BNType* type; + }; + struct BNStructureMember { BNType* type; @@ -853,9 +886,9 @@ extern "C" struct BNTypeParserResult { - BNNameAndType* types; - BNNameAndType* variables; - BNNameAndType* functions; + BNQualifiedNameAndType* types; + BNQualifiedNameAndType* variables; + BNQualifiedNameAndType* functions; size_t typeCount, variableCount, functionCount; }; @@ -1187,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); @@ -1204,6 +1244,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); @@ -1390,6 +1432,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, @@ -1768,17 +1811,31 @@ 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, 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 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, 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(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); @@ -1942,7 +1999,7 @@ extern "C" BNNameAndType* params, size_t paramCount, bool varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, const char** nameList, size_t nameCount); + BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); BINARYNINJACOREAPI void BNFreeType(BNType* type); BINARYNINJACOREAPI BNTypeClass BNGetTypeClass(BNType* type); @@ -1960,30 +2017,42 @@ 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); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokens(BNType* type, size_t* count); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensBeforeName(BNType* type, size_t* count); + 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* 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); + 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); + BINARYNINJACOREAPI void BNSetStructureWidth(BNStructure* s, uint64_t width); BINARYNINJACOREAPI size_t BNGetStructureAlignment(BNStructure* s); + BINARYNINJACOREAPI void BNSetStructureAlignment(BNStructure* s, size_t align); BINARYNINJACOREAPI bool BNIsStructurePacked(BNStructure* s); BINARYNINJACOREAPI void BNSetStructurePacked(BNStructure* s, bool packed); BINARYNINJACOREAPI bool BNIsStructureUnion(BNStructure* s); @@ -1992,28 +2061,29 @@ extern "C" BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNType* type, const char* name); BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNType* type, const char* name, uint64_t offset); BINARYNINJACOREAPI void BNRemoveStructureMember(BNStructure* s, size_t idx); + BINARYNINJACOREAPI void BNReplaceStructureMember(BNStructure* s, size_t idx, BNType* type, const char* name); BINARYNINJACOREAPI BNEnumeration* BNCreateEnumeration(void); 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); BINARYNINJACOREAPI void BNAddEnumerationMember(BNEnumeration* e, const char* name); BINARYNINJACOREAPI void BNAddEnumerationMemberWithValue(BNEnumeration* e, const char* name, uint64_t value); + BINARYNINJACOREAPI void BNRemoveEnumerationMember(BNEnumeration* e, size_t idx); + BINARYNINJACOREAPI void BNReplaceEnumerationMember(BNEnumeration* e, size_t idx, const char* name, uint64_t value); // 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 @@ -2142,6 +2212,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/binaryview.cpp b/binaryview.cpp index cc6667c5..8edbc2bf 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -129,6 +129,24 @@ void BinaryDataNotification::StringRemovedCallback(void* ctxt, BNBinaryView* obj } +void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(data)); + Ref<Type> typeObj = new Type(BNNewTypeReference(type)); + notify->OnTypeDefined(view, QualifiedName::FromAPIObject(name), typeObj); +} + + +void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(data)); + Ref<Type> typeObj = new Type(BNNewTypeReference(type)); + notify->OnTypeUndefined(view, QualifiedName::FromAPIObject(name), typeObj); +} + + BinaryDataNotification::BinaryDataNotification() { m_callbacks.context = this; @@ -143,6 +161,8 @@ BinaryDataNotification::BinaryDataNotification() m_callbacks.dataVariableUpdated = DataVariableUpdatedCallback; m_callbacks.stringFound = StringFoundCallback; m_callbacks.stringRemoved = StringRemovedCallback; + m_callbacks.typeDefined = TypeDefinedCallback; + m_callbacks.typeUndefined = TypeUndefinedCallback; } @@ -1366,6 +1386,8 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line token.value = lines[i].contents.tokens[j].value; token.size = lines[i].contents.tokens[j].size; token.operand = lines[i].contents.tokens[j].operand; + token.context = lines[i].contents.tokens[j].context; + token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } result.push_back(line); @@ -1409,6 +1431,8 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi token.value = lines[i].contents.tokens[j].value; token.size = lines[i].contents.tokens[j].size; token.operand = lines[i].contents.tokens[j].operand; + token.context = lines[i].contents.tokens[j].context; + token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } result.push_back(line); @@ -1423,9 +1447,9 @@ vector<LinearDisassemblyLine> 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)) @@ -1435,64 +1459,127 @@ bool BinaryView::ParseTypeString(const string& text, NameAndType& result, string return false; } - result.name = nt.name; - result.type = new Type(nt.type); + result.name = QualifiedName::FromAPIObject(&nt.name); + result.type = new Type(BNNewTypeReference(nt.type)); errors = ""; - BNFreeString(nt.name); + BNFreeQualifiedNameAndType(&nt); return true; } -map<string, Ref<Type>> BinaryView::GetTypes() +map<QualifiedName, Ref<Type>> BinaryView::GetTypes() { size_t count; - BNNameAndType* types = BNGetAnalysisTypeList(m_object, &count); + BNQualifiedNameAndType* types = BNGetAnalysisTypeList(m_object, &count); - map<string, Ref<Type>> result; + map<QualifiedName, Ref<Type>> result; for (size_t i = 0; i < count; i++) - result[types[i].name] = new Type(BNNewTypeReference(types[i].type)); + { + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } BNFreeTypeList(types, count); return result; } -Ref<Type> BinaryView::GetTypeByName(const string& name) +Ref<Type> BinaryView::GetTypeByName(const QualifiedName& name) { - BNType* type = BNGetAnalysisTypeByName(m_object, name.c_str()); + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetAnalysisTypeByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + if (!type) return nullptr; return new Type(type); } -bool BinaryView::IsTypeAutoDefined(const std::string& name) +Ref<Type> 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(); + bool result = BNIsAnalysisTypeAutoDefined(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +QualifiedName BinaryView::DefineType(const string& id, const QualifiedName& defaultName, Ref<Type> type) { - return BNIsAnalysisTypeAutoDefined(m_object, name.c_str()); + 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; } -void BinaryView::DefineType(const std::string& name, Ref<Type> type) +void BinaryView::DefineUserType(const QualifiedName& name, Ref<Type> type) { - BNDefineAnalysisType(m_object, name.c_str(), type->GetObject()); + BNQualifiedName nameObj = name.GetAPIObject(); + BNDefineUserAnalysisType(m_object, &nameObj, type->GetObject()); + QualifiedName::FreeAPIObject(&nameObj); } -void BinaryView::DefineUserType(const std::string& name, Ref<Type> type) +void BinaryView::UndefineType(const string& id) { - BNDefineUserAnalysisType(m_object, name.c_str(), type->GetObject()); + BNUndefineAnalysisType(m_object, id.c_str()); } -void BinaryView::UndefineType(const std::string& name) +void BinaryView::UndefineUserType(const QualifiedName& name) { - BNUndefineAnalysisType(m_object, name.c_str()); + BNQualifiedName nameObj = name.GetAPIObject(); + BNUndefineUserAnalysisType(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } -void BinaryView::UndefineUserType(const std::string& name) +void BinaryView::RenameType(const QualifiedName& oldName, const QualifiedName& newName) { - BNUndefineUserAnalysisType(m_object, name.c_str()); + BNQualifiedName oldNameObj = oldName.GetAPIObject(); + BNQualifiedName newNameObj = newName.GetAPIObject(); + BNRenameAnalysisType(m_object, &oldNameObj, &newNameObj); + QualifiedName::FreeAPIObject(&oldNameObj); + QualifiedName::FreeAPIObject(&newNameObj); +} + + +void BinaryView::RegisterPlatformTypes(Platform* platform) +{ + BNRegisterPlatformTypes(m_object, platform->GetObject()); } @@ -1604,6 +1691,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/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<std::string>& 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<std::string>& outVarName) + QualifiedName& outVarName) { BNType* localType = (*outType)->GetObject(); char** localVarName = nullptr; diff --git a/function.cpp b/function.cpp index 109b6f49..b1d008ee 100644 --- a/function.cpp +++ b/function.cpp @@ -567,6 +567,10 @@ vector<vector<InstructionTextToken>> Function::GetBlockAnnotations(Architecture* token.type = lines[i].tokens[j].type; token.text = lines[i].tokens[j].text; token.value = lines[i].tokens[j].value; + token.size = lines[i].tokens[j].size; + token.operand = lines[i].tokens[j].operand; + token.context = lines[i].tokens[j].context; + token.address = lines[i].tokens[j].address; line.push_back(token); } result.push_back(line); diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 47261453..db69c25a 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -101,6 +101,8 @@ const vector<DisassemblyTextLine>& FunctionGraphBlock::GetLines() token.value = lines[i].tokens[j].value; token.size = lines[i].tokens[j].size; token.operand = lines[i].tokens[j].operand; + token.context = lines[i].tokens[j].context; + token.address = lines[i].tokens[j].address; line.tokens.push_back(token); } result.push_back(line); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index a312bbd6..bf3b980e 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -579,6 +579,10 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<Ins 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); } @@ -603,6 +607,10 @@ bool LowLevelILFunction::GetInstructionText(Function* func, Architecture* arch, 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); } diff --git a/platform.cpp b/platform.cpp index 7a6571cc..afbcbbf3 100644 --- a/platform.cpp +++ b/platform.cpp @@ -253,3 +253,152 @@ Ref<Platform> Platform::GetAssociatedPlatformByAddress(uint64_t& addr) return nullptr; return new Platform(platform); } + + +map<QualifiedName, Ref<Type>> Platform::GetTypes() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformTypes(m_object, &count); + + map<QualifiedName, Ref<Type>> 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<QualifiedName, Ref<Type>> Platform::GetVariables() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformVariables(m_object, &count); + + map<QualifiedName, Ref<Type>> 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<QualifiedName, Ref<Type>> Platform::GetFunctions() +{ + size_t count; + BNQualifiedNameAndType* types = BNGetPlatformFunctions(m_object, &count); + + map<QualifiedName, Ref<Type>> 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<uint32_t, QualifiedNameAndType> Platform::GetSystemCalls() +{ + size_t count; + BNSystemCallInfo* calls = BNGetPlatformSystemCalls(m_object, &count); + + map<uint32_t, QualifiedNameAndType> 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<Type> 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<Type> 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<Type> 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<Type> 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(); + char* str = BNGenerateAutoPlatformTypeId(m_object, &nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; +} + + +Ref<NamedTypeReference> 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/__init__.py b/python/__init__.py index e4d45435..b1f5cd08 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -54,6 +54,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/architecture.py b/python/architecture.py index 3e899d68..5bafe949 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: @@ -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 @@ -1581,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``. @@ -1589,8 +1593,9 @@ 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) + :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: >>> arch.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') @@ -1606,32 +1611,37 @@ 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: - return (None, error_str) + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) - return (types.TypeParserResult(type_dict, variables, functions), error_str) + 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 - :return: a tuple of py:class:`TypeParserResult` and error string - :rtype: tuple(TypeParserResult, str) + :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: >>> file = "/Users/binja/tmp.c" @@ -1647,22 +1657,26 @@ 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: - return (None, error_str) + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - type_dict[parse.types[i].name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) - return (types.TypeParserResult(type_dict, variables, functions), error_str) + return types.TypeParserResult(type_dict, variables, functions) def register_calling_convention(self, cc): """ diff --git a/python/basicblock.py b/python/basicblock.py index 02e6a2c5..f6dbd60d 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 c021024f..9753b653 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -78,6 +78,12 @@ class BinaryDataNotification(object): 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 StringReference(object): def __init__(self, string_type, start, length): @@ -157,6 +163,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) @@ -239,6 +247,20 @@ class BinaryDataNotificationCallbacks(object): except: log.log_error(traceback.format_exc()) + 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, types.Type(core.BNNewTypeReference(type_obj))) + except: + 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, types.Type(core.BNNewTypeReference(type_obj))) + except: + log.log_error(traceback.format_exc()) + class _BinaryViewTypeMetaclass(type): @property @@ -825,7 +847,8 @@ class BinaryView(object): type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} for i in xrange(0, count.value): - result[type_list[i].name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + 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 @@ -1867,7 +1890,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): """ @@ -2731,7 +2754,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)) @@ -2831,51 +2856,117 @@ 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") (<type: int32_t>, '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 = types.Type(core.BNNewTypeReference(result.type)) - name = result.name - core.BNFreeNameAndType(result) + name = types.QualifiedName._from_core_struct(result.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: >>> 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) <type: int32_t> >>> """ + name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetAnalysisTypeByName(self.handle, name) if not obj: 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) + <type: int32_t> + >>> + """ + 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 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") @@ -2885,31 +2976,38 @@ class BinaryView(object): False >>> """ + 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 str 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) <type: int32_t> """ - 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): """ ``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: @@ -2919,45 +3017,86 @@ class BinaryView(object): >>> bv.get_type_by_name(name) <type: int32_t> """ + 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 str 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) <type: int32_t> - >>> bv.undefine_type(name) + >>> bv.undefine_type(type_id) >>> bv.get_type_by_name(name) >>> """ - core.BNUndefineAnalysisType(self.handle, name) + core.BNUndefineAnalysisType(self.handle, type_id) 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: >>> 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) <type: int32_t> - >>> 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") + <type: int32_t> + >>> bv.rename_type("foo", "bar") + >>> bv.get_type_by_name("bar") + <type: int32_t> + >>> + """ + 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 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, @@ -3025,6 +3164,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, diff --git a/python/function.py b/python/function.py index 9b00eec2..3aeb8e22 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 @@ -920,7 +922,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 @@ -970,7 +974,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) @@ -1241,12 +1247,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/generator.cpp b/python/generator.cpp index d3725b6d..1c0e7b16 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -97,17 +97,19 @@ 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: - { - string name = type->GetQualifiedName(type->GetEnumeration()->GetName()); - if (name.size() > 2 && name.substr(0, 2) == "BN") - name = name.substr(2); - fprintf(out, "%sEnum", name.c_str()); + case NamedTypeReferenceClass: + if (type->GetNamedTypeReference()->GetTypeClass() == EnumNamedTypeClass) + { + string name = type->GetNamedTypeReference()->GetName().GetString(); + if (name.size() > 2 && name.substr(0, 2) == "BN") + name = name.substr(2); + fprintf(out, "%sEnum", name.c_str()); + } + else + { + fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str()); + } break; - } case PointerTypeClass: if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass)) { @@ -161,7 +163,7 @@ int main(int argc, char* argv[]) Architecture::Register(new GeneratorArchitecture()); // Parse API header to get type and function information - map<string, Ref<Type>> types, vars, funcs; + map<QualifiedName, Ref<Type>> types, vars, funcs; string errors; bool ok = Architecture::GetByName("generator")->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "%s", errors.c_str()); @@ -195,14 +197,17 @@ int main(int argc, char* argv[]) fprintf(out, "# Type definitions\n"); 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, "\tpass\n"); } else if (i.second->GetClass() == EnumerationTypeClass) { - string name = i.first; if (name.size() > 2 && name.substr(0, 2) == "BN") name = name.substr(2); @@ -217,7 +222,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"); } @@ -227,9 +232,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, "\t\t(\"%s\", ", j.name.c_str()); @@ -243,6 +252,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) && @@ -251,7 +265,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) @@ -260,11 +274,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"); @@ -274,7 +288,7 @@ int main(int argc, char* argv[]) for (auto& j : i.second->GetParameters()) { fprintf(out, "\t\t"); - 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 @@ -293,7 +307,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, "\tresult = %s(*args)\n", funcName.c_str()); fprintf(out, "\tstring = ctypes.cast(result, ctypes.c_char_p).value\n"); fprintf(out, "\tBNFreeString(result)\n"); @@ -302,7 +316,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, "\tresult = %s(*args)\n", funcName.c_str()); fprintf(out, "\tif not result:\n"); fprintf(out, "\t\treturn None\n"); 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/platform.py b/python/platform.py index 04dce587..ccc80476 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): @@ -215,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) @@ -259,3 +309,44 @@ class Platform(object): new_addr.value = addr 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) + + 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 62a441cd..43aaa66f 100644 --- a/python/types.py +++ b/python/types.py @@ -22,9 +22,92 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType import callingconvention -import demangle +import function + + +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 + + 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) + + 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 Symbol(object): @@ -210,6 +293,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(handle = result) + @property def count(self): """Type count (read-only)""" @@ -227,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()) @@ -254,8 +395,27 @@ 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 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.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): @@ -294,6 +454,20 @@ 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_demangled_type_id(self, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoDemangledTypeId(name) + + @classmethod + def get_auto_demanged_type_id_source(self): + return core.BNGetAutoDemangledTypeIdSource() + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -301,28 +475,70 @@ 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 = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: - self.handle = core.BNCreateUnknownType() + 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) else: self.handle = handle def __del__(self): - core.BNFreeUnknownType(self.handle) + core.BNFreeNamedTypeReference(self.handle) + + @property + def type_class(self): + 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() - nameList = core.BNGetUnknownTypeName(self.handle, count) - result = [] - for i in xrange(count.value): - result.append(nameList[i]) - return demangle.get_qualified_name(result) + name = core.BNGetTypeReferenceName(self.handle) + result = QualifiedName._from_core_struct(name) + core.BNFreeQualifiedName(name) + return result @name.setter def name(self, value): - core.BNSetUnknownTypeName(self.handle, value) + value = QualifiedName(value)._get_core_struct() + core.BNSetTypeReferenceName(self.handle, value) + + def __repr__(self): + if self.type_class == NamedTypeReferenceClass.TypedefNamedTypeClass: + return "<named type: typedef %s>" % str(self.name) + if self.type_class == NamedTypeReferenceClass.StructNamedTypeClass: + return "<named type: struct %s>" % str(self.name) + if self.type_class == NamedTypeReferenceClass.UnionNamedTypeClass: + return "<named type: union %s>" % str(self.name) + if self.type_class == NamedTypeReferenceClass.EnumNamedTypeClass: + return "<named type: enum %s>" % str(self.name) + return "<named type: unknown %s>" % 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_demangled_type_ref(self, type_class, name): + type_id = Type.generate_auto_demangled_type_id(name) + return NamedTypeReference(type_class, type_id, name) class StructureMember(object): @@ -349,19 +565,6 @@ class Structure(object): 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 demangle.get_qualified_name(result) - - @name.setter - def name(self, value): - core.BNSetStructureName(self.handle, value) - - @property def members(self): """Structure member list (read-only)""" count = ctypes.c_ulonglong() @@ -375,14 +578,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) @@ -406,8 +617,6 @@ class Structure(object): raise AttributeError("attribute '%s' is read only" % name) def __repr__(self): - if len(self.name) > 0: - return "<struct: %s>" % self.name return "<struct: size %#x>" % self.width def append(self, t, name = ""): @@ -419,6 +628,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): @@ -441,14 +653,6 @@ class Enumeration(object): 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)""" count = ctypes.c_ulonglong() @@ -466,8 +670,6 @@ class Enumeration(object): raise AttributeError("attribute '%s' is read only" % name) def __repr__(self): - if len(self.name) > 0: - return "<enum: %s>" % self.name return "<enum: %s>" % repr(self.members) def append(self, name, value = None): @@ -476,6 +678,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): @@ -24,6 +24,219 @@ using namespace BinaryNinja; using namespace std; +QualifiedName::QualifiedName() +{ +} + + +QualifiedName::QualifiedName(const string& name) +{ + m_name.push_back(name); +} + + +QualifiedName::QualifiedName(const vector<string>& name): m_name(name) +{ +} + + +QualifiedName::QualifiedName(const QualifiedName& name): m_name(name.m_name) +{ +} + + +QualifiedName& QualifiedName::operator=(const string& name) +{ + m_name = vector<string>{name}; + return *this; +} + + +QualifiedName& QualifiedName::operator=(const vector<string>& 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<string>::iterator QualifiedName::begin() +{ + return m_name.begin(); +} + + +vector<string>::iterator QualifiedName::end() +{ + return m_name.end(); +} + + +vector<string>::const_iterator QualifiedName::begin() const +{ + return m_name.begin(); +} + + +vector<string>::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<string>::iterator loc, const string& name) +{ + m_name.insert(loc, name); +} + + +void QualifiedName::insert(vector<string>::iterator loc, vector<string>::iterator b, vector<string>::iterator e) +{ + m_name.insert(loc, b, e); +} + + +void QualifiedName::erase(vector<string>::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; +} + + +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; @@ -133,30 +346,18 @@ Ref<Enumeration> Type::GetEnumeration() const } -uint64_t Type::GetElementCount() const +Ref<NamedTypeReference> Type::GetNamedTypeReference() const { - return BNGetTypeElementCount(m_object); + BNNamedTypeReference* ref = BNGetTypeNamedTypeReference(m_object); + if (ref) + return new NamedTypeReference(ref); + return nullptr; } -string Type::GetQualifiedName(const vector<string>& names) +uint64_t Type::GetElementCount() const { - bool first = true; - string out; - for (auto &name : names) - { - if (!first) - { - out += "::" + name; - } - else - { - out += name; - } - if (name.length() != 0) - first = false; - } - return out; + return BNGetTypeElementCount(m_object); } @@ -169,15 +370,11 @@ string Type::GetString() const } -string Type::GetTypeAndName(const vector<string>& 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++) - { - 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; } @@ -199,6 +396,78 @@ string Type::GetStringAfterName() const } +vector<InstructionTextToken> Type::GetTokens() const +{ + size_t count; + BNInstructionTextToken* tokens = BNGetTypeTokens(m_object, &count); + + vector<InstructionTextToken> result; + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = tokens[i].type; + token.text = tokens[i].text; + token.value = tokens[i].value; + token.size = tokens[i].size; + token.operand = tokens[i].operand; + token.context = tokens[i].context; + token.address = tokens[i].address; + result.push_back(token); + } + + BNFreeTokenList(tokens, count); + return result; +} + + +vector<InstructionTextToken> Type::GetTokensBeforeName() const +{ + size_t count; + BNInstructionTextToken* tokens = BNGetTypeTokensBeforeName(m_object, &count); + + vector<InstructionTextToken> result; + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = tokens[i].type; + token.text = tokens[i].text; + token.value = tokens[i].value; + token.size = tokens[i].size; + token.operand = tokens[i].operand; + token.context = tokens[i].context; + token.address = tokens[i].address; + result.push_back(token); + } + + BNFreeTokenList(tokens, count); + return result; +} + + +vector<InstructionTextToken> Type::GetTokensAfterName() const +{ + size_t count; + BNInstructionTextToken* tokens = BNGetTypeTokensAfterName(m_object, &count); + + vector<InstructionTextToken> result; + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = tokens[i].type; + token.text = tokens[i].text; + token.value = tokens[i].value; + token.size = tokens[i].size; + token.operand = tokens[i].operand; + token.context = tokens[i].context; + token.address = tokens[i].address; + result.push_back(token); + } + + BNFreeTokenList(tokens, count); + return result; +} + + Ref<Type> Type::Duplicate() const { return new Type(BNDuplicateType(m_object)); @@ -235,9 +504,34 @@ Ref<Type> Type::StructureType(Structure* strct) } -Ref<Type> Type::UnknownNamedType(UnknownType* unknwn) +Ref<Type> 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> Type::NamedType(const QualifiedName& name, Type* type) +{ + return NamedType("", name, type); +} + + +Ref<Type> Type::NamedType(const string& id, const QualifiedName& name, Type* type) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromTypeAndId(id.c_str(), &nameObj, + type ? type->GetObject() : nullptr)); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +Ref<Type> Type::NamedType(BinaryView* view, const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(view->GetObject(), &nameObj)); + QualifiedName::FreeAPIObject(&nameObj); + return result; } @@ -283,76 +577,129 @@ void Type::SetFunctionCanReturn(bool canReturn) } -UnknownType::UnknownType(BNUnknownType* ut, vector<string> names) +string Type::GenerateAutoTypeId(const string& source, const QualifiedName& name) { - m_object = ut; - 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()); - delete [] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + char* str = BNGenerateAutoTypeId(source.c_str(), &nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; } -void UnknownType::SetName(const vector<string>& names) +string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) { - 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()); - delete [] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + char* str = BNGenerateAutoDemangledTypeId(&nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; } -vector<string> UnknownType::GetName() const +string Type::GetAutoDemangledTypeIdSource() { - size_t size; - char** name = BNGetUnknownTypeName(m_object, &size); - vector<string> result; - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; + char* str = BNGetAutoDemangledTypeIdSource(); + string result = str; + BNFreeString(str); return result; } -Structure::Structure(BNStructure* s) +NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { - m_object = s; + m_object = nt; } -vector<string> Structure::GetName() const +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const string& id, const QualifiedName& names) { - size_t size; - char** name = BNGetStructureName(m_object, &size); - vector<string> result; - for (size_t i = 0; i < size; i++) + m_object = BNCreateNamedType(); + BNSetTypeReferenceClass(m_object, cls); + if (id.size() != 0) { - result.push_back(name[i]); - BNFreeString(name[i]); + BNSetTypeReferenceId(m_object, id.c_str()); } - delete [] name; + if (names.size() != 0) + { + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + } +} + + +void NamedTypeReference::SetTypeClass(BNNamedTypeReferenceClass cls) +{ + BNSetTypeReferenceClass(m_object, cls); +} + + +BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const +{ + return BNGetTypeReferenceClass(m_object); +} + + +string NamedTypeReference::GetTypeId() const +{ + char* str = BNGetTypeReferenceId(m_object); + string result = str; + BNFreeString(str); return result; } -void Structure::SetName(const vector<string>& names) +void NamedTypeReference::SetTypeId(const string& id) { - 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; + BNSetTypeReferenceId(m_object, id.c_str()); +} + + +void NamedTypeReference::SetName(const QualifiedName& names) +{ + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); +} + + +QualifiedName NamedTypeReference::GetName() const +{ + BNQualifiedName name = BNGetTypeReferenceName(m_object); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); + return result; +} + + +Ref<NamedTypeReference> NamedTypeReference::GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const string& source, const QualifiedName& name) +{ + string id = Type::GenerateAutoTypeId(source, name); + return new NamedTypeReference(cls, id, name); +} + + +Ref<NamedTypeReference> NamedTypeReference::GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoDemangledTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + +Structure::Structure() +{ + m_object = BNCreateStructure(); +} + + +Structure::Structure(BNStructure* s) +{ + m_object = s; } @@ -382,12 +729,24 @@ uint64_t Structure::GetWidth() const } +void Structure::SetWidth(size_t width) +{ + BNSetStructureWidth(m_object, width); +} + + size_t Structure::GetAlignment() const { return BNGetStructureAlignment(m_object); } +void Structure::SetAlignment(size_t align) +{ + BNSetStructureAlignment(m_object, align); +} + + bool Structure::IsPacked() const { return BNIsStructurePacked(m_object); @@ -430,35 +789,15 @@ void Structure::RemoveMember(size_t idx) } -Enumeration::Enumeration(BNEnumeration* e) +void Structure::ReplaceMember(size_t idx, Type* type, const std::string& name) { - m_object = e; + BNReplaceStructureMember(m_object, idx, type->GetObject(), name.c_str()); } -vector<string> Enumeration::GetName() const -{ - vector<string> 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<string>& names) +Enumeration::Enumeration(BNEnumeration* e) { - 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; + m_object = e; } @@ -494,6 +833,18 @@ void Enumeration::AddMemberWithValue(const string& name, uint64_t value) } +void Enumeration::RemoveMember(size_t idx) +{ + BNRemoveEnumerationMember(m_object, idx); +} + + +void Enumeration::ReplaceMember(size_t idx, const string& name, uint64_t value) +{ + BNReplaceEnumerationMember(m_object, idx, name.c_str(), value); +} + + bool BinaryNinja::PreprocessSource(const string& source, const string& fileName, string& output, string& errors, const vector<string>& includeDirs) { |
