summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXusheng <xusheng@vector35.com>2021-05-05 17:23:49 +0800
committerXusheng <xusheng@vector35.com>2021-05-26 17:46:13 +0800
commit7c9ada78241e08bf36bd04d989f742a6de721575 (patch)
tree4134fd2f12a504ab17cc0b9acc1fb8d27552490f
parentfd1974b407be042fd84f0267a328a5adabce28e1 (diff)
Add the ability to automatically create struct members
-rw-r--r--binaryninjaapi.h42
-rw-r--r--binaryninjacore.h66
-rw-r--r--binaryview.cpp125
-rw-r--r--function.cpp11
-rw-r--r--python/architecture.py104
-rw-r--r--python/binaryview.py149
-rw-r--r--python/function.py14
-rw-r--r--python/generator.cpp3
-rw-r--r--python/types.py10
m---------suite/binaries0
-rw-r--r--suite/testcommon.py39
-rw-r--r--type.cpp37
-rw-r--r--ui/addressdialog.h44
-rw-r--r--ui/commands.h4
-rw-r--r--ui/flowgraphwidget.h1
-rw-r--r--ui/linearview.h1
-rw-r--r--ui/tokenizedtextview.h1
-rw-r--r--ui/typeview.h1
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"""
diff --git a/type.cpp b/type.cpp
index 08597f1a..bf7f83bd 100644
--- a/type.cpp
+++ b/type.cpp
@@ -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();