[docs]defget_class(self,class_name,init_class=False,step_func=None):""" Get a class descriptor for the class. :param str class_name: Name of class. :param bool init_class: Whether the class initializer <clinit> should be executed. :param func step_func: Callback function executed at every step of the simulation manager during the execution of the main <clinit> method """# try to get the soot class object from CLEjava_binary=self.state.javavm_registers.load("ip_binary")soot_class=java_binary.get_soot_class(class_name,none_if_missing=True)# create class descriptorclass_descriptor=SootClassDescriptor(class_name,soot_class)# load/initialize classifinit_class:self.init_class(class_descriptor,step_func=step_func)returnclass_descriptor
[docs]defget_superclass(self,class_):""" Get the superclass of the class. """ifnotclass_.is_loadedorclass_.superclass_nameisNone:returnNonereturnself.get_class(class_.superclass_name)
[docs]defget_class_hierarchy(self,base_class):""" Walks up the class hierarchy and returns a list of all classes between base class (inclusive) and java.lang.Object (exclusive). """classes=[base_class]whileclasses[-1]isnotNoneandclasses[-1]!="java.lang.Object":classes.append(self.get_superclass(classes[-1]))returnclasses[:-1]
[docs]defis_class_initialized(self,class_):""" Indicates whether the classes initializing method <clinit> was already executed on the state. """returnclass_inself.initialized_classes
[docs]definit_class(self,class_,step_func=None):""" This method simulates the loading of a class by the JVM, during which parts of the class (e.g. static fields) are initialized. For this, we run the class initializer method <clinit> (if available) and update the state accordingly. Note: Initialization is skipped, if the class has already been initialized (or if it's not loaded in CLE). """ifself.is_class_initialized(class_):l.debug("Class %r already initialized.",class_)returnl.debug("Initialize class %r.",class_)self.initialized_classes.add(class_)ifnotclass_.is_loaded:l.warning("Class %r is not loaded in CLE. Skip initializiation.",class_)returnclinit_method=resolve_method(self.state,"<clinit>",class_.name,include_superclasses=False,init_class=False)ifclinit_method.is_loaded:engine=UberEngine(self.state.project)# use a fresh engine, as the default engine instance may be in use at this timejavavm_simos=self.state.project.simosclinit_state=javavm_simos.state_call(addr=SootAddressDescriptor(clinit_method,0,0),base_state=self.state,ret_addr=SootAddressTerminator())simgr=self.state.project.factory.simgr(clinit_state)l.info(">"*15+" Run class initializer %r ... "+">"*15,clinit_method)simgr.run(step_func=step_func,engine=engine)l.debug("<"*15+" Run class initializer %r ... done "+"<"*15,clinit_method)# The only thing that can be updated during initialization are# static or rather global information, which are either stored on# the heap or in the vm_static_tableself.state.memory.vm_static_table=simgr.deadended[-1].memory.vm_static_table.copy()self.state.memory.heap=simgr.deadended[-1].memory.heap.copy()else:l.debug("Class initializer <clinit> is not loaded in CLE. Skip initializiation.")
@propertydefinitialized_classes(self):""" List of all initialized classes. """returnself._initialized_classes@SimStatePlugin.memodefcopy(self,memo):# pylint: disable=unused-argumentreturnSimJavaVmClassloader(initialized_classes=self.initialized_classes.copy())
[docs]defmerge(self,others,merge_conditions,common_ancestor=None):# pylint: disable=unused-argumentl.warning("Merging is not implemented for JavaVM classloader!")returnFalse
[docs]defwiden(self,others):# pylint: disable=unused-argumentl.warning("Widening is not implemented for JavaVM classloader!")returnFalse
# TODO use a default JavaVM preset# see for reference: angr/engines/__init__.pySimState.register_default("javavm_classloader",SimJavaVmClassloader)