From 3d403cfae9d5a366f112c8a5936a371a01cfd230 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 10 Jul 2017 21:40:51 -0400 Subject: Add confidence levels to type objects --- architecture.cpp | 18 +++- basicblock.cpp | 1 + binaryninjaapi.h | 250 +++++++++++++++++++++++++++++++++++++------- binaryninjacore.h | 105 +++++++++++++------ binaryview.cpp | 28 +++-- function.cpp | 48 ++++++--- functiongraphblock.cpp | 1 + lowlevelil.cpp | 2 + mediumlevelil.cpp | 2 + python/architecture.py | 4 +- python/basicblock.py | 3 +- python/binaryview.py | 23 ++-- python/callingconvention.py | 9 +- python/function.py | 48 ++++++--- python/lowlevelil.py | 3 +- python/mediumlevelil.py | 3 +- python/types.py | 165 +++++++++++++++++++++++------ type.cpp | 175 ++++++++++++++++++++++--------- 18 files changed, 682 insertions(+), 206 deletions(-) diff --git a/architecture.cpp b/architecture.cpp index eb70b16c..3e82ffd3 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -46,24 +46,31 @@ void InstructionInfo::AddBranch(BNBranchType type, uint64_t target, Architecture } -InstructionTextToken::InstructionTextToken(): type(TextToken), value(0) +InstructionTextToken::InstructionTextToken(): type(TextToken), value(0), confidence(BN_FULL_CONFIDENCE) { } 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), context(NoTokenContext), address(0) + size_t s, size_t o, uint8_t c) : type(t), text(txt), value(val), size(s), operand(o), context(NoTokenContext), + confidence(c), 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) + const string& txt, uint64_t a, uint64_t val, size_t s, size_t o, uint8_t c): + type(t), text(txt), value(val), size(s), operand(o), context(ctxt), confidence(c), address(a) { } +InstructionTextToken InstructionTextToken::WithConfidence(uint8_t conf) +{ + return InstructionTextToken(type, context, text, address, value, size, operand, conf); +} + + Architecture::Architecture(BNArchitecture* arch) { m_object = arch; @@ -161,6 +168,7 @@ bool Architecture::GetInstructionTextCallback(void* ctxt, const uint8_t* data, u (*result)[i].size = tokens[i].size; (*result)[i].operand = tokens[i].operand; (*result)[i].context = tokens[i].context; + (*result)[i].confidence = tokens[i].confidence; (*result)[i].address = tokens[i].address; } return true; @@ -990,7 +998,7 @@ 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].context, tokens[i].text, tokens[i].address, - tokens[i].value, tokens[i].size, tokens[i].operand)); + tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence)); } BNFreeInstructionText(tokens, count); diff --git a/basicblock.cpp b/basicblock.cpp index c2a2bddf..721f1ca6 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -276,6 +276,7 @@ vector BasicBlock::GetDisassemblyText(DisassemblySettings* token.size = lines[i].tokens[j].size; token.operand = lines[i].tokens[j].operand; token.context = lines[i].tokens[j].context; + token.confidence = lines[i].tokens[j].confidence; token.address = lines[i].tokens[j].address; line.tokens.push_back(token); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5850ad0..2341e39f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -285,6 +285,174 @@ namespace BinaryNinja } }; + class ConfidenceBase + { + protected: + uint8_t m_confidence; + + public: + ConfidenceBase(): m_confidence(0) + { + } + + ConfidenceBase(uint8_t conf): m_confidence(conf) + { + } + + uint8_t GetConfidence() const { return m_confidence; } + void SetConfidence(uint8_t conf) { m_confidence = conf; } + bool IsUnknown() const { return m_confidence == 0; } + }; + + template + class Confidence: public ConfidenceBase + { + T m_value; + + public: + Confidence() + { + } + + Confidence(const T& value): ConfidenceBase(BN_FULL_CONFIDENCE), m_value(value) + { + } + + Confidence(const T& value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Confidence& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator T() { return m_value; } + const operator T() const { return m_value; } + T* operator->() { return &m_value; } + const T* operator->() const { return &m_value; } + + T& GetValue() { return m_value; } + const T& GetValue() const { return m_value; } + void SetValue(const T& value) { m_value = value; } + + Confidence& operator=(const Confidence& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence& operator=(const T& value) + { + m_value = value; + m_confidence = BN_FULL_CONFIDENCE; + return *this; + } + + bool operator<(const Confidence& a) const + { + if (m_value < a.m_value) + return true; + if (a.m_value < m_value) + return false; + return m_confidence < a.m_confidence; + } + + bool operator==(const Confidence& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence& a) const + { + return !(*this == a); + } + }; + + template + class Confidence>: public ConfidenceBase + { + Ref m_value; + + public: + Confidence() + { + } + + Confidence(T* value): ConfidenceBase(value ? BN_FULL_CONFIDENCE : 0), m_value(value) + { + } + + Confidence(T* value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Ref& value): ConfidenceBase(value ? BN_FULL_CONFIDENCE : 0), m_value(value) + { + } + + Confidence(const Ref& value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Confidence>& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator Ref() const { return m_value; } + operator T*() const { return m_value.GetPtr(); } + T* operator->() const { return m_value.GetPtr(); } + bool operator!() const { return !m_value; } + + const Ref& GetValue() const { return m_value; } + void SetValue(T* value) { m_value = value; } + void SetValue(const Ref& value) { m_value = value; } + + Confidence>& operator=(const Confidence>& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence>& operator=(T* value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + Confidence>& operator=(const Ref& value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + bool operator<(const Confidence>& a) const + { + if (m_value < a.m_value) + return true; + if (a.m_value < m_value) + return false; + return m_confidence < a.m_confidence; + } + + bool operator==(const Confidence>& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence>& a) const + { + return !(*this == a); + } + }; + class LogListener { static void LogMessageCallback(void* ctxt, BNLogLevel level, const char* msg); @@ -775,14 +943,17 @@ namespace BinaryNinja uint64_t value; size_t size, operand; BNInstructionTextTokenContext context; + uint8_t confidence; 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); + size_t size = 0, size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE); 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); + size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE); + + InstructionTextToken WithConfidence(uint8_t conf); }; struct DisassemblyTextLine @@ -826,7 +997,7 @@ namespace BinaryNinja struct DataVariable { uint64_t address; - Ref type; + Confidence> type; bool autoDiscovered; }; @@ -1004,8 +1175,8 @@ namespace BinaryNinja void UpdateAnalysis(); void AbortAnalysis(); - void DefineDataVariable(uint64_t addr, Type* type); - void DefineUserDataVariable(uint64_t addr, Type* type); + void DefineDataVariable(uint64_t addr, const Confidence>& type); + void DefineUserDataVariable(uint64_t addr, const Confidence>& type); void UndefineDataVariable(uint64_t addr); void UndefineUserDataVariable(uint64_t addr); @@ -1632,7 +1803,7 @@ namespace BinaryNinja struct NameAndType { std::string name; - Ref type; + Confidence> type; }; struct QualifiedNameAndType @@ -1650,29 +1821,29 @@ namespace BinaryNinja uint64_t GetWidth() const; size_t GetAlignment() const; QualifiedName GetTypeName() const; - bool IsSigned() const; - bool IsConst() const; - bool IsVolatile() const; + Confidence IsSigned() const; + Confidence IsConst() const; + Confidence IsVolatile() const; bool IsFloat() const; - Ref GetChildType() const; - Ref GetCallingConvention() const; + Confidence> GetChildType() const; + Confidence> GetCallingConvention() const; std::vector GetParameters() const; bool HasVariableArguments() const; - bool CanReturn() const; + Confidence CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; Ref GetNamedTypeReference() const; - BNMemberScope GetScope() const; - void SetScope(BNMemberScope scope); - BNMemberAccess GetAccess() const; - void SetAccess(BNMemberAccess access); - void SetConst(bool cnst); - void SetVolatile(bool vltl); + Confidence GetScope() const; + void SetScope(const Confidence& scope); + Confidence GetAccess() const; + void SetAccess(const Confidence& access); + void SetConst(const Confidence& cnst); + void SetVolatile(const Confidence& vltl); void SetTypeName(const QualifiedName& name); uint64_t GetElementCount() const; - void SetFunctionCanReturn(bool canReturn); + void SetFunctionCanReturn(const Confidence& canReturn); std::string GetString() const; std::string GetTypeAndName(const QualifiedName& name) const; @@ -1687,7 +1858,7 @@ namespace BinaryNinja static Ref VoidType(); static Ref BoolType(); - static Ref IntegerType(size_t width, bool sign, const std::string& altName = ""); + static Ref IntegerType(size_t width, const Confidence& sign, const std::string& altName = ""); static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); @@ -1695,19 +1866,24 @@ namespace BinaryNinja static Ref NamedType(const std::string& id, const QualifiedName& name, Type* type); static Ref NamedType(BinaryView* view, const QualifiedName& name); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); - static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref PointerType(size_t width, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref ArrayType(Type* type, uint64_t elem); - static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector& params, bool varArg = false); + static Ref PointerType(Architecture* arch, const Confidence>& type, + const Confidence& cnst = Confidence(false, 0), + const Confidence& vltl = Confidence(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref PointerType(size_t width, const Confidence>& type, + const Confidence& cnst = Confidence(false, 0), + const Confidence& vltl = Confidence(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref ArrayType(const Confidence>& type, uint64_t elem); + static Ref FunctionType(const Confidence>& returnValue, + const Confidence>& callingConvention, + const std::vector& params, bool varArg = false); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); static std::string GetAutoDemangledTypeIdSource(); static std::string GenerateAutoDebugTypeId(const QualifiedName& name); static std::string GetAutoDebugTypeIdSource(); + + Confidence> WithConfidence(uint8_t conf); }; class NamedTypeReference: public CoreRefCountObject>& type, const std::string& name); + void AddMemberAtOffset(const Confidence>& type, const std::string& name, uint64_t offset); void RemoveMember(size_t idx); - void ReplaceMember(size_t idx, Type* type, const std::string& name); + void ReplaceMember(size_t idx, const Confidence>& type, const std::string& name); }; struct EnumerationMember @@ -1873,7 +2049,7 @@ namespace BinaryNinja struct VariableNameAndType { Variable var; - Ref type; + Confidence> type; std::string name; bool autoDefined; }; @@ -1881,7 +2057,7 @@ namespace BinaryNinja struct StackVariableReference { uint32_t sourceOperand; - Ref type; + Confidence> type; std::string name; Variable var; int64_t referencedOffset; @@ -1990,20 +2166,20 @@ namespace BinaryNinja Ref CreateFunctionGraph(); std::map> GetStackLayout(); - void CreateAutoStackVariable(int64_t offset, Ref type, const std::string& name); - void CreateUserStackVariable(int64_t offset, Ref type, const std::string& name); + void CreateAutoStackVariable(int64_t offset, const Confidence>& type, const std::string& name); + void CreateUserStackVariable(int64_t offset, const Confidence>& type, const std::string& name); void DeleteAutoStackVariable(int64_t offset); void DeleteUserStackVariable(int64_t offset); bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var); std::map GetVariables(); - void CreateAutoVariable(const Variable& var, Ref type, const std::string& name, + void CreateAutoVariable(const Variable& var, const Confidence>& type, const std::string& name, bool ignoreDisjointUses = false); - void CreateUserVariable(const Variable& var, Ref type, const std::string& name, + void CreateUserVariable(const Variable& var, const Confidence>& type, const std::string& name, bool ignoreDisjointUses = false); void DeleteAutoVariable(const Variable& var); void DeleteUserVariable(const Variable& var); - Ref GetVariableType(const Variable& var); + Confidence> GetVariableType(const Variable& var); std::string GetVariableName(const Variable& var); void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches); diff --git a/binaryninjacore.h b/binaryninjacore.h index eb9927ab..f5b89437 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,6 +92,8 @@ #define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL #define BN_MAX_VARIABLE_INDEX 0xfffff +#define BN_FULL_CONFIDENCE 255 + #ifdef __cplusplus extern "C" { @@ -714,6 +716,7 @@ extern "C" uint64_t address; BNType* type; bool autoDiscovered; + uint8_t typeConfidence; }; enum BNMediumLevelILOperation @@ -962,6 +965,7 @@ extern "C" uint64_t value; size_t size, operand; BNInstructionTextTokenContext context; + uint8_t confidence; uint64_t address; }; @@ -1080,10 +1084,41 @@ extern "C" char* (*serialize)(void* ctxt); }; + struct BNTypeWithConfidence + { + BNType* type; + uint8_t confidence; + }; + + struct BNCallingConventionWithConfidence + { + BNCallingConvention* convention; + uint8_t confidence; + }; + + struct BNBoolWithConfidence + { + bool value; + uint8_t confidence; + }; + + struct BNMemberScopeWithConfidence + { + BNMemberScope value; + uint8_t confidence; + }; + + struct BNMemberAccessWithConfidence + { + BNMemberAccess value; + uint8_t confidence; + }; + struct BNNameAndType { char* name; BNType* type; + uint8_t typeConfidence; }; struct BNQualifiedNameAndType @@ -1097,6 +1132,7 @@ extern "C" BNType* type; char* name; uint64_t offset; + uint8_t typeConfidence; }; struct BNEnumerationMember @@ -1199,11 +1235,13 @@ extern "C" BNType* type; char* name; bool autoDefined; + uint8_t typeConfidence; }; struct BNStackVariableReference { uint32_t sourceOperand; + uint8_t typeConfidence; BNType* type; char* name; uint64_t varIdentifier; @@ -2027,8 +2065,10 @@ extern "C" BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count); - BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); - BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); + BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, + BNTypeWithConfidence* type, const char* name); + BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, + BNTypeWithConfidence* type, const char* name); BINARYNINJACOREAPI void BNDeleteAutoStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, BNArchitecture* arch, uint64_t addr, @@ -2036,13 +2076,13 @@ extern "C" BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var); BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count); - BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type, + BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNTypeWithConfidence* type, const char* name, bool ignoreDisjointUses); - BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type, + BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNTypeWithConfidence* type, const char* name, bool ignoreDisjointUses); BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var); - BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetVariableType(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI uint64_t BNToVariableIdentifier(const BNVariable* var); BINARYNINJACOREAPI BNVariable BNFromVariableIdentifier(uint64_t id); @@ -2093,8 +2133,8 @@ extern "C" BNLinearDisassemblyPosition* pos, BNDisassemblySettings* settings, size_t* count); BINARYNINJACOREAPI void BNFreeLinearDisassemblyLines(BNLinearDisassemblyLine* lines, size_t count); - BINARYNINJACOREAPI void BNDefineDataVariable(BNBinaryView* view, uint64_t addr, BNType* type); - BINARYNINJACOREAPI void BNDefineUserDataVariable(BNBinaryView* view, uint64_t addr, BNType* type); + BINARYNINJACOREAPI void BNDefineDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNDefineUserDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); BINARYNINJACOREAPI void BNUndefineDataVariable(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI void BNUndefineUserDataVariable(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI BNDataVariable* BNGetDataVariables(BNBinaryView* view, size_t* count); @@ -2451,17 +2491,18 @@ extern "C" // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); - BINARYNINJACOREAPI BNType* BNCreateIntegerType(size_t width, bool sign, const char* altName); + BINARYNINJACOREAPI BNType* BNCreateIntegerType(size_t width, BNBoolWithConfidence* sign, const char* altName); BINARYNINJACOREAPI BNType* BNCreateFloatType(size_t width, const char* altName); BINARYNINJACOREAPI BNType* BNCreateStructureType(BNStructure* s); BINARYNINJACOREAPI BNType* BNCreateEnumerationType(BNArchitecture* arch, BNEnumeration* e, size_t width, bool isSigned); - BINARYNINJACOREAPI BNType* BNCreatePointerType(BNArchitecture* arch, BNType* type, bool cnst, bool vltl, - BNReferenceType refType); - BINARYNINJACOREAPI BNType* BNCreatePointerTypeOfWidth(size_t width, BNType* type, bool cnst, bool vltl, - BNReferenceType refType); - BINARYNINJACOREAPI BNType* BNCreateArrayType(BNType* type, uint64_t elem); - BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNType* returnValue, BNCallingConvention* callingConvention, - BNNameAndType* params, size_t paramCount, bool varArg); + BINARYNINJACOREAPI BNType* BNCreatePointerType(BNArchitecture* arch, BNTypeWithConfidence* type, + BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); + BINARYNINJACOREAPI BNType* BNCreatePointerTypeOfWidth(size_t width, BNTypeWithConfidence* type, + BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); + BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); + BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, + BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params, + size_t paramCount, bool varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2472,27 +2513,27 @@ extern "C" BINARYNINJACOREAPI BNTypeClass BNGetTypeClass(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeWidth(BNType* type); BINARYNINJACOREAPI size_t BNGetTypeAlignment(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeSigned(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeConst(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeVolatile(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeSigned(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeConst(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeVolatile(BNType* type); BINARYNINJACOREAPI bool BNIsTypeFloatingPoint(BNType* type); - BINARYNINJACOREAPI BNType* BNGetChildType(BNType* type); - BINARYNINJACOREAPI BNCallingConvention* BNGetTypeCallingConvention(BNType* type); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetChildType(BNType* type); + BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); BINARYNINJACOREAPI bool BNTypeHasVariableArguments(BNType* type); - BINARYNINJACOREAPI bool BNFunctionTypeCanReturn(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence 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 BNMemberScope BNTypeGetMemberScope(BNType* type); - BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScope scope); - BINARYNINJACOREAPI BNMemberAccess BNTypeGetMemberAccess(BNType* type); - BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccess access); - BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, bool cnst); - BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, bool vltl); + BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn); + BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); + BINARYNINJACOREAPI BNMemberAccessWithConfidence BNTypeGetMemberAccess(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccessWithConfidence* access); + BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); + BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); @@ -2533,10 +2574,12 @@ extern "C" BINARYNINJACOREAPI void BNSetStructureType(BNStructure* s, BNStructureType type); BINARYNINJACOREAPI BNStructureType BNGetStructureType(BNStructure* s); - BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNType* type, const char* name); - BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNType* type, const char* name, uint64_t offset); + BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNTypeWithConfidence* type, const char* name); + BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNTypeWithConfidence* 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 void BNReplaceStructureMember(BNStructure* s, size_t idx, BNTypeWithConfidence* type, + const char* name); BINARYNINJACOREAPI BNEnumeration* BNCreateEnumeration(void); BINARYNINJACOREAPI BNEnumeration* BNNewEnumerationReference(BNEnumeration* e); diff --git a/binaryview.cpp b/binaryview.cpp index b330508d..03764f85 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -84,7 +84,7 @@ void BinaryDataNotification::DataVariableAddedCallback(void* ctxt, BNBinaryView* Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableAdded(view, varObj); } @@ -96,7 +96,7 @@ void BinaryDataNotification::DataVariableRemovedCallback(void* ctxt, BNBinaryVie Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableRemoved(view, varObj); } @@ -108,7 +108,7 @@ void BinaryDataNotification::DataVariableUpdatedCallback(void* ctxt, BNBinaryVie Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableUpdated(view, varObj); } @@ -884,15 +884,21 @@ void BinaryView::AbortAnalysis() } -void BinaryView::DefineDataVariable(uint64_t addr, Type* type) +void BinaryView::DefineDataVariable(uint64_t addr, const Confidence>& type) { - BNDefineDataVariable(m_object, addr, type->GetObject()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNDefineDataVariable(m_object, addr, &tc); } -void BinaryView::DefineUserDataVariable(uint64_t addr, Type* type) +void BinaryView::DefineUserDataVariable(uint64_t addr, const Confidence>& type) { - BNDefineUserDataVariable(m_object, addr, type->GetObject()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNDefineUserDataVariable(m_object, addr, &tc); } @@ -918,7 +924,7 @@ map BinaryView::GetDataVariables() { DataVariable var; var.address = vars[i].address; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.autoDiscovered = vars[i].autoDiscovered; result[var.address] = var; } @@ -931,7 +937,7 @@ map BinaryView::GetDataVariables() bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) { var.address = 0; - var.type = nullptr; + var.type = Confidence>(nullptr, 0); var.autoDiscovered = false; BNDataVariable result; @@ -939,7 +945,7 @@ bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) return false; var.address = result.address; - var.type = new Type(result.type); + var.type = Confidence>(new Type(result.type), result.typeConfidence); var.autoDiscovered = result.autoDiscovered; return true; } @@ -1388,6 +1394,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line 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.confidence = lines[i].contents.tokens[j].confidence; token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } @@ -1433,6 +1440,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi 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.confidence = lines[i].contents.tokens[j].confidence; token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } diff --git a/function.cpp b/function.cpp index b570499c..0e1fa5cf 100644 --- a/function.cpp +++ b/function.cpp @@ -353,7 +353,8 @@ vector Function::GetStackVariablesReferencedByInstructio { StackVariableReference ref; ref.sourceOperand = refs[i].sourceOperand; - ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr; + ref.type = Confidence>(refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr, + refs[i].typeConfidence); ref.name = refs[i].name; ref.var = Variable::FromIdentifier(refs[i].varIdentifier); ref.referencedOffset = refs[i].referencedOffset; @@ -491,7 +492,7 @@ map> Function::GetStackLayout() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; result[vars[i].var.storage].push_back(var); @@ -502,15 +503,21 @@ map> Function::GetStackLayout() } -void Function::CreateAutoStackVariable(int64_t offset, Ref type, const string& name) +void Function::CreateAutoStackVariable(int64_t offset, const Confidence>& type, const string& name) { - BNCreateAutoStackVariable(m_object, offset, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateAutoStackVariable(m_object, offset, &tc, name.c_str()); } -void Function::CreateUserStackVariable(int64_t offset, Ref type, const string& name) +void Function::CreateUserStackVariable(int64_t offset, const Confidence>& type, const string& name) { - BNCreateUserStackVariable(m_object, offset, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateUserStackVariable(m_object, offset, &tc, name.c_str()); } @@ -533,7 +540,7 @@ bool Function::GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, if (!BNGetStackVariableAtFrameOffset(m_object, arch->GetObject(), addr, offset, &var)) return false; - result.type = new Type(BNNewTypeReference(var.type)); + result.type = Confidence>(new Type(BNNewTypeReference(var.type)), var.typeConfidence); result.name = var.name; result.var = var.var; result.autoDefined = var.autoDefined; @@ -553,7 +560,7 @@ map Function::GetVariables() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; result[vars[i].var] = var; @@ -564,15 +571,23 @@ map Function::GetVariables() } -void Function::CreateAutoVariable(const Variable& var, Ref type, const string& name, bool ignoreDisjointUses) +void Function::CreateAutoVariable(const Variable& var, const Confidence>& type, + const string& name, bool ignoreDisjointUses) { - BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateAutoVariable(m_object, &var, &tc, name.c_str(), ignoreDisjointUses); } -void Function::CreateUserVariable(const Variable& var, Ref type, const string& name, bool ignoreDisjointUses) +void Function::CreateUserVariable(const Variable& var, const Confidence>& type, + const string& name, bool ignoreDisjointUses) { - BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateUserVariable(m_object, &var, &tc, name.c_str(), ignoreDisjointUses); } @@ -588,12 +603,12 @@ void Function::DeleteUserVariable(const Variable& var) } -Ref Function::GetVariableType(const Variable& var) +Confidence> Function::GetVariableType(const Variable& var) { - BNType* type = BNGetVariableType(m_object, &var); - if (!type) + BNTypeWithConfidence type = BNGetVariableType(m_object, &var); + if (!type.type) return nullptr; - return new Type(type); + return Confidence>(new Type(type.type), type.confidence); } @@ -694,6 +709,7 @@ vector> Function::GetBlockAnnotations(Architecture* token.size = lines[i].tokens[j].size; token.operand = lines[i].tokens[j].operand; token.context = lines[i].tokens[j].context; + token.confidence = lines[i].tokens[j].confidence; token.address = lines[i].tokens[j].address; line.push_back(token); } diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 938fb635..20b2515b 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -102,6 +102,7 @@ const vector& FunctionGraphBlock::GetLines() token.size = lines[i].tokens[j].size; token.operand = lines[i].tokens[j].operand; token.context = lines[i].tokens[j].context; + token.confidence = lines[i].tokens[j].confidence; token.address = lines[i].tokens[j].address; line.tokens.push_back(token); } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index c48b5b92..4ff16a05 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -658,6 +658,7 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector>> bv.define_data_var(bv.entry_point, t[0]) >>> """ - core.BNDefineDataVariable(self.handle, addr, var_type.handle) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNDefineDataVariable(self.handle, addr, tc) def define_user_data_var(self, addr, var_type): """ @@ -1864,7 +1867,10 @@ class BinaryView(object): >>> bv.define_user_data_var(bv.entry_point, t[0]) >>> """ - core.BNDefineUserDataVariable(self.handle, addr, var_type.handle) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNDefineUserDataVariable(self.handle, addr, tc) def undefine_data_var(self, addr): """ @@ -1910,7 +1916,7 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, types.Type(var.type), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type, confidence = var.typeConfidence), var.autoDiscovered) def get_function_at(self, addr, plat=None): """ @@ -2781,8 +2787,9 @@ class BinaryView(object): size = lines[i].contents.tokens[j].size operand = lines[i].contents.tokens[j].operand context = lines[i].contents.tokens[j].context + confidence = lines[i].contents.tokens[j].confidence address = lines[i].contents.tokens[j].address - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) contents = function.DisassemblyTextLine(addr, tokens) result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) diff --git a/python/callingconvention.py b/python/callingconvention.py index 4c87eef6..e6aa323c 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -25,6 +25,7 @@ import ctypes import _binaryninjacore as core import architecture import log +import types class CallingConvention(object): @@ -40,7 +41,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, handle = None): + def __init__(self, arch, handle = None, confidence = types.Type.max_confidence): if handle is None: self.arch = arch self._pending_reg_lists = {} @@ -109,6 +110,8 @@ class CallingConvention(object): else: self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg) + self.confidence = confidence + def __del__(self): core.BNFreeCallingConvention(self.handle) @@ -220,3 +223,7 @@ class CallingConvention(object): def __str__(self): return self.name + + def with_confidence(self, confidence): + return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), + confidence = confidence) diff --git a/python/function.py b/python/function.py index 8beebe66..3cd5396f 100644 --- a/python/function.py +++ b/python/function.py @@ -183,9 +183,11 @@ class Variable(object): if name is None: name = core.BNGetVariableName(func.handle, var) if var_type is None: - var_type = core.BNGetVariableType(func.handle, var) - if var_type: - var_type = types.Type(var_type) + var_type_conf = core.BNGetVariableType(func.handle, var) + if var_type_conf.type: + var_type = types.Type(var_type, confidence = var_type_conf.confidence) + else: + var_type = None self.name = name self.type = var_type @@ -390,7 +392,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, - types.Type(handle = core.BNNewTypeReference(v[i].type)))) + types.Type(handle = core.BNNewTypeReference(v[i].type), confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -403,7 +405,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, - types.Type(handle = core.BNNewTypeReference(v[i].type)))) + types.Type(handle = core.BNNewTypeReference(v[i].type), confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -616,7 +618,7 @@ class Function(object): refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - var_type = types.Type(core.BNNewTypeReference(refs[i].type)) + var_type = types.Type(core.BNNewTypeReference(refs[i].type), confidence = refs[i].typeConfidence) result.append(StackVariableReference(refs[i].sourceOperand, var_type, refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type), refs[i].referencedOffset)) @@ -730,8 +732,9 @@ class Function(object): size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand context = lines[i].tokens[j].context + confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address - tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) result.append(tokens) core.BNFreeInstructionTextLines(lines, count.value) return result @@ -853,10 +856,16 @@ class Function(object): core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct()) def create_auto_stack_var(self, offset, var_type, name): - core.BNCreateAutoStackVariable(self.handle, offset, var_type.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateAutoStackVariable(self.handle, offset, tc, name) def create_user_stack_var(self, offset, var_type, name): - core.BNCreateUserStackVariable(self.handle, offset, var_type.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateUserStackVariable(self.handle, offset, tc, name) def delete_auto_stack_var(self, offset): core.BNDeleteAutoStackVariable(self.handle, offset) @@ -869,14 +878,20 @@ class Function(object): var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - core.BNCreateAutoVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateAutoVariable(self.handle, var_data, tc, name, ignore_disjoint_uses) def create_user_var(self, var, var_type, name, ignore_disjoint_uses = False): var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - core.BNCreateUserVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateUserVariable(self.handle, var_data, tc, name, ignore_disjoint_uses) def delete_auto_var(self, var): var_data = core.BNVariable() @@ -899,7 +914,7 @@ class Function(object): if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var): return None result = Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage, - found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type))) + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type), confidence = found_var.typeConfidence)) core.BNFreeVariableNameAndType(found_var) return result @@ -1043,8 +1058,9 @@ class FunctionGraphBlock(object): size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand context = lines[i].tokens[j].context + confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address - tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) result.append(DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -1101,8 +1117,9 @@ class FunctionGraphBlock(object): size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand context = lines[i].tokens[j].context + confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address - tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) yield DisassemblyTextLine(addr, tokens) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1384,13 +1401,14 @@ class InstructionTextToken(object): """ def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, - context = InstructionTextTokenContext.NoTokenContext, address = 0): + context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.Type.max_confidence): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value self.size = size self.operand = operand self.context = InstructionTextTokenContext(context) + self.confidence = confidence self.address = address def __str__(self): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index c359a79c..62e33a75 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -309,8 +309,9 @@ class LowLevelILInstruction(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..275746cc 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -265,8 +265,9 @@ class MediumLevelILInstruction(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result diff --git a/python/types.py b/python/types.py index f8e416f4..c3d7156e 100644 --- a/python/types.py +++ b/python/types.py @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType import callingconvention import function @@ -198,8 +198,11 @@ class Symbol(object): class Type(object): - def __init__(self, handle): + max_confidence = 255 + + def __init__(self, handle, confidence = max_confidence): self.handle = handle + self.confidence = confidence def __del__(self): core.BNFreeType(self.handle) @@ -232,12 +235,14 @@ class Type(object): @property def signed(self): """Wether type is signed (read-only)""" - return core.BNIsTypeSigned(self.handle) + result = core.BNIsTypeSigned(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def const(self): """Whether type is const (read-only)""" - return core.BNIsTypeConst(self.handle) + result = core.BNIsTypeConst(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def modified(self): @@ -248,33 +253,33 @@ class Type(object): def target(self): """Target (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, confidence = result.confidence) @property def element_type(self): """Target (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, confidence = result.confidence) @property def return_value(self): """Return value (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, confidence = result.confidence) @property def calling_convention(self): """Calling convention (read-only)""" result = core.BNGetTypeCallingConvention(self.handle) - if result is None: + if not result.convention: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(None, result, confidence = result.confidence) @property def parameters(self): @@ -283,7 +288,7 @@ class Type(object): params = core.BNGetTypeParameters(self.handle, count) result = [] for i in xrange(0, count.value): - result.append((Type(core.BNNewTypeReference(params[i].type)), params[i].name)) + result.append((Type(core.BNNewTypeReference(params[i].type), confidence = params[i].typeConfidence), params[i].name)) core.BNFreeTypeParameterList(params, count.value) return result @@ -295,7 +300,8 @@ class Type(object): @property def can_return(self): """Whether type can return (read-only)""" - return core.BNFunctionTypeCanReturn(self.handle) + result = core.BNFunctionTypeCanReturn(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def structure(self): @@ -330,6 +336,8 @@ class Type(object): return core.BNGetTypeString(self.handle) def __repr__(self): + if self.confidence < Type.max_confidence: + return "" % (str(self), (self.confidence * 100) / Type.max_confidence) return "" % str(self) def get_string_before_name(self): @@ -351,8 +359,9 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -367,8 +376,9 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -383,8 +393,9 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -397,14 +408,23 @@ class Type(object): return Type(core.BNCreateBoolType()) @classmethod - def int(self, width, sign = True, altname=""): + def int(self, width, sign = None, altname=""): """ ``int`` class method for creating an int Type. :param int width: width of the integer in bytes :param bool sign: optional variable representing signedness """ - return Type(core.BNCreateIntegerType(width, sign, altname)) + if sign is None: + sign = BoolWithConfidence(True, confidence = 0) + elif not isinstance(sign, BoolWithConfidence): + sign = BoolWithConfidence(sign) + + sign_conf = core.BNBoolWithConfidence() + sign_conf.value = sign.value + sign_conf.confidence = sign.confidence + + return Type(core.BNCreateIntegerType(width, sign_conf, altname)) @classmethod def float(self, width): @@ -444,12 +464,40 @@ class Type(object): return Type(core.BNCreateEnumerationType(e.handle, width)) @classmethod - def pointer(self, arch, t, const=False): - return Type(core.BNCreatePointerType(arch.handle, t.handle, const)) + def pointer(self, arch, t, const=None, volatile=None, ref_type=None): + if const is None: + const = BoolWithConfidence(False, confidence = 0) + elif not isinstance(const, BoolWithConfidence): + const = BoolWithConfidence(const) + + if volatile is None: + volatile = BoolWithConfidence(False, confidence = 0) + elif not isinstance(volatile, BoolWithConfidence): + volatile = BoolWithConfidence(volatile) + + if ref_type is None: + ref_type = ReferenceType.PointerReferenceType + + type_conf = core.BNTypeWithConfidence() + type_conf.type = t.handle + type_conf.confidence = t.confidence + + const_conf = core.BNBoolWithConfidence() + const_conf.value = const.value + const_conf.confidence = const.confidence + + volatile_conf = core.BNBoolWithConfidence() + volatile_conf.value = volatile.value + volatile_conf.confidence = volatile.confidence + + return Type(core.BNCreatePointerType(arch.handle, type_conf, const_conf, volatile_conf, ref_type)) @classmethod def array(self, t, count): - return Type(core.BNCreateArrayType(t.handle, count)) + type_conf = core.BNTypeWithConfidence() + type_conf.type = t.handle + type_conf.confidence = t.confidence + return Type(core.BNCreateArrayType(type_conf, count)) @classmethod def function(self, ret, params, calling_convention=None, variable_arguments=False): @@ -466,13 +514,26 @@ class Type(object): if isinstance(params[i], Type): param_buf[i].name = "" param_buf[i].type = params[i].handle + param_buf[i].typeConfidence = params[i].confidence else: param_buf[i].name = params[i][1] - param_buf[i].type = params[i][0] - if calling_convention is not None: - calling_convention = calling_convention.handle - return Type(core.BNCreateFunctionType(ret.handle, calling_convention, param_buf, len(params), - variable_arguments)) + param_buf[i].type = params[i][0].handle + param_buf[i].typeConfidence = params[i][0].confidence + + ret_conf = core.BNTypeWithConfidence() + ret_conf.type = ret.handle + ret_conf.confidence = ret.confidence + + conv_conf = core.BNCallingConventionWithConfidence() + if calling_convention is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + conv_conf.convention = calling_convention.handle + conv_conf.confidence = calling_convention.confidence + + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), + variable_arguments)) @classmethod def generate_auto_type_id(self, source, name): @@ -488,6 +549,9 @@ class Type(object): def get_auto_demanged_type_id_source(self): return core.BNGetAutoDemangledTypeIdSource() + def with_confidence(self, confidence): + return Type(handle = core.BNNewTypeReference(self.handle), confidence = confidence) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -495,6 +559,36 @@ class Type(object): raise AttributeError("attribute '%s' is read only" % name) +class BoolWithConfidence(object): + def __init__(self, value, confidence = Type.max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + def __bool__(self): + return self.value + + def __nonzero__(self): + return self.value + + +class ReferenceTypeWithConfidence(object): + def __init__(self, value, confidence = Type.max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + class NamedTypeReference(object): def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: @@ -611,7 +705,7 @@ class Structure(object): members = core.BNGetStructureMembers(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type)), + result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type), confidence = members[i].typeConfidence), members[i].name, members[i].offset)) core.BNFreeStructureMemberList(members, count.value) return result @@ -664,16 +758,25 @@ class Structure(object): return "" % self.width def append(self, t, name = ""): - core.BNAddStructureMember(self.handle, t.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNAddStructureMember(self.handle, tc, name) def insert(self, offset, t, name = ""): - core.BNAddStructureMemberAtOffset(self.handle, t.handle, name, offset) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNAddStructureMemberAtOffset(self.handle, tc, name, offset) def remove(self, i): core.BNRemoveStructureMember(self.handle, i) def replace(self, i, t, name = ""): - core.BNReplaceStructureMember(self.handle, i, t.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNReplaceStructureMember(self.handle, i, tc, name) class EnumerationMember(object): diff --git a/type.cpp b/type.cpp index 6e55bb69..837b212d 100644 --- a/type.cpp +++ b/type.cpp @@ -261,15 +261,17 @@ size_t Type::GetAlignment() const } -bool Type::IsSigned() const +Confidence Type::IsSigned() const { - return BNIsTypeSigned(m_object); + BNBoolWithConfidence result = BNIsTypeSigned(m_object); + return Confidence(result.value, result.confidence); } -bool Type::IsConst() const +Confidence Type::IsConst() const { - return BNIsTypeConst(m_object); + BNBoolWithConfidence result = BNIsTypeConst(m_object); + return Confidence(result.value, result.confidence); } @@ -279,56 +281,70 @@ bool Type::IsFloat() const } -BNMemberScope Type::GetScope() const +Confidence Type::GetScope() const { - return BNTypeGetMemberScope(m_object); + BNMemberScopeWithConfidence result = BNTypeGetMemberScope(m_object); + return Confidence(result.value, result.confidence); } -void Type::SetScope(BNMemberScope scope) +void Type::SetScope(const Confidence& scope) { - return BNTypeSetMemberScope(m_object, scope); + BNMemberScopeWithConfidence mc; + mc.value = scope.GetValue(); + mc.confidence = scope.GetConfidence(); + return BNTypeSetMemberScope(m_object, &mc); } -BNMemberAccess Type::GetAccess() const +Confidence Type::GetAccess() const { - return BNTypeGetMemberAccess(m_object); + BNMemberAccessWithConfidence result = BNTypeGetMemberAccess(m_object); + return Confidence(result.value, result.confidence); } -void Type::SetAccess(BNMemberAccess access) +void Type::SetAccess(const Confidence& access) { - return BNTypeSetMemberAccess(m_object, access); + BNMemberAccessWithConfidence mc; + mc.value = access.GetValue(); + mc.confidence = access.GetConfidence(); + return BNTypeSetMemberAccess(m_object, &mc); } -void Type::SetConst(bool cnst) +void Type::SetConst(const Confidence& cnst) { - BNTypeSetConst(m_object, cnst); + BNBoolWithConfidence bc; + bc.value = cnst.GetValue(); + bc.confidence = cnst.GetConfidence(); + BNTypeSetConst(m_object, &bc); } -void Type::SetVolatile(bool vltl) +void Type::SetVolatile(const Confidence& vltl) { - BNTypeSetVolatile(m_object, vltl); + BNBoolWithConfidence bc; + bc.value = vltl.GetValue(); + bc.confidence = vltl.GetConfidence(); + BNTypeSetVolatile(m_object, &bc); } -Ref Type::GetChildType() const +Confidence> Type::GetChildType() const { - BNType* type = BNGetChildType(m_object); - if (type) - return new Type(type); + BNTypeWithConfidence type = BNGetChildType(m_object); + if (type.type) + return Confidence>(new Type(type.type), type.confidence); return nullptr; } -Ref Type::GetCallingConvention() const +Confidence> Type::GetCallingConvention() const { - BNCallingConvention* cc = BNGetTypeCallingConvention(m_object); - if (cc) - return new CoreCallingConvention(cc); + BNCallingConventionWithConfidence cc = BNGetTypeCallingConvention(m_object); + if (cc.convention) + return Confidence>(new CoreCallingConvention(cc.convention), cc.confidence); return nullptr; } @@ -343,7 +359,7 @@ vector Type::GetParameters() const { NameAndType param; param.name = types[i].name; - param.type = new Type(BNNewTypeReference(types[i].type)); + param.type = Confidence>(new Type(BNNewTypeReference(types[i].type)), types[i].typeConfidence); result.push_back(param); } @@ -358,9 +374,10 @@ bool Type::HasVariableArguments() const } -bool Type::CanReturn() const +Confidence Type::CanReturn() const { - return BNFunctionTypeCanReturn(m_object); + BNBoolWithConfidence result = BNFunctionTypeCanReturn(m_object); + return Confidence(result.value, result.confidence); } @@ -447,6 +464,7 @@ vector Type::GetTokens() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -471,6 +489,7 @@ vector Type::GetTokensBeforeName() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -495,6 +514,7 @@ vector Type::GetTokensAfterName() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -522,9 +542,12 @@ Ref Type::BoolType() } -Ref Type::IntegerType(size_t width, bool sign, const string& altName) +Ref Type::IntegerType(size_t width, const Confidence& sign, const string& altName) { - return new Type(BNCreateIntegerType(width, sign, altName.c_str())); + BNBoolWithConfidence bc; + bc.value = sign.GetValue(); + bc.confidence = sign.GetConfidence(); + return new Type(BNCreateIntegerType(width, &bc, altName.c_str())); } @@ -577,45 +600,86 @@ Ref Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t wid } -Ref Type::PointerType(Architecture* arch, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref Type::PointerType(Architecture* arch, const Confidence>& type, + const Confidence& cnst, const Confidence& vltl, BNReferenceType refType) { - return new Type(BNCreatePointerType(arch->GetObject(), type->GetObject(), cnst, vltl, refType)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + + BNBoolWithConfidence cnstConf; + cnstConf.value = cnst.GetValue(); + cnstConf.confidence = cnst.GetConfidence(); + + BNBoolWithConfidence vltlConf; + vltlConf.value = vltl.GetValue(); + vltlConf.confidence = vltl.GetConfidence(); + + return new Type(BNCreatePointerType(arch->GetObject(), &typeConf, &cnstConf, &vltlConf, refType)); } -Ref Type::PointerType(size_t width, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref Type::PointerType(size_t width, const Confidence>& type, + const Confidence& cnst, const Confidence& vltl, BNReferenceType refType) { - return new Type(BNCreatePointerTypeOfWidth(width, type->GetObject(), cnst, vltl, refType)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + + BNBoolWithConfidence cnstConf; + cnstConf.value = cnst.GetValue(); + cnstConf.confidence = cnst.GetConfidence(); + + BNBoolWithConfidence vltlConf; + vltlConf.value = vltl.GetValue(); + vltlConf.confidence = vltl.GetConfidence(); + + return new Type(BNCreatePointerTypeOfWidth(width, &typeConf, &cnstConf, &vltlConf, refType)); } -Ref Type::ArrayType(Type* type, uint64_t elem) +Ref Type::ArrayType(const Confidence>& type, uint64_t elem) { - return new Type(BNCreateArrayType(type->GetObject(), elem)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + return new Type(BNCreateArrayType(&typeConf, elem)); } -Ref Type::FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector& params, bool varArg) +Ref Type::FunctionType(const Confidence>& returnValue, + const Confidence>& callingConvention, + const std::vector& params, bool varArg) { + BNTypeWithConfidence returnValueConf; + returnValueConf.type = returnValue->GetObject(); + returnValueConf.confidence = returnValue.GetConfidence(); + + BNCallingConventionWithConfidence callingConventionConf; + callingConventionConf.convention = callingConvention ? callingConvention->GetObject() : nullptr; + callingConventionConf.confidence = callingConvention.GetConfidence(); + BNNameAndType* paramArray = new BNNameAndType[params.size()]; for (size_t i = 0; i < params.size(); i++) { paramArray[i].name = (char*)params[i].name.c_str(); paramArray[i].type = params[i].type->GetObject(); + paramArray[i].typeConfidence = params[i].type.GetConfidence(); } - Type* type = new Type(BNCreateFunctionType(returnValue->GetObject(), - callingConvention ? callingConvention->GetObject() : nullptr, - paramArray, params.size(), varArg)); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, + paramArray, params.size(), varArg)); delete[] paramArray; return type; } -void Type::SetFunctionCanReturn(bool canReturn) +void Type::SetFunctionCanReturn(const Confidence& canReturn) { - BNSetFunctionCanReturn(m_object, canReturn); + BNBoolWithConfidence bc; + bc.value = canReturn.GetValue(); + bc.confidence = canReturn.GetConfidence(); + BNSetFunctionCanReturn(m_object, &bc); } @@ -687,6 +751,12 @@ void Type::SetTypeName(const QualifiedName& names) } +Confidence> Type::WithConfidence(uint8_t conf) +{ + return Confidence>(this, conf); +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; @@ -870,15 +940,21 @@ BNStructureType Structure::GetStructureType() const } -void Structure::AddMember(Type* type, const string& name) +void Structure::AddMember(const Confidence>& type, const string& name) { - BNAddStructureMember(m_object, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNAddStructureMember(m_object, &tc, name.c_str()); } -void Structure::AddMemberAtOffset(Type* type, const string& name, uint64_t offset) +void Structure::AddMemberAtOffset(const Confidence>& type, const string& name, uint64_t offset) { - BNAddStructureMemberAtOffset(m_object, type->GetObject(), name.c_str(), offset); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNAddStructureMemberAtOffset(m_object, &tc, name.c_str(), offset); } @@ -888,9 +964,12 @@ void Structure::RemoveMember(size_t idx) } -void Structure::ReplaceMember(size_t idx, Type* type, const std::string& name) +void Structure::ReplaceMember(size_t idx, const Confidence>& type, const std::string& name) { - BNReplaceStructureMember(m_object, idx, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNReplaceStructureMember(m_object, idx, &tc, name.c_str()); } -- cgit v1.3.1