diff options
| author | Peter LaFosse <peter@vector35.com> | 2021-09-30 11:16:54 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2021-09-30 12:52:52 -0400 |
| commit | 3ec56b73b718e84fa5c40030fe27c2cdbff5c5f7 (patch) | |
| tree | daeda3aedb1d1af253c80a66c22a8d8c6f482ab2 /python | |
| parent | 670993d8e8559eff92d6d47cbf0a7c3a5a3ac998 (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.py | 93 | ||||
| -rw-r--r-- | python/function.py | 51 |
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") |
