diff options
| author | Peter LaFosse <peter@vector35.com> | 2020-06-12 16:27:36 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2020-06-23 09:02:48 -0400 |
| commit | e0fbcc712f8ca31914d2f1e04b7f8b16eff44d66 (patch) | |
| tree | 1c79e6e76f4d0bdf6dfc09c3cd3036dbf96c56f2 /python | |
| parent | 4ffa5187aa0c9589dffac5bf00f3a7dd423578e8 (diff) | |
Add BinaryView.parse_types_from_string to the python API and update how the underlying BNParseTypesString works
Diffstat (limited to 'python')
| -rw-r--r-- | python/binaryview.py | 52 | ||||
| -rw-r--r-- | python/platform.py | 4 |
2 files changed, 49 insertions, 7 deletions
diff --git a/python/binaryview.py b/python/binaryview.py index 1cf802a2..3e1478be 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -4579,9 +4579,10 @@ class BinaryView(object): def parse_type_string(self, text): """ - ``parse_type_string`` converts `C-style` string into a :py:Class:`Type`. + ``parse_type_string`` parses string containing C into a single type :py:Class:`Type`. + In contrast to the :py:'platform - :param str text: `C-style` string of type to create + :param str text: C source code string of type to create :return: A tuple of a :py:Class:`Type` and type name :rtype: tuple(Type, QualifiedName) :Example: @@ -4590,12 +4591,12 @@ class BinaryView(object): (<type: int32_t>, 'foo') >>> """ - if not isinstance(text, str): - raise AttributeError("Text must be a string") + if not (isinstance(text, str) or isinstance(text, unicode)): + raise AttributeError("Source must be a string") result = core.BNQualifiedNameAndType() errors = ctypes.c_char_p() if not core.BNParseTypeString(self.handle, text, result, errors): - error_str = errors.value + error_str = errors.value.decode("utf-8") core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError(error_str) type_obj = types.Type(core.BNNewTypeReference(result.type), platform = self.platform) @@ -4603,6 +4604,47 @@ class BinaryView(object): core.BNFreeQualifiedNameAndType(result) return type_obj, name + def parse_types_from_string(self, text): + """ + ``parse_types_from_string`` parses string containing C into a :py:Class:`TypeParserResult` objects. This API + unlike the :py:Function:`platform.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 + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult + :Example: + + >>> bv.parse_types_from_string('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') + ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:{'bar': + <type: int32_t(int32_t x)>}}, '') + >>> + """ + if not (isinstance(text, str) or isinstance(text, unicode)): + raise AttributeError("Source must be a string") + + parse = core.BNTypeParserResult() + errors = ctypes.c_char_p() + if not core.BNParseTypesString(self.handle, text, parse, errors): + error_str = errors.value.decode("utf-8") + core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) + raise SyntaxError(error_str) + + type_dict = {} + variables = {} + functions = {} + for i in range(0, parse.typeCount): + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self.platform) + for i in range(0, parse.variableCount): + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self.platform) + for i in range(0, parse.functionCount): + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self.platform) + core.BNFreeTypeParserResult(parse) + return types.TypeParserResult(type_dict, variables, functions) + def get_type_by_name(self, name): """ ``get_type_by_name`` returns the defined type whose name corresponds with the provided ``name`` diff --git a/python/platform.py b/python/platform.py index 5031d2d6..8d7d1d99 100644 --- a/python/platform.py +++ b/python/platform.py @@ -411,7 +411,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): errors = ctypes.c_char_p() result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, len(include_dirs), auto_type_source) - error_str = errors.value + error_str = errors.value.decode("utf-8") core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: raise SyntaxError(error_str) @@ -460,7 +460,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): errors = ctypes.c_char_p() result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, len(include_dirs), auto_type_source) - error_str = errors.value + error_str = errors.value.decode("utf-8") core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: raise SyntaxError(error_str) |
