diff options
| author | Xusheng <xusheng@vector35.com> | 2021-05-05 17:23:49 +0800 |
|---|---|---|
| committer | Xusheng <xusheng@vector35.com> | 2021-05-26 17:46:13 +0800 |
| commit | 7c9ada78241e08bf36bd04d989f742a6de721575 (patch) | |
| tree | 4134fd2f12a504ab17cc0b9acc1fb8d27552490f | |
| parent | fd1974b407be042fd84f0267a328a5adabce28e1 (diff) | |
Add the ability to automatically create struct members
| -rw-r--r-- | binaryninjaapi.h | 42 | ||||
| -rw-r--r-- | binaryninjacore.h | 66 | ||||
| -rw-r--r-- | binaryview.cpp | 125 | ||||
| -rw-r--r-- | function.cpp | 11 | ||||
| -rw-r--r-- | python/architecture.py | 104 | ||||
| -rw-r--r-- | python/binaryview.py | 149 | ||||
| -rw-r--r-- | python/function.py | 14 | ||||
| -rw-r--r-- | python/generator.cpp | 3 | ||||
| -rw-r--r-- | python/types.py | 10 | ||||
| m--------- | suite/binaries | 0 | ||||
| -rw-r--r-- | suite/testcommon.py | 39 | ||||
| -rw-r--r-- | type.cpp | 37 | ||||
| -rw-r--r-- | ui/addressdialog.h | 44 | ||||
| -rw-r--r-- | ui/commands.h | 4 | ||||
| -rw-r--r-- | ui/flowgraphwidget.h | 1 | ||||
| -rw-r--r-- | ui/linearview.h | 1 | ||||
| -rw-r--r-- | ui/tokenizedtextview.h | 1 | ||||
| -rw-r--r-- | ui/typeview.h | 1 |
18 files changed, 601 insertions, 51 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 89f5fd84..459ddcb5 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1163,6 +1163,14 @@ __attribute__ ((format (printf, 1, 2))) uint64_t addr; }; + struct TypeFieldReference + { + Ref<Function> func; + Ref<Architecture> arch; + uint64_t addr; + size_t size; + }; + struct ILReferenceSource { Ref<Function> func; @@ -1400,6 +1408,8 @@ __attribute__ ((format (printf, 1, 2))) struct QualifiedNameAndType; struct PossibleValueSet; class Metadata; + class Structure; + class QueryMetadataException: public std::exception { const std::string m_error; @@ -1609,7 +1619,7 @@ __attribute__ ((format (printf, 1, 2))) std::vector<TypeReferenceSource> GetTypeReferencesForType(const QualifiedName& type); // References to type field - std::vector<ReferenceSource> GetCodeReferencesForTypeField(const QualifiedName& type, uint64_t offset); + std::vector<TypeFieldReference> GetCodeReferencesForTypeField(const QualifiedName& type, uint64_t offset); std::vector<uint64_t> GetDataReferencesForTypeField(const QualifiedName& type, uint64_t offset); std::vector<TypeReferenceSource> GetTypeReferencesForTypeField(const QualifiedName& type, uint64_t offset); @@ -1618,7 +1628,17 @@ __attribute__ ((format (printf, 1, 2))) std::vector<TypeReferenceSource> GetCodeReferencesForTypeFieldFrom(ReferenceSource src); std::vector<TypeReferenceSource> GetCodeReferencesForTypeFieldFrom(ReferenceSource src, uint64_t len); - std::vector<uint64_t> GetAllFieldsReferencedByCode(const QualifiedName& type); + std::vector<uint64_t> GetAllFieldsReferenced(const QualifiedName& type); + std::map<uint64_t, std::vector<size_t>> GetAllSizesReferenced( + const QualifiedName& type); + std::map<uint64_t, std::vector<Confidence<Ref<Type>>>> + GetAllTypesReferenced(const QualifiedName& type); + std::vector<size_t> GetSizesReferenced(const QualifiedName& type, + uint64_t offset); + std::vector<Confidence<Ref<Type>>> GetTypesReferenced( + const QualifiedName& type, uint64_t offset); + + Ref<Structure> CreateStructureBasedOnFieldAccesses(const QualifiedName& type); std::vector<uint64_t> GetCallees(ReferenceSource addr); std::vector<ReferenceSource> GetCallers(uint64_t addr); @@ -1828,6 +1848,11 @@ __attribute__ ((format (printf, 1, 2))) static bool ParseExpression(Ref<BinaryView> view, const std::string& expression, uint64_t &offset, uint64_t here, std::string& errorString); bool HasSymbols() const; bool HasDataVariables() const; + + Ref<Structure> CreateStructureFromOffsetAccess(const QualifiedName& type, + bool* newMemberAdded) const; + Confidence<Ref<Type>> CreateStructureMemberFromAccess(const QualifiedName& name, + uint64_t offset) const; }; @@ -2668,6 +2693,8 @@ __attribute__ ((format (printf, 1, 2))) bool AddTypeMemberTokens(BinaryView* data, std::vector<InstructionTextToken>& tokens, int64_t offset, std::vector<std::string>& nameList, size_t size = 0, bool indirect = false); + + static std::string GetSizeSuffix(size_t size); }; class TypeBuilder @@ -2854,9 +2881,10 @@ __attribute__ ((format (printf, 1, 2))) StructureBuilder& SetStructureType(BNStructureType type); BNStructureType GetStructureType() const; StructureBuilder& AddMember(const Confidence<Ref<Type>>& type, const std::string& name); - StructureBuilder& AddMemberAtOffset(const Confidence<Ref<Type>>& type, const std::string& name, uint64_t offset); + StructureBuilder& AddMemberAtOffset(const Confidence<Ref<Type>>& type, + const std::string& name, uint64_t offset, bool overwriteExisting = true); StructureBuilder& RemoveMember(size_t idx); - StructureBuilder& ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name); + StructureBuilder& ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name, bool overwriteExisting = true); }; struct EnumerationMember @@ -3106,8 +3134,10 @@ __attribute__ ((format (printf, 1, 2))) void RemoveUserCodeReference(Architecture* fromArch, uint64_t fromAddr, uint64_t toAddr); void AddUserTypeReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name); void RemoveUserTypeReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name); - void AddUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name, uint64_t offset); - void RemoveUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name, uint64_t offset); + void AddUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, + const QualifiedName& name, uint64_t offset, size_t size = 0); + void RemoveUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, + const QualifiedName& name, uint64_t offset, size_t size = 0); Ref<LowLevelILFunction> GetLowLevelIL() const; Ref<LowLevelILFunction> GetLowLevelILIfAvailable() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index f2a487cb..71cc538d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1730,6 +1730,14 @@ extern "C" uint64_t addr; }; + struct BNTypeFieldReference + { + BNFunction* func; + BNArchitecture* arch; + uint64_t addr; + size_t size; + }; + struct BNILReferenceSource { BNFunction* func; @@ -1739,6 +1747,20 @@ extern "C" size_t exprId; }; + struct BNTypeFieldReferenceSizeInfo + { + uint64_t offset; + size_t* sizes; + size_t count; + }; + + struct BNTypeFieldReferenceTypeInfo + { + uint64_t offset; + BNTypeWithConfidence* types; + size_t count; + }; + struct BNVariableReferenceSource { BNVariable var; @@ -3192,10 +3214,12 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNAddUserTypeReference(BNFunction* func, BNArchitecture* fromArch, uint64_t fromAddr, BNQualifiedName* name); BINARYNINJACOREAPI void BNRemoveUserTypeReference(BNFunction* func, BNArchitecture* fromArch, uint64_t fromAddr, BNQualifiedName* name); - BINARYNINJACOREAPI void BNAddUserTypeFieldReference(BNFunction* func, BNArchitecture* fromArch, uint64_t fromAddr, - BNQualifiedName* name, uint64_t offset); - BINARYNINJACOREAPI void BNRemoveUserTypeFieldReference(BNFunction* func, BNArchitecture* fromArch, uint64_t fromAddr, - BNQualifiedName* name, uint64_t offset); + BINARYNINJACOREAPI void BNAddUserTypeFieldReference(BNFunction* func, + BNArchitecture* fromArch, uint64_t fromAddr, BNQualifiedName* name, uint64_t offset, + size_t size); + BINARYNINJACOREAPI void BNRemoveUserTypeFieldReference(BNFunction* func, + BNArchitecture* fromArch, uint64_t fromAddr, BNQualifiedName* name, uint64_t offset, + size_t size); BINARYNINJACOREAPI BNBasicBlock* BNNewBasicBlockReference(BNBasicBlock* block); BINARYNINJACOREAPI void BNFreeBasicBlock(BNBasicBlock* block); @@ -3384,6 +3408,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNReferenceSource* BNGetCodeReferencesInRange(BNBinaryView* view, uint64_t addr, uint64_t len, size_t* count); BINARYNINJACOREAPI void BNFreeCodeReferences(BNReferenceSource* refs, size_t count); + BINARYNINJACOREAPI void BNFreeTypeFieldReferences(BNTypeFieldReference* refs, size_t count); BINARYNINJACOREAPI void BNFreeILReferences(BNILReferenceSource* refs, size_t count); BINARYNINJACOREAPI uint64_t* BNGetCodeReferencesFrom(BNBinaryView* view, BNReferenceSource* src, size_t* count); BINARYNINJACOREAPI uint64_t* BNGetCodeReferencesFromInRange(BNBinaryView* view, BNReferenceSource* src, uint64_t len, size_t* count); @@ -3397,6 +3422,13 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNFreeDataReferences(uint64_t* refs); BINARYNINJACOREAPI void BNFreeTypeReferences(BNTypeReferenceSource* refs, size_t count); + BINARYNINJACOREAPI void BNFreeTypeFieldReferenceSizeInfo( + BNTypeFieldReferenceSizeInfo* refs, size_t count); + BINARYNINJACOREAPI void BNFreeTypeFieldReferenceTypeInfo( + BNTypeFieldReferenceTypeInfo* refs, size_t count); + BINARYNINJACOREAPI void BNFreeTypeFieldReferenceSizes(size_t* refs, size_t count); + BINARYNINJACOREAPI void BNFreeTypeFieldReferenceTypes(BNTypeWithConfidence* refs, + size_t count); // References to type BINARYNINJACOREAPI BNReferenceSource* BNGetCodeReferencesForType(BNBinaryView* view, BNQualifiedName* type, size_t* count); @@ -3404,7 +3436,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNTypeReferenceSource* BNGetTypeReferencesForType(BNBinaryView* view, BNQualifiedName* type, size_t* count); // References to type field - BINARYNINJACOREAPI BNReferenceSource* BNGetCodeReferencesForTypeField(BNBinaryView* view, + BINARYNINJACOREAPI BNTypeFieldReference* BNGetCodeReferencesForTypeField(BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); BINARYNINJACOREAPI uint64_t* BNGetDataReferencesForTypeField(BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); @@ -3416,8 +3448,16 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNTypeReferenceSource* BNGetCodeReferencesForTypeFieldsFrom(BNBinaryView* view, BNReferenceSource* addr, size_t* count); BINARYNINJACOREAPI BNTypeReferenceSource* BNGetCodeReferencesForTypeFieldsFromInRange(BNBinaryView* view, BNReferenceSource* addr, uint64_t len, size_t* count); - BINARYNINJACOREAPI uint64_t* BNGetAllFieldsReferencedByCode(BNBinaryView* view, + BINARYNINJACOREAPI uint64_t* BNGetAllFieldsReferenced(BNBinaryView* view, BNQualifiedName* type, size_t* count); + BINARYNINJACOREAPI BNTypeFieldReferenceSizeInfo* BNGetAllSizesReferenced( + BNBinaryView* view, BNQualifiedName* type, size_t* count); + BINARYNINJACOREAPI BNTypeFieldReferenceTypeInfo* BNGetAllTypesReferenced( + BNBinaryView* view, BNQualifiedName* type, size_t* count); + BINARYNINJACOREAPI size_t* BNGetSizesReferenced( + BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); + BINARYNINJACOREAPI BNTypeWithConfidence* BNGetTypesReferenced( + BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); BINARYNINJACOREAPI void BNRegisterGlobalFunctionRecognizer(BNFunctionRecognizer* rec); @@ -4491,11 +4531,12 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNStructureType BNGetStructureBuilderType(BNStructureBuilder* s); BINARYNINJACOREAPI void BNAddStructureBuilderMember(BNStructureBuilder* s, const BNTypeWithConfidence* const type, const char* name); - BINARYNINJACOREAPI void BNAddStructureBuilderMemberAtOffset(BNStructureBuilder* s, const BNTypeWithConfidence* const type, - const char* name, uint64_t offset); + BINARYNINJACOREAPI void BNAddStructureBuilderMemberAtOffset(BNStructureBuilder* s, + const BNTypeWithConfidence* const type, const char* name, uint64_t offset, + bool overwriteExisting); BINARYNINJACOREAPI void BNRemoveStructureBuilderMember(BNStructureBuilder* s, size_t idx); - BINARYNINJACOREAPI void BNReplaceStructureBuilderMember(BNStructureBuilder* s, size_t idx, const BNTypeWithConfidence* const type, - const char* name); + BINARYNINJACOREAPI void BNReplaceStructureBuilderMember(BNStructureBuilder* s, size_t idx, + const BNTypeWithConfidence* const type, const char* name, bool overwriteExisting); BINARYNINJACOREAPI BNEnumerationBuilder* BNCreateEnumerationBuilder(void); BINARYNINJACOREAPI BNEnumerationBuilder* BNCreateEnumerationBuilderFromEnumeration(BNEnumeration* e); @@ -4515,6 +4556,11 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNRemoveEnumerationBuilderMember(BNEnumerationBuilder* e, size_t idx); BINARYNINJACOREAPI void BNReplaceEnumerationBuilderMember(BNEnumerationBuilder* e, size_t idx, const char* name, uint64_t value); + BINARYNINJACOREAPI BNStructure* BNCreateStructureFromOffsetAccess(BNBinaryView* view, + BNQualifiedName* name, bool* newMember); + BINARYNINJACOREAPI BNTypeWithConfidence BNCreateStructureMemberFromAccess( + BNBinaryView* view, BNQualifiedName* name, uint64_t offset); + // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, const char** includeDirs, size_t includeDirCount); diff --git a/binaryview.cpp b/binaryview.cpp index f37b60ff..e57b6bf4 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1917,25 +1917,26 @@ vector<TypeReferenceSource> BinaryView::GetTypeReferencesForType(const Qualified } -vector<ReferenceSource> BinaryView::GetCodeReferencesForTypeField(const QualifiedName& type, uint64_t offset) +vector<TypeFieldReference> BinaryView::GetCodeReferencesForTypeField(const QualifiedName& type, uint64_t offset) { size_t count; BNQualifiedName nameObj = type.GetAPIObject(); - BNReferenceSource* refs = BNGetCodeReferencesForTypeField(m_object, &nameObj, offset, &count); + BNTypeFieldReference* refs = BNGetCodeReferencesForTypeField(m_object, &nameObj, offset, &count); QualifiedName::FreeAPIObject(&nameObj); - vector<ReferenceSource> result; + vector<TypeFieldReference> result; result.reserve(count); for (size_t i = 0; i < count; i++) { - ReferenceSource src; + TypeFieldReference src; src.func = new Function(BNNewFunctionReference(refs[i].func)); src.arch = new CoreArchitecture(refs[i].arch); src.addr = refs[i].addr; + src.size = refs[i].size; result.push_back(src); } - BNFreeCodeReferences(refs, count); + BNFreeTypeFieldReferences(refs, count); return result; } @@ -2063,11 +2064,11 @@ vector<TypeReferenceSource> BinaryView::GetCodeReferencesForTypeFieldFrom(Refere } -vector<uint64_t> BinaryView::GetAllFieldsReferencedByCode(const QualifiedName& type) +vector<uint64_t> BinaryView::GetAllFieldsReferenced(const QualifiedName& type) { size_t count; BNQualifiedName nameObj = type.GetAPIObject(); - uint64_t* fields = BNGetAllFieldsReferencedByCode(m_object, &nameObj, &count); + uint64_t* fields = BNGetAllFieldsReferenced(m_object, &nameObj, &count); vector<uint64_t> result(fields, &fields[count]); // Data refs and the fields above are both an array of uint64_t, so they can be freed in @@ -2077,6 +2078,93 @@ vector<uint64_t> BinaryView::GetAllFieldsReferencedByCode(const QualifiedName& t } +std::map<uint64_t, std::vector<size_t>> BinaryView::GetAllSizesReferenced( + const QualifiedName& type) +{ + size_t count; + BNQualifiedName nameObj = type.GetAPIObject(); + BNTypeFieldReferenceSizeInfo* fields = BNGetAllSizesReferenced(m_object, + &nameObj, &count); + + std::map<uint64_t, std::vector<size_t>> result; + for (size_t i = 0; i < count; i++) + { + auto& sizes = result[fields[i].offset]; + for (size_t j = 0; j < fields[i].count; j++) + { + sizes.push_back(fields[i].sizes[j]); + } + } + + BNFreeTypeFieldReferenceSizeInfo(fields, count); + return result; +} + + +std::map<uint64_t, std::vector<Confidence<Ref<Type>>>> + BinaryView::GetAllTypesReferenced(const QualifiedName& type) +{ + size_t count; + BNQualifiedName nameObj = type.GetAPIObject(); + BNTypeFieldReferenceTypeInfo* fields = BNGetAllTypesReferenced(m_object, + &nameObj, &count); + + std::map<uint64_t, std::vector<Confidence<Ref<Type>>>> result; + for (size_t i = 0; i < count; i++) + { + auto& types = result[fields[i].offset]; + for (size_t j = 0; j < fields[i].count; j++) + { + BNTypeWithConfidence tc = fields[i].types[j]; + Ref<Type> type = tc.type ? new Type(tc.type) : nullptr; + types.push_back(Confidence<Ref<Type>>(type, tc.confidence)); + } + } + + BNFreeTypeFieldReferenceTypeInfo(fields, count); + return result; +} + + +std::vector<size_t> BinaryView::GetSizesReferenced(const QualifiedName& type, + uint64_t offset) +{ + size_t count; + BNQualifiedName nameObj = type.GetAPIObject(); + size_t* refs = BNGetSizesReferenced(m_object, &nameObj, offset, &count); + + std::vector<size_t> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result[i] = refs[i]; + + BNFreeTypeFieldReferenceSizes(refs, count); + return result; +} + + +std::vector<Confidence<Ref<Type>>> BinaryView::GetTypesReferenced( + const QualifiedName& type, uint64_t offset) +{ + size_t count; + BNQualifiedName nameObj = type.GetAPIObject(); + BNTypeWithConfidence* types = BNGetTypesReferenced(m_object, &nameObj, offset, + &count); + + std::vector<Confidence<Ref<Type>>> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + BNTypeWithConfidence tc = types[i]; + Ref<Type> type = tc.type ? new Type(tc.type) : nullptr; + result.push_back(Confidence<Ref<Type>>(type, tc.confidence)); + } + + BNFreeTypeFieldReferenceTypes(types, count); + return result; +} + + vector<uint64_t> BinaryView::GetCallees(ReferenceSource callSite) { size_t count; @@ -3465,6 +3553,29 @@ bool BinaryView::ParseExpression(Ref<BinaryView> view, const string& expression, } +Ref<Structure> BinaryView::CreateStructureFromOffsetAccess(const QualifiedName& type, + bool* newMemberAdded) const +{ + BNQualifiedName typeObj = type.GetAPIObject(); + BNStructure* result = BNCreateStructureFromOffsetAccess(m_object, &typeObj, + newMemberAdded); + return new Structure(result); +} + + +Confidence<Ref<Type>> BinaryView::CreateStructureMemberFromAccess( + const QualifiedName& name, uint64_t offset) const +{ + BNQualifiedName typeObj = name.GetAPIObject(); + BNTypeWithConfidence type = BNCreateStructureMemberFromAccess(m_object, &typeObj, + offset); + + if (type.type) + return Confidence<Ref<Type>>(new Type(type.type), type.confidence); + return nullptr; +} + + Relocation::Relocation(BNRelocation* reloc) { m_object = reloc; diff --git a/function.cpp b/function.cpp index 45333ebf..1d0551db 100644 --- a/function.cpp +++ b/function.cpp @@ -303,17 +303,20 @@ void Function::RemoveUserTypeReference(Architecture* fromArch, uint64_t fromAddr } -void Function::AddUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name, uint64_t offset) +void Function::AddUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name, uint64_t offset, size_t size) { BNQualifiedName nameObj = name.GetAPIObject(); - BNAddUserTypeFieldReference(m_object, fromArch->GetObject(), fromAddr, &nameObj, offset); + BNAddUserTypeFieldReference(m_object, fromArch->GetObject(), fromAddr, &nameObj, offset, + size); } -void Function::RemoveUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, const QualifiedName& name, uint64_t offset) +void Function::RemoveUserTypeFieldReference(Architecture* fromArch, uint64_t fromAddr, + const QualifiedName& name, uint64_t offset, size_t size) { BNQualifiedName nameObj = name.GetAPIObject(); - BNRemoveUserTypeFieldReference(m_object, fromArch->GetObject(), fromAddr, &nameObj, offset); + BNRemoveUserTypeFieldReference(m_object, fromArch->GetObject(), fromAddr, &nameObj, + offset, size); } diff --git a/python/architecture.py b/python/architecture.py index 19ef7831..e23f39d7 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -2808,3 +2808,107 @@ class ReferenceSource(object): @address.setter def address(self, value): self._address = value + + +class TypeFieldReference(object): + def __init__(self, func, arch, addr, size): + self._function = func + self._arch = arch + self._address = addr + self._size = size + + def __repr__(self): + if self._arch: + return "<ref: %s@%#x, size: %#x>" % (self._arch.name, self._address, self._size) + else: + return "<ref: %#x, size: %#x>" % (self._address, self._size) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self.function, self.arch, self.address, self._size) ==\ + (other.address, other.function, other.arch, other.size) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + if self.address < other.address: + return True + elif self.address > other.address: + return False + else: + return self.size < other.size + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + if self.address > other.address: + return True + elif self.address < other.address: + return False + else: + return self.size > other.size + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + if self.address > other.address: + return True + elif self.address < other.address: + return False + else: + return self.size >= other.size + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + if self.address < other.address: + return True + elif self.address > other.address: + return False + else: + return self.size <= other.size + + def __hash__(self): + return hash((self._function, self._arch, self._address, self._size)) + + @property + def function(self): + """ """ + return self._function + + @function.setter + def function(self, value): + self._function = value + + @property + def arch(self): + """ """ + return self._arch + + @arch.setter + def arch(self, value): + self._arch = value + + @property + def address(self): + """ """ + return self._address + + @address.setter + def address(self, value): + self._address = value + + @property + def size(self): + """ """ + return self._size + + @size.setter + def address(self, value): + self._size = value
\ No newline at end of file diff --git a/python/binaryview.py b/python/binaryview.py index 7fc37287..84dde18c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3505,12 +3505,12 @@ class BinaryView(object): def get_code_refs_for_type_field(self, name, offset): """ - ``get_code_refs_for_type`` returns a list of ReferenceSource objects (xrefs or cross-references) that reference the provided type field. + ``get_code_refs_for_type`` returns a list of TypeFieldReference objects (xrefs or cross-references) that reference the provided type field. :param QualifiedName name: name of type to query for references :param int offset: offset of the field, relative to the type :return: List of References for the given type - :rtype: list(ReferenceSource) + :rtype: list(TypeFieldReference) :Example: >>> bv.get_code_refs_for_type_field('A', 0x8) @@ -3533,8 +3533,9 @@ class BinaryView(object): else: arch = None addr = refs[i].addr - result.append(binaryninja.architecture.ReferenceSource(func, arch, addr)) - core.BNFreeCodeReferences(refs, count.value) + size = refs[i].size + result.append(binaryninja.architecture.TypeFieldReference(func, arch, addr, size)) + core.BNFreeTypeFieldReferences(refs, count.value) return result @@ -3730,9 +3731,9 @@ class BinaryView(object): core.BNRemoveUserDataReference(self.handle, from_addr, to_addr) - def get_all_type_fields_referenced_by_code(self, name): + def get_all_fields_referenced(self, name): """ - ``get_all_type_fields_referenced_by_code`` returns a list of offsets in the QualifiedName + ``get_all_fields_referenced`` returns a list of offsets in the QualifiedName specified by name, which are referenced by code. :param QualifiedName name: name of type to query for references @@ -3740,14 +3741,14 @@ class BinaryView(object): :rtype: list(integer) :Example: - >>> bv.get_all_type_fields_referenced_by_code('A') - ['<type D, offset 0x8, direct>', '<type C, offset 0x10, indirect>'] + >>> bv.get_all_fields_referenced('A') + [0, 8, 16, 24, 32, 40] >>> """ count = ctypes.c_ulonglong(0) name = types.QualifiedName(name)._get_core_struct() - refs = core.BNGetAllFieldsReferencedByCode(self.handle, name, count) + refs = core.BNGetAllFieldsReferenced(self.handle, name, count) result = [] for i in range(0, count.value): @@ -3756,6 +3757,136 @@ class BinaryView(object): core.BNFreeDataReferences(refs, count.value) return result + def get_all_sizes_referenced(self, name): + """ + ``get_all_sizes_referenced`` returns a map from field offset to a list of sizes of + the accesses to it. + + :param QualifiedName name: name of type to query for references + :return: A map from field offset to the size of the code accesses to it + :rtype: map + :Example: + + >>> bv.get_all_sizes_referenced('B') + {0: [1, 8], 8: [8], 16: [1, 8]} + >>> + + """ + count = ctypes.c_ulonglong(0) + name = types.QualifiedName(name)._get_core_struct() + refs = core.BNGetAllSizesReferenced(self.handle, name, count) + + result = {} + for i in range(0, count.value): + result[refs[i].offset] = [] + for j in range(0, refs[i].count): + result[refs[i].offset].append(refs[i].sizes[j]) + + core.BNFreeTypeFieldReferenceSizeInfo(refs, count.value) + return result + + def get_all_types_referenced(self, name): + """ + ``get_all_types_referenced`` returns a map from field offset to a related to the + type field access. + + :param QualifiedName name: name of type to query for references + :return: A map from field offset to a list of incoming types written to it + :rtype: map + :Example: + + >>> bv.get_all_types_referenced('B') + {0: [<type: char, 0% confidence>], 8: [<type: int64_t, 0% confidence>], + 16: [<type: char, 0% confidence>, <type: bool>]} + >>> + + """ + count = ctypes.c_ulonglong(0) + name = types.QualifiedName(name)._get_core_struct() + refs = core.BNGetAllTypesReferenced(self.handle, name, count) + + result = {} + for i in range(0, count.value): + result[refs[i].offset] = [] + for j in range(0, refs[i].count): + typeObj = types.Type(core.BNNewTypeReference(refs[i].types[j].type),\ + confidence = refs[i].types[j].confidence) + result[refs[i].offset].append(typeObj) + + core.BNFreeTypeFieldReferenceTypeInfo(refs, count.value) + return result + + def get_sizes_referenced(self, name, offset): + """ + ``get_sizes_referenced`` returns a list of sizes of the accesses to it. + + :param QualifiedName name: name of type to query for references + :param int offset: offset of the field + :return: a list of sizes of the accesses to it. + :rtype: list + :Example: + + >>> bv.get_sizes_referenced('B', 16) + [1, 8] + >>> + + """ + count = ctypes.c_ulonglong(0) + name = types.QualifiedName(name)._get_core_struct() + refs = core.BNGetSizesReferenced(self.handle, name, offset, count) + + result = [] + for i in range(0, count.value): + result.append(refs[i]) + + core.BNFreeTypeFieldReferenceSizes(refs, count.value) + return result + + def get_types_referenced(self, name, offset): + """ + ``get_types_referenced`` returns a list of types related to the type field access. + + :param QualifiedName name: name of type to query for references + :param int offset: offset of the field + :return: a list of types related to the type field access. + :rtype: list + :Example: + + >>> bv.get_types_referenced('B', 0x10) + [<type: bool>, <type: char, 0% confidence>] + >>> + """ + count = ctypes.c_ulonglong(0) + name = types.QualifiedName(name)._get_core_struct() + refs = core.BNGetTypesReferenced(self.handle, name, offset, count) + + result = [] + for i in range(0, count.value): + typeObj = types.Type(core.BNNewTypeReference(refs[i].type),\ + confidence = refs[i].confidence) + result.append(typeObj) + + core.BNFreeTypeFieldReferenceTypes(refs, count.value) + return result + + def create_structure_from_offset_access(self, name): + newMemberAdded = ctypes.c_bool(False) + name = types.QualifiedName(name)._get_core_struct() + struct = core.BNCreateStructureFromOffsetAccess(self.handle, name, newMemberAdded) + if struct is None: + return None + return types.Structure(struct) + + @classmethod + def create_structure_member_from_access(self, name, offset): + name = types.QualifiedName(name)._get_core_struct() + result = core.BNCreateStructureMemberFromAccess(self.handle, name, offset) + if not result.type: + return None + + return types.Type(core.BNNewTypeReference(result.type),\ + confidence = result.confidence) + def get_callers(self, addr): """ ``get_callers`` returns a list of ReferenceSource objects (xrefs or cross-references) that call the provided virtual address. diff --git a/python/function.py b/python/function.py index cb8a869c..0ec6142d 100644 --- a/python/function.py +++ b/python/function.py @@ -2364,7 +2364,7 @@ class Function(object): name = types.QualifiedName(name)._get_core_struct() core.BNRemoveUserTypeReference(self.handle, from_arch.handle, from_addr, name) - def add_user_type_field_ref(self, from_addr, name, offset, from_arch=None): + def add_user_type_field_ref(self, from_addr, name, offset, from_arch = None, size = 0): """ ``add_user_type_field_ref`` places a user-defined type field cross-reference from the instruction at the given address and architecture to the specified type. If the specified @@ -2375,10 +2375,11 @@ class Function(object): :param QualifiedName name: name of the referenced type :param int offset: offset of the field, relative to the type :param Architecture from_arch: (optional) architecture of the source instruction + :param int size: (optional) the size of the access :rtype: None :Example: - >>> current_function.add_user_type_field_ref(here, 'A'. 0x8) + >>> current_function.add_user_type_field_ref(here, 'A', 0x8) """ @@ -2386,9 +2387,10 @@ class Function(object): from_arch = self.arch name = types.QualifiedName(name)._get_core_struct() - core.BNAddUserTypeFieldReference(self.handle, from_arch.handle, from_addr, name, offset) + core.BNAddUserTypeFieldReference(self.handle, from_arch.handle, from_addr, name,\ + offset, size) - def remove_user_type_field_ref(self, from_addr, name, offset, from_arch=None): + def remove_user_type_field_ref(self, from_addr, name, offset, from_arch = None, size = 0): """ ``remove_user_type_field_ref`` removes a user-defined type field cross-reference. If the given address is not contained within this function, or if there is no @@ -2398,6 +2400,7 @@ class Function(object): :param QualifiedName name: name of the referenced type :param int offset: offset of the field, relative to the type :param Architecture from_arch: (optional) architecture of the source instruction + :param int size: (optional) the size of the access :rtype: None :Example: @@ -2409,7 +2412,8 @@ class Function(object): from_arch = self.arch name = types.QualifiedName(name)._get_core_struct() - core.BNRemoveUserTypeFieldReference(self.handle, from_arch.handle, from_addr, name, offset) + core.BNRemoveUserTypeFieldReference(self.handle, from_arch.handle, from_addr, name,\ + offset, size) def get_low_level_il_at(self, addr, arch=None): """ diff --git a/python/generator.cpp b/python/generator.cpp index f78324cf..4901b07a 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -344,7 +344,8 @@ int main(int argc, char* argv[]) { if ((arg.type->GetClass() == PointerTypeClass) && (arg.type->GetChildType()->GetWidth() == 1) && - (arg.type->GetChildType()->IsSigned())) + (arg.type->GetChildType()->IsSigned()) && + (!arg.type->GetChildType()->IsBool())) { stringArgument = true; break; diff --git a/python/types.py b/python/types.py index 39378963..af62e5b4 100644 --- a/python/types.py +++ b/python/types.py @@ -19,6 +19,8 @@ # IN THE SOFTWARE. from __future__ import absolute_import + +from binaryninja.log import log_warn max_confidence = 255 import ctypes @@ -1452,26 +1454,26 @@ class Structure(object): tc.confidence = t.confidence core.BNAddStructureBuilderMember(self._handle, tc, name) - def insert(self, offset, t, name = ""): + def insert(self, offset, t, name = "", overwriteExisting = True): if not self._mutable: raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") tc = core.BNTypeWithConfidence() tc.type = t.handle tc.confidence = t.confidence - core.BNAddStructureBuilderMemberAtOffset(self._handle, tc, name, offset) + core.BNAddStructureBuilderMemberAtOffset(self._handle, tc, name, offset, overwriteExisting) def remove(self, i): if not self._mutable: raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") core.BNRemoveStructureBuilderMember(self._handle, i) - def replace(self, i, t, name = ""): + def replace(self, i, t, name = "", overwriteExisting = True): if not self._mutable: raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") tc = core.BNTypeWithConfidence() tc.type = t.handle tc.confidence = t.confidence - core.BNReplaceStructureBuilderMember(self._handle, i, tc, name) + core.BNReplaceStructureBuilderMember(self._handle, i, tc, name, overwriteExisting) def mutable_copy(self): if self._mutable: diff --git a/suite/binaries b/suite/binaries -Subproject 922461236a4b7fbe761821ae80d8a550939b69d +Subproject 37a3fa26e79b78d60e41fcbb3708840e7a79fdf diff --git a/suite/testcommon.py b/suite/testcommon.py index 0d65c8b8..47dfb70e 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -1136,6 +1136,45 @@ class TestBuilder(Builder): self.delete_package("type_xref.bndb") return fixOutput(sorted(retinfo)) + def test_auto_create_struct(self): + """Automatically create a structure""" + retinfo = [] + file_name = self.unpackage_file("auto_create_members.bndb") + if not os.path.exists(file_name): + return retinfo + + with BinaryViewType.get_view_of_file(file_name) as bv: + if bv is None: + return retinfo + + test_types = ['struct_1', 'struct_2', 'struct_3'] + for test_type in test_types: + offsets = bv.get_all_fields_referenced(test_type) + for offset in offsets: + retinfo.append('type %s, offset 0x%x is referenced' % + (test_type, offset)) + + refs = bv.get_all_sizes_referenced(test_type) + for offset in refs: + sizes = refs[offset] + for size in sizes: + retinfo.append('type %s, offset 0x%x is referenced of size 0x%x'\ + % (test_type, offset, size)) + + refs = bv.get_all_types_referenced(test_type) + for offset in refs: + types = refs[offset] + for refType in types: + retinfo.append('type %s, offset 0x%x is referenced of type %s'\ + % (test_type, offset, refType)) + + struct = bv.create_structure_from_offset_access(test_type) + for member in struct.members: + retinfo.append('type %s, member: %s' % (test_type, member)) + + self.delete_package("auto_create_members.bndb") + return fixOutput(sorted(retinfo)) + def test_hlil_arrays(self): """HLIL array resolution failure""" @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include <inttypes.h> using namespace BinaryNinja; using namespace std; @@ -1000,6 +1001,33 @@ bool Type::AddTypeMemberTokens(BinaryView* data, vector<InstructionTextToken>& t } +string Type::GetSizeSuffix(size_t size) +{ + char sizeStr[32]; + + switch (size) + { + case 0: + return ""; + case 1: + return ".b"; + case 2: + return ".w"; + case 4: + return ".d"; + case 8: + return ".q"; + case 10: + return ".t"; + case 16: + return ".o"; + default: + sprintf(sizeStr, ".%" PRIuPTR, size); + return sizeStr; + } +} + + TypeBuilder::TypeBuilder() { m_object = BNCreateVoidTypeBuilder(); @@ -1919,12 +1947,13 @@ StructureBuilder& StructureBuilder::AddMember(const Confidence<Ref<Type>>& type, } -StructureBuilder& StructureBuilder::AddMemberAtOffset(const Confidence<Ref<Type>>& type, const string& name, uint64_t offset) +StructureBuilder& StructureBuilder::AddMemberAtOffset(const Confidence<Ref<Type>>& type, + const string& name, uint64_t offset, bool overwriteExisting) { BNTypeWithConfidence tc; tc.type = type->GetObject(); tc.confidence = type.GetConfidence(); - BNAddStructureBuilderMemberAtOffset(m_object, &tc, name.c_str(), offset); + BNAddStructureBuilderMemberAtOffset(m_object, &tc, name.c_str(), offset, overwriteExisting); return *this; } @@ -1936,12 +1965,12 @@ StructureBuilder& StructureBuilder::RemoveMember(size_t idx) } -StructureBuilder& StructureBuilder::ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name) +StructureBuilder& StructureBuilder::ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name, bool overwriteExisting) { BNTypeWithConfidence tc; tc.type = type->GetObject(); tc.confidence = type.GetConfidence(); - BNReplaceStructureBuilderMember(m_object, idx, &tc, name.c_str()); + BNReplaceStructureBuilderMember(m_object, idx, &tc, name.c_str(), overwriteExisting); return *this; } diff --git a/ui/addressdialog.h b/ui/addressdialog.h index 557030ba..261f0732 100644 --- a/ui/addressdialog.h +++ b/ui/addressdialog.h @@ -89,4 +89,48 @@ public: const QString& title = "Go to File Offset", const QString& prompt = "Enter Expression", bool defaultToCurrent = false); ~FileOffsetDialogWithPreview() {} uint64_t getOffset() const { return m_fileOffset; } +}; + +class BINARYNINJAUIAPI AddUserXrefDialog: public QDialog +{ + Q_OBJECT + + QComboBox* m_combo; + QStringListModel* m_model; + QLabel* m_previewText, m_sizePrompt; + QLineEdit* m_sizeInput; + BinaryViewRef m_view; + uint64_t m_addr; + uint64_t m_here; + size_t m_size; + bool m_resultValid; + QTimer* m_updateTimer; + QStringList m_historyEntries; + int m_historySize; + GetSymbolsListThread* m_updateThread; + QColor m_defaultColor; + QFont m_defaultFont; + QString m_prompt; + bool m_initialTextSelection; + std::string m_errorString; + bool m_resultAmbiguous; + + void commitHistory(); + void customEvent(QEvent* event); + +private Q_SLOTS: + void updateTimerEvent(); + void accepted(); + void updatePreview(); + void updatePreviewText(); + void updatePreviewWithText(QString data); + +public: + AddUserXrefDialog(QWidget* parent, BinaryViewRef view, uint64_t here = 0, + size_t size = 0, const QString& title = "Add User Type Field Cross Reference", + const QString& sizeTitle = "Size of Reference (optional)", + const QString& prompt = "Enter Expression", bool defaultToCurrent = false); + ~AddUserXrefDialog() { delete m_updateThread; } + uint64_t getOffset() const { return m_addr; } + size_t getSize() const { return m_size; } };
\ No newline at end of file diff --git a/ui/commands.h b/ui/commands.h index a47f9ab5..fabea073 100644 --- a/ui/commands.h +++ b/ui/commands.h @@ -20,7 +20,9 @@ bool BINARYNINJAUIAPI askForNewType(QWidget* parent, BinaryViewRef data, Functio bool BINARYNINJAUIAPI inputNewType(QWidget* parent, BinaryViewRef data, FunctionRef currentFunction, uint64_t currentAddr, size_t selectionSize, HighlightTokenState& highlight); bool BINARYNINJAUIAPI createInferredMember(QWidget* parent, BinaryViewRef data, HighlightTokenState& highlight, - FunctionRef func, BNFunctionGraphType type); + FunctionRef func, BNFunctionGraphType ilType); +bool BINARYNINJAUIAPI createStructMembers(QWidget* parent, BinaryViewRef data, + HighlightTokenState& highlight, FunctionRef func); bool BINARYNINJAUIAPI inputPossibleValueSet(QWidget* parent, BinaryViewRef data, FunctionRef currentFunction, HighlightTokenState& highlight, uint64_t defSiteAddress, size_t ilInstructionIndex = BN_INVALID_EXPR); diff --git a/ui/flowgraphwidget.h b/ui/flowgraphwidget.h index 61b1353b..0ba5c823 100644 --- a/ui/flowgraphwidget.h +++ b/ui/flowgraphwidget.h @@ -324,6 +324,7 @@ private Q_SLOTS: void createFunc(); void changeType(); void inferStructureType(); + void autoCreateMembers(); void comment(); void addUserXref(); void functionComment(); diff --git a/ui/linearview.h b/ui/linearview.h index 99fae229..74bc6b7a 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -271,6 +271,7 @@ private Q_SLOTS: void createArray(); void createStruct(); void createNewTypes(); + void autoCreateMembers(); size_t getStringLength(uint64_t startAddr); diff --git a/ui/tokenizedtextview.h b/ui/tokenizedtextview.h index e1ead04f..699c6caa 100644 --- a/ui/tokenizedtextview.h +++ b/ui/tokenizedtextview.h @@ -97,6 +97,7 @@ class BINARYNINJAUIAPI TokenizedTextView: public QAbstractScrollArea, public Vie void makeString(); void changeType(); void inferStructureType(); + void autoCreateMembers(); size_t getStringLength(uint64_t startAddr); void setInstructionHighlight(BNHighlightColor color); diff --git a/ui/typeview.h b/ui/typeview.h index 60b11703..47b45d2a 100644 --- a/ui/typeview.h +++ b/ui/typeview.h @@ -251,6 +251,7 @@ private Q_SLOTS: void createUnion(); void setStructureSize(); void addUserXref(); + void autoCreateMembers(); void updateLineNumberAreaWidth(size_t lineCount); void focusFilter(); void toggleCollapseType(); |
