summaryrefslogtreecommitdiff
path: root/python/typelibrary.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/typelibrary.py')
-rw-r--r--python/typelibrary.py441
1 files changed, 301 insertions, 140 deletions
diff --git a/python/typelibrary.py b/python/typelibrary.py
index 8a340928..d4e5b0a2 100644
--- a/python/typelibrary.py
+++ b/python/typelibrary.py
@@ -38,173 +38,334 @@ from binaryninja import range
from binaryninja import with_metaclass
class TypeLibrary(object):
- def __init__(self, handle):
- self.handle = core.handle_of_type(handle, core.BNTypeLibrary)
+ def __init__(self, handle):
+ self.handle = core.handle_of_type(handle, core.BNTypeLibrary)
- def __del__(self):
- core.BNFreeTypeLibrary(self.handle)
+ def __del__(self):
+ core.BNFreeTypeLibrary(self.handle)
- def __repr__(self):
- return "<typelib '{}':{}>".format(self.name, self.arch.name)
+ def __repr__(self):
+ return "<typelib '{}':{}>".format(self.name, self.arch.name)
- @classmethod
- def new(cls, arch, name):
- handle = core.BNNewTypeLibrary(arch.handle, name)
- return TypeLibrary(handle)
+ @classmethod
+ def new(cls, arch, name):
+ """
+ Creates an empty type library object with a random GUID and
+ the provided name.
- @classmethod
- def load_from_file(cls, path):
- handle = core.BNLoadTypeLibraryFromFile(path)
- if handle is None:
- return None
- return TypeLibrary(handle)
+ :param Architecture arch
+ :param str name
+ :rtype: TypeLibrary
+ """
+ handle = core.BNNewTypeLibrary(arch.handle, name)
+ return TypeLibrary(handle)
- def write_to_file(self, path):
- core.BNWriteTypeLibraryToFile(self.handle, path)
+ @classmethod
+ def load_from_file(cls, path):
+ """
+ Loads a finalized type library instance from file
- @classmethod
- def from_name(cls, arch, name):
- handle = core.BNLookupTypeLibraryByName(arch.handle, name)
- if handle is None:
- return None
- return TypeLibrary(handle)
+ :param str path
+ :rtype: TypeLibrary
+ """
+ handle = core.BNLoadTypeLibraryFromFile(path)
+ if handle is None:
+ return None
+ return TypeLibrary(handle)
- @classmethod
- def from_guid(cls, arch, guid):
- handle = core.BNLookupTypeLibraryByGuid(arch.handle, guid)
- if handle is None:
- return None
- return TypeLibrary(handle)
+ def write_to_file(self, path):
+ """
+ Saves a finalized type library instance to file
- @property
- def arch(self):
- arch = core.BNGetTypeLibraryArchitecture(self.handle)
- if arch is None:
- return None
- return binaryninja.architecture.CoreArchitecture._from_cache(handle=arch)
+ :param str path
+ :rtype: None
+ """
+ core.BNWriteTypeLibraryToFile(self.handle, path)
- @property
- def name(self):
- name = core.BNGetTypeLibraryName(self.handle)
- return name
+ @classmethod
+ def from_name(cls, arch, name):
+ """
+ `from_name` looks up the first type library found with a matching name. Keep
+ in mind that names are not necessarily unique.
- @name.setter
- def name(self, value):
- core.BNSetTypeLibraryName(self.handle, value)
+ :param Architecture arch
+ :param str name
+ :rtype: TypeLibrary
+ """
+ handle = core.BNLookupTypeLibraryByName(arch.handle, name)
+ if handle is None:
+ return None
+ return TypeLibrary(handle)
- @property
- def dependency_name(self):
- return core.BNGetTypeLibraryDependencyName(self.handle)
+ @classmethod
+ def from_guid(cls, arch, guid):
+ """
+ `from_guid` attempts to grab a type library associated with the provided
+ Architecture and GUID pair
- @dependency_name.setter
- def dependency_name(self, value):
- core.BNSetTypeLibraryDependencyName(self.handle, value)
+ :param Architecture arch
+ :param str guid
+ :rtype: TypeLibrary
+ """
+ handle = core.BNLookupTypeLibraryByGuid(arch.handle, guid)
+ if handle is None:
+ return None
+ return TypeLibrary(handle)
- @property
- def guid(self):
- return core.BNGetTypeLibraryGuid(self.handle)
+ @property
+ def arch(self):
+ """The Architecture this type library is associated with"""
+ arch = core.BNGetTypeLibraryArchitecture(self.handle)
+ if arch is None:
+ return None
+ return binaryninja.architecture.CoreArchitecture._from_cache(handle=arch)
- @guid.setter
- def guid(self, value):
- core.BNSetTypeLibraryGuid(self.handle, value)
+ @property
+ def name(self):
+ """The primary name associated with this type library"""
+ name = core.BNGetTypeLibraryName(self.handle)
+ return name
- @property
- def alternate_names(self):
- count = ctypes.c_ulonglong(0)
- result = []
- names = core.BNGetTypeLibraryAlternateNames(self.handle, count)
- for i in range(0, count.value):
- result.append(names[i])
- core.BNFreeStringList(names, count.value)
- return result
+ @name.setter
+ def name(self, value):
+ """Sets the name of a type library instance that has not been finalized"""
+ core.BNSetTypeLibraryName(self.handle, value)
- def add_alternate_name(self, name):
- core.BNAddTypeLibraryAlternateName(self.handle, name)
+ @property
+ def dependency_name(self):
+ """
+ The `dependency_name` of a library is the name used to record dependencies across
+ type libraries. This allows, for example, a library with the name "musl_libc" to have
+ dependencies on it recorded as "libc_generic", allowing a type library to be used across
+ multiple platforms where each has a specific libc that also provides the name "libc_generic"
+ as an `alternate_name`.
+ """
+ return core.BNGetTypeLibraryDependencyName(self.handle)
- @property
- def platform_names(self):
- count = ctypes.c_ulonglong(0)
- result = []
- platforms = core.BNGetTypeLibraryPlatforms(self.handle, count)
- for i in range(0, count.value):
- result.append(platforms[i])
- core.BNFreeStringList(platforms, count.value)
- return result
+ @dependency_name.setter
+ def dependency_name(self, value):
+ """Sets the dependency name of a type library instance that has not been finalized"""
+ core.BNSetTypeLibraryDependencyName(self.handle, value)
- def add_platform(self, plat):
- if not isinstance(plat, platform.Platform):
- raise ValueError("plat must be a Platform object")
- core.BNAddTypeLibraryPlatform(self.handle, plat.handle)
+ @property
+ def guid(self):
+ """Returns the GUID associated with the type library"""
+ return core.BNGetTypeLibraryGuid(self.handle)
- def clear_platforms(self):
- core.BNClearTypeLibraryPlatforms(self.handle)
+ @guid.setter
+ def guid(self, value):
+ """Sets the GUID of a type library instance that has not been finalized"""
+ core.BNSetTypeLibraryGuid(self.handle, value)
- def finalize(self):
- core.BNFinalizeTypeLibrary(self.handle)
+ @property
+ def alternate_names(self):
+ """
+ A list of extra names that will be considered a match by ``Platform.get_type_libraries_by_name``
+ """
+ count = ctypes.c_ulonglong(0)
+ result = []
+ names = core.BNGetTypeLibraryAlternateNames(self.handle, count)
+ for i in range(0, count.value):
+ result.append(names[i])
+ core.BNFreeStringList(names, count.value)
+ return result
- def query_metadata(self, key):
- md_handle = core.BNTypeLibraryQueryMetadata(self.handle, key)
- if md_handle is None:
- return None
- return metadata.Metadata(handle=md_handle).value
+ def add_alternate_name(self, name):
+ """Adds an extra name to this type library used during library lookups and dependency resolution"""
+ core.BNAddTypeLibraryAlternateName(self.handle, name)
- def store_metadata(self, key, md):
- if not isinstance(md, metadata.Metadata):
- md = metadata.Metadata(md)
- core.BNTypeLibraryStoreMetadata(self.handle, key, md.handle)
+ @property
+ def platform_names(self):
+ """
+ Returns a list of all platform names that this type library will register with during platform
+ type registration.
- def remove_metadata(self, key):
- core.BNTypeLibraryRemoveMetadata(self.handle, key)
+ This returns strings, not Platform objects, as type libraries can be distributed with support for
+ Platforms that may not be present.
+ """
+ count = ctypes.c_ulonglong(0)
+ result = []
+ platforms = core.BNGetTypeLibraryPlatforms(self.handle, count)
+ for i in range(0, count.value):
+ result.append(platforms[i])
+ core.BNFreeStringList(platforms, count.value)
+ return result
- def add_named_object(self, name, t):
- if not isinstance(name, types.QualifiedName):
- name = types.QualifiedName(name)
- if not isinstance(t, types.Type):
- raise ValueError("t must be a Type")
- core.BNAddTypeLibraryNamedObject(self.handle, name._get_core_struct(), t.handle)
+ def add_platform(self, plat):
+ """
+ Associate a platform with a type library instance that has not been finalized.
- def add_named_type(self, name, t):
- if not isinstance(name, types.QualifiedName):
- name = types.QualifiedName(name)
- if not isinstance(t, types.Type):
- raise ValueError("t must be a Type")
- core.BNAddTypeLibraryNamedType(self.handle, name._get_core_struct(), t.handle)
+ This will cause the library to be searchable by ``Platform.get_type_libraries_by_name``
+ when loaded.
- def get_named_object(self, name):
- if not isinstance(name, types.QualifiedName):
- name = types.QualifiedName(name)
- t = core.BNGetTypeLibraryNamedObject(self.handle, name._get_core_struct())
- if t is None:
- return None
- return types.Type(t)
+ This does not have side affects until finalization of the type library.
+ """
+ if not isinstance(plat, platform.Platform):
+ raise ValueError("plat must be a Platform object")
+ core.BNAddTypeLibraryPlatform(self.handle, plat.handle)
- def get_named_type(self, name):
- if not isinstance(name, types.QualifiedName):
- name = types.QualifiedName(name)
- t = core.BNGetTypeLibraryNamedType(self.handle, name._get_core_struct())
- if t is None:
- return None
- return types.Type(t)
+ def clear_platforms(self):
+ """Clears the list of platforms associated with a type library instance that has not been finalized"""
+ core.BNClearTypeLibraryPlatforms(self.handle)
- @property
- def named_objects(self):
- count = ctypes.c_ulonglong(0)
- result = {}
- named_types = core.BNGetTypeLibraryNamedObjects(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 finalize(self):
+ """
+ Flags a newly created type library instance as finalized and makes it available for Platform and Architecture
+ type library searches
+ """
+ core.BNFinalizeTypeLibrary(self.handle)
- @property
- def named_types(self):
- 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 query_metadata(self, key):
+ """
+ `query_metadata` retrieves a metadata associated with the given key stored in the type library
+
+ :param string key: key to query
+ :rtype: metadata associated with the key
+ :Example:
+
+ >>> lib.store_metadata("ordinals", {"9": "htons"})
+ >>> lib.query_metadata("ordinals")["9"]
+ "htons"
+ """
+ md_handle = core.BNTypeLibraryQueryMetadata(self.handle, key)
+ if md_handle is None:
+ return None
+ return metadata.Metadata(handle=md_handle).value
+
+ def store_metadata(self, key, md):
+ """
+ `store_metadata` stores an object for the given key in the current type library. Objects stored using
+ `store_metadata` can be retrieved from any reference to the library. Objects stored are not arbitrary python
+ objects! The values stored must be able to be held in a Metadata object. See :py:class:`Metadata`
+ for more information. Python objects could obviously be serialized using pickle but this intentionally
+ a task left to the user since there is the potential security issues.
+
+ This is primarily intended as a way to store Platform specific information relevant to BinaryView implementations;
+ for example the PE BinaryViewType uses type library metadata to retrieve ordinal information, when available.
+
+ :param string key: key value to associate the Metadata object with
+ :param Varies md: object to store.
+ :rtype: None
+ :Example:
+
+ >>> lib.store_metadata("ordinals", {"9": "htons"})
+ >>> lib.query_metadata("ordinals")["9"]
+ "htons"
+ """
+ if not isinstance(md, metadata.Metadata):
+ md = metadata.Metadata(md)
+ core.BNTypeLibraryStoreMetadata(self.handle, key, md.handle)
+
+ def remove_metadata(self, key):
+ """
+ `remove_metadata` removes the metadata associated with key from the current type library.
+
+ :param string key: key associated with metadata
+ :rtype: None
+ :Example:
+
+ >>> lib.store_metadata("integer", 1337)
+ >>> lib.remove_metadata("integer")
+ """
+ core.BNTypeLibraryRemoveMetadata(self.handle, key)
+
+ def add_named_object(self, name, t):
+ """
+ `add_named_object` directly inserts a named object into the type library's object store.
+ This is not done recursively, so care should be taken that types referring to other types
+ through NamedTypeReferences are already appropriately prepared.
+
+ To add types and objects from an existing BinaryView, it is recommended to use
+ :py:meth:`BinaryView.export_object_to_library`, which will automatically pull in
+ all referenced types and record additional dependencies as needed.
+
+ :param QualifiedName name
+ :param Type t
+ :rtype: None
+ """
+ if not isinstance(name, types.QualifiedName):
+ name = types.QualifiedName(name)
+ if not isinstance(t, types.Type):
+ raise ValueError("t must be a Type")
+ core.BNAddTypeLibraryNamedObject(self.handle, name._get_core_struct(), t.handle)
+
+ def add_named_type(self, name, t):
+ """
+ `add_named_type` directly inserts a named object into the type library's object store.
+ This is not done recursively, so care should be taken that types referring to other types
+ through NamedTypeReferences are already appropriately prepared.
+
+ To add types and objects from an existing BinaryView, it is recommended to use
+ :py:meth:`BinaryView.export_type_to_library`, which will automatically pull in
+ all referenced types and record additional dependencies as needed.
+
+ :param QualifiedName name
+ :param Type t
+ :rtype: None
+ """
+ if not isinstance(name, types.QualifiedName):
+ name = types.QualifiedName(name)
+ if not isinstance(t, types.Type):
+ raise ValueError("t must be a Type")
+ core.BNAddTypeLibraryNamedType(self.handle, name._get_core_struct(), t.handle)
+
+ def get_named_object(self, name):
+ """
+ `get_named_object` direct extracts a reference to a contained object -- when
+ attempting to extract types from a library into a BinaryView, consider using
+ :py:meth:`BinaryView.import_library_object` instead.
+
+ :param QualifiedName name
+ :rtype: Type
+ """
+ if not isinstance(name, types.QualifiedName):
+ name = types.QualifiedName(name)
+ t = core.BNGetTypeLibraryNamedObject(self.handle, name._get_core_struct())
+ if t is None:
+ return None
+ return types.Type(t)
+
+ def get_named_type(self, name):
+ """
+ `get_named_type` direct extracts a reference to a contained type -- when
+ attempting to extract types from a library into a BinaryView, consider using
+ :py:meth:`BinaryView.import_library_type` instead.
+
+ :param QualifiedName name
+ :rtype: Type
+ """
+ if not isinstance(name, types.QualifiedName):
+ name = types.QualifiedName(name)
+ t = core.BNGetTypeLibraryNamedType(self.handle, name._get_core_struct())
+ if t is None:
+ return None
+ return types.Type(t)
+
+ @property
+ def named_objects(self):
+ """
+ A dict containing all named objects (functions, exported variables) provided by a type library (read-only)
+ """
+ count = ctypes.c_ulonglong(0)
+ result = {}
+ named_types = core.BNGetTypeLibraryNamedObjects(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
+
+ @property
+ 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