diff options
| author | Glenn Smith <glenn@vector35.com> | 2023-11-06 21:22:51 -0500 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2023-11-06 21:31:10 -0500 |
| commit | 9664293566835578211572938174462967719297 (patch) | |
| tree | 5ce88ae2acb8ffbf5177da95e2332978cbb82910 | |
| parent | 6436615567547349434351468012512505109552 (diff) | |
Type Containers: API Docs
| -rw-r--r-- | binaryninjaapi.h | 157 | ||||
| -rw-r--r-- | python/binaryview.py | 14 | ||||
| -rw-r--r-- | python/debuginfo.py | 7 | ||||
| -rw-r--r-- | python/platform.py | 4 | ||||
| -rw-r--r-- | python/typecontainer.py | 111 | ||||
| -rw-r--r-- | python/typelibrary.py | 6 |
6 files changed, 289 insertions, 10 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 021069e5..5585dc20 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -5133,9 +5133,23 @@ namespace BinaryNinja { 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 = {}); + /*! 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. + \return Full view Type Container + */ class TypeContainer GetTypeContainer(); + + /*! Type Container for ONLY auto types in the BinaryView. Any changes to types will + NOT promote auto types to user types. + \return Auto types only Type Container + */ class TypeContainer GetAutoTypeContainer(); + + /*! Type Container for ONLY user types in the BinaryView. + \return User types only Type Container + */ class TypeContainer GetUserTypeContainer(); + std::map<QualifiedName, Ref<Type>> GetTypes(); /*! List of all types, sorted such that types are after all types on which they depend @@ -13584,6 +13598,9 @@ namespace BinaryNinja { std::vector<Ref<TypeLibrary>> GetTypeLibrariesByName(const std::string& name); + /*! Type Container for all registered types in the Platform. + \return Platform types Type Container + */ TypeContainer GetTypeContainer(); Ref<Type> GetTypeByName(const QualifiedName& name); @@ -15215,6 +15232,11 @@ namespace BinaryNinja { std::vector<std::string> GetParsers() const; + /*! Type Container for all types in the DebugInfo that resulted from the parse of + the given parser. + \param parserName Name of parser + \return Type Container for types from that parser + */ TypeContainer GetTypeContainer(const std::string& parserName); std::vector<NameAndType> GetTypes(const std::string& parserName = "") const; @@ -15639,9 +15661,9 @@ namespace BinaryNinja { */ void SetGuid(const std::string& guid); - /*! Get a TypeContainer interface for this type library - - \return Container interface + /*! Type Container for all TYPES within the Type Library. Objects are not included. + The Type Container's Platform will be the first platform associated with the Type Library. + \return Type Library Type Container */ TypeContainer GetTypeContainer(); @@ -15766,6 +15788,12 @@ namespace BinaryNinja { void Finalize(); }; + /*! + 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. + + \ingroup types + */ class TypeContainer { BNTypeContainer* m_object; @@ -15774,8 +15802,21 @@ namespace BinaryNinja { explicit TypeContainer(BNTypeContainer* container); explicit TypeContainer(TypeContainer&& other); + /*! Get the Type Container for a given BinaryView + \param data BinaryView source + */ TypeContainer(Ref<BinaryView> data); + + /*! Get the Type Container for a Type Library + \note The Platform for the Type Container will be the first Platform + associated with the Type Library + \param library TypeLibrary source + */ TypeContainer(Ref<TypeLibrary> library); + + /*! Get the Type Container for a Platform + \param platform Platform source + */ TypeContainer(Ref<Platform> platform); ~TypeContainer(); @@ -15787,29 +15828,137 @@ namespace BinaryNinja { BNTypeContainer* GetObject() const { return m_object; } + /*! 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 + */ std::string GetId() const; + + /*! Get a user-friendly name for the Type Container. + \return Display name + */ std::string GetName() const; + + /*! Get the type of underlying model the Type Container is accessing. + \return Container type enum + */ BNTypeContainerType GetType() const; + + /*! Test if the Type Container supports mutable operations (add, rename, delete) + \return True if mutable + */ bool IsMutable() const; + + /*! 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 + */ Ref<Platform> GetPlatform() const; + + /*! Add or update a single type in the 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. + \param name Name of type to add + \param type Definition of type to add + \return String of added type's id, if successful, std::nullopt otherwise + */ std::optional<std::string> AddType(QualifiedName name, Ref<Type> type); + + /*! 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 List of (name, definition) pairs of new types to add + \param progress Optional function to call for progress updates + \return Map of name -> id of type in Type Container for all added typesif successful, + std::nullopt otherwise. + */ std::optional<std::unordered_map<QualifiedName, std::string>> AddTypes( - const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, std::function<bool(size_t, size_t)> progress = {}); + + /*! Rename a type in the Type Container. All references to this type will be updated + (by id) to use the new name. + \param typeId Id of type to update + \param newName New name for the type + \return True if successful + */ bool RenameType(const std::string& typeId, const QualifiedName& newName); + + /*! 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 typeId Id of type to delete + \return True if successful + */ bool DeleteType(const std::string& typeId); + + /*! Get the unique id of the type in the Type Container with the given name. + If no type with that name exists, returns std::nullopt. + \param typeName Name of type + \return Type id, if exists, else, std::nullopt + */ std::optional<std::string> GetTypeId(const QualifiedName& typeName) const; + + /*! Get the unique name of the type in the Type Container with the given id. + If no type with that id exists, returns std::nullopt. + \param typeId Id of type + \return Type name, if exists, else, std::nullopt + */ std::optional<QualifiedName> GetTypeName(const std::string& typeId) const; + + /*! Get the definition of the type in the Type Container with the given id. + If no type with that id exists, returns std::nullopt. + \param typeId Id of type + \return Type object, if exists, else, std::nullopt + */ std::optional<Ref<Type>> GetTypeById(const std::string& typeId) const; + + /*! Get a mapping of all types in a Type Container. + \return All types in a map of type id -> (type name, type definition) + */ std::optional<std::unordered_map<std::string, std::pair<QualifiedName, Ref<Type>>>> GetTypes() const; + + /*! Get the definition of the type in the Type Container with the given name. + If no type with that name exists, returns None. + \param typeName Name of type + \return Type object, if exists, else, None + */ std::optional<Ref<Type>> GetTypeByName(const QualifiedName& typeName) const; + + /*! Get all type ids in a Type Container. + \return List of all type ids + */ std::optional<std::unordered_set<std::string>> GetTypeIds() const; + + /*! Get all type names in a Type Container. + \return List of all type names + */ std::optional<std::unordered_set<QualifiedName>> GetTypeNames() const; + + /*! Get a mapping of all type ids and type names in a Type Container. + \return Map of type id -> type name + */ std::optional<std::unordered_map<std::string, QualifiedName>> GetTypeNamesAndIds() const; + /*! Parse an entire block of source into types, variables, and functions, with + knowledge of the types in the Type Container. + + \param text Source code to parse + \param fileName 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 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 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 + */ bool ParseTypesFromSource( const std::string& text, const std::string& fileName, diff --git a/python/binaryview.py b/python/binaryview.py index de434074..ea0aba4f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -7035,16 +7035,30 @@ class BinaryView: @property def type_container(self) -> 'typecontainer.TypeContainer': + """ + 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. + :return: Full view Type Container + """ container = core.BNGetAnalysisTypeContainer(self.handle) return typecontainer.TypeContainer(handle=container) @property def auto_type_container(self) -> 'typecontainer.TypeContainer': + """ + Type Container for ONLY auto types in the BinaryView. Any changes to types will + NOT promote auto types to user types. + :return: Auto types only Type Container + """ container = core.BNGetAnalysisAutoTypeContainer(self.handle) return typecontainer.TypeContainer(handle=container) @property def user_type_container(self) -> 'typecontainer.TypeContainer': + """ + Type Container for ONLY user types in the BinaryView. + :return: User types only Type Container + """ container = core.BNGetAnalysisUserTypeContainer(self.handle) return typecontainer.TypeContainer(handle=container) diff --git a/python/debuginfo.py b/python/debuginfo.py index 65f879ea..6884a9ca 100644 --- a/python/debuginfo.py +++ b/python/debuginfo.py @@ -305,7 +305,12 @@ class DebugInfo(object): def get_type_container(self, parser_name: str) -> 'typecontainer.TypeContainer': - """Returns a TypeContainer interface for one of the parsers in this DebugInfo""" + """ + Type Container for all types in the DebugInfo that resulted from the parse of + the given parser. + :param parser_name: Name of parser + :return: Type Container for types from that parser + """ return typecontainer.TypeContainer(core.BNGetDebugInfoTypeContainer(self.handle, parser_name)) def types_from_parser(self, name: Optional[str] = None) -> Iterator[Tuple[str, _types.Type]]: diff --git a/python/platform.py b/python/platform.py index 2c4a26f6..74fd8248 100644 --- a/python/platform.py +++ b/python/platform.py @@ -362,6 +362,10 @@ class Platform(metaclass=_PlatformMetaClass): @property def type_container(self) -> 'typecontainer.TypeContainer': + """ + Type Container for all registered types in the Platform. + :return: Platform types Type Container + """ return typecontainer.TypeContainer(core.BNGetPlatformTypeContainer(self.handle)) def get_type_by_name(self, name): 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 diff --git a/python/typelibrary.py b/python/typelibrary.py index 364a458d..90c4a6d3 100644 --- a/python/typelibrary.py +++ b/python/typelibrary.py @@ -285,9 +285,9 @@ class TypeLibrary: @property def type_container(self) -> 'typecontainer.TypeContainer': """ - `type_container` returns a TypeContainer interface for interacting with the type library. - - :return: TypeContainer interface + Type Container for all TYPES within the Type Library. Objects are not included. + The Type Container's Platform will be the first platform associated with the Type Library. + :return: Type Library Type Container """ return typecontainer.TypeContainer(core.BNGetTypeLibraryTypeContainer(self.handle)) |
