def _get_type_tokens_after_name(self, ctxt, type, platform, base_confidence, parent_type, escaping, result, result_count): try: platform_py = None if platform: platform_py = _platform.Platform( handle=core.BNNewPlatformReference(platform)) parent_type_py = None if parent_type: parent_type_py = types.Type( handle=core.BNNewTypeReference(parent_type)) result_py = self.get_type_tokens_after_name( types.Type(handle=core.BNNewTypeReference(type)), platform_py, base_confidence, parent_type_py, escaping) TypePrinter._cached_tokens = _function.InstructionTextToken._get_core_struct( result_py) result[0] = TypePrinter._cached_tokens result_count[0] = len(result_py) return True except: log_error(traceback.format_exc()) return False
def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source`` parses the source string and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories :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 :Example: >>> platform.parse_types_from_source('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 filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() 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 core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: 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) 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) 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) core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions)
def _get_lines_for_data(self, ctxt, view, addr, type, prefix, prefixCount, width, count, typeCtx, ctxCount): try: file_metadata = filemetadata.FileMetadata( handle=core.BNGetFileForView(view)) view = binaryview.BinaryView(file_metadata=file_metadata, handle=core.BNNewViewReference(view)) type = types.Type(handle=core.BNNewTypeReference(type)) prefixTokens = function.InstructionTextToken.get_instruction_lines( prefix, prefixCount) pycontext = [] for i in range(ctxCount): pycontext.append( TypeContext( types.Type(core.BNNewTypeReference(typeCtx[i].type)), typeCtx[i].offset)) result = self.perform_get_lines_for_data(ctxt, view, addr, type, prefixTokens, width, pycontext) count[0] = len(result) line_buf = (core.BNDisassemblyTextLine * len(result))() for i in range(len(result)): line = result[i] color = line.highlight if not isinstance( color, enums.HighlightStandardColor) and not isinstance( color, highlight.HighlightColor): raise ValueError( "Specified color is not one of HighlightStandardColor, highlight.HighlightColor" ) if isinstance(color, enums.HighlightStandardColor): color = highlight.HighlightColor(color) line_buf[i].highlight = color._get_core_struct() if line.address is None: if len(line.tokens) > 0: line_buf[i].addr = line.tokens[0].address else: line_buf[i].addr = 0 else: line_buf[i].addr = line.address if line.il_instruction is not None: line_buf[i].instrIndex = line.il_instruction.instr_index else: line_buf[i].instrIndex = 0xffffffffffffffff line_buf[i].count = len(line.tokens) line_buf[ i].tokens = function.InstructionTextToken.get_instruction_lines( line.tokens) return ctypes.cast(line_buf, ctypes.c_void_p).value except: log.log_error(traceback.format_exc()) return None
def _is_valid_for_data(self, ctxt, view, addr, type, context, ctxCount): try: file_metadata = FileMetadata(handle=core.BNGetFileForView(view)) view = BinaryView(file_metadata=file_metadata, handle=core.BNNewViewReference(view)) type = Type(handle=core.BNNewTypeReference(type)) pycontext = [] for i in range(0, ctxCount): pycontext.append(Type(core.BNNewTypeReference(context[i]))) return self.perform_is_valid_for_data(ctxt, view, addr, type, pycontext) except: log_error(traceback.format_exc()) return False
def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str filename: filename of file to be parsed :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 :Example: >>> file = "/Users/binja/tmp.c" >>> open(file).read() 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' >>> platform.parse_types_from_source_file(file) ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions: {'bar': <type: int32_t(int32_t x)>}}, '') >>> """ if not (isinstance(filename, str) and os.path.isfile(filename) and os.access(filename, os.R_OK)): raise AttributeError("File {} doesn't exist or isn't readable".format(filename)) dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() 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.decode("utf-8") core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: 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) 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) 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) core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions)
def parameters(self): """Type parameters list (read-only)""" count = ctypes.c_ulonglong() params = core.BNGetTypeParameters(self.handle, count) result = [] for i in range(0, count.value): param_type = Type(core.BNNewTypeReference(params[i].type), platform=self.platform, confidence=params[i].typeConfidence) if params[i].defaultLocation: param_location = None else: name = params[i].name if (params[i].location.type == VariableSourceType.RegisterVariableSourceType) and ( self.platform is not None): name = self.platform.arch.get_reg_name( params[i].location.storage) elif params[ i].location.type == VariableSourceType.StackVariableSourceType: name = "arg_%x" % params[i].location.storage param_location = binaryninja.function.Variable( None, params[i].location.type, params[i].location.index, params[i].location.storage, name, param_type) result.append( FunctionParameter(param_type, params[i].name, param_location)) core.BNFreeTypeParameterList(params, count.value) return result
def __getitem__(self, name): try: member = core.BNGetStructureMemberByName(self.handle, name) return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence), member.contents.name, member.contents.offset) finally: core.BNFreeStructureMember(member)
def functions(self): """List of platform-specific function definitions (read-only)""" count = ctypes.c_ulonglong(0) type_list = core.BNGetPlatformFunctions(self.handle, count) result = {} for i in range(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result
def members(self): """Structure member list (read-only)""" count = ctypes.c_ulonglong() members = core.BNGetStructureMembers(self.handle, count) result = [] for i in range(0, count.value): result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type), confidence = members[i].typeConfidence), members[i].name, members[i].offset)) core.BNFreeStructureMemberList(members, count.value) return result
def member_at_offset(self, offset): try: if self._mutable: member = core.BNGetStructureBuilderMemberAtOffset(self._handle, offset, None) else: member = core.BNGetStructureMemberAtOffset(self._handle, offset, None) return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence), member.contents.name, member.contents.offset) finally: core.BNFreeStructureMember(member)
def system_calls(self): """List of system calls for this platform (read-only)""" count = ctypes.c_ulonglong(0) call_list = core.BNGetPlatformSystemCalls(self.handle, count) result = {} for i in range(0, count.value): name = types.QualifiedName._from_core_struct(call_list[i].name) t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) core.BNFreeSystemCallList(call_list, count.value) return result
def named_types(self): """ A dict containing all named types provided by a type library (read-only) """ count = ctypes.c_ulonglong(0) result = {} named_types = core.BNGetTypeLibraryNamedTypes(self.handle, count) for i in range(0, count.value): name = types.QualifiedName._from_core_struct(named_types[i].name) result[name] = types.Type(core.BNNewTypeReference(named_types[i].type)) core.BNFreeQualifiedNameAndTypeArray(named_types, count.value) return result
def get_type_lines( self, type: types.Type, data: binaryview.BinaryView, name: types.QualifiedNameType, line_width=80, collapsed=False, escaping: TokenEscapingType = TokenEscapingType. BackticksTokenEscapingType ) -> List[types.TypeDefinitionLine]: if not isinstance(name, types.QualifiedName): name = types.QualifiedName(name) count = ctypes.c_ulonglong() core_lines = ctypes.POINTER(core.BNTypeDefinitionLine)() if not core.BNGetTypePrinterTypeLines( self.handle, type.handle, data.handle, name._to_core_struct(), line_width, collapsed, ctypes.c_int(escaping), core_lines, count): raise RuntimeError("BNGetTypePrinterTypeLines returned False") lines = [] for i in range(count.value): tokens = _function.InstructionTextToken._from_core_struct( core_lines[i].tokens, core_lines[i].count) type_ = types.Type.create(handle=core.BNNewTypeReference( core_lines[i].type), platform=data.platform) root_type = types.Type.create(handle=core.BNNewTypeReference( core_lines[i].rootType), platform=data.platform) root_type_name = core.pyNativeStr(core_lines[i].rootTypeName) line = types.TypeDefinitionLine(core_lines[i].lineType, tokens, type_, root_type, root_type_name, core_lines[i].offset, core_lines[i].fieldIndex) lines.append(line) core.BNFreeTypeDefinitionLineList(core_lines, count.value) return lines
def _get_type_string(self, ctxt, type, platform, name, escaping, result): try: platform_py = None if platform: platform_py = _platform.Platform( handle=core.BNNewPlatformReference(platform)) result_py = self.get_type_string( types.Type(handle=core.BNNewTypeReference(type)), platform_py, types.QualifiedName._from_core_struct(name.contents), escaping) TypePrinter._cached_string = core.cstr(result_py) result[0] = TypePrinter._cached_string return True except: log_error(traceback.format_exc()) return False
def _get_type_lines(self, ctxt, type, data, name, line_width, collapsed, escaping, result, result_count): try: result_py = self.get_type_lines( types.Type(handle=core.BNNewTypeReference(type)), binaryview.BinaryView(handle=core.BNNewViewReference(data)), types.QualifiedName._from_core_struct(name.contents), line_width, collapsed, escaping) TypePrinter._cached_lines = (core.BNTypeDefinitionLine * len(result_py))() for (i, line) in enumerate(result_py): TypePrinter._cached_lines[i] = line._to_core_struct() result[0] = TypePrinter._cached_lines result_count[0] = len(result_py) return True except: log_error(traceback.format_exc()) return False
def parse_type_string( 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: existing_types = [] existing_types_cpp = (core.BNQualifiedNameTypeAndId * len(existing_types))() for (i, qnatid) in enumerate(existing_types): existing_types_cpp[i] = qnatid._to_core_struct() result_cpp = core.BNQualifiedNameAndType() errors_cpp = ctypes.POINTER(core.BNTypeParserError)() error_count = ctypes.c_size_t() success = core.BNTypeParserParseTypeString(self.handle, source, platform.handle, existing_types_cpp, len(existing_types), 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 errors = [] for i in range(error_count.value): errors.append(TypeParserError._from_core_struct(errors_cpp[i])) core.BNFreeTypeParserErrors(errors_cpp, error_count.value) return result, errors
def _parse_type_string(self, ctxt, source, platform_, existingTypes, existingTypeCount, result, errors, errorCount) -> bool: try: source_py = core.pyNativeStr(source) platform_py = platform.Platform( handle=core.BNNewPlatformReference(platform_)) existing_types_py = [] for i in range(existingTypeCount): existing_types_py.append( QualifiedNameTypeAndId._from_core_struct(existingTypes[i])) (result_py, errors_py) = self.parse_type_string(source_py, platform_py, existing_types_py) if result_py is not None and result is not None: result[0].name = types.QualifiedName( result_py[0])._to_core_struct() result[0].type = core.BNNewTypeReference(result_py[1].handle) if errorCount is not None: errorCount[0] = len(errors_py) if errors is not None: errors_out = (core.BNTypeParserError * len(errors_py))() for i in range(len(errors_py)): errors_out[i] = errors_py[i]._to_core_struct() TypeParser._cached_error = errors_out errors[0] = errors_out return result_py is not None except: errorCount[0] = 0 log_error(traceback.format_exc()) return False
def with_confidence(self, confidence): return Type(handle=core.BNNewTypeReference(self.handle), platform=self.platform, confidence=confidence)
def _to_core_struct(self) -> core.BNQualifiedNameTypeAndId: result = core.BNQualifiedNameTypeAndId() result.name = types.QualifiedName(self.name)._to_core_struct() result.type = core.BNNewTypeReference(self.type.handle) result.id = self.id return result
def _from_core_struct( cls, struct: core.BNQualifiedNameTypeAndId) -> 'QualifiedNameTypeAndId': name = types.QualifiedName._from_core_struct(struct.name) type = types.Type.create(handle=core.BNNewTypeReference(struct.type)) return QualifiedNameTypeAndId(name, struct.id, type)
def _to_core_struct(self) -> core.BNParsedType: result = core.BNParsedType() result.name = types.QualifiedName(self.name)._to_core_struct() result.type = core.BNNewTypeReference(self.type.handle) result.isUser = self.is_user return result
def _from_core_struct(cls, struct: core.BNParsedType) -> 'ParsedType': name = types.QualifiedName._from_core_struct(struct.name) type = types.Type.create(handle=core.BNNewTypeReference(struct.type)) return ParsedType(name, type, struct.isUser)