diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/binaryview.py | 21 | ||||
| -rw-r--r-- | python/platform.py | 13 | ||||
| -rw-r--r-- | python/typeparser.py | 22 |
3 files changed, 42 insertions, 14 deletions
diff --git a/python/binaryview.py b/python/binaryview.py index be4eab96..9093bcda 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -6190,13 +6190,15 @@ class BinaryView: finally: core.BNFreeQualifiedNameAndType(result) - def parse_types_from_string(self, text: str) -> '_types.TypeParserResult': + def parse_types_from_string(self, text: str, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None) -> '_types.TypeParserResult': """ ``parse_types_from_string`` parses string containing C into a :py:Class:`TypeParserResult` objects. This API unlike the :py:meth:`Platform.parse_types_from_source` allows the reference of types already defined in the 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 :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -6209,12 +6211,27 @@ class BinaryView: if not isinstance(text, str): raise ValueError("Source must be a string") + if options is None: + options = [] + if include_dirs is None: + include_dirs = [] + parse = core.BNTypeParserResult() try: + options_cpp = (ctypes.c_char_p * len(options))() + for (i, s) in enumerate(options): + options_cpp[i] = core.cstr(s) + + include_dirs_cpp = (ctypes.c_char_p * len(include_dirs))() + for (i, s) in enumerate(include_dirs): + include_dirs_cpp[i] = core.cstr(s) + errors = ctypes.c_char_p() type_list = core.BNQualifiedNameList() type_list.count = 0 - if not core.BNParseTypesString(self.handle, text, parse, errors, type_list): + if not core.BNParseTypesString( + self.handle, text, options_cpp, len(options), include_dirs_cpp, + len(include_dirs), parse, errors, type_list): assert errors.value is not None, "core.BNParseTypesString returned errors set to None" error_str = errors.value.decode("utf-8") core.free_string(errors) diff --git a/python/platform.py b/python/platform.py index fc46882b..05cbaabf 100644 --- a/python/platform.py +++ b/python/platform.py @@ -26,6 +26,7 @@ from typing import List, Dict, Optional import binaryninja from . import _binaryninjacore as core from . import types +from . import typeparser from . import callingconvention from . import typelibrary from . import architecture @@ -411,8 +412,8 @@ class Platform(metaclass=_PlatformMetaClass): :param include_dirs: optional list of string filename include directories :type include_dirs: list(str) :param str auto_type_source: optional source of types if used for automatically generated types - :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult + :return: :py:class:`BasicTypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: BasicTypeParserResult :Example: >>> platform.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') @@ -453,7 +454,7 @@ class Platform(metaclass=_PlatformMetaClass): name = types.QualifiedName._from_core_struct(parse.functions[i].name) functions[name] = types.Type.create(core.BNNewTypeReference(parse.functions[i].type), platform=self) core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) + return typeparser.BasicTypeParserResult(type_dict, variables, functions) def parse_types_from_source_file(self, filename, include_dirs: Optional[List[str]] = None, auto_type_source=None): """ @@ -464,8 +465,8 @@ class Platform(metaclass=_PlatformMetaClass): :param include_dirs: optional list of string filename include directories :type include_dirs: list(str) :param str auto_type_source: optional source of types if used for automatically generated types - :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult + :return: :py:class:`BasicTypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: BasicTypeParserResult :Example: >>> file = "/Users/binja/tmp.c" @@ -506,7 +507,7 @@ class Platform(metaclass=_PlatformMetaClass): name = types.QualifiedName._from_core_struct(parse.functions[i].name) functions[name] = types.Type.create(core.BNNewTypeReference(parse.functions[i].type), platform=self) core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) + return typeparser.BasicTypeParserResult(type_dict, variables, functions) @property def arch(self): diff --git a/python/typeparser.py b/python/typeparser.py index f1dffe13..f4eba3cf 100644 --- a/python/typeparser.py +++ b/python/typeparser.py @@ -121,6 +121,16 @@ class ParsedType: @dataclasses.dataclass(frozen=True) +class BasicTypeParserResult: + types: Dict['types.QualifiedName', 'types.Type'] + variables: Dict['types.QualifiedName', 'types.Type'] + functions: Dict['types.QualifiedName', 'types.Type'] + + def __repr__(self): + return f"<types: {self.types}, variables: {self.variables}, functions: {self.functions}>" + + +@dataclasses.dataclass(frozen=True) class TypeParserResult: types: Dict['types.QualifiedName', ParsedType] variables: Dict['types.QualifiedName', ParsedType] @@ -392,14 +402,14 @@ class TypeParser(metaclass=_TypeParserMetaclass): return False def preprocess_source( - self, source: str, file_name: str, platform: platform.Platform, + self, source: str, file_name: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None ) -> Tuple[Optional[str], List[TypeParserError]]: raise NotImplementedError("Not implemented") def parse_types_from_source( - self, source: str, file_name: str, platform: platform.Platform, + self, source: str, file_name: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None, auto_type_source: str = "" @@ -407,7 +417,7 @@ class TypeParser(metaclass=_TypeParserMetaclass): raise NotImplementedError("Not implemented") def parse_type_string( - self, source: str, platform: platform.Platform, + self, source: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None ) -> Tuple[Optional[Tuple['types.QualifiedNameType', 'types.Type']], List[TypeParserError]]: raise NotImplementedError("Not implemented") @@ -416,7 +426,7 @@ class TypeParser(metaclass=_TypeParserMetaclass): class CoreTypeParser(TypeParser): def preprocess_source( - self, source: str, file_name: str, platform: platform.Platform, + self, source: str, file_name: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None ) -> Tuple[Optional[str], List[TypeParserError]]: @@ -464,7 +474,7 @@ class CoreTypeParser(TypeParser): return output, errors def parse_types_from_source( - self, source: str, file_name: str, platform: platform.Platform, + self, source: str, file_name: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None, auto_type_source: str = "" @@ -514,7 +524,7 @@ class CoreTypeParser(TypeParser): def parse_type_string( - self, source: str, platform: platform.Platform, + self, source: str, platform: 'platform.Platform', existing_types: Optional[List[QualifiedNameTypeAndId]] = None ) -> Tuple[Optional[Tuple['types.QualifiedNameType', 'types.Type']], List[TypeParserError]]: if existing_types is None: |
