summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h45
-rw-r--r--binaryninjacore.h37
-rw-r--r--platform.cpp145
-rw-r--r--platform/windows/platform_windows.cpp80
-rw-r--r--python/platform.py102
-rw-r--r--typeparser.cpp6
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