From 0de62768c8afc5ca27576b59d4591ca8dbbd7cee Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 24 Jun 2017 01:33:04 -0400 Subject: Adding settings system apis, and binaryview metadata apis --- binaryview.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryview.cpp b/binaryview.cpp index b18b065b..6eb299a3 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1826,6 +1826,57 @@ vector BinaryView::GetAllocatedRanges() } +void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue) +{ + if (!inValue) + return; + BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); +} + + +bool BinaryView::QueryMetadata(const std::string& key, Metadata** outValue) +{ + BNMetadata* value = nullptr; + bool status = BNBinaryViewQueryMetadata(m_object, key.c_str(), &value); + if (!status) + { + *outValue = nullptr; + return false; + } + *outValue = new Metadata(value); + return true; +} + +string BinaryView::GetStringMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsString()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetString(); + delete data; + return result; +} + +vector BinaryView::GetRawMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsRaw()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetRaw(); + delete data; + return result; +} + +uint64_t BinaryView::GetUIntMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsUnsignedInteger()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetUnsignedInteger(); + delete data; + return result; +} + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } -- cgit v1.3.1 From c407679358f035aa9e16e3bb740f8e6d9a73d138 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 1 Jul 2017 10:02:12 -0400 Subject: Refactor of metadata api names. modify how QueryMetadata works --- binaryninjaapi.h | 2 +- binaryninjacore.h | 24 ++++++++++++------------ binaryview.cpp | 42 ++++++++++++++++-------------------------- metadata.cpp | 26 +++++++++++++------------- settings.cpp | 1 + 5 files changed, 43 insertions(+), 52 deletions(-) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 426095b0..13ca3446 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1128,7 +1128,7 @@ namespace BinaryNinja std::vector GetAllocatedRanges(); void StoreMetadata(const std::string& key, Metadata* inValue); - bool QueryMetadata(const std::string& key, Metadata** outValue); + std::unique_ptr QueryMetadata(const std::string& key); std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); diff --git a/binaryninjacore.h b/binaryninjacore.h index 25aa150d..0394517f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2917,17 +2917,17 @@ extern "C" // Create Metadata of various types BINARYNINJACOREAPI BNMetadata* BNNewMetadataReference(BNMetadata* data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredBooleanData(bool data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredStringData(const char* data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredUnsignedIntegerData(uint64_t data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredSignedIntegerData(int64_t data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredDoubleData(double data); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredBooleanListData(const bool* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredStringListData(const char** data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredUnsignedIntegerListData(const uint64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredSignedIntegerListData(const int64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredDoubleListData(const double* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateStructuredRawData(const uint8_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataBooleanData(bool data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataStringData(const char* data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerData(uint64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerData(int64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleData(double data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataBooleanListData(const bool* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataStringListData(const char** data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerListData(const uint64_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerListData(const int64_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleListData(const double* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataRawData(const uint8_t* data, size_t size); BINARYNINJACOREAPI void BNFreeMetadata(BNMetadata* data); BINARYNINJACOREAPI void BNFreeMetadataBooleanList(bool* data); BINARYNINJACOREAPI void BNFreeMetadataStringList(char** data, size_t size); @@ -2963,7 +2963,7 @@ extern "C" // Store/Query structured data to/from a BinaryView BINARYNINJACOREAPI void BNBinaryViewStoreMetadata(BNBinaryView* view, const char* key, BNMetadata* value); - BINARYNINJACOREAPI bool BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key, BNMetadata** value); + BINARYNINJACOREAPI BNMetadata* BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key); #ifdef __cplusplus } #endif diff --git a/binaryview.cpp b/binaryview.cpp index 6eb299a3..b330508d 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "binaryninjaapi.h" using namespace BinaryNinja; @@ -1833,48 +1834,37 @@ void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue) BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); } - -bool BinaryView::QueryMetadata(const std::string& key, Metadata** outValue) +unique_ptr BinaryView::QueryMetadata(const std::string& key) { - BNMetadata* value = nullptr; - bool status = BNBinaryViewQueryMetadata(m_object, key.c_str(), &value); - if (!status) - { - *outValue = nullptr; - return false; - } - *outValue = new Metadata(value); - return true; + BNMetadata* value = BNBinaryViewQueryMetadata(m_object, key.c_str()); + if (!value) + return nullptr; + auto a = new Metadata(value); + return unique_ptr(a); } string BinaryView::GetStringMetadata(const string& key) { - Metadata* data; - if (!QueryMetadata(key, &data) || !data || data->IsString()) + auto data = QueryMetadata(key); + if (!data || !data->IsString()) throw QueryMetadataException("Failed to find key: " + key); - auto result = data->GetString(); - delete data; - return result; + return data->GetString(); } vector BinaryView::GetRawMetadata(const string& key) { - Metadata* data; - if (!QueryMetadata(key, &data) || !data || data->IsRaw()) + auto data = QueryMetadata(key); + if (!data || !data->IsRaw()) throw QueryMetadataException("Failed to find key: " + key); - auto result = data->GetRaw(); - delete data; - return result; + return data->GetRaw(); } uint64_t BinaryView::GetUIntMetadata(const string& key) { - Metadata* data; - if (!QueryMetadata(key, &data) || !data || data->IsUnsignedInteger()) + auto data = QueryMetadata(key); + if (!data || !data->IsUnsignedInteger()) throw QueryMetadataException("Failed to find key: " + key); - auto result = data->GetUnsignedInteger(); - delete data; - return result; + return data->GetUnsignedInteger(); } BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) diff --git a/metadata.cpp b/metadata.cpp index 2f398940..3f01f4bb 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -3,34 +3,34 @@ using namespace std; using namespace BinaryNinja; -Metadata::Metadata(BNMetadata* structuredData) +Metadata::Metadata(BNMetadata* metadata) { - m_object = structuredData; + m_object = metadata; } Metadata::Metadata(bool data) { - m_object = BNCreateStructuredBooleanData(data); + m_object = BNCreateMetadataBooleanData(data); } Metadata::Metadata(const string& data) { - m_object = BNCreateStructuredStringData(data.c_str()); + m_object = BNCreateMetadataStringData(data.c_str()); } Metadata::Metadata(uint64_t data) { - m_object = BNCreateStructuredUnsignedIntegerData(data); + m_object = BNCreateMetadataUnsignedIntegerData(data); } Metadata::Metadata(int64_t data) { - m_object = BNCreateStructuredSignedIntegerData(data); + m_object = BNCreateMetadataSignedIntegerData(data); } Metadata::Metadata(double data) { - m_object = BNCreateStructuredDoubleData(data); + m_object = BNCreateMetadataDoubleData(data); } Metadata::Metadata(const vector& data) @@ -39,7 +39,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = data[i]; - m_object = BNCreateStructuredBooleanListData(input, data.size()); + m_object = BNCreateMetadataBooleanListData(input, data.size()); delete[] input; } @@ -49,7 +49,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = BNAllocString(data[i].c_str()); - m_object = BNCreateStructuredStringListData((const char**)input, data.size()); + m_object = BNCreateMetadataStringListData((const char**)input, data.size()); for (size_t i = 0; i < data.size(); i++) BNFreeString(input[i]); @@ -62,7 +62,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = data[i]; - m_object = BNCreateStructuredUnsignedIntegerListData(input, data.size()); + m_object = BNCreateMetadataUnsignedIntegerListData(input, data.size()); delete[] input; } @@ -72,7 +72,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = data[i]; - m_object = BNCreateStructuredSignedIntegerListData(input, data.size()); + m_object = BNCreateMetadataSignedIntegerListData(input, data.size()); delete[] input; } @@ -82,7 +82,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = data[i]; - m_object = BNCreateStructuredDoubleListData(input, data.size()); + m_object = BNCreateMetadataDoubleListData(input, data.size()); delete[] input; } @@ -92,7 +92,7 @@ Metadata::Metadata(const vector& data) for (size_t i = 0; i < data.size(); i++) input[i] = data[i]; - m_object = BNCreateStructuredRawData(input, data.size()); + m_object = BNCreateMetadataRawData(input, data.size()); delete[] input; } diff --git a/settings.cpp b/settings.cpp index 97c2a232..b7e08793 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,4 +1,5 @@ #include "binaryninjaapi.h" +#include using namespace BinaryNinja; using namespace std; -- cgit v1.3.1 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(-) (limited to 'binaryview.cpp') 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 From 3d3b803d18f0d61b5e36367c9eb660b234cdc66e Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 12 Jul 2017 16:04:28 -0400 Subject: Metadata enhancements. Metadata objects are now serialized to the DB --- binaryninjaapi.h | 27 +++++- binaryninjacore.h | 56 ++++++------ binaryview.cpp | 7 +- metadata.cpp | 158 +++++++++++++------------------- python/__init__.py | 1 + python/binaryview.py | 67 +++++++++++++- python/metadata.py | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 435 insertions(+), 129 deletions(-) create mode 100644 python/metadata.py (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5850ad0..83f6b582 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -876,7 +876,7 @@ namespace BinaryNinja \param dest the address to write len number of bytes. \param offset the virtual offset to find and read len bytes from - ....\param len the number of bytes to read from offset and write to dest + \param len the number of bytes to read from offset and write to dest */ virtual size_t PerformRead(void* dest, uint64_t offset, size_t len) { (void)dest; (void)offset; (void)len; return 0; } virtual size_t PerformWrite(uint64_t offset, const void* data, size_t len) { (void)offset; (void)data; (void)len; return 0; } @@ -1128,8 +1128,8 @@ namespace BinaryNinja std::vector GetAllocatedRanges(); - void StoreMetadata(const std::string& key, Metadata* inValue); - std::unique_ptr QueryMetadata(const std::string& key); + void StoreMetadata(const std::string& key, Ref value); + Ref QueryMetadata(const std::string& key); std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); @@ -2929,8 +2929,15 @@ namespace BinaryNinja Metadata(const std::vector& data); Metadata(const std::vector& data); Metadata(const std::vector& data); + Metadata(const std::vector>& data); + Metadata(const std::map>& data); + Metadata(MetadataType type); virtual ~Metadata() {} + bool operator==(const Metadata& rhs); + Ref operator[](const std::string& key); + Ref operator[](size_t idx); + MetadataType GetType() const; bool GetBoolean() const; std::string GetString() const; @@ -2943,6 +2950,18 @@ namespace BinaryNinja std::vector GetSignedIntegerList() const; std::vector GetDoubleList() const; std::vector GetRaw() const; + std::vector> GetArray(); + std::map> GetKeyValueStore(); + + //For key-value data only + Ref Get(const std::string& key); + bool SetValueForKey(const std::string& key, Ref data); + + //For array data only + Ref Get(size_t idx); + bool Append(Ref data); + + size_t Size() const; bool IsBoolean() const; bool IsString() const; @@ -2955,5 +2974,7 @@ namespace BinaryNinja bool IsSignedIntegerList() const; bool IsDoubleList() const; bool IsRaw() const; + bool IsArray() const; + bool IsKeyValueStore() const; }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index eb9927ab..54691360 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1299,6 +1299,13 @@ extern "C" bool pointer, intermediate; }; + struct BNMetadataValueStore + { + size_t size; + char** keys; + BNMetadata** values; + }; + enum BNHighlightColorStyle { StandardHighlightColor = 0, @@ -1478,17 +1485,15 @@ extern "C" enum BNMetadataType { + InvalidDataType, BooleanDataType, StringDataType, UnsignedIntegerDataType, SignedIntegerDataType, DoubleDataType, - BooleanListDataType, - StringListDataType, - UnsignedIntegerListDataType, - SignedIntegerListDataType, - DoubleListDataType, - RawDataType + RawDataType, + KeyValueDataType, + ArrayDataType }; BINARYNINJACOREAPI char* BNAllocString(const char* contents); @@ -2924,18 +2929,22 @@ extern "C" BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerData(uint64_t data); BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerData(int64_t data); BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleData(double data); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataBooleanListData(const bool* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataStringListData(const char** data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerListData(const uint64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerListData(const int64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleListData(const double* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataOfType(BNMetadataType type); BINARYNINJACOREAPI BNMetadata* BNCreateMetadataRawData(const uint8_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataArray(BNMetadata** data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataValueStore(const char** keys, BNMetadata** values, size_t size); + + BINARYNINJACOREAPI bool BNMetadataIsEqual(BNMetadata* lhs, BNMetadata* rhs); + + BINARYNINJACOREAPI bool BNMetadataSetValueForKey(BNMetadata* data, const char* key, BNMetadata* md); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForKey(BNMetadata* data, const char* key); + BINARYNINJACOREAPI bool BNMetadataArrayAppend(BNMetadata* data, BNMetadata* md); + BINARYNINJACOREAPI size_t BNMetadataSize(BNMetadata* data); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForIdx(BNMetadata* data, size_t idx); + + BINARYNINJACOREAPI void BNFreeMetadataArray(BNMetadata** data); + BINARYNINJACOREAPI void BNFreeMetadataValueStore(BNMetadataValueStore* data); BINARYNINJACOREAPI void BNFreeMetadata(BNMetadata* data); - BINARYNINJACOREAPI void BNFreeMetadataBooleanList(bool* data); - BINARYNINJACOREAPI void BNFreeMetadataStringList(char** data, size_t size); - BINARYNINJACOREAPI void BNFreeMetadataUnsignedIntegerList(uint64_t* data); - BINARYNINJACOREAPI void BNFreeMetadataSignedIntegerList(int64_t* data); - BINARYNINJACOREAPI void BNFreeMetadataDoubleList(double* data); BINARYNINJACOREAPI void BNFreeMetadataRaw(uint8_t* data); // Retrieve Structured Data BINARYNINJACOREAPI bool BNMetadataGetBoolean(BNMetadata* data); @@ -2943,12 +2952,10 @@ extern "C" BINARYNINJACOREAPI uint64_t BNMetadataGetUnsignedInteger(BNMetadata* data); BINARYNINJACOREAPI int64_t BNMetadataGetSignedInteger(BNMetadata* data); BINARYNINJACOREAPI double BNMetadataGetDouble(BNMetadata* data); - BINARYNINJACOREAPI bool* BNMetadataGetBooleanList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI char** BNMetadataGetStringList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI uint64_t* BNMetadataGetUnsignedIntegerList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI int64_t* BNMetadataGetSignedIntegerList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI double* BNMetadataGetDoubleList(BNMetadata* data, size_t* size); BINARYNINJACOREAPI uint8_t* BNMetadataGetRaw(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI BNMetadata** BNMetadataGetArray(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI BNMetadataValueStore* BNMetadataGetValueStore(BNMetadata* data); + //Query type of Metadata BINARYNINJACOREAPI BNMetadataType BNMetadataGetType(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsBoolean(BNMetadata* data); @@ -2956,12 +2963,9 @@ extern "C" BINARYNINJACOREAPI bool BNMetadataIsUnsignedInteger(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsSignedInteger(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsDouble(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsBooleanList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsStringList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsUnsignedIntegerList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsSignedIntegerList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsDoubleList(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsRaw(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsArray(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsKeyValueStore(BNMetadata* data); // Store/Query structured data to/from a BinaryView BINARYNINJACOREAPI void BNBinaryViewStoreMetadata(BNBinaryView* view, const char* key, BNMetadata* value); diff --git a/binaryview.cpp b/binaryview.cpp index b330508d..3f1196d0 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1827,20 +1827,19 @@ vector BinaryView::GetAllocatedRanges() } -void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue) +void BinaryView::StoreMetadata(const std::string& key, Ref inValue) { if (!inValue) return; BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); } -unique_ptr BinaryView::QueryMetadata(const std::string& key) +Ref BinaryView::QueryMetadata(const std::string& key) { BNMetadata* value = BNBinaryViewQueryMetadata(m_object, key.c_str()); if (!value) return nullptr; - auto a = new Metadata(value); - return unique_ptr(a); + return new Metadata(value); } string BinaryView::GetStringMetadata(const string& key) diff --git a/metadata.cpp b/metadata.cpp index 3f01f4bb..18d3500b 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -33,67 +33,66 @@ Metadata::Metadata(double data) m_object = BNCreateMetadataDoubleData(data); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(MetadataType type) { - auto input = new bool[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; - - m_object = BNCreateMetadataBooleanListData(input, data.size()); - delete[] input; + m_object = BNCreateMetadataOfType(type); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const vector& data) { - char** input = new char*[data.size()]; + auto input = new uint8_t[data.size()]; for (size_t i = 0; i < data.size(); i++) - input[i] = BNAllocString(data[i].c_str()); - - m_object = BNCreateMetadataStringListData((const char**)input, data.size()); + input[i] = data[i]; - for (size_t i = 0; i < data.size(); i++) - BNFreeString(input[i]); + m_object = BNCreateMetadataRawData(input, data.size()); delete[] input; } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const std::vector>& data) { - auto input = new uint64_t[data.size()]; + BNMetadata** dataList = new BNMetadata*[data.size()]; for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + dataList[i] = data[i]->m_object; - m_object = BNCreateMetadataUnsignedIntegerListData(input, data.size()); - delete[] input; + m_object = BNCreateMetadataArray(dataList, data.size()); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const std::map>& data) { - auto input = new int64_t[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + char** keys = new char*[data.size()]; + BNMetadata** values = new BNMetadata*[data.size()]; - m_object = BNCreateMetadataSignedIntegerListData(input, data.size()); - delete[] input; + size_t i = 0; + for (auto &elm : data) + { + keys[i] = BNAllocString(elm.first.c_str()); + values[i++] = elm.second->m_object; + } + m_object = BNCreateMetadataValueStore((const char**)keys, values, data.size()); + for (size_t j = 0; j < data.size(); j++) + BNFreeString(keys[j]); + delete[] keys; + delete[] values; } -Metadata::Metadata(const vector& data) +bool Metadata::operator==(const Metadata& rhs) { - auto input = new double[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + return BNMetadataIsEqual(m_object, rhs.m_object); +} - m_object = BNCreateMetadataDoubleListData(input, data.size()); - delete[] input; +Ref Metadata::operator[](const std::string& key) +{ + return new Metadata(BNMetadataGetForKey(m_object, key.c_str())); } -Metadata::Metadata(const vector& data) +Ref Metadata::operator[](size_t idx) { - auto input = new uint8_t[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + return new Metadata(BNMetadataGetForIdx(m_object, idx)); +} - m_object = BNCreateMetadataRawData(input, data.size()); - delete[] input; +bool Metadata::SetValueForKey(const string& key, Ref data) +{ + return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object); } MetadataType Metadata::GetType() const @@ -126,60 +125,44 @@ double Metadata::GetDouble() const return BNMetadataGetDouble(m_object); } -vector Metadata::GetBooleanList() const -{ - size_t outSize; - bool* outList = BNMetadataGetBooleanList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataBooleanList(outList); - return result; -} - -vector Metadata::GetStringList() const +vector Metadata::GetRaw() const { size_t outSize; - char** outList = BNMetadataGetStringList(m_object, &outSize); - vector result; - for (size_t i = 0; i < outSize; i++) - result.push_back(string(outList[i])); - BNFreeMetadataStringList(outList, outSize); + uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataRaw(outList); return result; } -vector Metadata::GetUnsignedIntegerList() const +vector> Metadata::GetArray() { - size_t outSize; - uint64_t* outList = BNMetadataGetUnsignedIntegerList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataUnsignedIntegerList(outList); + size_t size = 0; + BNMetadata** data = BNMetadataGetArray(m_object, &size); + vector> result; + for (size_t i = 0; i < size; i++) + result.push_back(new Metadata(data[i])); return result; } -vector Metadata::GetSignedIntegerList() const +map> Metadata::GetKeyValueStore() { - size_t outSize; - int64_t* outList = BNMetadataGetSignedIntegerList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataSignedIntegerList(outList); + BNMetadataValueStore* data = BNMetadataGetValueStore(m_object); + map> result; + for (size_t i = 0; i < data->size; i++) + { + result[data->keys[i]] = new Metadata(data->values[i]); + } return result; } -vector Metadata::GetDoubleList() const +bool Metadata::Append(Ref data) { - size_t outSize; - double* outList = BNMetadataGetDoubleList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataDoubleList(outList); - return result; + return BNMetadataArrayAppend(m_object, data->m_object); } -vector Metadata::GetRaw() const +size_t Metadata::Size() const { - size_t outSize; - uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataRaw(outList); - return result; + return BNMetadataSize(m_object); } bool Metadata::IsBoolean() const @@ -207,32 +190,17 @@ bool Metadata::IsDouble() const return BNMetadataIsDouble(m_object); } -bool Metadata::IsBooleanList() const -{ - return BNMetadataIsBooleanList(m_object); -} - -bool Metadata::IsStringList() const -{ - return BNMetadataIsStringList(m_object); -} - -bool Metadata::IsUnsignedIntegerList() const -{ - return BNMetadataIsUnsignedIntegerList(m_object); -} - -bool Metadata::IsSignedIntegerList() const +bool Metadata::IsRaw() const { - return BNMetadataIsSignedIntegerList(m_object); + return BNMetadataIsRaw(m_object); } -bool Metadata::IsDoubleList() const +bool Metadata::IsArray() const { - return BNMetadataIsDoubleList(m_object); + return BNMetadataIsArray(m_object); } -bool Metadata::IsRaw() const +bool Metadata::IsKeyValueStore() const { - return BNMetadataIsRaw(m_object); + return BNMetadataIsKeyValueStore(m_object); } diff --git a/python/__init__.py b/python/__init__.py index ec25839b..b066e863 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -48,6 +48,7 @@ from .highlight import * from .scriptingprovider import * from .pluginmanager import * from .setting import * +from .metadata import * def shutdown(): diff --git a/python/binaryview.py b/python/binaryview.py index ad583966..d04dca86 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -26,7 +26,8 @@ import threading # Binary Ninja components import _binaryninjacore as core -from enums import AnalysisState, SymbolType, InstructionTextTokenType, Endianness, ModificationStatus, StringType, SegmentFlag +from enums import (AnalysisState, SymbolType, InstructionTextTokenType, + Endianness, ModificationStatus, StringType, SegmentFlag, MetadataType) import function import startup import architecture @@ -39,6 +40,7 @@ import databuffer import basicblock import types import lineardisassembly +import metadata class BinaryDataNotification(object): @@ -1689,11 +1691,25 @@ class BinaryView(object): return core.BNSaveToFilename(self.handle, str(dest)) def register_notification(self, notify): + """ + `register_notification` provides a mechanism for receiving callbacks for various analysis events. A full + list of callbacks can be seen in :py:Class:`BinaryDataNotification`. + + :param BinaryDataNotification notify: notify is a subclassed instance of :py:Class:`BinaryDataNotification`. + :rtype: None + """ cb = BinaryDataNotificationCallbacks(self, notify) cb._register() self.notifications[notify] = cb def unregister_notification(self, notify): + """ + `unregister_notification` unregisters the :py:Class:`BinaryDataNotification` object passed to + `register_notification` + + :param BinaryDataNotification notify: notify is a subclassed instance of :py:Class:`BinaryDataNotification`. + :rtype: None + """ if notify in self.notifications: self.notifications[notify]._unregister() del self.notifications[notify] @@ -1827,6 +1843,7 @@ class BinaryView(object): event = AnalysisCompletionEvent(self, lambda: wait.complete()) core.BNUpdateAnalysis(self.handle) wait.wait() + del event # Get rid of unused variable warning def abort_analysis(self): """ @@ -3247,6 +3264,54 @@ class BinaryView(object): core.BNFreeStringList(outgoing_names, len(name_list)) return result + def query_metadata(self, key): + """ + `query_metadata` retrieves a Metadata object stored in the current BinaryView. + + :param string key: key to query + :rtype: Metadata object + :Example: + + >>> bv.store_metadata("integer", Metadata(1337)) + >>> int(bv.query_metadata("integer")) + 1337L + >>> bv.store_metadata("list", Metadata([1,2,3])) + >>> map(int, list(bv.query_metadata("list"))) + [1L, 2L, 3L] + >>> bv.store_metadata("string", Metadata("my_data")) + >>> str(bv.query_metadata("string")) + 'my_data' + """ + md_handle = core.BNBinaryViewQueryMetadata(self.handle, key) + if md_handle is None: + raise KeyError(key) + return metadata.Metadata(handle=md_handle) + + def store_metadata(self, key, md): + """ + `store_metadata` stores a Metadata object for the given key in the current BinaryView. + Metadata objects stored using this `store_metadata` are stored in the database and can be retrieved when + the database is reopend. + + :param string key: key value to associate the Metadata object with + :param Metadata md: Metadata object to store + :rtype: None + :Example: + + >>> bv.store_metadata("integer", Metadata(1337)) + >>> int(bv.query_metadata("integer")) + 1337L + >>> bv.store_metadata("list", Metadata([1,2,3])) + >>> map(int, list(bv.query_metadata("list"))) + [1L, 2L, 3L] + >>> bv.store_metadata("string", Metadata("my_data")) + >>> str(bv.query_metadata("string")) + 'my_data' + """ + if not isinstance(md, metadata.Metadata): + raise ValueError("metadata argument must be of type Metadata") + core.BNBinaryViewStoreMetadata(self.handle, key, md.handle) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) diff --git a/python/metadata.py b/python/metadata.py new file mode 100644 index 00000000..f0e7764d --- /dev/null +++ b/python/metadata.py @@ -0,0 +1,248 @@ +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from enums import MetadataType + + +class Metadata(object): + def __init__(self, value=None, signed=None, raw=None, handle=None): + if handle is not None: + self.handle = handle + elif isinstance(value, int): + if signed: + self.handle = core.BNCreateMetadataSignedIntegerData(value) + else: + self.handle = core.BNCreateMetadataUnsignedIntegerData(value) + elif isinstance(value, bool): + self.handle = core.BNCreateMetadataBooleanData(value) + elif isinstance(value, str): + if raw: + buffer = (ctypes.c_ubyte * len(value)).from_buffer_copy(value) + self.handle = core.BNCreateMetadataRawData(buffer, len(value)) + else: + self.handle = core.BNCreateMetadataStringData(value) + elif isinstance(value, float): + self.handle = core.BNCreateMetadataDoubleData(value) + elif isinstance(value, list): + self.handle = core.BNCreateMetadataOfType(MetadataType.ArrayDataType) + for elm in value: + md = Metadata(elm, signed, raw) + core.BNMetadataArrayAppend(self.handle, md.handle) + elif isinstance(value, dict): + self.handle = core.BNCreateMetadataOfType(MetadataType.KeyValueDataType) + for elm in value: + md = Metadata(value[elm], signed, raw) + core.BNMetadataSetValueForKey(self.handle, str(elm), md.handle) + else: + raise ValueError("List doesn't not contain type of: int, bool, str, float, list, dict") + + @property + def value(self): + if self.is_integer: + return int(self) + elif self.is_string or self.is_raw: + return str(self) + elif self.is_float: + return float(self) + elif self.is_boolean: + return bool(self) + elif self.is_array: + return list(self) + elif self.is_dict: + return dict(self) + raise NotImplementedError() + + @property + def type(self): + return MetadataType(core.BNMetadataGetType(self.handle)) + + @property + def is_integer(self): + return self.is_signed_integer or self.is_unsigned_integer + + @property + def is_signed_integer(self): + return core.BNMetadataIsSignedInteger(self.handle) + + @property + def is_unsigned_integer(self): + return core.BNMetadataIsUnsignedInteger(self.handle) + + @property + def is_float(self): + return core.BNMetadataIsDouble(self.handle) + + @property + def is_boolean(self): + return core.BNMetadataIsBoolean(self.handle) + + @property + def is_string(self): + return core.BNMetadataIsString(self.handle) + + @property + def is_raw(self): + return core.BNMetadataIsRaw(self.handle) + + @property + def is_array(self): + return core.BNMetadataIsArray(self.handle) + + @property + def is_dict(self): + return core.BNMetadataIsKeyValueStore(self.handle) + + def __len__(self): + if self.is_array or self.is_dict or self.is_string or self.is_raw: + return core.BNMetadataSize(self.handle) + raise Exception("Metadata object doesn't support len()") + + def __iter__(self): + if self.is_array: + for i in xrange(core.BNMetadataSize(self.handle)): + yield Metadata(handle=core.BNMetadataGetForIdx(self.handle, i)) + elif self.is_dict: + result = core.BNMetadataGetValueStore(self.handle) + try: + for i in xrange(result.contents.size): + yield result.contents.keys[i] + finally: + core.BNFreeMetadataValueStore(result) + else: + raise Exception("Metadata object doesn't support iteration") + + def __getitem__(self, value): + if self.is_array: + if not isinstance(value, int): + raise ValueError("Metadata object only supports integers for indexing") + if value >= len(self): + raise IndexError("Index value out of range") + return Metadata(handle=core.BNMetadataGetForIdx(self.handle, value)) + if self.is_dict: + if not isinstance(value, str): + raise ValueError("Metadata object only supports strings for indexing") + handle = core.BNMetadataGetForKey(self.handle, value) + if handle is None: + raise KeyError(value) + return Metadata(handle=handle) + + def __str__(self): + if self.is_string: + return core.BNMetadataGetString(self.handle) + if self.is_raw: + length = ctypes.c_ulonglong() + length.value = 0 + native_list = core.BNMetadataGetRaw(self.handle, ctypes.byref(length)) + out_list = [] + for i in xrange(length.value): + out_list.append(native_list[i]) + core.BNFreeMetadataRaw(native_list) + return ''.join(chr(a) for a in out_list) + + raise ValueError("Metadata object not a string or raw type") + + def __int__(self): + if self.is_signed_integer: + return core.BNMetadataGetSignedInteger(self.handle) + if self.is_unsigned_integer: + return core.BNMetadataGetUnsignedInteger(self.handle) + + raise ValueError("Metadata object not of integer type") + + def __float__(self): + if not self.is_float: + raise ValueError("Metadata object is not float type") + return core.BNMetadataGetDouble(self.handle) + + def __nonzero__(self): + if not self.is_boolean: + raise ValueError("Metadata object is not boolean type") + return core.BNMetadataGetBoolean(self.handle) + + def __eq__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) == other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) == other + elif isinstance(other, float) and self.is_float: + return float(self) == other + elif isinstance(other, bool) and self.is_boolean: + return bool(self) == other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b: + return False + return True + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return False + return True + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) == int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) == str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) == float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) == bool(other) + raise NotImplementedError() + + def __ne__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) != other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) != other + elif isinstance(other, float) and self.is_float: + return float(self) != other + elif isinstance(other, bool): + return bool(self) != other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return True + areEqual = True + for a, b in zip(self, other): + if a != b: + areEqual = False + return not areEqual + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return True + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return True + return False + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) != int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) != str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) != float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) != bool(other) -- cgit v1.3.1 From 0e6019edc8c5949de4989ef9577c07913946135b Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 12 Jul 2017 22:47:12 -0400 Subject: Adding remove_metadata API to BinaryView. Add remove APIs to Metadata --- binaryninjaapi.h | 6 ++++-- binaryninjacore.h | 6 +++++- binaryview.cpp | 5 +++++ metadata.cpp | 12 +++++++++++- python/binaryview.py | 15 ++++++++++++++- python/metadata.py | 12 ++++++++++-- 6 files changed, 49 insertions(+), 7 deletions(-) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 83f6b582..01e5f986 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1130,6 +1130,7 @@ namespace BinaryNinja void StoreMetadata(const std::string& key, Ref value); Ref QueryMetadata(const std::string& key); + void RemoveMetadata(const std::string& key); std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); @@ -2956,11 +2957,12 @@ namespace BinaryNinja //For key-value data only Ref Get(const std::string& key); bool SetValueForKey(const std::string& key, Ref data); + void RemoveKey(const std::string& key); //For array data only - Ref Get(size_t idx); + Ref Get(size_t index); bool Append(Ref data); - + void RemoveIndex(size_t index); size_t Size() const; bool IsBoolean() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 54691360..3a8b63df 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2939,8 +2939,10 @@ extern "C" BINARYNINJACOREAPI bool BNMetadataSetValueForKey(BNMetadata* data, const char* key, BNMetadata* md); BINARYNINJACOREAPI BNMetadata* BNMetadataGetForKey(BNMetadata* data, const char* key); BINARYNINJACOREAPI bool BNMetadataArrayAppend(BNMetadata* data, BNMetadata* md); + BINARYNINJACOREAPI void BNMetadataRemoveKey(BNMetadata* data, const char* key); BINARYNINJACOREAPI size_t BNMetadataSize(BNMetadata* data); - BINARYNINJACOREAPI BNMetadata* BNMetadataGetForIdx(BNMetadata* data, size_t idx); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForIndex(BNMetadata* data, size_t index); + BINARYNINJACOREAPI void BNMetadataRemoveIndex(BNMetadata* data, size_t index); BINARYNINJACOREAPI void BNFreeMetadataArray(BNMetadata** data); BINARYNINJACOREAPI void BNFreeMetadataValueStore(BNMetadataValueStore* data); @@ -2970,6 +2972,8 @@ extern "C" // Store/Query structured data to/from a BinaryView BINARYNINJACOREAPI void BNBinaryViewStoreMetadata(BNBinaryView* view, const char* key, BNMetadata* value); BINARYNINJACOREAPI BNMetadata* BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key); + BINARYNINJACOREAPI void BNBinaryViewRemoveMetadata(BNBinaryView* view, const char* key); + #ifdef __cplusplus } #endif diff --git a/binaryview.cpp b/binaryview.cpp index 3f1196d0..1f6820ff 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1842,6 +1842,11 @@ Ref BinaryView::QueryMetadata(const std::string& key) return new Metadata(value); } +void BinaryView::RemoveMetadata(const std::string& key) +{ + BNBinaryViewRemoveMetadata(m_object, key.c_str()); +} + string BinaryView::GetStringMetadata(const string& key) { auto data = QueryMetadata(key); diff --git a/metadata.cpp b/metadata.cpp index 18d3500b..f9c48b04 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -87,7 +87,7 @@ Ref Metadata::operator[](const std::string& key) Ref Metadata::operator[](size_t idx) { - return new Metadata(BNMetadataGetForIdx(m_object, idx)); + return new Metadata(BNMetadataGetForIndex(m_object, idx)); } bool Metadata::SetValueForKey(const string& key, Ref data) @@ -95,6 +95,11 @@ bool Metadata::SetValueForKey(const string& key, Ref data) return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object); } +void Metadata::RemoveKey(const string& key) +{ + return BNMetadataRemoveKey(m_object, key.c_str()); +} + MetadataType Metadata::GetType() const { return BNMetadataGetType(m_object); @@ -160,6 +165,11 @@ bool Metadata::Append(Ref data) return BNMetadataArrayAppend(m_object, data->m_object); } +void Metadata::RemoveIndex(size_t index) +{ + BNMetadataRemoveIndex(m_object, index); +} + size_t Metadata::Size() const { return BNMetadataSize(m_object); diff --git a/python/binaryview.py b/python/binaryview.py index d04dca86..ee019dcb 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -27,7 +27,7 @@ import threading # Binary Ninja components import _binaryninjacore as core from enums import (AnalysisState, SymbolType, InstructionTextTokenType, - Endianness, ModificationStatus, StringType, SegmentFlag, MetadataType) + Endianness, ModificationStatus, StringType, SegmentFlag) import function import startup import architecture @@ -3312,6 +3312,19 @@ class BinaryView(object): raise ValueError("metadata argument must be of type Metadata") core.BNBinaryViewStoreMetadata(self.handle, key, md.handle) + def remove_metadata(self, key): + """ + `remove_metadata` removes the Metadata object associated with key from the current BinaryView + + :param string key: key to remove from the BinaryView + :rtype: None + :Example: + + >>> bv.store_metadata("integer", Metadata(1337)) + >>> bv.remove_metadata("integer") + """ + core.BNBinaryViewRemoveMetadata(self.handle, key) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) diff --git a/python/metadata.py b/python/metadata.py index f0e7764d..2817d777 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -114,6 +114,14 @@ class Metadata(object): def is_dict(self): return core.BNMetadataIsKeyValueStore(self.handle) + def remove(self, key_or_index): + if isinstance(key_or_index, str) and self.is_dict: + core.BNMetadataRemoveKey(self.handle, key_or_index) + elif isinstance(key_or_index, int) and self.is_array: + core.BNMetadataRemoveIndex(self.handle, key_or_index) + else: + raise TypeError("remove only valid for dict and array objects") + def __len__(self): if self.is_array or self.is_dict or self.is_string or self.is_raw: return core.BNMetadataSize(self.handle) @@ -122,7 +130,7 @@ class Metadata(object): def __iter__(self): if self.is_array: for i in xrange(core.BNMetadataSize(self.handle)): - yield Metadata(handle=core.BNMetadataGetForIdx(self.handle, i)) + yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)) elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: @@ -139,7 +147,7 @@ class Metadata(object): raise ValueError("Metadata object only supports integers for indexing") if value >= len(self): raise IndexError("Index value out of range") - return Metadata(handle=core.BNMetadataGetForIdx(self.handle, value)) + return Metadata(handle=core.BNMetadataGetForIndex(self.handle, value)) if self.is_dict: if not isinstance(value, str): raise ValueError("Metadata object only supports strings for indexing") -- cgit v1.3.1 From 9d19db2be1fa408217f4544e5a68312fcab44fad Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Fri, 14 Jul 2017 14:45:55 -0400 Subject: Add UpdateAnalysisAndWait to API. --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + binaryview.cpp | 10 ++++++++++ 3 files changed, 12 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 01e5f986..2562334d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1001,6 +1001,7 @@ namespace BinaryNinja void RemoveAnalysisFunction(Function* func); void CreateUserFunction(Platform* platform, uint64_t start); void RemoveUserFunction(Function* func); + void UpdateAnalysisAndWait(); void UpdateAnalysis(); void AbortAnalysis(); diff --git a/binaryninjacore.h b/binaryninjacore.h index 3a8b63df..5ee00003 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1910,6 +1910,7 @@ extern "C" BINARYNINJACOREAPI void BNRemoveAnalysisFunction(BNBinaryView* view, BNFunction* func); BINARYNINJACOREAPI void BNCreateUserFunction(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNRemoveUserFunction(BNBinaryView* view, BNFunction* func); + BINARYNINJACOREAPI void BNUpdateAnalysisAndWait(BNBinaryView* view); BINARYNINJACOREAPI void BNUpdateAnalysis(BNBinaryView* view); BINARYNINJACOREAPI void BNAbortAnalysis(BNBinaryView* view); BINARYNINJACOREAPI bool BNIsFunctionUpdateNeeded(BNFunction* func); diff --git a/binaryview.cpp b/binaryview.cpp index 1f6820ff..522dbe6a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -872,6 +872,12 @@ void BinaryView::RemoveUserFunction(Function* func) } +void BinaryView::UpdateAnalysisAndWait() +{ + BNUpdateAnalysisAndWait(m_object); +} + + void BinaryView::UpdateAnalysis() { BNUpdateAnalysis(m_object); @@ -1319,6 +1325,10 @@ uint64_t BinaryView::GetNextDataAfterAddress(uint64_t addr) return BNGetNextDataAfterAddress(m_object, addr); } +uint64_t BinaryView::GetNextDataVariableAfterAddress(uint64_t addr) +{ + return BNGetNextDataVariableAfterAddress(m_object, addr); +} uint64_t BinaryView::GetPreviousFunctionStartBeforeAddress(uint64_t addr) { -- cgit v1.3.1 From 78d90c30df96364cdc8dde1954be7341531cfe07 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 22:05:32 -0400 Subject: Adding section semantics to deal with semantically read-only sections inside of writable areas --- binaryninjaapi.h | 9 +++++++-- binaryninjacore.h | 19 +++++++++++++++---- binaryview.cpp | 33 +++++++++++++++++++++++++-------- python/binaryview.py | 47 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 83 insertions(+), 25 deletions(-) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8213675d..8a09529e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1030,6 +1030,7 @@ namespace BinaryNinja std::string linkedSection, infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct QualifiedNameAndType; @@ -1159,6 +1160,8 @@ namespace BinaryNinja bool IsOffsetWritable(uint64_t offset) const; bool IsOffsetExecutable(uint64_t offset) const; bool IsOffsetBackedByFile(uint64_t offset) const; + bool IsOffsetCodeSemantics(uint64_t offset) const; + bool IsOffsetWritableSemantics(uint64_t offset) const; uint64_t GetNextValidOffset(uint64_t offset) const; uint64_t GetStart() const; @@ -1299,11 +1302,13 @@ namespace BinaryNinja 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 = "", + void AddAutoSection(const std::string& name, uint64_t start, uint64_t length, + BNSectionSemantics semantics = DefaultSectionSemantics, const std::string& type = "", uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "", const std::string& infoSection = "", uint64_t infoData = 0); void RemoveAutoSection(const std::string& name); - void AddUserSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "", + void AddUserSection(const std::string& name, uint64_t start, uint64_t length, + BNSectionSemantics semantics = DefaultSectionSemantics, const std::string& type = "", uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "", const std::string& infoSection = "", uint64_t infoData = 0); void RemoveUserSection(const std::string& name); diff --git a/binaryninjacore.h b/binaryninjacore.h index 3c8757ed..b69d79f9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1504,6 +1504,14 @@ extern "C" uint32_t flags; }; + enum BNSectionSemantics + { + DefaultSectionSemantics, + ReadOnlyCodeSectionSemantics, + ReadOnlyDataSectionSemantics, + ReadWriteDataSectionSemantics + }; + struct BNSection { char* name; @@ -1513,6 +1521,7 @@ extern "C" char* infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct BNAddressRange @@ -1727,6 +1736,8 @@ extern "C" BINARYNINJACOREAPI bool BNIsOffsetWritable(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI bool BNIsOffsetExecutable(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI bool BNIsOffsetBackedByFile(BNBinaryView* view, uint64_t offset); + BINARYNINJACOREAPI bool BNIsOffsetCodeSemantics(BNBinaryView* view, uint64_t offset); + BINARYNINJACOREAPI bool BNIsOffsetWritableSemantics(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI uint64_t BNGetNextValidOffset(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI uint64_t BNGetStartOffset(BNBinaryView* view); BINARYNINJACOREAPI uint64_t BNGetEndOffset(BNBinaryView* view); @@ -1777,12 +1788,12 @@ extern "C" 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, - uint64_t infoData); + BNSectionSemantics semantics, const char* type, uint64_t align, uint64_t entrySize, + const char* linkedSection, const char* infoSection, uint64_t infoData); BINARYNINJACOREAPI void BNRemoveAutoSection(BNBinaryView* view, const char* name); BINARYNINJACOREAPI void BNAddUserSection(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, - uint64_t infoData); + BNSectionSemantics semantics, const char* type, uint64_t align, uint64_t entrySize, + const char* linkedSection, const char* infoSection, uint64_t infoData); BINARYNINJACOREAPI void BNRemoveUserSection(BNBinaryView* view, const char* name); BINARYNINJACOREAPI BNSection* BNGetSections(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI BNSection* BNGetSectionsAt(BNBinaryView* view, uint64_t addr, size_t* count); diff --git a/binaryview.cpp b/binaryview.cpp index 23a62aec..2c7da23e 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -758,6 +758,18 @@ bool BinaryView::IsOffsetBackedByFile(uint64_t offset) const } +bool BinaryView::IsOffsetCodeSemantics(uint64_t offset) const +{ + return BNIsOffsetCodeSemantics(m_object, offset); +} + + +bool BinaryView::IsOffsetWritableSemantics(uint64_t offset) const +{ + return BNIsOffsetWritableSemantics(m_object, offset); +} + + uint64_t BinaryView::GetNextValidOffset(uint64_t offset) const { return BNGetNextValidOffset(m_object, offset); @@ -1716,11 +1728,12 @@ bool BinaryView::GetAddressForDataOffset(uint64_t offset, uint64_t& 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) +void BinaryView::AddAutoSection(const string& name, uint64_t start, uint64_t length, BNSectionSemantics semantics, + const string& type, uint64_t align, uint64_t entrySize, const string& linkedSection, + const string& infoSection, uint64_t infoData) { - BNAddAutoSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(), - infoSection.c_str(), infoData); + BNAddAutoSection(m_object, name.c_str(), start, length, semantics, type.c_str(), align, entrySize, + linkedSection.c_str(), infoSection.c_str(), infoData); } @@ -1730,11 +1743,12 @@ void BinaryView::RemoveAutoSection(const string& name) } -void BinaryView::AddUserSection(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) +void BinaryView::AddUserSection(const string& name, uint64_t start, uint64_t length, BNSectionSemantics semantics, + const string& type, uint64_t align, uint64_t entrySize, const string& linkedSection, + const string& infoSection, uint64_t infoData) { - BNAddUserSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(), - infoSection.c_str(), infoData); + BNAddUserSection(m_object, name.c_str(), start, length, semantics, type.c_str(), align, entrySize, + linkedSection.c_str(), infoSection.c_str(), infoData); } @@ -1762,6 +1776,7 @@ vector
BinaryView::GetSections() section.infoData = sections[i].infoData; section.align = sections[i].align; section.entrySize = sections[i].entrySize; + section.semantics = sections[i].semantics; result.push_back(section); } @@ -1788,6 +1803,7 @@ vector
BinaryView::GetSectionsAt(uint64_t addr) section.infoData = sections[i].infoData; section.align = sections[i].align; section.entrySize = sections[i].entrySize; + section.semantics = sections[i].semantics; result.push_back(section); } @@ -1811,6 +1827,7 @@ bool BinaryView::GetSectionByName(const string& name, Section& result) result.infoData = section.infoData; result.align = section.align; result.entrySize = section.entrySize; + result.semantics = section.semantics; BNFreeSection(§ion); return true; diff --git a/python/binaryview.py b/python/binaryview.py index bdba11af..d977de50 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -27,7 +27,7 @@ import threading # Binary Ninja components import _binaryninjacore as core from enums import (AnalysisState, SymbolType, InstructionTextTokenType, - Endianness, ModificationStatus, StringType, SegmentFlag) + Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) import function import startup import architecture @@ -422,7 +422,7 @@ class Segment(object): class Section(object): - def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size): + def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics): self.name = name self.type = section_type self.start = start @@ -432,6 +432,7 @@ class Section(object): self.info_data = info_data self.align = align self.entry_size = entry_size + self.semantics = SectionSemantics(semantics) @property def end(self): @@ -899,7 +900,8 @@ class BinaryView(object): for i in xrange(0, count.value): result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, - section_list[i].infoData, section_list[i].align, section_list[i].entrySize) + section_list[i].infoData, section_list[i].align, section_list[i].entrySize, + section_list[i].semantics) core.BNFreeSectionList(section_list, count.value) return result @@ -1678,6 +1680,28 @@ class BinaryView(object): """ return core.BNIsOffsetExecutable(self.handle, addr) + def is_offset_code_semantics(self, addr): + """ + ``is_offset_code_semantics`` checks if an virtual address ``addr`` is semantically valid for code. + + :param int addr: a virtual address to be checked + :return: true if the virtual address is valid for writing, false if the virtual address is invalid or error + :rtype: bool + """ + return core.BNIsOffsetCodeSemantics(self.handle, addr) + + def is_offset_writable_semantics(self, addr): + """ + ``is_offset_writable_semantics`` checks if an virtual address ``addr`` is semantically writable. Some sections + may have writable permissions for linking purposes but can be treated as read-only for the purposes of + analysis. + + :param int addr: a virtual address to be checked + :return: true if the virtual address is valid for writing, false if the virtual address is invalid or error + :rtype: bool + """ + return core.BNIsOffsetWritableSemantics(self.handle, addr) + def save(self, dest): """ ``save`` saves the original binary file to the provided destination ``dest`` along with any modifications. @@ -3218,17 +3242,17 @@ class BinaryView(object): 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, + def add_auto_section(self, name, start, length, semantics = SectionSemantics.DefaultSectionSemantics, + type = "", align = 1, entry_size = 1, linked_section = "", info_section = "", info_data = 0): + core.BNAddAutoSection(self.handle, name, start, length, semantics, type, align, entry_size, linked_section, info_section, info_data) def remove_auto_section(self, name): core.BNRemoveAutoSection(self.handle, name) - def add_user_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", - info_section = "", info_data = 0): - core.BNAddUserSection(self.handle, name, start, length, type, align, entry_size, linked_section, + def add_user_section(self, name, start, length, semantics = SectionSemantics.DefaultSectionSemantics, + type = "", align = 1, entry_size = 1, linked_section = "", info_section = "", info_data = 0): + core.BNAddUserSection(self.handle, name, start, length, semantics, type, align, entry_size, linked_section, info_section, info_data) def remove_user_section(self, name): @@ -3241,7 +3265,8 @@ class BinaryView(object): for i in xrange(0, count.value): result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, - section_list[i].infoData, section_list[i].align, section_list[i].entrySize)) + section_list[i].infoData, section_list[i].align, section_list[i].entrySize, + section_list[i].semantics)) core.BNFreeSectionList(section_list, count.value) return result @@ -3250,7 +3275,7 @@ class BinaryView(object): if not core.BNGetSectionByName(self.handle, name, section): return None result = Section(section.name, section.type, section.start, section.length, section.linkedSection, - section.infoSection, section.infoData, section.align, section.entrySize) + section.infoSection, section.infoData, section.align, section.entrySize, section.semantics) core.BNFreeSection(section) return result -- cgit v1.3.1 From 09af54fba214ee5e0baf6a9bacce0ceebbd34deb Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 28 Aug 2017 17:04:24 -0400 Subject: Add AddAnalysisOption API to support Initial LinearSweep Core. --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + binaryview.cpp | 6 ++++++ python/binaryview.py | 16 ++++++++++++++++ 4 files changed, 24 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 1cd65744..5fb95021 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1185,6 +1185,7 @@ namespace BinaryNinja void RegisterNotification(BinaryDataNotification* notify); void UnregisterNotification(BinaryDataNotification* notify); + void AddAnalysisOption(const std::string& name); void AddFunctionForAnalysis(Platform* platform, uint64_t addr); void AddEntryPointForAnalysis(Platform* platform, uint64_t start); void RemoveAnalysisFunction(Function* func); diff --git a/binaryninjacore.h b/binaryninjacore.h index f81b821c..f20cc1f2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2008,6 +2008,7 @@ extern "C" const char* name, uint64_t value); // Analysis + BINARYNINJACOREAPI void BNAddAnalysisOption(BNBinaryView* view, const char* name); BINARYNINJACOREAPI void BNAddFunctionForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNAddEntryPointForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNRemoveAnalysisFunction(BNBinaryView* view, BNFunction* func); diff --git a/binaryview.cpp b/binaryview.cpp index 2c7da23e..213be79a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -854,6 +854,12 @@ bool BinaryView::Save(FileAccessor* file) } +void BinaryView::AddAnalysisOption(const string& name) +{ + BNAddAnalysisOption(m_object, name.c_str()); +} + + void BinaryView::AddFunctionForAnalysis(Platform* platform, uint64_t addr) { BNAddFunctionForAnalysis(m_object, platform->GetObject(), addr); diff --git a/python/binaryview.py b/python/binaryview.py index bf8a87e0..d002b38f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1831,6 +1831,22 @@ class BinaryView(object): """ core.BNRemoveUserFunction(self.handle, func.handle) + def add_analysis_option(self, name): + """ + ``add_analysis_option`` adds an analysis option. Analysis options elaborate the analysis phase. The user must + start analysis by calling either ``update_analysis()`` or ``update_analysis_and_wait()``. + + :param str name: name of the analysis option. Available options: + "linearsweep" : apply linearsweep analysis during the next analysis update (run-once semantics) + + :rtype: None + :Example: + + >>> bv.add_analysis_option("linearsweep") + >>> bv.update_analysis_and_wait() + """ + core.BNAddAnalysisOption(self.handle, name) + def update_analysis(self): """ ``update_analysis`` asynchronously starts the analysis running and returns immediately. Analysis of BinaryViews -- cgit v1.3.1