summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2024-04-02 13:33:19 -0400
committerGlenn Smith <glenn@vector35.com>2024-04-03 16:04:50 -0400
commit6955825444658317609313782745220062335525 (patch)
tree91b1a07c193828478a365b734cafdb0b3a7beab5
parent6320364130513117734495793886487928062891 (diff)
Add `importDependencies` argument to `ParseTypeString` to control library imports
-rw-r--r--binaryninjaapi.h48
-rw-r--r--binaryninjacore.h8
-rw-r--r--binaryview.cpp12
-rw-r--r--python/binaryview.py12
-rw-r--r--python/typecontainer.py42
-rw-r--r--typecontainer.cpp51
6 files changed, 143 insertions, 30 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index f723cb54..83d42e0c 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -5858,11 +5858,12 @@ namespace BinaryNinja {
\param[in] text Text containing the type definition
\param[out] result Reference into which the resulting type and name will be written
\param[out] errors Reference to a list into which any parse errors will be written
- \param typesAllowRedefinition
+ \param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
+ \param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
\return Whether parsing was successful
*/
bool ParseTypeString(const std::string& text, QualifiedNameAndType& result, std::string& errors,
- const std::set<QualifiedName>& typesAllowRedefinition = {});
+ const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
/*! Parse an entire block of source into types, variables, and functions
@@ -5871,14 +5872,25 @@ namespace BinaryNinja {
\param[out] variables Reference to a list of QualifiedNames and Types the parsed variables will be writen to
\param[out] functions Reference to a list of QualifiedNames and Types the parsed functions will be writen to
\param[out] errors Reference to a list into which any parse errors will be written
- \param typesAllowRedefinition
+ \param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
+ \param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
\return Whether parsing was successful
*/
bool ParseTypeString(const std::string& text, std::map<QualifiedName, Ref<Type>>& types,
std::map<QualifiedName, Ref<Type>>& variables, std::map<QualifiedName, Ref<Type>>& functions,
- std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {});
+ std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
+
+ /*! Parse an entire block of source into a structure containing types, variables, and functions
+
+ \param[in] text Source code to parse
+ \param[out] result Reference to a TypeParserResult structure into which types, variables, and functions will be written
+ \param[out] errors Reference to a list into which any parse errors will be written
+ \param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
+ \param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
+ \return Whether parsing was successful
+ */
bool ParseTypesFromSource(const std::string& text, const std::vector<std::string>& options, const std::vector<std::string>& includeDirs, TypeParserResult& result,
- std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {});
+ std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
/*! Type Container for all types (user and auto) in the BinaryView. Any auto types
modified through the Type Container will be converted into user types.
@@ -17287,12 +17299,23 @@ namespace BinaryNinja {
with knowledge of the types in the Type Container.
\param source Source code to parse
+ \param importDependencies If Type Library / Type Archive types should be imported during parsing
\param result Reference into which the resulting type and name will be written
\param errors Reference to a list into which any parse errors will be written
\return True if parsing was successful
*/
bool ParseTypeString(
const std::string& source,
+ bool importDependencies,
+ QualifiedNameAndType& result,
+ std::vector<TypeParserError>& errors
+ );
+
+ /*!
+ \deprecated Use `ParseTypeString` with the extra `importDependencies` param
+ */
+ bool ParseTypeString(
+ const std::string& source,
QualifiedNameAndType& result,
std::vector<TypeParserError>& errors
);
@@ -17305,6 +17328,7 @@ namespace BinaryNinja {
\param options Optional string arguments to pass as options, e.g. command line arguments
\param includeDirs Optional list of directories to include in the header search path
\param autoTypeSource Optional source of types if used for automatically generated types
+ \param importDependencies If Type Library / Type Archive types should be imported during parsing
\param result Reference to structure into which the results will be written
\param errors Reference to a list into which any parse errors will be written
\return True if successful
@@ -17315,6 +17339,20 @@ namespace BinaryNinja {
const std::vector<std::string>& options,
const std::vector<std::string>& includeDirs,
const std::string& autoTypeSource,
+ bool importDependencies,
+ TypeParserResult& result,
+ std::vector<TypeParserError>& errors
+ );
+
+ /*!
+ \deprecated Use `ParseTypesFromSource` with the extra `importDependencies` param
+ */
+ bool ParseTypesFromSource(
+ const std::string& text,
+ const std::string& fileName,
+ const std::vector<std::string>& options,
+ const std::vector<std::string>& includeDirs,
+ const std::string& autoTypeSource,
TypeParserResult& result,
std::vector<TypeParserError>& errors
);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 0533c5b7..6017eec5 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -4662,10 +4662,10 @@ extern "C"
BINARYNINJACOREAPI bool BNGetDataVariableAtAddress(BNBinaryView* view, uint64_t addr, BNDataVariable* var);
BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNQualifiedNameAndType* result,
- char** errors, BNQualifiedNameList* typesAllowRedefinition);
+ char** errors, BNQualifiedNameList* typesAllowRedefinition, bool importDepencencies);
BINARYNINJACOREAPI bool BNParseTypesString(BNBinaryView* view, const char* text, const char* const* options, size_t optionCount,
const char* const* includeDirs, size_t includeDirCount, BNTypeParserResult* result, char** errors,
- BNQualifiedNameList* typesAllowRedefinition);
+ BNQualifiedNameList* typesAllowRedefinition, bool importDepencencies);
BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj);
BINARYNINJACOREAPI void BNFreeQualifiedNameAndTypeArray(BNQualifiedNameAndType* obj, size_t count);
BINARYNINJACOREAPI void BNFreeQualifiedNameTypeAndId(BNQualifiedNameTypeAndId* obj);
@@ -4746,14 +4746,14 @@ extern "C"
BINARYNINJACOREAPI bool BNTypeContainerGetTypeNames(BNTypeContainer* container, BNQualifiedName** typeNames, size_t* count);
BINARYNINJACOREAPI bool BNTypeContainerGetTypeNamesAndIds(BNTypeContainer* container, char*** typeIds, BNQualifiedName** typeNames, size_t* count);
BINARYNINJACOREAPI bool BNTypeContainerParseTypeString(BNTypeContainer* container,
- const char* source, BNQualifiedNameAndType* result,
+ const char* source, bool importDepencencies, BNQualifiedNameAndType* result,
BNTypeParserError** errors, size_t* errorCount
);
BINARYNINJACOREAPI bool BNTypeContainerParseTypesFromSource(BNTypeContainer* container,
const char* source, const char* fileName,
const char* const* options, size_t optionCount,
const char* const* includeDirs, size_t includeDirCount,
- const char* autoTypeSource, BNTypeParserResult* result,
+ const char* autoTypeSource, bool importDepencencies, BNTypeParserResult* result,
BNTypeParserError** errors, size_t* errorCount
);
diff --git a/binaryview.cpp b/binaryview.cpp
index feb3b765..51ee2ee9 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -3717,7 +3717,7 @@ bool BinaryView::ParsePossibleValueSet(
bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& result, string& errors,
- const std::set<QualifiedName>& typesAllowRedefinition)
+ const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
{
BNQualifiedNameAndType nt;
char* errorStr;
@@ -3732,7 +3732,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul
i++;
}
- if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr, &typesList))
+ if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr, &typesList, importDependencies))
{
errors = errorStr;
BNFreeString(errorStr);
@@ -3751,7 +3751,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul
bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Type>>& types,
map<QualifiedName, Ref<Type>>& variables, map<QualifiedName, Ref<Type>>& functions, string& errors,
- const std::set<QualifiedName>& typesAllowRedefinition)
+ const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
{
BNTypeParserResult result;
char* errorStr = nullptr;
@@ -3774,7 +3774,7 @@ bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Ty
vector<const char*> includeDirs;
bool ok = BNParseTypesString(m_object, source.c_str(), options.data(), options.size(),
- includeDirs.data(), includeDirs.size(), &result, &errorStr, &typesList);
+ includeDirs.data(), includeDirs.size(), &result, &errorStr, &typesList, importDependencies);
if (errorStr)
{
errors = errorStr;
@@ -3805,7 +3805,7 @@ bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Ty
bool BinaryView::ParseTypesFromSource(const string& source, const vector<string>& options, const vector<string>& includeDirs,
- TypeParserResult& result, string& errors, const std::set<QualifiedName>& typesAllowRedefinition)
+ TypeParserResult& result, string& errors, const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
{
BNQualifiedNameList typesList;
typesList.count = typesAllowRedefinition.size();
@@ -3829,7 +3829,7 @@ bool BinaryView::ParseTypesFromSource(const string& source, const vector<string>
char* errorStr = nullptr;
bool ok = BNParseTypesString(m_object, source.c_str(), coreOptions.data(), coreOptions.size(),
- coreIncludeDirs.data(), coreIncludeDirs.size(), &apiResult, &errorStr, &typesList);
+ coreIncludeDirs.data(), coreIncludeDirs.size(), &apiResult, &errorStr, &typesList, importDependencies);
if (errorStr)
{
errors = errorStr;
diff --git a/python/binaryview.py b/python/binaryview.py
index 933bc12c..0f1f77c2 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -7026,7 +7026,7 @@ class BinaryView:
return iter(LinearDisassemblyIterator(self, settings))
- def parse_type_string(self, text: str) -> Tuple['_types.Type', '_types.QualifiedName']:
+ def parse_type_string(self, text: str, import_dependencies: bool = True) -> Tuple['_types.Type', '_types.QualifiedName']:
"""
``parse_type_string`` parses string containing C into a single type :py:class:`Type`.
In contrast to the :py:func:`~binaryninja.platform.Platform.parse_types_from_source` or :py:func:`~binaryninja.platform.Platform.parse_types_from_source_file`, ``parse_type_string``
@@ -7034,6 +7034,7 @@ class BinaryView:
view, while those two APIs do not.
:param str text: C source code string of type to create
+ :param import_dependencies: If Type Library / Type Archive types should be imported during parsing
:return: A tuple of a :py:class:`Type` and type name
:rtype: tuple(Type, QualifiedName)
:Example:
@@ -7050,7 +7051,7 @@ class BinaryView:
errors = ctypes.c_char_p()
type_list = core.BNQualifiedNameList()
type_list.count = 0
- if not core.BNParseTypeString(self.handle, text, result, errors, type_list):
+ if not core.BNParseTypeString(self.handle, text, result, errors, type_list, import_dependencies):
assert errors.value is not None, "core.BNParseTypeString returned 'errors' set to None"
error_str = errors.value.decode("utf-8")
core.free_string(errors)
@@ -7061,7 +7062,7 @@ class BinaryView:
finally:
core.BNFreeQualifiedNameAndType(result)
- def parse_types_from_string(self, text: str, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None) -> '_types.TypeParserResult':
+ def parse_types_from_string(self, text: str, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None, import_dependencies: bool = True) -> '_types.TypeParserResult':
"""
``parse_types_from_string`` parses string containing C into a :py:class:`TypeParserResult` objects. This API
unlike the :py:func:`~binaryninja.platform.Platform.parse_types_from_source` allows the reference of types already defined
@@ -7070,6 +7071,7 @@ class BinaryView:
:param str text: C source code string of types, variables, and function types, to create
:param options: Optional list of string options to be passed into the type parser
:param include_dirs: Optional list of header search directories
+ :param import_dependencies: If Type Library / Type Archive types should be imported during parsing
:return: :py:class:`~binaryninja.typeparser.TypeParserResult` (a SyntaxError is thrown on parse error)
:rtype: TypeParserResult
:Example:
@@ -7102,7 +7104,7 @@ class BinaryView:
type_list.count = 0
if not core.BNParseTypesString(
self.handle, text, options_cpp, len(options), include_dirs_cpp,
- len(include_dirs), parse, errors, type_list):
+ len(include_dirs), parse, errors, type_list, import_dependencies):
assert errors.value is not None, "core.BNParseTypesString returned errors set to None"
error_str = errors.value.decode("utf-8")
core.free_string(errors)
@@ -7170,7 +7172,7 @@ class BinaryView:
value = ''
if not core.BNParsePossibleValueSet(self.handle, value, state, result, here, errors):
if errors:
- assert errors.value is not None, "core.BNParseTypesString returned errors set to None"
+ assert errors.value is not None, "core.BNParsePossibleValueSet returned errors set to None"
error_str = errors.value.decode("utf-8")
else:
error_str = "Error parsing specified PossibleValueSet"
diff --git a/python/typecontainer.py b/python/typecontainer.py
index a0e35f2d..cc1b3288 100644
--- a/python/typecontainer.py
+++ b/python/typecontainer.py
@@ -300,9 +300,46 @@ class TypeContainer:
core.BNFreeStringList(result_ids, result_count.value)
return result
+ def parse_type_string(
+ self, source: str, import_dependencies: bool = True
+ ) -> Tuple[Optional[Tuple['_types.QualifiedNameType', '_types.Type']], List['typeparser.TypeParserError']]:
+ """
+ Parse a single type and name from a string containing their definition, with
+ knowledge of the types in the Type Container.
+
+ :param source: Source code to parse
+ :param import_dependencies: If Type Library / Type Archive types should be imported during parsing
+ :return: A tuple of (result, errors) where result is a tuple of (type, name) or
+ None of there was a fatal error.
+ """
+ result_cpp = core.BNQualifiedNameAndType()
+ errors_cpp = ctypes.POINTER(core.BNTypeParserError)()
+ error_count = ctypes.c_size_t()
+
+ success = core.BNTypeContainerParseTypeString(
+ self.handle, source, import_dependencies, result_cpp, errors_cpp, error_count
+ )
+
+ if success:
+ result = (
+ _types.QualifiedName._from_core_struct(result_cpp.name),
+ _types.Type.create(handle=core.BNNewTypeReference(result_cpp.type))
+ )
+ core.BNFreeQualifiedNameAndType(result_cpp)
+ else:
+ result = None
+ core.BNFreeTypeParserResult(result_cpp)
+
+ errors = []
+ for i in range(error_count.value):
+ errors.append(typeparser.TypeParserError._from_core_struct(errors_cpp[i]))
+ core.BNFreeTypeParserErrors(errors_cpp, error_count.value)
+
+ return result, errors
+
def parse_types_from_source(self, source: str, file_name: str,
options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None,
- auto_type_source: str = ""
+ auto_type_source: str = "", import_dependencies: bool = True
) -> Tuple[Optional['typeparser.TypeParserResult'], List['typeparser.TypeParserError']]:
"""
Parse an entire block of source into types, variables, and functions, with
@@ -313,6 +350,7 @@ class TypeContainer:
:param options: Optional string arguments to pass as options, e.g. command line arguments
:param include_dirs: Optional list of directories to include in the header search path
:param auto_type_source: Optional source of types if used for automatically generated types
+ :param import_dependencies: If Type Library / Type Archive types should be imported during parsing
:return: A tuple of (result, errors) where the result is None if there was a fatal error
"""
if options is None:
@@ -335,7 +373,7 @@ class TypeContainer:
success = core.BNTypeContainerParseTypesFromSource(
self.handle, source, file_name,
options_cpp, len(options),
- include_dirs_cpp, len(include_dirs), auto_type_source,
+ include_dirs_cpp, len(include_dirs), auto_type_source, import_dependencies,
result_cpp, errors_cpp, error_count
)
diff --git a/typecontainer.cpp b/typecontainer.cpp
index bd31a134..6050fde3 100644
--- a/typecontainer.cpp
+++ b/typecontainer.cpp
@@ -331,6 +331,7 @@ std::optional<std::unordered_map<std::string, QualifiedName>> TypeContainer::Get
bool TypeContainer::ParseTypeString(
const std::string& source,
+ bool importDependencies,
BinaryNinja::QualifiedNameAndType& result,
std::vector<TypeParserError>& errors
)
@@ -339,7 +340,7 @@ bool TypeContainer::ParseTypeString(
BNTypeParserError* apiErrors;
size_t errorCount;
- auto success = BNTypeContainerParseTypeString(m_object, source.c_str(), &apiResult,
+ auto success = BNTypeContainerParseTypeString(m_object, source.c_str(), importDependencies, &apiResult,
&apiErrors, &errorCount);
for (size_t j = 0; j < errorCount; j ++)
@@ -367,12 +368,23 @@ bool TypeContainer::ParseTypeString(
}
+bool TypeContainer::ParseTypeString(
+ const std::string& source,
+ BinaryNinja::QualifiedNameAndType& result,
+ std::vector<TypeParserError>& errors
+)
+{
+ return ParseTypeString(source, true, result, errors);
+}
+
+
bool TypeContainer::ParseTypesFromSource(
const std::string& text,
const std::string& fileName,
const std::vector<std::string>& options,
const std::vector<std::string>& includeDirs,
const std::string& autoTypeSource,
+ bool importDependencies,
BinaryNinja::TypeParserResult& result,
std::vector<TypeParserError>& errors
)
@@ -393,8 +405,8 @@ bool TypeContainer::ParseTypesFromSource(
size_t errorCount;
auto success = BNTypeContainerParseTypesFromSource(m_object, text.c_str(), fileName.c_str(),
- apiOptions, options.size(), apiIncludeDirs, includeDirs.size(), autoTypeSource.c_str(), &apiResult,
- &apiErrors, &errorCount);
+ apiOptions, options.size(), apiIncludeDirs, includeDirs.size(), autoTypeSource.c_str(), importDependencies,
+ &apiResult, &apiErrors, &errorCount);
delete [] apiOptions;
delete [] apiIncludeDirs;
@@ -403,11 +415,11 @@ bool TypeContainer::ParseTypesFromSource(
{
TypeParserError error;
error.severity = apiErrors[j].severity,
- error.message = apiErrors[j].message,
- error.fileName = apiErrors[j].fileName,
- error.line = apiErrors[j].line,
- error.column = apiErrors[j].column,
- errors.push_back(error);
+ error.message = apiErrors[j].message,
+ error.fileName = apiErrors[j].fileName,
+ error.line = apiErrors[j].line,
+ error.column = apiErrors[j].column,
+ errors.push_back(error);
}
BNFreeTypeParserErrors(apiErrors, errorCount);
@@ -449,3 +461,26 @@ bool TypeContainer::ParseTypesFromSource(
BNFreeTypeParserResult(&apiResult);
return true;
}
+
+
+bool TypeContainer::ParseTypesFromSource(
+ const std::string& text,
+ const std::string& fileName,
+ const std::vector<std::string>& options,
+ const std::vector<std::string>& includeDirs,
+ const std::string& autoTypeSource,
+ BinaryNinja::TypeParserResult& result,
+ std::vector<TypeParserError>& errors
+)
+{
+ return ParseTypesFromSource(
+ text,
+ fileName,
+ options,
+ includeDirs,
+ autoTypeSource,
+ true,
+ result,
+ errors
+ );
+}