importctypesimportinspectfromtypingimportGenerator,Optional,List,Tuple,Union,Mapping,Any,Dict,Iteratorfromdataclassesimportdataclassfrom.importbinaryviewfrom.importfunctionfrom.import_binaryninjacoreascorefrom.importtypes[docs]classComponent:""" Components are objects that can contain Functions and other Components. They can be queried for information about the functions contained within them. Components have a Guid, which persistent across saves and loads of the database, and should be used for retrieving components when such is required and a reference to the Component cannot be held. """[docs]def__init__(self,handle=None):asserthandleisnotNone,"Cannot create component directly, run `bv.create_component?`"self.handle=handleself.guid=core.BNComponentGetGuid(self.handle) def__eq__(self,other):ifnotisinstance(other,Component):returnNotImplementedreturncore.BNComponentsEqual(self.handle,other.handle)def__ne__(self,other):ifnotisinstance(other,Component):returnNotImplementedreturncore.BNComponentsNotEqual(self.handle,other.handle)def__repr__(self):returnf'<Component "{self.display_name}" "({self.guid[:8]}...")>'def__del__(self):if(hasattr(self,'handle')):core.BNFreeComponent(self.handle)def__str__(self):returnself._sprawl_component(self)def__hash__(self):returnhash(self.guid)def_sprawl_component(self,c,depth=1,out=None):""" Recursive quick function to print out the component's tree of items :param c: Current cycle's component. On initial call, pass `self` :param depth: Current tree depth. :param out: Current text :return: """_out=([repr(c)]ifnotoutelseout.split('\n'))+[(' '*depth+repr(f))forfinc.functions]_out+=[' '*(depth+1)+repr(i)foriin(c.get_referenced_data_variables()+c.get_referenced_types())]foriinc.components:_out.append(' '*depth+repr(i))_out=self._sprawl_component(i,depth+1,'\n'.join(_out)).split('\n')return'\n'.join(_out)[docs]defadd_function(self,func:'function.Function')->bool:""" Add function to this component. :param func: Function to add :return: True if function was successfully added. """returncore.BNComponentAddFunctionReference(self.handle,func.handle) [docs]defcontains_function(self,func:'function.Function')->bool:""" Check whether this component contains a function. :param func: Function to check :return: True if this component contains the function. """returncore.BNComponentContainsFunction(self.handle,func.handle) [docs]defremove_function(self,func:'function.Function')->bool:""" Remove function from this component. :param func: Function to remove :return: True if function was successfully removed. """returncore.BNComponentRemoveFunctionReference(self.handle,func.handle) [docs]defadd_component(self,component:'Component')->bool:""" Move component to this component. This will remove it from the old parent. :param component: Component to add to this component. :return: True if the component was successfully moved to this component """returncore.BNComponentAddComponent(self.handle,component.handle) [docs]defcontains_component(self,component:'Component')->bool:""" Check whether this component contains a component. :param component: Component to check :return: True if this component contains the component. """returncore.BNComponentContainsComponent(self.handle,component.handle) [docs]defremove_component(self,component:'Component')->bool:""" Remove a component from the current component, moving it to the root. This function has no effect when used from the root component. Use `BinaryView.remove_component` to Remove a component from the tree entirely. :param component: Component to remove :return: """returnself.view.root_component.add_component(component) [docs]defadd_data_variable(self,data_variable):returncore.BNComponentAddDataVariable(self.handle,data_variable.address) [docs]defcontains_data_variable(self,data_variable):returncore.BNComponentContainsDataVariable(self.handle,data_variable.address) [docs]defremove_data_variable(self,data_variable):returncore.BNComponentRemoveDataVariable(self.handle,data_variable.address) @propertydefdisplay_name(self)->str:"""Original Name of the component (read-only)"""returncore.BNComponentGetDisplayName(self.handle)@propertydefname(self)->str:"""Original name set for this component :note: The `.display_name` property should be used for `bv.get_component_by_path()` lookups. This can differ from the .display_name property if one of its sibling components has the same .original_name; In that case, .name will be an automatically generated unique name (e.g. "MyComponentName (1)") while .original_name will remain what was originally set (e.g. "MyComponentName") If this component has a duplicate name and is moved to a component where none of its siblings share its name, the .name property will return the original "MyComponentName" """returncore.BNComponentGetOriginalName(self.handle)@name.setterdefname(self,_name):core.BNComponentSetName(self.handle,_name)@propertydefparent(self)->Optional['Component']:""" The component that contains this component, if it exists. """bn_component=core.BNComponentGetParent(self.handle)ifbn_componentisnotNone:returnComponent(bn_component)returnNone@propertydefview(self):bn_binaryview=core.BNComponentGetView(self.handle)ifbn_binaryviewisnotNone:returnbinaryview.BinaryView(handle=bn_binaryview)returnNone@propertydefcomponents(self)->List['Component']:""" ``components`` is an iterator for all Components contained within this Component :return: A list of components :Example: >>> for subcomp in component.components: ... print(repr(component)) """count=ctypes.c_ulonglong(0)bn_components=core.BNComponentGetContainedComponents(self.handle,count)components=[]try:foriinrange(count.value):components.append(Component(core.BNNewComponentReference(bn_components[i])))finally:core.BNFreeComponents(bn_components,count.value)returncomponents@propertydeffunction_list(self)->List['function.Function']:""" ``function_list`` List of all Functions contained within this Component :warning: .functions Should be used instead of this in any performance sensitive context. :return: A list of functions :Example: >>> for func in component.functions: ... print(func.name) """count=ctypes.c_ulonglong(0)bn_functions=core.BNComponentGetContainedFunctions(self.handle,count)funcs=[]try:foriinrange(count.value):bn_function=core.BNNewFunctionReference(bn_functions[i])funcs.append(function.Function(self.view,bn_function))finally:core.BNFreeFunctionList(bn_functions,count.value)returnfuncs@propertydeffunctions(self)->Iterator['function.Function']:""" ``functions`` is an iterator for all Functions contained within this Component :return: An iterator containing Components :rtype: ComponentIterator :Example: >>> for func in component.functions: ... print(func.name) """@dataclassclassFunctionIterator:view:'binaryview.BinaryView'comp:Componentdef__iter__(self):count=ctypes.c_ulonglong(0)bn_functions=core.BNComponentGetContainedFunctions(self.comp.handle,count)try:foriinrange(count.value):bn_function=core.BNNewFunctionReference(bn_functions[i])yieldfunction.Function(self.view,bn_function)finally:core.BNFreeFunctionList(bn_functions,count.value)returniter(FunctionIterator(self.view,self))@propertydefdata_variable_list(self):data_vars=[]count=ctypes.c_ulonglong(0)bn_data_vars=core.BNComponentGetContainedDataVariables(self.handle,count)try:foriinrange(count.value):bn_data_var=bn_data_vars[i]data_var=binaryview.DataVariable.from_core_struct(bn_data_var,self.view)data_vars.append(data_var)finally:core.BNFreeDataVariables(bn_data_vars,count.value)returndata_vars@propertydefdata_variables(self):@dataclassclassDataVariableIterator:view:'binaryview.BinaryView'comp:Componentdef__iter__(self):count=ctypes.c_ulonglong(0)bn_data_vars=core.BNComponentGetContainedDataVariables(self.comp.handle,count)try:foriinrange(count.value):bn_data_var=bn_data_vars[i]yieldbinaryview.DataVariable.from_core_struct(bn_data_var,self.view)finally:core.BNFreeDataVariables(bn_data_vars,count.value)returniter(DataVariableIterator(self.view,self))[docs]defget_referenced_data_variables(self,recursive=False):""" Get data variables referenced by this component :param recursive: Optional; Get all DataVariables referenced by this component and sub-components. :return: List of DataVariables """data_vars=[]count=ctypes.c_ulonglong(0)ifrecursive:bn_data_vars=core.BNComponentGetReferencedDataVariablesRecursive(self.handle,count)else:bn_data_vars=core.BNComponentGetReferencedDataVariables(self.handle,count)try:foriinrange(count.value):bn_data_var=bn_data_vars[i]data_var=binaryview.DataVariable.from_core_struct(bn_data_var,self.view)data_vars.append(data_var)finally:core.BNFreeDataVariables(bn_data_vars,count.value)returndata_vars [docs]defget_referenced_types(self,recursive=False):""" Get Types referenced by this component :param recursive: Optional; Get all Types referenced by this component and sub-components. :return: List of Types """_types=[]count=ctypes.c_ulonglong(0)ifrecursive:bn_types=core.BNComponentGetReferencedTypesRecursive(self.handle,count)else:bn_types=core.BNComponentGetReferencedTypes(self.handle,count)try:foriinrange(count.value):_types.append(types.Type.create(core.BNNewTypeReference(bn_types[i])))finally:core.BNComponentFreeReferencedTypes(bn_types,count.value)return_types