diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/__init__.py | 28 | ||||
| -rw-r--r-- | python/basicblock.py | 25 | ||||
| -rw-r--r-- | python/binaryview.py | 19 | ||||
| -rw-r--r-- | python/bncompleter.py | 8 | ||||
| -rw-r--r-- | python/demangle.py | 2 | ||||
| -rw-r--r-- | python/filemetadata.py | 2 | ||||
| -rw-r--r-- | python/highlevelil.py | 2 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 2 | ||||
| -rw-r--r-- | python/plugin.py | 107 | ||||
| -rw-r--r-- | python/project.py | 2 | ||||
| -rw-r--r-- | python/variable.py | 31 |
11 files changed, 205 insertions, 23 deletions
diff --git a/python/__init__.py b/python/__init__.py index 144d022a..9e31f906 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -94,6 +94,8 @@ if core.BNGetProduct() == "Binary Ninja Enterprise Client": def shutdown(): """ ``shutdown`` cleanly shuts down the core, stopping all workers and closing all log files. + + .. note:: This will be called automatically on script exit if you import the binaryninja module. """ core.BNShutdown() @@ -103,13 +105,30 @@ atexit.register(shutdown) @dataclass class CoreVersionInfo: + """ + Structure representing the Binary Ninja Version. + + Use :py:func:`core_version_info` to look up the current version of Binary Ninja loaded. + """ + major: int + """Major version number, e.g. 4.0.5000-dev would be 4""" + minor: int + """Minor version number, e.g. 4.0.5000-dev would be 0""" + build: int + """Build version number, e.g. 4.0.5000-dev would be 5000""" + channel: str + """Release channel name, e.g. "dev" or "Stable" """ def get_unique_identifier(): + """ + Generate a GUID + :return: A GUID string + """ return core.BNGetUniqueIdentifierString() @@ -299,6 +318,10 @@ def core_set_license(licenseData: str) -> None: def get_memory_usage_info() -> Mapping[str, int]: + """ + Get counts of various Binary Ninja objects in memory. + :return: Dictionary of {class name: count} for objects in memory + """ count = ctypes.c_ulonglong() info = core.BNGetMemoryUsageInfo(count) assert info is not None, "core.BNGetMemoryUsageInfo returned None" @@ -341,7 +364,7 @@ def load(*args, **kwargs) -> BinaryView: return bv -@deprecation.deprecated(deprecated_in="3.5.4378", details='Use :py:func:`BinaryView.load` instead') +@deprecation.deprecated(deprecated_in="3.5.4378", details='Use :py:func:`load` instead') def open_view(*args, **kwargs) -> BinaryView: return load(*args, **kwargs) @@ -383,6 +406,9 @@ def connect_vscode_debugger(port=5678): class UIPluginInHeadlessError(Exception): + """ + Error thrown when trying to load a UI plugin in a headless Binary Ninja installation. + """ def __init__(self, *args, **kwargs): Exception.__init__(self, *args, **kwargs) diff --git a/python/basicblock.py b/python/basicblock.py index a22b540f..6c03fe32 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -33,6 +33,18 @@ from . import function as _function @dataclass(frozen=True) class BasicBlockEdge: + """ + ``class BasicBlockEdge`` represents the edges that connect basic blocks in graph view. + + :cvar type: The :py:meth:`enums.BranchType` of the edge; Whether the edge is a true branch, false branch, unconditional, etc. + :cvar source: The basic block that the edge originates from. + :cvar target: The basic block that the edge is going to. + :cvar backedge: Whether this edge targets to a node whose control flow can eventually flow back through the source node of this edge. + :Example: + + >>> current_basic_block.outgoing_edges + [<TrueBranch: x86_64@0x6>, <FalseBranch: x86_64@0x1f>] + """ type: BranchType source: 'BasicBlock' target: 'BasicBlock' @@ -50,7 +62,18 @@ class BasicBlockEdge: class BasicBlock: """ - The ``BasicBlock`` object is returned during analysis and should not be directly instantiated. + The ``class BasicBlock`` object is returned during analysis and should not be directly instantiated. + + Basic blocks contain a sequence of instructions that must execute in-order with no branches. + We include calls in basic blocks, which technically violates that assumption, but you can mark + functions as `func.can_return = False` if a given function should terminate basic blocks. + :Example: + + >>> for func in bv.functions: + >>> for bb in func: + >>> # Any block-based analysis could start here + >>> for inst in bb: + >>> pass # Optionally do something here with instructions """ def __init__(self, handle: core.BNBasicBlockHandle, view: Optional['binaryview.BinaryView'] = None): self._view = view diff --git a/python/binaryview.py b/python/binaryview.py index ec8475c8..aaad9b0f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -455,7 +455,7 @@ class AnalysisCompletionEvent: """ The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving callbacks when analysis is complete. The callback runs once. A completion event must be added - for each new analysis in order to be notified of each analysis completion. The + for each new analysis in order to be notified of each analysis completion. The AnalysisCompletionEvent class takes responsibility for keeping track of the object's lifetime. :Example: @@ -2019,7 +2019,7 @@ class BinaryView: either and are used explicitly for subclassing a BinaryView. .. note:: An important note on the ``*_user_*()`` methods. Binary Ninja makes a distinction between edits \ - performed by the user and actions performed by auto analysis. Auto analysis actions that can quickly be recalculated \ + performed by the user and actions performed by auto analysis. Auto analysis actions that can quickly be recalculated \ are not saved to the database. Auto analysis actions that take a long time and all user edits are stored in the \ database (e.g. :py:func:`remove_user_function` rather than :py:func:`remove_function`). Thus use ``_user_`` methods if saving \ to the database is desired. @@ -3752,7 +3752,7 @@ class BinaryView: """ ``read`` returns the data reads at most ``length`` bytes from virtual address ``addr``. - .. note:: Python2 returns a str, but Python3 returns a bytes object. str(DataBufferObject) will \ + .. note:: Python2 returns a str, but Python3 returns a bytes object. str(DataBufferObject) will \ still get you a str in either case. :param int addr: virtual address to read from. @@ -4184,10 +4184,9 @@ class BinaryView: def update_analysis(self) -> None: """ - ``update_analysis`` asynchronously starts the analysis running and returns immediately. Analysis of BinaryViews - does not occur automatically, the user must start analysis by calling either :py:func:`update_analysis` or - :py:func:`update_analysis_and_wait`. An analysis update **must** be run after changes are made which could change - analysis results such as adding functions. + ``update_analysis`` asynchronously starts the analysis running and returns immediately. + An analysis update **must** be run after changes are made which could change analysis + results such as adding functions. :rtype: None """ @@ -4196,9 +4195,7 @@ class BinaryView: def update_analysis_and_wait(self) -> None: """ ``update_analysis_and_wait`` blocking call to update the analysis, this call returns when the analysis is - complete. Analysis of BinaryViews does not occur automatically, the user must start analysis by calling either - :py:func:`update_analysis` or :py:func:`update_analysis_and_wait`. An analysis update **must** be run after changes are - made which could change analysis results such as adding functions. + complete. An analysis update **must** be run after changes are made which could change analysis results such as adding functions. :rtype: None """ @@ -6202,7 +6199,7 @@ class BinaryView: ) -> bool: """ ``is_skip_and_return_zero_patch_available`` queries the architecture plugin to determine if the - instruction at ``addr`` is similar to an x86 "call" instruction which can be made to return zero. The actual + instruction at ``addr`` is similar to an x86 "call" instruction which can be made to return zero. The actual logic of which is implemented in the ``perform_is_skip_and_return_zero_patch_available`` in the corresponding architecture. diff --git a/python/bncompleter.py b/python/bncompleter.py index 9a33659b..3b632aab 100644 --- a/python/bncompleter.py +++ b/python/bncompleter.py @@ -25,14 +25,14 @@ Tip: to use the tab key as the completion key, call Notes: - Exceptions raised by the completer function are *ignored* (and generally cause - the completion to fail). This is a feature -- since readline sets the tty + the completion to fail). This is a feature -- since readline sets the tty device in raw (or cbreak) mode, printing a traceback wouldn't work well without some complicated hoopla to save, reset and restore the tty state. - The evaluation of the NAME.NAME... form may cause arbitrary application defined code to be executed if an object with a __getattr__ hook is found. Since it is the responsibility of the application (or the user) to enable this - feature, I consider this an acceptable risk. More complicated expressions + feature, I consider this an acceptable risk. More complicated expressions (e.g. function calls or indexing operations) are *not* evaluated. - When the original stdin is not a tty device, GNU readline is never @@ -89,7 +89,7 @@ class Completer: """Return the next possible completion for 'text'. This is called successively with state == 0, 1, 2, ... until it - returns None. The completion should begin with 'text'. + returns None. The completion should begin with 'text'. """ if self.use_main_ns: @@ -152,7 +152,7 @@ class Completer: Assuming the text is of the form NAME.NAME....[NAME], and is evaluable in self.namespace, it will be evaluated and its attributes - (as revealed by dir()) are used as possible completions. (For class + (as revealed by dir()) are used as possible completions. (For class instances, class members are also considered.) WARNING: this can still invoke arbitrary C code, if an object diff --git a/python/demangle.py b/python/demangle.py index 89532f78..874b13cf 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -158,7 +158,7 @@ def simplify_name_to_string(input_name): def simplify_name_to_qualified_name(input_name, simplify=True): """ - ``simplify_name_to_qualified_name`` simplifies a templated C++ name with default arguments and returns a qualified name. This can also tokenize a string to a qualified name with/without simplifying it + ``simplify_name_to_qualified_name`` simplifies a templated C++ name with default arguments and returns a qualified name. This can also tokenize a string to a qualified name with/without simplifying it :param input_name: String or qualified name to be simplified :type input_name: Union[str, QualifiedName] diff --git a/python/filemetadata.py b/python/filemetadata.py index e51436b1..4dbde1a7 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -519,7 +519,7 @@ class FileMetadata: """ ``navigate`` navigates the UI to the specified virtual address - .. note:: Despite the confusing name, ``view`` in this context is not a BinaryView but rather a string describing the different UI Views. Check :py:attr:`view` while in different views to see examples such as ``Linear:ELF``, ``Graph:PE``. + .. note:: Despite the confusing name, ``view`` in this context is not a BinaryView but rather a string describing the different UI Views. Check :py:attr:`view` while in different views to see examples such as ``Linear:ELF``, ``Graph:PE``. :param str view: view name :param int offset: address to navigate to diff --git a/python/highlevelil.py b/python/highlevelil.py index da1d9346..ff35c018 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -2888,7 +2888,7 @@ class HighLevelILFunction: @property def aliased_vars(self) -> List["variable.Variable"]: - """This returns a list of Variables that are taken reference to and used elsewhere. You may also wish to consider `HighLevelIlFunction.vars` and `HighLevelIlFunction.source_function.parameter_vars`""" + """This returns a list of Variables that are taken reference to and used elsewhere. You may also wish to consider `HighLevelIlFunction.vars` and `HighLevelIlFunction.source_function.parameter_vars`""" if self.source_function is None: return [] diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index e8e020ea..db5da1a1 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -3710,7 +3710,7 @@ class MediumLevelILFunction: @property def aliased_vars(self) -> List["variable.Variable"]: - """This returns a list of Variables that are taken reference to and used elsewhere. You may also wish to consider `MediumLevelIlFunction.vars` and `MediumLevelIlFunction.source_function.parameter_vars`""" + """This returns a list of Variables that are taken reference to and used elsewhere. You may also wish to consider `MediumLevelIlFunction.vars` and `MediumLevelIlFunction.source_function.parameter_vars`""" if self.source_function is None: return [] diff --git a/python/plugin.py b/python/plugin.py index 4d65db0b..455d511e 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -103,6 +103,13 @@ class _PluginCommandMetaClass(type): class PluginCommand(metaclass=_PluginCommandMetaClass): + """ + The ``class PluginCommand` contains all the plugin registration methods as class methods. + + You shouldn't need to create an instance of this class, instead see `register`, + `register_for_address`, `register_for_function`, and similar class methods for examples + on how to register your plugin. + """ _registered_commands = [] def __init__(self, cmd): @@ -369,6 +376,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` as an argument :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView): + >>> log_info(f"My plugin was called on bv: `{bv}`") + >>> PluginCommand.register("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView) -> bool: + >>> return False + >>> PluginCommand.register("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -395,6 +412,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and address as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and address to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, address: int): + >>> log_info(f"My plugin was called on bv: `{bv}` at address {hex(address)}") + >>> PluginCommand.register_for_address("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, address: int) -> bool: + >>> return False + >>> PluginCommand.register_for_address("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_address`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -421,6 +448,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView`, start address, and length as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView`, start address, and length to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, start: int, length: int): + >>> log_info(f"My plugin was called on bv: `{bv}` at {hex(start)} of length {hex(length)}") + >>> PluginCommand.register_for_range("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, start: int, length: int) -> bool: + >>> return False + >>> PluginCommand.register_for_range("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_range`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -447,6 +484,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~function.Function` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~function.Function` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, func: Function): + >>> log_info(f"My plugin was called on func {func} in bv `{bv}`") + >>> PluginCommand.register_for_function("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, func: Function) -> bool: + >>> return False + >>> PluginCommand.register_for_function("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -474,6 +521,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~lowlevelil.LowLevelILFunction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~lowlevelil.LowLevelILFunction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, func: LowLevelILFunction): + >>> log_info(f"My plugin was called on func {func} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_function("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, func: LowLevelILFunction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_function("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -502,6 +559,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~lowlevelil.LowLevelILInstruction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~lowlevelil.LowLevelILInstruction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, inst: LowLevelILInstruction): + >>> log_info(f"My plugin was called on inst {inst} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, inst: LowLevelILInstruction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -531,6 +598,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~mediumlevelil.MediumLevelILFunction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~mediumlevelil.MediumLevelILFunction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, func: MediumLevelILFunction): + >>> log_info(f"My plugin was called on func {func} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_function("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, func: MediumLevelILFunction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_function("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -559,6 +636,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~mediumlevelil.MediumLevelILInstruction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~mediumlevelil.MediumLevelILInstruction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, inst: MediumLevelILInstruction): + >>> log_info(f"My plugin was called on inst {inst} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, inst: MediumLevelILInstruction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -588,6 +675,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~highlevelil.HighLevelILFunction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~highlevelil.HighLevelILFunction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, func: HighLevelILFunction): + >>> log_info(f"My plugin was called on func {func} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_function("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, func: HighLevelILFunction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_function("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_high_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ @@ -616,6 +713,16 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~highlevelil.HighLevelILInstruction` as arguments :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~highlevelil.HighLevelILInstruction` to determine whether the plugin should be enabled for that view :rtype: None + :Example: + + >>> def my_plugin(bv: BinaryView, inst: HighLevelILInstruction): + >>> log_info(f"My plugin was called on inst {inst} in bv `{bv}`") + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin", "My plugin description (not used)", my_plugin) + True + >>> def is_valid(bv: BinaryView, inst: HighLevelILInstruction) -> bool: + >>> return False + >>> PluginCommand.register_for_low_level_il_instruction("My Plugin (With Valid Function)", "My plugin description (not used)", my_plugin, is_valid) + True .. warning:: Calling ``register_for_high_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ diff --git a/python/project.py b/python/project.py index d9b9880d..a080123a 100644 --- a/python/project.py +++ b/python/project.py @@ -664,7 +664,7 @@ class Project: and the project on disk vs in memory may not agree on state if an exception occurs while a bulk operation is happening. - :example: + :Example: >>> from pathlib import Path >>> with project.bulk_operation(): ... for i in Path('/bin/').iterdir(): diff --git a/python/variable.py b/python/variable.py index 0a86b850..75e95712 100644 --- a/python/variable.py +++ b/python/variable.py @@ -644,16 +644,28 @@ class StackVariableReference: @dataclass(frozen=True, order=True) class CoreVariable: + """ + ``class CoreVariable`` is the base class for other variable types, + such as :py:meth:`VariableNameAndType` and :py:meth:`Variable` + + :cvar index: Internal identifier + :cvar storage: If this variable is a stack variable + (`source_type == VariableSourceType.StackVariableSourceType`), + then the storage location is the offset onto the stack that contains + the first byte of this variable. Otherwise it's used as an internal identifier. + """ _source_type: int index: int storage: int @property def identifier(self) -> int: + """A UID for a variable within a function.""" return core.BNToVariableIdentifier(self.to_BNVariable()) @property def source_type(self) -> VariableSourceType: + """Whether this variable was created based off of an underlying register, stack location, or flag.""" return VariableSourceType(self._source_type) def to_BNVariable(self): @@ -675,6 +687,16 @@ class CoreVariable: @dataclass(frozen=True, order=True) class VariableNameAndType(CoreVariable): + """ + ``class VariableNameAndType`` is a lightweight wrapper around a + variable and its name, useful for shuttling between APIs that require + them both. While :py:meth:`Variable` has :py:meth:`Variable.name` and + :py:meth:`Variable.type` fields, those require additional core calls + each time you fetch them. + + :cvar name: The variable's name + :cvar type: The variable's type + """ name: str type: 'binaryninja.types.Type' @@ -689,6 +711,10 @@ class VariableNameAndType(CoreVariable): class Variable(CoreVariable): + """ + ``class Variable`` represents variables in Binary Ninja. Variables are resolved + in medium level IL, so variables objects are only valid for MLIL and above. + """ def __init__(self, func: FunctionOrILFunction, source_type: VariableSourceType, index: int, storage: int): super(Variable, self).__init__(int(source_type), index, storage) if isinstance(func, binaryninja.function.Function): @@ -759,10 +785,12 @@ class Variable(CoreVariable): @property def core_variable(self) -> CoreVariable: + """Retrieve the underlying :py:meth:`CoreVariable` class""" return CoreVariable(self._source_type, self.index, self.storage) @property def var_name_and_type(self) -> VariableNameAndType: + """Convert to :py:meth:`VariableNameAndType` """ return VariableNameAndType.from_core_variable(self, self.name, self.type) @property @@ -794,7 +822,7 @@ class Variable(CoreVariable): @property def ssa_versions(self) -> Generator[int, None, None]: - """Returns the SSA versions associated with this variable. Doesn't return anything for aliased variables.""" + """Returns the SSA versions associated with this variable. Doesn't return anything for aliased variables.""" if self._il_function is None: raise NotImplementedError("No IL function associated with variable") @@ -825,6 +853,7 @@ class Variable(CoreVariable): @property def dead_store_elimination(self) -> DeadStoreElimination: + """returns the dead store elimination setting for this variable""" return DeadStoreElimination( core.BNGetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable()) ) |
