diff options
Diffstat (limited to 'python/typecontainer.py')
| -rw-r--r-- | python/typecontainer.py | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/python/typecontainer.py b/python/typecontainer.py index 3f371213..b25a69f7 100644 --- a/python/typecontainer.py +++ b/python/typecontainer.py @@ -34,7 +34,15 @@ ProgressFuncType = Callable[[int, int], bool] class TypeContainer: + """ + A ``TypeContainer`` is a generic interface to access various Binary Ninja models + that contain types. Types are stored with both a unique id and a unique name. + """ def __init__(self, handle: core.BNTypeContainerHandle): + """ + Construct a Type Container, internal use only + :param handle: Handle pointer + """ binaryninja._init_plugins() self.handle: core.BNTypeContainerHandle = core.handle_of_type(handle, core.BNTypeContainer) @@ -47,27 +55,62 @@ class TypeContainer: @property def id(self) -> str: + """ + Get an id string for the Type Container. This will be unique within a given + analysis session, but may not be globally unique. + :return: Identifier string + """ return core.BNTypeContainerGetId(self.handle) @property def name(self) -> str: + """ + Get a user-friendly name for the Type Container. + :return: Display name + """ return core.BNTypeContainerGetName(self.handle) @property def container_type(self) -> 'enums.TypeContainerType': + """ + Get the type of underlying model the Type Container is accessing. + :return: Container type enum + """ return core.BNTypeContainerGetType(self.handle) @property def mutable(self) -> bool: + """ + Test if the Type Container supports mutable operations (add, rename, delete) + :return: True if mutable + """ return core.BNTypeContainerIsMutable(self.handle) @property def platform(self) -> 'platform.Platform': + """ + Get the Platform object associated with this Type Container. All Type Containers + have exactly one associated Platform (as opposed to, e.g. Type Libraries). + :return: Associated Platform object + """ handle = core.BNTypeContainerGetPlatform(self.handle) assert handle is not None return platform.Platform(handle=handle) def add_types(self, types: Mapping['ty_.QualifiedNameType', 'ty_.Type'], progress_func: Optional[ProgressFuncType] = None) -> Optional[Mapping['ty_.QualifiedName', str]]: + """ + Add or update types to a Type Container. If the Type Container already contains + a type with the same name as a type being added, the existing type will be + replaced with the definition given to this function, and references will be + updated in the source model. + + An optional progress callback is included because adding many types can be a slow operation. + + :param types: Dict from name -> definition of new types to add + :param progress_func: Optional function to call for progress updates + :return: Dict from name -> id of type in Type Container for all added types if successful, + None otherwise. + """ api_names = (core.BNQualifiedName * len(types))() api_types = (ctypes.POINTER(core.BNType) * len(types))() for (i, (key, value)) in enumerate(types.items()): @@ -101,18 +144,43 @@ class TypeContainer: return result def rename_type(self, type_id: str, new_name: 'ty_.QualifiedNameType') -> bool: + """ + Rename a type in the Type Container. All references to this type will be updated + (by id) to use the new name. + :param type_id: Id of type to update + :param new_name: New name for the type + :return: True if successful + """ return core.BNTypeContainerRenameType(self.handle, type_id, ty_.QualifiedName(new_name)._to_core_struct()) def delete_type(self, type_id: str) -> bool: + """ + Delete a type in the Type Container. Behavior of references to this type is + not specified and you may end up with broken references if any still exist. + :param type_id: Id of type to delete + :return: True if successful + """ return core.BNTypeContainerDeleteType(self.handle, type_id) def get_type_id(self, type_name: 'ty_.QualifiedNameType') -> Optional[str]: + """ + Get the unique id of the type in the Type Container with the given name. + If no type with that name exists, returns None. + :param type_name: Name of type + :return: Type id, if exists, else, None + """ result = ctypes.c_char_p() if not core.BNTypeContainerGetTypeId(self.handle, ty_.QualifiedName(type_name)._to_core_struct(), result): return None return core.pyNativeStr(result.value) def get_type_name(self, type_id: str) -> Optional['ty_.QualifiedName']: + """ + Get the unique name of the type in the Type Container with the given id. + If no type with that id exists, returns None. + :param type_id: Id of type + :return: Type name, if exists, else, None + """ api_result = core.BNQualifiedName() if not core.BNTypeContainerGetTypeName(self.handle, type_id, api_result): return None @@ -121,6 +189,12 @@ class TypeContainer: return result def get_type_by_id(self, type_id: str) -> Optional['ty_.Type']: + """ + Get the definition of the type in the Type Container with the given id. + If no type with that id exists, returns None. + :param type_id: Id of type + :return: Type object, if exists, else, None + """ result = ctypes.POINTER(core.BNType)() if not core.BNTypeContainerGetTypeById(self.handle, type_id, result): return None @@ -128,6 +202,10 @@ class TypeContainer: @property def types(self) -> Optional[Mapping[str, Tuple['ty_.QualifiedName', 'ty_.Type']]]: + """ + Get a mapping of all types in a Type Container. + :return: All types in a dict of type id -> (type name, type definition) + """ result_names = ctypes.POINTER(core.BNQualifiedName)() result_ids = ctypes.POINTER(ctypes.c_char_p)() result_types = ctypes.POINTER(ctypes.POINTER(core.BNType))() @@ -149,6 +227,12 @@ class TypeContainer: return result def get_type_by_name(self, type_name: 'ty_.QualifiedNameType') -> Optional['ty_.Type']: + """ + Get the definition of the type in the Type Container with the given name. + If no type with that name exists, returns None. + :param type_name: Name of type + :return: Type object, if exists, else, None + """ result = ctypes.POINTER(core.BNType)() if not core.BNTypeContainerGetTypeByName(self.handle, ty_.QualifiedName(type_name)._to_core_struct(), result): return None @@ -156,6 +240,10 @@ class TypeContainer: @property def type_ids(self) -> Optional[List[str]]: + """ + Get all type ids in a Type Container. + :return: List of all type ids + """ result_ids = ctypes.POINTER(ctypes.c_char_p)() result_count = ctypes.c_size_t(0) if not core.BNTypeContainerGetTypeIds(self.handle, result_ids, result_count): @@ -171,6 +259,10 @@ class TypeContainer: @property def type_names(self) -> Optional[List['ty_.QualifiedName']]: + """ + Get all type names in a Type Container. + :return: List of all type names + """ result_names = ctypes.POINTER(core.BNQualifiedName)() result_count = ctypes.c_size_t(0) if not core.BNTypeContainerGetTypeNames(self.handle, result_names, result_count): @@ -186,6 +278,10 @@ class TypeContainer: @property def type_names_and_ids(self) -> Optional[Mapping[str, 'ty_.QualifiedName']]: + """ + Get a mapping of all type ids and type names in a Type Container. + :return: Dict of type id -> type name + """ result_names = ctypes.POINTER(core.BNQualifiedName)() result_ids = ctypes.POINTER(ctypes.c_char_p)() result_count = ctypes.c_size_t(0) @@ -202,10 +298,21 @@ class TypeContainer: core.BNFreeStringList(result_ids, result_count.value) return result - def parse_types_from_source(self, source: str, file_name: str, platform: 'platform.Platform', + 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 = "" ) -> Tuple[Optional['typeparser.TypeParserResult'], List['typeparser.TypeParserError']]: + """ + Parse an entire block of source into types, variables, and functions, with + knowledge of the types in the Type Container. + + :param source: Source code to parse + :param file_name: Name of the file containing the source (optional: exists on disk) + :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 + :return: A tuple of (result, errors) where the result is None if there was a fatal error + """ if options is None: options = [] if include_dirs is None: @@ -224,7 +331,7 @@ class TypeContainer: error_count = ctypes.c_size_t() success = core.BNTypeContainerParseTypesFromSource( - self.handle, source, file_name, platform.handle, + self.handle, source, file_name, options_cpp, len(options), include_dirs_cpp, len(include_dirs), auto_type_source, result_cpp, errors_cpp, error_count |
