diff options
| author | Peter LaFosse <peter@vector35.com> | 2019-09-13 09:56:00 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2019-11-15 21:10:58 -0500 |
| commit | db48820f5fed420ad298278e8e6b055baa4ddf06 (patch) | |
| tree | 2b41a6f081f924b622887ddc42f5f579eebbd849 | |
| parent | 3c329e77e0318db070099be2d1731c4e7ac510ba (diff) | |
Type workflow improvements
Expand type context for data renderers
Add additional linearview helper routines for defining variables inside of structures
fix unit tests
| -rw-r--r-- | binaryninjaapi.h | 52 | ||||
| -rw-r--r-- | binaryninjacore.h | 18 | ||||
| -rw-r--r-- | datarenderer.cpp | 39 | ||||
| -rw-r--r-- | python/datarender.py | 4 | ||||
| -rw-r--r-- | python/types.py | 8 | ||||
| -rw-r--r-- | suite/api_test.py | 4 | ||||
| -rw-r--r-- | type.cpp | 27 | ||||
| -rw-r--r-- | ui/commands.h | 5 | ||||
| -rw-r--r-- | ui/createstructdialog.h | 2 | ||||
| -rw-r--r-- | ui/createtypedialog.h | 2 | ||||
| -rw-r--r-- | ui/linearview.h | 20 |
11 files changed, 131 insertions, 50 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 94bfb8cc..00b7d719 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -700,14 +700,13 @@ __attribute__ ((format (printf, 1, 2))) void AddRequiredPluginDependency(const std::string& name); void AddOptionalPluginDependency(const std::string& name); bool DemangleMS(Architecture* arch, - const std::string& mangledName, - Type** outType, - QualifiedName& outVarName); - bool DemangleGNU3(Architecture* arch, - const std::string& mangledName, - Type** outType, - QualifiedName& outVarName); - + const std::string& mangledName, + Type** outType, + QualifiedName& outVarName); + bool DemangleGNU3(Ref<Architecture> arch, + const std::string& mangledName, + Type** outType, + QualifiedName& outVarName); void RegisterMainThread(MainThreadActionHandler* handler); Ref<MainThreadAction> ExecuteOnMainThread(const std::function<void()>& action); void ExecuteOnMainThreadAndWait(const std::function<void()>& action); @@ -2469,7 +2468,7 @@ __attribute__ ((format (printf, 1, 2))) Confidence<bool> IsSigned() const; Confidence<bool> IsConst() const; Confidence<bool> IsVolatile() const; - bool IsFloat() const; + Confidence<Ref<Type>> GetChildType() const; Confidence<Ref<CallingConvention>> GetCallingConvention() const; std::vector<FunctionParameter> GetParameters() const; @@ -2536,6 +2535,28 @@ __attribute__ ((format (printf, 1, 2))) static std::string GetAutoDebugTypeIdSource(); Confidence<Ref<Type>> WithConfidence(uint8_t conf); + + bool IsReferenceOfType(BNNamedTypeReferenceClass refType); + bool IsStructReference() { return IsReferenceOfType(StructNamedTypeClass); } + bool IsEnumReference() { return IsReferenceOfType(EnumNamedTypeClass); } + bool IsUnionReference() { return IsReferenceOfType(UnionNamedTypeClass); } + bool IsClassReference() { return IsReferenceOfType(ClassNamedTypeClass); } + bool IsTypedefReference() { return IsReferenceOfType(TypedefNamedTypeClass); } + bool IsStructOrClassReference() { return IsReferenceOfType(StructNamedTypeClass) || IsReferenceOfType(ClassNamedTypeClass); } + + bool IsVoid() const { return GetClass() == VoidTypeClass; } + bool IsBool() const { return GetClass() == BoolTypeClass; } + bool IsInteger() const { return GetClass() == IntegerTypeClass; } + bool IsFloat() const { return GetClass() == FloatTypeClass; } + bool IsStructure() const { return GetClass() == StructureTypeClass; } + bool IsEnumeration() const { return GetClass() == EnumerationTypeClass; } + bool IsPointer() const { return GetClass() == PointerTypeClass; } + bool IsArray() const { return GetClass() == ArrayTypeClass; } + bool IsFunction() const { return GetClass() == FunctionTypeClass; } + bool IsVarArgs() const { return GetClass() == VarArgsTypeClass; } + bool IsValue() const { return GetClass() == ValueTypeClass; } + bool IsNamedTypeRefer() const { return GetClass() == NamedTypeReferenceClass; } + bool IsWideChar() const { return GetClass() == WideCharTypeClass; } }; class NamedTypeReference: public CoreRefCountObject<BNNamedTypeReference, BNNewNamedTypeReference, @@ -2576,6 +2597,7 @@ __attribute__ ((format (printf, 1, 2))) std::vector<StructureMember> GetMembers() const; bool GetMemberByName(const std::string& name, StructureMember& result) const; + bool GetMemberAtOffset(int64_t offset, StructureMember& result) const; uint64_t GetWidth() const; void SetWidth(size_t width); size_t GetAlignment() const; @@ -4692,20 +4714,20 @@ __attribute__ ((format (printf, 1, 2))) class DataRenderer: public CoreRefCountObject<BNDataRenderer, BNNewDataRendererReference, BNFreeDataRenderer> { static bool IsValidForDataCallback(void* ctxt, BNBinaryView* data, uint64_t addr, BNType* type, - BNType** typeCtx, size_t ctxCount); + BNTypeContext** typeCtx, size_t ctxCount); static BNDisassemblyTextLine* GetLinesForDataCallback(void* ctxt, BNBinaryView* data, uint64_t addr, BNType* type, - const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNType** typeCxt, + const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNTypeContext** typeCxt, size_t ctxCount); static void FreeCallback(void* ctxt); public: DataRenderer(); DataRenderer(BNDataRenderer* renderer); - virtual bool IsValidForData(BinaryView* data, uint64_t addr, Type* type, std::vector<Type*>& context); + virtual bool IsValidForData(BinaryView* data, uint64_t addr, Type* type, std::vector<std::pair<Type*, size_t>>& context); virtual std::vector<DisassemblyTextLine> GetLinesForData(BinaryView* data, uint64_t addr, Type* type, - const std::vector<InstructionTextToken>& prefix, size_t width, std::vector<Type*>& context); + const std::vector<InstructionTextToken>& prefix, size_t width, std::vector<std::pair<Type*, size_t>>& context); - static bool IsStructOfTypeName(Type* type, const QualifiedName& name, std::vector<Type*>& context); - static bool IsStructOfTypeName(Type* type, const std::string& name, std::vector<Type*>& context); + static bool IsStructOfTypeName(Type* type, const QualifiedName& name, std::vector<std::pair<Type*, size_t>>& context); + static bool IsStructOfTypeName(Type* type, const std::string& name, std::vector<std::pair<Type*, size_t>>& context); }; class DataRendererContainer diff --git a/binaryninjacore.h b/binaryninjacore.h index bd66661d..7f6b725f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -245,6 +245,8 @@ extern "C" NameSpaceSeparatorToken = 23, TagToken = 24, StructOffsetToken = 25, + StructOffsetByteValueToken = 26, + StructureHexDumpTextToken = 27, // The following are output by the analysis system automatically, these should // not be used directly by the architecture plugins CodeSymbolToken = 64, @@ -1906,14 +1908,20 @@ extern "C" void (*destructFunction)(void* ctxt, BNFunction* func); }; + struct BNTypeContext + { + BNType* type; + size_t offset; + }; + struct BNCustomDataRenderer { void* context; void (*freeObject)(void* ctxt); - bool (*isValidForData)(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, BNType** typeCtx, + bool (*isValidForData)(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, BNTypeContext** typeCtx, size_t ctxCount); BNDisassemblyTextLine* (*getLinesForData)(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, - const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNType** typeCtx, + const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNTypeContext** typeCtx, size_t ctxCount); }; @@ -3577,6 +3585,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); BINARYNINJACOREAPI BNStructureMember* BNGetStructureMemberByName(BNStructure* s, const char* name); + BINARYNINJACOREAPI BNStructureMember* BNGetStructureMemberAtOffset(BNStructure* s, int64_t offset); BINARYNINJACOREAPI void BNFreeStructureMember(BNStructureMember* s); BINARYNINJACOREAPI BNStructureMember* BNGetStructureMembers(BNStructure* s, size_t* count); BINARYNINJACOREAPI void BNFreeStructureMemberList(BNStructureMember* members, size_t count); @@ -3935,6 +3944,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNAddGraphReportToCollection(BNReportCollection* reports, BNBinaryView* view, const char* title, BNFlowGraph* graph); + BINARYNINJACOREAPI bool BNIsGNU3MangledString(const char* mangledName); BINARYNINJACOREAPI bool BNDemangleGNU3(BNArchitecture* arch, const char* mangledName, BNType** outType, @@ -4186,10 +4196,10 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNDataRenderer* BNCreateDataRenderer(BNCustomDataRenderer* renderer); BINARYNINJACOREAPI BNDataRenderer* BNNewDataRendererReference(BNDataRenderer* renderer); BINARYNINJACOREAPI bool BNIsValidForData(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, - BNType** typeCtx, size_t ctxCount); + BNTypeContext** typeCtx, size_t ctxCount); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetLinesForData(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, - BNType** typeCtx, size_t ctxCount); + BNTypeContext** typeCtx, size_t ctxCount); BINARYNINJACOREAPI void BNFreeDataRenderer(BNDataRenderer* renderer); BINARYNINJACOREAPI BNDataRendererContainer* BNGetDataRendererContainer(); BINARYNINJACOREAPI void BNRegisterGenericDataRenderer(BNDataRendererContainer* container, BNDataRenderer* renderer); diff --git a/datarenderer.cpp b/datarenderer.cpp index 4004b7d4..3d892987 100644 --- a/datarenderer.cpp +++ b/datarenderer.cpp @@ -22,38 +22,38 @@ DataRenderer::DataRenderer() } -bool DataRenderer::IsStructOfTypeName(Type* type, const QualifiedName& name, vector<Type*>& context) +bool DataRenderer::IsStructOfTypeName(Type* type, const QualifiedName& name, vector<pair<Type*, size_t>>& context) { return (type->GetClass() == StructureTypeClass) && (context.size() > 0) && - (context[0]->GetClass() == NamedTypeReferenceClass) && - (context[0]->GetNamedTypeReference()->GetName() == name); + (context[context.size() - 1].first->GetClass() == NamedTypeReferenceClass) && + (context[context.size() - 1].first->GetNamedTypeReference()->GetName() == name); } -bool DataRenderer::IsStructOfTypeName(Type* type, const string& name, vector<Type*>& context) +bool DataRenderer::IsStructOfTypeName(Type* type, const string& name, vector<pair<Type*, size_t>>& context) { return DataRenderer::IsStructOfTypeName(type, QualifiedName(name), context); } bool DataRenderer::IsValidForDataCallback(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, - BNType** typeCtx, size_t ctxCount) + BNTypeContext** typeCtx, size_t ctxCount) { DataRenderer* renderer = (DataRenderer*)ctxt; Ref<BinaryView> viewObj = new BinaryView(BNNewViewReference(view)); Ref<Type> typeObj = new Type(BNNewTypeReference(type)); - vector<Type*> context; + vector<pair<Type*, size_t>> context; context.reserve(ctxCount); for (size_t i = 0; i < ctxCount; i++) - context.push_back(new Type(BNNewTypeReference(typeCtx[i]))); + context.push_back({new Type(BNNewTypeReference(typeCtx[i]->type)), typeCtx[i]->offset}); return renderer->IsValidForData(viewObj, addr, typeObj, context); } BNDisassemblyTextLine* DataRenderer::GetLinesForDataCallback(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type, - const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNType** typeCtx, + const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count, BNTypeContext** typeCtx, size_t ctxCount) { DataRenderer* renderer = (DataRenderer*)ctxt; @@ -61,10 +61,10 @@ BNDisassemblyTextLine* DataRenderer::GetLinesForDataCallback(void* ctxt, BNBinar Ref<Type> typeObj = new Type(BNNewTypeReference(type)); vector<InstructionTextToken> prefixes = InstructionTextToken::ConvertInstructionTextTokenList(prefix, prefixCount); - vector<Type*> context; + vector<pair<Type*, size_t>> context; context.reserve(ctxCount); for (size_t i = 0; i < ctxCount; i++) - context.push_back(new Type(BNNewTypeReference(typeCtx[i]))); + context.push_back({new Type(BNNewTypeReference(typeCtx[i]->type)), typeCtx[i]->offset}); auto lines = renderer->GetLinesForData(viewObj, addr, typeObj, prefixes, width, context); *count = lines.size(); BNDisassemblyTextLine* buf = new BNDisassemblyTextLine[lines.size()]; @@ -89,11 +89,14 @@ void DataRenderer::FreeCallback(void* ctxt) } -bool DataRenderer::IsValidForData(BinaryView* data, uint64_t addr, Type* type, vector<Type*>& context) +bool DataRenderer::IsValidForData(BinaryView* data, uint64_t addr, Type* type, vector<pair<Type*, size_t>>& context) { - BNType** typeCtx = new BNType*[context.size()]; + BNTypeContext** typeCtx = new BNTypeContext*[context.size()]; for (size_t i = 0; i < context.size(); i++) - typeCtx[i] = context[i]->GetObject(); + { + typeCtx[i]->type = context[i].first->GetObject(); + typeCtx[i]->offset = context[i].second; + } bool result = BNIsValidForData(m_object, data->GetObject(), addr, type->GetObject(), typeCtx, context.size()); delete[] typeCtx; return result; @@ -101,13 +104,15 @@ bool DataRenderer::IsValidForData(BinaryView* data, uint64_t addr, Type* type, v vector<DisassemblyTextLine> DataRenderer::GetLinesForData(BinaryView* data, uint64_t addr, Type* type, - const std::vector<InstructionTextToken>& prefix, size_t width, vector<Type*>& context) + const std::vector<InstructionTextToken>& prefix, size_t width, vector<pair<Type*, size_t>>& context) { BNInstructionTextToken* prefixes = InstructionTextToken::CreateInstructionTextTokenList(prefix); - BNType** typeCtx = new BNType*[context.size()]; + BNTypeContext** typeCtx = new BNTypeContext*[context.size()]; for (size_t i = 0; i < context.size(); i++) - typeCtx[i] = context[i]->GetObject(); - + { + typeCtx[i]->type = context[i].first->GetObject(); + typeCtx[i]->offset = context[i].second; + } size_t count = 0; BNDisassemblyTextLine* lines = BNGetLinesForData(m_object, data->GetObject(), addr, type->GetObject(), prefixes, prefix.size(), width, &count, typeCtx, context.size()); diff --git a/python/datarender.py b/python/datarender.py index 0aaa81a7..4b81b1dd 100644 --- a/python/datarender.py +++ b/python/datarender.py @@ -79,8 +79,8 @@ class DataRenderer(object): @classmethod def is_type_of_struct_name(cls, type, name, context): return (type.type_class == enums.TypeClass.StructureTypeClass and len(context) > 0 - and context[0].type_class == enums.TypeClass.NamedTypeReferenceClass and - context[0].named_type_reference.name == name) + and context[-1].type_class == enums.TypeClass.NamedTypeReferenceClass and + context[-1].named_type_reference.name == name) def register_type_specific(self): core.BNRegisterTypeSpecificDataRenderer(core.BNGetDataRendererContainer(), self.handle) diff --git a/python/types.py b/python/types.py index db56a19c..ed4360d6 100644 --- a/python/types.py +++ b/python/types.py @@ -1083,6 +1083,14 @@ class Structure(object): finally: core.BNFreeStructureMember(member) + def member_at_offset(self, offset): + try: + member = core.BNGetStructureMemberAtOffset(self.handle, offset) + return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence), + member.contents.name, member.contents.offset) + finally: + core.BNFreeStructureMember(member) + @property def members(self): """Structure member list (read-only)""" diff --git a/suite/api_test.py b/suite/api_test.py index bd94f5e1..90ba6c7d 100644 --- a/suite/api_test.py +++ b/suite/api_test.py @@ -414,7 +414,7 @@ class DemanglerTest(unittest.TestCase): "int32_t QList<QAbstractState*>::end()", "int32_t BinaryNinjaCore::ArchitectureWrapper::GetOpcodeDisplayLength() const", "int32_t BinaryNinjaCore::ScriptingInstance::SetCurrentSelection(uint64_t, uint64_t)", - "qt_meta_stringdata_QHistoryState", + "qt_meta_stringdata_QHistoryState _qt_meta_stringdata_QHistoryState", "int32_t (anonymous namespace)::TypeDestructor::DestructorImpl<QStringList, true>::Destruct(int32_t, void*)", "int32_t QGb18030Codec::_name()", "int32_t QList<QObject*>::detach()", @@ -428,4 +428,4 @@ class DemanglerTest(unittest.TestCase): for i, test in enumerate(tests): t, n = demangle_gnu3(Architecture['x86'], test) - assert self.get_type_string(t, n) == results[i] + self.get_type_string(t, n) == results[i] @@ -489,12 +489,6 @@ Confidence<bool> Type::IsConst() const } -bool Type::IsFloat() const -{ - return BNIsTypeFloatingPoint(m_object); -} - - Confidence<BNMemberScope> Type::GetScope() const { BNMemberScopeWithConfidence result = BNTypeGetMemberScope(m_object); @@ -934,6 +928,12 @@ string Type::GetAutoDebugTypeIdSource() } +bool Type::IsReferenceOfType(BNNamedTypeReferenceClass refType) +{ + return (GetClass() == NamedTypeReferenceClass) && (GetNamedTypeReference()->GetTypeClass() == refType); +} + + QualifiedName Type::GetTypeName() const { BNQualifiedName name = BNTypeGetTypeName(m_object); @@ -1111,6 +1111,21 @@ bool Structure::GetMemberByName(const string& name, StructureMember& result) con } +bool Structure::GetMemberAtOffset(int64_t offset, StructureMember& result) const +{ + BNStructureMember* member = BNGetStructureMemberAtOffset(m_object, offset); + if (member) + { + result.type = new Type(BNNewTypeReference(member->type)); + result.name = member->name; + result.offset = member->offset; + BNFreeStructureMember(member); + return true; + } + return false; +} + + uint64_t Structure::GetWidth() const { return BNGetStructureWidth(m_object); diff --git a/ui/commands.h b/ui/commands.h index f95664f1..0a591437 100644 --- a/ui/commands.h +++ b/ui/commands.h @@ -18,7 +18,7 @@ bool BINARYNINJAUIAPI askForNewType(QWidget* parent, BinaryViewRef data, Functio TypeRef& type, BinaryNinja::QualifiedName& name); bool BINARYNINJAUIAPI inputNewType(QWidget* parent, BinaryViewRef data, FunctionRef currentFunction, uint64_t currentAddr, HighlightTokenState& highlight); -bool BINARYNINJAUIAPI createInferredMember(BinaryViewRef data, HighlightTokenState& highlight); +bool BINARYNINJAUIAPI createInferredMember(QWidget* parent, BinaryViewRef data, HighlightTokenState& highlight, FunctionRef func); bool BINARYNINJAUIAPI overwriteCode(BinaryViewRef data, ArchitectureRef arch, uint64_t addr, size_t len, const BinaryNinja::DataBuffer& buffer); @@ -29,3 +29,6 @@ StructureRef BINARYNINJAUIAPI getInnerMostStructureContaining(BinaryViewRef data size_t& memberIndex, const std::vector<std::string>& nameList, size_t nameIndex, TypeRef& type, std::string& typeName); StructureRef BINARYNINJAUIAPI getInnerMostStructureContainingOffset(BinaryViewRef data, StructureRef structure, const std::vector<std::string>& nameList, size_t nameIndex, size_t& offset, TypeRef& type, std::string& typeName); + +// Auto generate a structure name +std::string BINARYNINJAUIAPI createStructureName(BinaryViewRef data);
\ No newline at end of file diff --git a/ui/createstructdialog.h b/ui/createstructdialog.h index df117411..096adefb 100644 --- a/ui/createstructdialog.h +++ b/ui/createstructdialog.h @@ -16,7 +16,7 @@ class BINARYNINJAUIAPI CreateStructDialog: public QDialog uint64_t m_resultSize; public: - CreateStructDialog(QWidget* parent); + CreateStructDialog(QWidget* parent, const std::string& name); BinaryNinja::QualifiedName getName() { return m_resultName; } uint64_t getSize() { return m_resultSize; } diff --git a/ui/createtypedialog.h b/ui/createtypedialog.h index 1d0effe3..552f2076 100644 --- a/ui/createtypedialog.h +++ b/ui/createtypedialog.h @@ -16,7 +16,7 @@ class BINARYNINJAUIAPI CreateTypeDialog: public QDialog std::map<BinaryNinja::QualifiedName, TypeRef> m_results; public: - CreateTypeDialog(QWidget* parent, BinaryViewRef data, const QString& definition); + CreateTypeDialog(QWidget* parent, BinaryViewRef data, const QString& title, const QString& definition); std::map<BinaryNinja::QualifiedName, TypeRef> getResults() { return m_results; } private Q_SLOTS: diff --git a/ui/linearview.h b/ui/linearview.h index b30e127c..53e8802c 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -127,6 +127,18 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ bool isLineValidHighlight(const BinaryNinja::LinearDisassemblyLine& line); void ensureLineVisible(size_t line); + TypeRef createStructure(BinaryNinja::QualifiedName& name, uint64_t size); + StructureRef defineInnerType(TypeRef type, TypeRef baseType, uint64_t offset, uint64_t size); + StructureRef defineInnerPointer(TypeRef type, ArchitectureRef arch, uint64_t baseAddress, uint64_t offset, uint64_t size); + StructureRef defineInnerStruct(TypeRef type, uint64_t offset, uint64_t size); + StructureRef defineInnerArray(TypeRef type, uint64_t offset, uint64_t size); + StructureRef defineInnerName(TypeRef type, uint64_t offset, uint64_t size); + StructureRef defineInnerUnknownType(QWidget* parent, TypeRef type, uint64_t offset, uint64_t size); + StructureRef defineInnerIntegerSize(TypeRef type, uint64_t offset, uint64_t size); + StructureRef defineInnerSign(TypeRef type, uint64_t offset, uint64_t size); + TypeRef getPointerTypeAndName(ArchitectureRef arch, uint64_t addr, std::string& name); + std::string getVariableName(uint64_t addr); + private Q_SLOTS: void viewInHexEditor(); void viewInGraph(); @@ -155,15 +167,21 @@ private Q_SLOTS: void skipAndReturnZero(); void skipAndReturnValue(); + void makeTypes(TypeRef type); void makeInt8(); void makeInt16(); void makeInt32(); void makeInt64(); void toggleIntSize(); + void toggleIntSign(); void makePtr(); void makeString(); void changeType(); - void inferStructureType(); + void createStructOrinferStructureType(); + void createArray(); + void createStruct(); + void createNewTypes(); + size_t getStringLength(uint64_t startAddr); void displayAsDefault(); |
