diff options
| -rw-r--r-- | binaryninjaapi.h | 45 | ||||
| -rw-r--r-- | binaryninjacore.h | 37 | ||||
| -rw-r--r-- | platform.cpp | 145 | ||||
| -rw-r--r-- | platform/windows/platform_windows.cpp | 80 | ||||
| -rw-r--r-- | python/platform.py | 102 | ||||
| -rw-r--r-- | typeparser.cpp | 6 |
6 files changed, 414 insertions, 1 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 114b6e85..bb243e52 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -14518,6 +14518,28 @@ namespace BinaryNinja { static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count); static void FreeRegisterListCallback(void* ctxt, uint32_t* regs, size_t count); static BNType* GetGlobalRegisterTypeCallback(void* ctxt, uint32_t reg); + static void AdjustTypeParserInputCallback( + void* ctxt, + BNTypeParser* parser, + const char* const* argumentsIn, + size_t argumentsLenIn, + const char* const* sourceFileNamesIn, + const char* const* sourceFileValuesIn, + size_t sourceFilesLenIn, + char*** argumentsOut, + size_t* argumentsLenOut, + char*** sourceFileNamesOut, + char*** sourceFileValuesOut, + size_t* sourceFilesLenOut + ); + static void FreeTypeParserInputCallback( + void* ctxt, + char** arguments, + size_t argumentsLen, + char** sourceFileNames, + char** sourceFileValues, + size_t sourceFilesLen + ); public: Platform(BNPlatform* platform); @@ -14678,6 +14700,18 @@ namespace BinaryNinja { */ virtual Ref<Type> GetGlobalRegisterType(uint32_t reg); + /*! Modify the input passed to the Type Parser with Platform-specific features. + + \param[in] parser Type Parser instance + \param[in,out] arguments Arguments to the type parser + \param[in,out] sourceFiles Source file names and contents + */ + virtual void AdjustTypeParserInput( + Ref<class TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ); + Ref<Platform> GetRelatedPlatform(Architecture* arch); void AddRelatedPlatform(Architecture* arch, Platform* platform); Ref<Platform> GetAssociatedPlatformByAddress(uint64_t& addr); @@ -14776,6 +14810,11 @@ namespace BinaryNinja { virtual std::vector<uint32_t> GetGlobalRegisters() override; virtual Ref<Type> GetGlobalRegisterType(uint32_t reg) override; + virtual void AdjustTypeParserInput( + Ref<class TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ) override; }; /*! @@ -14834,6 +14873,12 @@ namespace BinaryNinja { */ static std::string FormatParseErrors(const std::vector<TypeParserError>& errors); + /*! + Get the Type Parser's registered name + \return Parser name + */ + std::string GetName() const; + /** Get the string representation of an option for passing to ParseTypes* \param option Option type diff --git a/binaryninjacore.h b/binaryninjacore.h index a7b968e6..77471530 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1882,6 +1882,29 @@ extern "C" void (*freeRegisterList)(void* ctxt, uint32_t* regs, size_t len); BNType* (*getGlobalRegisterType)(void* ctxt, uint32_t reg); + + void (*adjustTypeParserInput)( + void* ctxt, + BNTypeParser* parser, + const char* const* argumentsIn, + size_t argumentsLenIn, + const char* const* sourceFileNamesIn, + const char* const* sourceFileValuesIn, + size_t sourceFilesLenIn, + char*** argumentsOut, + size_t* argumentsLenOut, + char*** sourceFileNamesOut, + char*** sourceFileValuesOut, + size_t* sourceFilesLenOut + ); + void (*freeTypeParserInput)( + void* ctxt, + char** arguments, + size_t argumentsLen, + char** sourceFileNames, + char** sourceFileValues, + size_t sourceFilesLen + ); } BNCustomPlatform; typedef struct BNBasicBlockEdge @@ -6408,6 +6431,20 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetPlatformGlobalRegisters(BNPlatform* platform, size_t* count); BINARYNINJACOREAPI BNType* BNGetPlatformGlobalRegisterType(BNPlatform* platform, uint32_t reg); + BINARYNINJACOREAPI void BNPlatformAdjustTypeParserInput( + BNPlatform* platform, + BNTypeParser* parser, + const char* const* argumentsIn, + size_t argumentsLenIn, + const char* const* sourceFileNamesIn, + const char* const* sourceFileValuesIn, + size_t sourceFilesLenIn, + char*** argumentsOut, + size_t* argumentsLenOut, + char*** sourceFileNamesOut, + char*** sourceFileValuesOut, + size_t* sourceFilesLenOut + ); BINARYNINJACOREAPI BNPlatform* BNGetArchitectureStandalonePlatform(BNArchitecture* arch); diff --git a/platform.cpp b/platform.cpp index f123b76d..ec27b710 100644 --- a/platform.cpp +++ b/platform.cpp @@ -42,6 +42,8 @@ Platform::Platform(Architecture* arch, const string& name) plat.getGlobalRegisters = GetGlobalRegistersCallback; plat.freeRegisterList = FreeRegisterListCallback; plat.getGlobalRegisterType = GetGlobalRegisterTypeCallback; + plat.adjustTypeParserInput = AdjustTypeParserInputCallback; + plat.freeTypeParserInput = FreeTypeParserInputCallback; m_object = BNCreateCustomPlatform(arch->GetObject(), name.c_str(), &plat); AddRefForRegistration(); } @@ -56,6 +58,8 @@ Platform::Platform(Architecture* arch, const string& name, const string& typeFil plat.getGlobalRegisters = GetGlobalRegistersCallback; plat.freeRegisterList = FreeRegisterListCallback; plat.getGlobalRegisterType = GetGlobalRegisterTypeCallback; + plat.adjustTypeParserInput = AdjustTypeParserInputCallback; + plat.freeTypeParserInput = FreeTypeParserInputCallback; const char** includeDirList = new const char*[includeDirs.size()]; for (size_t i = 0; i < includeDirs.size(); i++) includeDirList[i] = includeDirs[i].c_str(); @@ -97,6 +101,78 @@ uint32_t* Platform::GetGlobalRegistersCallback(void* ctxt, size_t* count) } +void Platform::AdjustTypeParserInputCallback( + void* ctxt, + BNTypeParser* parser, + const char* const* argumentsIn, + size_t argumentsLenIn, + const char* const* sourceFileNamesIn, + const char* const* sourceFileValuesIn, + size_t sourceFilesLenIn, + char*** argumentsOut, + size_t* argumentsLenOut, + char*** sourceFileNamesOut, + char*** sourceFileValuesOut, + size_t* sourceFilesLenOut +) +{ + CallbackRef<Platform> plat(ctxt); + Ref<TypeParser> parserCpp = new CoreTypeParser(parser); + + vector<string> arguments; + for (size_t i = 0; i < argumentsLenIn; i ++) + { + arguments.push_back(argumentsIn[i]); + } + vector<pair<string, string>> sourceFiles; + for (size_t i = 0; i < sourceFilesLenIn; i ++) + { + sourceFiles.push_back(make_pair(sourceFileNamesIn[i], sourceFileValuesIn[i])); + } + + plat->AdjustTypeParserInput( + parserCpp, + arguments, + sourceFiles + ); + + vector<const char*> argumentsPtrs; + for (auto& argument : arguments) + { + argumentsPtrs.push_back(argument.c_str()); + } + *argumentsOut = BNAllocStringList(argumentsPtrs.data(), argumentsPtrs.size()); + *argumentsLenOut = arguments.size(); + + vector<const char*> sourceFileNamesPtrs; + vector<const char*> sourceFileValuesPtrs; + for (auto& [sourceFileName, sourceFileValue] : sourceFiles) + { + sourceFileNamesPtrs.push_back(sourceFileName.c_str()); + sourceFileValuesPtrs.push_back(sourceFileValue.c_str()); + } + *sourceFileNamesOut = BNAllocStringList(sourceFileNamesPtrs.data(), sourceFileNamesPtrs.size()); + *sourceFileValuesOut = BNAllocStringList(sourceFileValuesPtrs.data(), sourceFileValuesPtrs.size()); + *sourceFilesLenOut = sourceFiles.size(); +} + + +void Platform::FreeTypeParserInputCallback( + void* ctxt, + char** arguments, + size_t argumentsLen, + char** sourceFileNames, + char** sourceFileValues, + size_t sourceFilesLen +) +{ + (void)ctxt; + BNFreeStringList(arguments, argumentsLen); + BNFreeStringList(sourceFileNames, sourceFilesLen); + BNFreeStringList(sourceFileValues, sourceFilesLen); +} + + void Platform::FreeRegisterListCallback(void*, uint32_t* regs, size_t) { delete[] regs; @@ -358,6 +434,75 @@ Ref<Type> CorePlatform::GetGlobalRegisterType(uint32_t reg) } +void Platform::AdjustTypeParserInput( + Ref<TypeParser> parser, + vector<string>& arguments, + vector<pair<string, string>>& sourceFiles +) +{ + (void)parser; + (void)arguments; + (void)sourceFiles; +} + + +void CorePlatform::AdjustTypeParserInput( + Ref<TypeParser> parser, + vector<string>& arguments, + vector<pair<string, string>>& sourceFiles +) +{ + vector<const char*> argumentsIn; + for (size_t i = 0; i < arguments.size(); i ++) + { + argumentsIn.push_back(arguments[i].c_str()); + } + vector<const char*> sourceFileNamesIn; + vector<const char*> sourceFileValuesIn; + for (size_t i = 0; i < sourceFiles.size(); i ++) + { + sourceFileNamesIn.push_back(sourceFiles[i].first.c_str()); + sourceFileValuesIn.push_back(sourceFiles[i].second.c_str()); + } + + char** argumentsOut; + size_t argumentsLenOut; + char** sourceFileNamesOut; + char** sourceFileValuesOut; + size_t sourceFilesLenOut; + + BNPlatformAdjustTypeParserInput( + m_object, + parser->m_object, + argumentsIn.data(), + argumentsIn.size(), + sourceFileNamesIn.data(), + sourceFileValuesIn.data(), + sourceFileNamesIn.size(), + &argumentsOut, + &argumentsLenOut, + &sourceFileNamesOut, + &sourceFileValuesOut, + &sourceFilesLenOut + ); + + arguments.clear(); + for (size_t i = 0; i < argumentsLenOut; i ++) + { + arguments.push_back(argumentsOut[i]); + } + sourceFiles.clear(); + for (size_t i = 0; i < sourceFilesLenOut; i ++) + { + sourceFiles.push_back(make_pair(sourceFileNamesOut[i], sourceFileValuesOut[i])); + } + + BNFreeStringList(argumentsOut, argumentsLenOut); + BNFreeStringList(sourceFileNamesOut, sourceFilesLenOut); + BNFreeStringList(sourceFileValuesOut, sourceFilesLenOut); +} + + Ref<Platform> Platform::GetRelatedPlatform(Architecture* arch) { BNPlatform* platform = BNGetRelatedPlatform(m_object, arch->GetObject()); diff --git a/platform/windows/platform_windows.cpp b/platform/windows/platform_windows.cpp index cb256660..f104215d 100644 --- a/platform/windows/platform_windows.cpp +++ b/platform/windows/platform_windows.cpp @@ -57,6 +57,26 @@ public: return nullptr; } + + virtual void AdjustTypeParserInput( + Ref<TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ) override + { + if (parser->GetName() != "ClangTypeParser") + { + return; + } + + for (auto& arg: arguments) + { + if (arg.find("--target=") == 0 && arg.find("-unknown-") != std::string::npos) + { + arg = "--target=i386-pc-windows-msvc"; + } + } + } }; @@ -97,6 +117,26 @@ public: return nullptr; } + + virtual void AdjustTypeParserInput( + Ref<TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ) override + { + if (parser->GetName() != "ClangTypeParser") + { + return; + } + + for (auto& arg: arguments) + { + if (arg.find("--target=") == 0 && arg.find("-unknown-") != std::string::npos) + { + arg = "--target=x86_64-pc-windows-msvc"; + } + } + } }; @@ -116,6 +156,26 @@ public: RegisterStdcallCallingConvention(cc); } } + + virtual void AdjustTypeParserInput( + Ref<TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ) override + { + if (parser->GetName() != "ClangTypeParser") + { + return; + } + + for (auto& arg: arguments) + { + if (arg.find("--target=") == 0 && arg.find("-unknown-") != std::string::npos) + { + arg = "--target=armv7-pc-windows-msvc"; + } + } + } }; @@ -142,6 +202,26 @@ public: SetSystemCallConvention(cc); } } + + virtual void AdjustTypeParserInput( + Ref<TypeParser> parser, + std::vector<std::string>& arguments, + std::vector<std::pair<std::string, std::string>>& sourceFiles + ) override + { + if (parser->GetName() != "ClangTypeParser") + { + return; + } + + for (auto& arg: arguments) + { + if (arg.find("--target=") == 0 && arg.find("-unknown-") != std::string::npos) + { + arg = "--target=aarch64-pc-windows-msvc"; + } + } + } }; diff --git a/python/platform.py b/python/platform.py index 0fd54e52..c0a5ce65 100644 --- a/python/platform.py +++ b/python/platform.py @@ -21,7 +21,7 @@ import os import ctypes import traceback -from typing import List, Dict, Optional +from typing import List, Dict, Optional, Tuple # Binary Ninja components import binaryninja @@ -84,7 +84,10 @@ class Platform(metaclass=_PlatformMetaClass): self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_regs) self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) self._cb.getGlobalRegisterType = self._cb.getGlobalRegisterType.__class__(self._get_global_reg_type) + self._cb.adjustTypeParserInput = self._cb.adjustTypeParserInput.__class__(self._adjust_type_parser_input) + self._cb.freeTypeParserInput = self._cb.freeTypeParserInput.__class__(self._free_type_parser_input) self._pending_reg_lists = {} + self._pending_parser_input_lists = {} if self.__class__.type_file_path is None: _handle = core.BNCreateCustomPlatform(arch.handle, self.__class__.name, self._cb) assert _handle is not None @@ -161,6 +164,103 @@ class Platform(metaclass=_PlatformMetaClass): log_error(traceback.format_exc()) return None + def _adjust_type_parser_input( + self, + ctxt, + parser, + arguments_in, + arguments_len_in, + source_file_names_in, + source_file_values_in, + source_files_len_in, + arguments_out, + arguments_len_out, + source_file_names_out, + source_file_values_out, + source_files_len_out + ): + try: + parser_py = typeparser.TypeParser(handle=parser) + + arguments = [] + for i in range(arguments_len_in): + arguments.append(core.pyNativeStr(arguments_in[i])) + + source_files = [] + for i in range(source_files_len_in): + source_files.append((core.pyNativeStr(source_file_names_in[i]), core.pyNativeStr(source_file_values_in[i]))) + + arguments, source_files = self.adjust_type_parser_input(parser_py, arguments, source_files) + + arguments_len_out[0] = len(arguments) + arguments_buf = (ctypes.c_char_p * len(arguments))() + for i, r in enumerate(arguments): + arguments_buf[i] = core.cstr(r) + arguments_ptr = ctypes.cast(arguments_buf, ctypes.c_void_p) + arguments_out[0] = arguments_buf + self._pending_parser_input_lists[arguments_ptr.value] = (arguments_ptr.value, arguments_buf) + + source_files_len_out[0] = len(source_files) + source_file_names_buf = (ctypes.c_char_p * len(source_files))() + source_file_values_buf = (ctypes.c_char_p * len(source_files))() + for i, (name, value) in enumerate(source_files): + source_file_names_buf[i] = core.cstr(name) + source_file_values_buf[i] = core.cstr(value) + source_file_names_ptr = ctypes.cast(source_file_names_buf, ctypes.c_void_p) + source_file_names_out[0] = source_file_names_buf + source_file_values_ptr = ctypes.cast(source_file_values_buf, ctypes.c_void_p) + source_file_values_out[0] = source_file_values_buf + self._pending_parser_input_lists[source_file_names_ptr.value] = (source_file_names_ptr.value, source_file_names_buf) + self._pending_parser_input_lists[source_file_values_ptr.value] = (source_file_values_ptr.value, source_file_values_buf) + + except: + arguments_len_out[0] = 0 + source_files_len_out[0] = 0 + traceback.print_exc() + + def _free_type_parser_input( + self, + ctxt, + arguments, + arguments_len, + source_file_names, + source_file_values, + source_files_len + ): + try: + buf = ctypes.cast(arguments, ctypes.c_void_p) + if buf.value not in self._pending_parser_input_lists: + raise ValueError("freeing arguments list that wasn't allocated") + del self._pending_parser_input_lists[buf.value] + + buf = ctypes.cast(source_file_names, ctypes.c_void_p) + if buf.value not in self._pending_parser_input_lists: + raise ValueError("freeing source_file_names list that wasn't allocated") + del self._pending_parser_input_lists[buf.value] + + buf = ctypes.cast(source_file_values, ctypes.c_void_p) + if buf.value not in self._pending_parser_input_lists: + raise ValueError("freeing source_file_values list that wasn't allocated") + del self._pending_parser_input_lists[buf.value] + except: + log_error(traceback.format_exc()) + + def adjust_type_parser_input( + self, + parser: 'typeparser.TypeParser', + arguments: List[str], + source_files: List[Tuple[str, str]] + ) -> Tuple[List[str], List[Tuple[str, str]]]: + """ + Modify the arguments passed to the Type Parser with Platform-specific features. + + :param parser: Type Parser instance + :param arguments: Default arguments passed to the parser + :param source_files: Source file names and contents + :return: A tuple of (modified arguments, modified source files) + """ + return arguments, source_files + def __del__(self): if core is not None: core.BNFreePlatform(self.handle) diff --git a/typeparser.cpp b/typeparser.cpp index 67dadd95..c32bcec1 100644 --- a/typeparser.cpp +++ b/typeparser.cpp @@ -99,6 +99,12 @@ std::string TypeParser::FormatParseErrors(const std::vector<TypeParserError>& er } +std::string TypeParser::GetName() const +{ + return BNGetTypeParserName(m_object); +} + + bool TypeParser::GetOptionText(BNTypeParserOption option, std::string value, std::string& result) const { // Default: Don't accept anything |
