diff options
| -rw-r--r-- | binaryninjaapi.h | 35 | ||||
| -rw-r--r-- | binaryninjacore.h | 6 | ||||
| -rw-r--r-- | python/typeprinter.py | 53 | ||||
| -rw-r--r-- | typeprinter.cpp | 93 |
4 files changed, 187 insertions, 0 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8cb0a7b2..c59b554a 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -11766,6 +11766,8 @@ namespace BinaryNinja { static bool GetTypeLinesCallback(void* ctxt, BNType* type, BNBinaryView* data, BNQualifiedName* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); + static bool PrintAllTypesCallback(void* ctxt, BNQualifiedName* names, BNType** types, size_t typeCount, + BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); static void FreeTokensCallback(void* ctxt, BNInstructionTextToken* tokens, size_t count); static void FreeStringCallback(void* ctxt, char* string); static void FreeLinesCallback(void* ctxt, BNTypeDefinitionLine* lines, size_t count); @@ -11890,6 +11892,37 @@ namespace BinaryNinja { bool collapsed = false, BNTokenEscapingType escaping = NoTokenEscapingType ) = 0; + + /*! + Print all types to a single big string, including headers, sections, etc + \param types All types to print + \param data Binary View in which all the types are defined + \param lineWidth Maximum width of lines, in characters + \param escaping Style of escaping literals which may not be parsable + \return All the types in a string + */ + virtual std::string PrintAllTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, + int lineWidth = 80, + BNTokenEscapingType escaping = NoTokenEscapingType + ); + + /*! + Default implementation of PrintAllTypes + Print all types to a single big string, including headers, sections, etc + \param types All types to print + \param data Binary View in which all the types are defined + \param lineWidth Maximum width of lines, in characters + \param escaping Style of escaping literals which may not be parsable + \return All the types in a string + */ + std::string DefaultPrintAllTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, + int lineWidth = 80, + BNTokenEscapingType escaping = NoTokenEscapingType + ); }; /*! @@ -11919,6 +11952,8 @@ namespace BinaryNinja { virtual std::vector<TypeDefinitionLine> GetTypeLines(Ref<Type> type, Ref<BinaryView> data, const QualifiedName& name, int lineWidth, bool collapsed, BNTokenEscapingType escaping) override; + virtual std::string PrintAllTypes(const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, int lineWidth, BNTokenEscapingType escaping) override; }; // DownloadProvider diff --git a/binaryninjacore.h b/binaryninjacore.h index b17af806..876ec84e 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2572,6 +2572,8 @@ extern "C" bool (*getTypeLines)(void* ctxt, BNType* type, BNBinaryView* data, BNQualifiedName* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); + bool (*printAllTypes)(void* ctxt, BNQualifiedName* names, BNType** types, size_t typeCount, + BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); void (*freeTokens)(void* ctxt, BNInstructionTextToken* tokens, size_t count); void (*freeString)(void* ctxt, char* string); void (*freeLines)(void* ctxt, BNTypeDefinitionLine* lines, size_t count); @@ -5550,6 +5552,10 @@ extern "C" BNType* type, BNBinaryView* data, BNQualifiedName* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); + BINARYNINJACOREAPI bool BNTypePrinterPrintAllTypes(BNTypePrinter* printer, BNQualifiedName* names, BNType** types, + size_t typeCount, BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); + BINARYNINJACOREAPI bool BNTypePrinterDefaultPrintAllTypes(BNTypePrinter* printer, BNQualifiedName* names, BNType** types, + size_t typeCount, BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); BINARYNINJACOREAPI void BNFreeTypeParserResult(BNTypeParserResult* result); BINARYNINJACOREAPI void BNFreeTypeParserErrors(BNTypeParserError* errors, size_t count); diff --git a/python/typeprinter.py b/python/typeprinter.py index 354084dd..993ac5d0 100644 --- a/python/typeprinter.py +++ b/python/typeprinter.py @@ -96,6 +96,7 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): self._cb.getTypeStringBeforeName = self._cb.getTypeStringBeforeName.__class__(self._get_type_string_before_name) self._cb.getTypeStringAfterName = self._cb.getTypeStringAfterName.__class__(self._get_type_string_after_name) self._cb.getTypeLines = self._cb.getTypeLines.__class__(self._get_type_lines) + self._cb.printAllTypes = self._cb.printAllTypes.__class__(self._print_all_types) self._cb.freeTokens = self._cb.freeTokens.__class__(self._free_tokens) self._cb.freeString = self._cb.freeString.__class__(self._free_string) self._cb.freeLines = self._cb.freeLines.__class__(self._free_lines) @@ -235,6 +236,27 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): log_error(traceback.format_exc()) return False + def _print_all_types(self, ctxt, names, types_, type_count, data, line_width, escaping, result): + try: + types_py = [] + for i in range(type_count): + types_py.append(( + types.QualifiedName._from_core_struct(names[i]), + types.Type(handle=core.BNNewTypeReference(types_[i])) + )) + + result_py = self.print_all_types( + types_py, + binaryview.BinaryView(handle=core.BNNewViewReference(data)), + line_width, escaping) + + TypePrinter._cached_string = core.cstr(result_py) + result[0] = TypePrinter._cached_string + return True + except: + log_error(traceback.format_exc()) + return False + def _free_tokens(self, ctxt, tokens, count): try: TypePrinter._cached_tokens = None @@ -262,6 +284,20 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): log_error(traceback.format_exc()) return False + def _default_print_all_types(self, types_: List[Tuple[types.QualifiedNameType, types.Type]], data: binaryview.BinaryView, line_width = 80, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> str: + cpp_names = (core.BNQualifiedName * len(types_))() + cpp_types = (ctypes.POINTER(core.BNType) * len(types_))() + + i = 0 + for (name, type) in types_: + cpp_names[i] = types.QualifiedName(name)._to_core_struct() + cpp_types[i] = type.handle + i += 1 + + result = ctypes.c_char_p() + core.BNTypePrinterDefaultPrintAllTypes(self.handle, cpp_names, cpp_types, len(types_), data.handle, line_width, ctypes.c_int(escaping), result) + return core.pyNativeStr(result.value) + def get_type_tokens(self, type: types.Type, platform: Optional[_platform.Platform] = None, name: types.QualifiedNameType = "", base_confidence: int = core.max_confidence, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> List[_function.InstructionTextToken]: raise NotImplementedError() @@ -283,6 +319,9 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): def get_type_lines(self, type: types.Type, data: binaryview.BinaryView, name: types.QualifiedNameType, line_width = 80, collapsed = False, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> List[types.TypeDefinitionLine]: raise NotImplementedError() + def print_all_types(self, types: List[Tuple[types.QualifiedNameType, types.Type]], data: binaryview.BinaryView, line_width = 80, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> str: + return self._default_print_all_types(types, data, line_width, escaping) + class CoreTypePrinter(TypePrinter): @@ -388,3 +427,17 @@ class CoreTypePrinter(TypePrinter): lines.append(line) core.BNFreeTypeDefinitionLineList(core_lines, count.value) return lines + + def print_all_types(self, types_: List[Tuple[types.QualifiedNameType, types.Type]], data: binaryview.BinaryView, line_width = 80, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> str: + cpp_names = (core.BNQualifiedName * len(types_))() + cpp_types = (ctypes.POINTER(core.BNType) * len(types_))() + + i = 0 + for (name, type) in types_: + cpp_names[i] = types.QualifiedName(name)._to_core_struct() + cpp_types[i] = type.handle + i += 1 + + result = ctypes.c_char_p() + core.BNTypePrinterPrintAllTypes(self.handle, cpp_names, cpp_types, len(types_), data.handle, line_width, ctypes.c_int(escaping), result) + return core.pyNativeStr(result.value) diff --git a/typeprinter.cpp b/typeprinter.cpp index aed010b2..3242f323 100644 --- a/typeprinter.cpp +++ b/typeprinter.cpp @@ -116,6 +116,22 @@ bool TypePrinter::GetTypeLinesCallback(void* ctxt, BNType* type, BNBinaryView* d } +bool TypePrinter::PrintAllTypesCallback(void* ctxt, BNQualifiedName* names, BNType** types, size_t typeCount, + BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result) +{ + TypePrinter* printer = (TypePrinter*)ctxt; + vector<pair<QualifiedName, Ref<Type>>> apiTypes; + for (size_t i = 0; i < typeCount; ++i) + { + apiTypes.push_back({QualifiedName::FromAPIObject(&names[i]), new Type(types[i])}); + } + + string resultStr = printer->PrintAllTypes(apiTypes, new BinaryView(data), lineWidth, escaping); + *result = BNAllocString(resultStr.c_str()); + return true; +} + + void TypePrinter::FreeTokensCallback(void* ctxt, BNInstructionTextToken* tokens, size_t count) { InstructionTextToken::FreeInstructionTextTokenList(tokens, count); @@ -246,6 +262,50 @@ std::string TypePrinter::GetTypeStringAfterName( } +std::string TypePrinter::PrintAllTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, + int lineWidth, + BNTokenEscapingType escaping +) +{ + return DefaultPrintAllTypes(types, data, lineWidth, escaping); +} + + +std::string TypePrinter::DefaultPrintAllTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, + int lineWidth, + BNTokenEscapingType escaping +) +{ + BNQualifiedName* apiNames = new BNQualifiedName[types.size()]; + BNType** apiTypes = new BNType*[types.size()]; + + for (size_t i = 0; i < types.size(); i ++) + { + apiNames[i] = types[i].first.GetAPIObject(); + apiTypes[i] = types[i].second->GetObject(); + } + + char* resultStr; + BNTypePrinterDefaultPrintAllTypes(m_object, apiNames, apiTypes, types.size(), data->GetObject(), + lineWidth, escaping, &resultStr); + + for (size_t i = 0; i < types.size(); i ++) + { + QualifiedName::FreeAPIObject(&apiNames[i]); + } + delete[] apiTypes; + delete[] apiNames; + + std::string result = resultStr; + BNFreeString(resultStr); + return result; +} + + CoreTypePrinter::CoreTypePrinter(BNTypePrinter* printer): TypePrinter(printer) { @@ -398,3 +458,36 @@ std::vector<TypeDefinitionLine> CoreTypePrinter::GetTypeLines(Ref<Type> type, return cppLines; } + + +std::string CoreTypePrinter::PrintAllTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + Ref<BinaryView> data, + int lineWidth, + BNTokenEscapingType escaping +) +{ + BNQualifiedName* apiNames = new BNQualifiedName[types.size()]; + BNType** apiTypes = new BNType*[types.size()]; + + for (size_t i = 0; i < types.size(); i ++) + { + apiNames[i] = types[i].first.GetAPIObject(); + apiTypes[i] = types[i].second->GetObject(); + } + + char* resultStr; + BNTypePrinterPrintAllTypes(m_object, apiNames, apiTypes, types.size(), data->GetObject(), + lineWidth, escaping, &resultStr); + + for (size_t i = 0; i < types.size(); i ++) + { + QualifiedName::FreeAPIObject(&apiNames[i]); + } + delete[] apiTypes; + delete[] apiNames; + + std::string result = resultStr; + BNFreeString(resultStr); + return result; +} |
