summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2021-09-30 11:16:54 -0400
committerPeter LaFosse <peter@vector35.com>2021-09-30 12:52:52 -0400
commit3ec56b73b718e84fa5c40030fe27c2cdbff5c5f7 (patch)
treedaeda3aedb1d1af253c80a66c22a8d8c6f482ab2 /python
parent670993d8e8559eff92d6d47cbf0a7c3a5a3ac998 (diff)
Allow string representation of types to be passed as parameters to methods which require Type objects
Diffstat (limited to 'python')
-rw-r--r--python/binaryview.py93
-rw-r--r--python/function.py51
2 files changed, 115 insertions, 29 deletions
diff --git a/python/binaryview.py b/python/binaryview.py
index d02aace3..a92479f3 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -74,6 +74,7 @@ NotificationType = Mapping['BinaryDataNotification', 'BinaryDataNotificationCall
ProgressFuncType = Callable[[int, int], bool]
DataMatchCallbackType = Callable[[int, 'databuffer.DataBuffer'], bool]
LineMatchCallbackType = Callable[[int, 'lineardisassembly.LinearDisassemblyLine'], bool]
+StringOrType = Union[str, '_types.Type', '_types.TypeBuilder']
class RelocationWriteException(Exception):
pass
@@ -3406,12 +3407,13 @@ class BinaryView:
"""
core.BNAbortAnalysis(self.handle)
- def define_data_var(self, addr:int, var_type:'_types.Type') -> None:
+ def define_data_var(self, addr:int, var_type:StringOrType, name:Optional[Union[str, '_types.CoreSymbol']]=None) -> None:
"""
``define_data_var`` defines a non-user data variable ``var_type`` at the virtual address ``addr``.
:param int addr: virtual address to define the given data variable
- :param Type var_type: type to be defined at the given virtual address
+ :param StringOrType var_type: type to be defined at the given virtual address
+ :param Optional[Union[str, '_types.CoreSymbol']] name: Optionally additionally define a symbol at this location
:rtype: None
:Example:
@@ -3419,17 +3421,30 @@ class BinaryView:
>>> t
(<type: int32_t>, 'foo')
>>> bv.define_data_var(bv.entry_point, t[0])
- >>>
+ >>> bv.define_data_var(bv.entry_point + 4, "int", "foo")
+ >>> bv.get_symbol_at(bv.entry_point + 4)
+ <DataSymbol: "foo" @ 0x23950>
+ >>> bv.get_data_var_at(bv.entry_point + 4)
+ <var 0x23950: int32_t>
"""
+
+ if isinstance(var_type, str):
+ (var_type, _) = self.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNDefineDataVariable(self.handle, addr, tc)
- def define_user_data_var(self, addr:int, var_type:'_types.Type') -> None:
+ if name is not None:
+ if isinstance(name, str):
+ name = _types.Symbol(SymbolType.DataSymbol, addr, name)
+ self.define_auto_symbol(name)
+
+ def define_user_data_var(self, addr:int, var_type:StringOrType, name:Optional[Union[str, '_types.CoreSymbol']]=None) -> None:
"""
``define_user_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``.
:param int addr: virtual address to define the given data variable
:param binaryninja.Type var_type: type to be defined at the given virtual address
+ :param Optional[Union[str, _types.CoreSymbol]] name: Optionally, additionally define a symbol at this same address
:rtype: None
:Example:
@@ -3437,11 +3452,23 @@ class BinaryView:
>>> t
(<type: int32_t>, 'foo')
>>> bv.define_user_data_var(bv.entry_point, t[0])
- >>>
+ >>> bv.define_user_data_var(bv.entry_point + 4, "int", "foo")
+ >>> bv.get_symbol_at(bv.entry_point + 4)
+ <DataSymbol: "foo" @ 0x23950>
+ >>> bv.get_data_var_at(bv.entry_point + 4)
+ <var 0x23950: int32_t>
"""
+
+ if isinstance(var_type, str):
+ (var_type, _) = self.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNDefineUserDataVariable(self.handle, addr, tc)
+ if name is not None:
+ if isinstance(name, str):
+ name = _types.Symbol(SymbolType.DataSymbol, addr, name)
+ self.define_user_symbol(name)
+
def undefine_data_var(self, addr:int) -> None:
"""
``undefine_data_var`` removes the non-user data variable at the virtual address ``addr``.
@@ -6089,14 +6116,14 @@ class BinaryView:
_name = _types.QualifiedName(name)._to_core_struct()
return core.BNIsAnalysisTypeAutoDefined(self.handle, _name)
- def define_type(self, type_id:str, default_name:'_types.QualifiedNameType', type_obj:'_types.Type') -> '_types.QualifiedName':
+ def define_type(self, type_id:str, default_name:Optional['_types.QualifiedNameType'], type_obj:StringOrType) -> '_types.QualifiedName':
"""
``define_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of types for
the current :py:Class:`BinaryView`. This method should only be used for automatically generated types.
:param str type_id: Unique identifier for the automatically generated type
:param QualifiedName default_name: Name of the type to be registered
- :param Type type_obj: Type object to be registered
+ :param StringOrType type_obj: Type object to be registered
:return: Registered name of the type. May not be the same as the requested name if the user has renamed types.
:rtype: QualifiedName
:Example:
@@ -6105,20 +6132,29 @@ class BinaryView:
>>> registered_name = bv.define_type(Type.generate_auto_type_id("source", name), name, type)
>>> bv.get_type_by_name(registered_name)
<type: int32_t>
+ >>> registered_name = bv.define_type("mytypeid", None, "int bar")
+ >>> bv.get_type_by_name(registered_name)
+ <type: int32_t>
"""
+
+ if isinstance(type_obj, str):
+ (type_obj, new_name) = self.parse_type_string(type_obj)
+ if default_name is None:
+ default_name = new_name
+ assert default_name is not None, "default_name can only be None if named type is derived from string passed to type_obj"
name = _types.QualifiedName(default_name)._to_core_struct()
reg_name = core.BNDefineAnalysisType(self.handle, type_id, name, type_obj.handle)
result = _types.QualifiedName._from_core_struct(reg_name)
core.BNFreeQualifiedName(reg_name)
return result
- def define_user_type(self, name:'_types.QualifiedNameType', type_obj:'_types.Type') -> None:
+ def define_user_type(self, name:Optional['_types.QualifiedNameType'], type_obj:StringOrType) -> None:
"""
``define_user_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of user
types for the current :py:Class:`BinaryView`.
:param QualifiedName name: Name of the user type to be registered
- :param Type type_obj: Type object to be registered
+ :param StringOrType type_obj: Type object to be registered
:rtype: None
:Example:
@@ -6126,7 +6162,15 @@ class BinaryView:
>>> bv.define_user_type(name, type)
>>> bv.get_type_by_name(name)
<type: int32_t>
+ >>> bv.define_user_type(None, "int bas")
+ >>> bv.get_type_by_name("bas")
+ <type: int32_t>
"""
+ if isinstance(type_obj, str):
+ (type_obj, new_name) = self.parse_type_string(type_obj)
+ if name is None:
+ name = new_name
+ assert name is not None, "name can only be None if named type is derived from string passed to type_obj"
_name = _types.QualifiedName(name)._to_core_struct()
core.BNDefineUserAnalysisType(self.handle, _name, type_obj.handle)
@@ -6235,7 +6279,7 @@ class BinaryView:
return None
return _types.Type.create(handle, platform = self.platform)
- def export_type_to_library(self, lib:typelibrary.TypeLibrary, name:str, type_obj:'_types.Type') -> None:
+ def export_type_to_library(self, lib:typelibrary.TypeLibrary, name:Optional[str], type_obj:StringOrType) -> None:
"""
``export_type_to_library`` recursively exports ``type_obj`` into ``lib`` as a type with name ``name``
@@ -6244,17 +6288,24 @@ class BinaryView:
:param TypeLibrary lib:
:param QualifiedName name:
- :param Type type_obj:
+ :param StringOrType type_obj:
:rtype: None
"""
- _name = _types.QualifiedName(name)
+ _name = None
+ if name is not None:
+ _name = _types.QualifiedName(name)
if not isinstance(lib, typelibrary.TypeLibrary):
raise ValueError("lib must be a TypeLibrary object")
- if not isinstance(type_obj, _types.Type):
+ if isinstance(type_obj, str):
+ (type_obj, new_name) = self.parse_type_string(type_obj)
+ if name is None:
+ _name = new_name
+ if not isinstance(type_obj, (_types.Type, _types.TypeBuilder)):
raise ValueError("type_obj must be a Type object")
+ assert _name is not None, "name can only be None if named type is derived from string passed to type_obj"
core.BNBinaryViewExportTypeToTypeLibrary(self.handle, lib.handle, _name._to_core_struct(), type_obj.handle)
- def export_object_to_library(self, lib:typelibrary.TypeLibrary, name:str, type_obj:'_types.Type') -> None:
+ def export_object_to_library(self, lib:typelibrary.TypeLibrary, name:Optional[str], type_obj:StringOrType) -> None:
"""
``export_object_to_library`` recursively exports ``type_obj`` into ``lib`` as an object with name ``name``
@@ -6263,14 +6314,22 @@ class BinaryView:
:param TypeLibrary lib:
:param QualifiedName name:
- :param Type type_obj:
+ :param StringOrType type_obj:
:rtype: None
"""
- _name = _types.QualifiedName(name)
+
+ _name = None
+ if name is not None:
+ _name = _types.QualifiedName(name)
if not isinstance(lib, typelibrary.TypeLibrary):
raise ValueError("lib must be a TypeLibrary object")
- if not isinstance(type_obj, _types.Type):
+ if isinstance(type_obj, str):
+ (type_obj, new_name) = self.parse_type_string(type_obj)
+ if name is None:
+ _name = new_name
+ if not isinstance(type_obj, (_types.Type, _types.TypeBuilder)):
raise ValueError("type_obj must be a Type object")
+ assert _name is not None, "name can only be None if named type is derived from string passed to type_obj"
core.BNBinaryViewExportObjectToTypeLibrary(self.handle, lib.handle, _name._to_core_struct(), type_obj.handle)
def register_platform_types(self, platform:'_platform.Platform') -> None:
diff --git a/python/function.py b/python/function.py
index f42e8582..c1d793fc 100644
--- a/python/function.py
+++ b/python/function.py
@@ -65,6 +65,7 @@ ILFunctionType = Union['lowlevelil.LowLevelILFunction', 'mediumlevelil.MediumLev
'highlevelil.HighLevelILFunction']
ILInstructionType = Union['lowlevelil.LowLevelILInstruction', 'mediumlevelil.MediumLevelILInstruction',
'highlevelil.HighLevelILInstruction']
+StringOrType = Union[str, '_types.Type', '_types.TypeBuilder']
def _function_name_():
return inspect.stack()[1][0].f_code.co_name
@@ -789,7 +790,7 @@ class Function:
return types.Type.create(core.BNGetFunctionType(self.handle), platform = self.platform)
@function_type.setter
- def function_type(self, value:'types.Type') -> None:
+ def function_type(self, value:Union['types.Type', str]) -> None: # type: ignore
if isinstance(value, str):
(value, new_name) = self.view.parse_type_string(value)
self.name = str(new_name)
@@ -908,11 +909,15 @@ class Function:
return types.Type.create(core.BNNewTypeReference(result.type), platform = self.platform, confidence = result.confidence)
@return_type.setter
- def return_type(self, value:'types.Type') -> None:
+ def return_type(self, value:StringOrType) -> None:
type_conf = core.BNTypeWithConfidence()
if value is None:
type_conf.type = None
type_conf.confidence = 0
+ elif isinstance(value, str):
+ (value, _) = self.view.parse_type_string(value)
+ type_conf.type = value
+ type_conf.confidence = core.max_confidence
else:
type_conf.type = value.handle
type_conf.confidence = value.confidence
@@ -2133,10 +2138,14 @@ class Function:
settings_obj = None
return flowgraph.CoreFlowGraph(core.BNCreateFunctionGraph(self.handle, graph_type, settings_obj))
- def apply_imported_types(self, sym:'types.CoreSymbol', type:'types.Type'=None) -> None:
+ def apply_imported_types(self, sym:'types.CoreSymbol', type:Optional[StringOrType]=None) -> None:
+ if isinstance(type, str):
+ (type, _) = self.view.parse_type_string(type)
core.BNApplyImportedTypes(self.handle, sym.handle, None if type is None else type.handle)
- def apply_auto_discovered_type(self, func_type:'types.Type') -> None:
+ def apply_auto_discovered_type(self, func_type:StringOrType) -> None:
+ if isinstance(func_type, str):
+ (func_type, _) = self.view.parse_type_string(func_type)
core.BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle)
def set_auto_indirect_branches(self, source:int, branches:List[Tuple['architecture.Architecture', int]],
@@ -2196,17 +2205,25 @@ class Function:
finally:
core.BNFreeInstructionTextLines(lines, count.value)
- def set_auto_type(self, value:'types.Type') -> None:
+ def set_auto_type(self, value:StringOrType) -> None:
+ if isinstance(value, str):
+ (value, _) = self.view.parse_type_string(value)
core.BNSetFunctionAutoType(self.handle, value.handle)
- def set_user_type(self, value:'types.Type') -> None:
+ def set_user_type(self, value:StringOrType) -> None:
+ if isinstance(value, str):
+ (value, _) = self.view.parse_type_string(value)
core.BNSetFunctionUserType(self.handle, value.handle)
- def set_auto_return_type(self, value:'types.Type') -> None:
+ def set_auto_return_type(self, value:StringOrType) -> None:
type_conf = core.BNTypeWithConfidence()
if value is None:
type_conf.type = None
type_conf.confidence = 0
+ elif isinstance(value, str):
+ (value, _) = self.view.parse_type_string(value)
+ type_conf.type = value
+ type_conf.confidence = core.max_confidence
else:
type_conf.type = value.handle
type_conf.confidence = value.confidence
@@ -2446,11 +2463,15 @@ class Function:
color = _highlight.HighlightColor(color)
core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._to_core_struct())
- def create_auto_stack_var(self, offset:int, var_type:'types.Type', name:str) -> None:
+ def create_auto_stack_var(self, offset:int, var_type:StringOrType, name:str) -> None:
+ if isinstance(var_type, str):
+ (var_type, _) = self.view.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNCreateAutoStackVariable(self.handle, offset, tc, name)
- def create_user_stack_var(self, offset:int, var_type:'types.Type', name:str) -> None:
+ def create_user_stack_var(self, offset:int, var_type:StringOrType, name:str) -> None:
+ if isinstance(var_type, str):
+ (var_type, _) = self.view.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNCreateUserStackVariable(self.handle, offset, tc, name)
@@ -2460,13 +2481,17 @@ class Function:
def delete_user_stack_var(self, offset:int) -> None:
core.BNDeleteUserStackVariable(self.handle, offset)
- def create_auto_var(self, var:'variable.Variable', var_type:'types.Type', name:str,
+ def create_auto_var(self, var:'variable.Variable', var_type:StringOrType, name:str,
ignore_disjoint_uses:bool=False) -> None:
+ if isinstance(var_type, str):
+ (var_type, _) = self.view.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNCreateAutoVariable(self.handle, var.to_BNVariable(), tc, name, ignore_disjoint_uses)
- def create_user_var(self, var:'variable.Variable', var_type:'types.Type', name:str,
+ def create_user_var(self, var:'variable.Variable', var_type:StringOrType, name:str,
ignore_disjoint_uses:bool=False) -> None:
+ if isinstance(var_type, str):
+ (var_type, _) = self.view.parse_type_string(var_type)
tc = var_type._to_core_struct()
core.BNCreateUserVariable(self.handle, var.to_BNVariable(), tc, name, ignore_disjoint_uses)
@@ -2555,8 +2580,10 @@ class Function:
core.BNSetAutoCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack,
adjust.value, adjust.confidence)
- def set_call_type_adjustment(self, addr:int, adjust_type:'types.Type', arch:Optional['architecture.Architecture']=None) -> \
+ def set_call_type_adjustment(self, addr:int, adjust_type:StringOrType, arch:Optional['architecture.Architecture']=None) -> \
None:
+ if isinstance(adjust_type, str):
+ (adjust_type, _) = self.view.parse_type_string(adjust_type)
if arch is None:
if self.arch is None:
raise Exception(f"Can't call {_function_name_()} for function with no architecture specified")