def java_lang_System_identityHashCode__Ljava_lang_Object__I(frame, args): ref = args[0] if ref is None: frame.stack.append(0) return assert type(ref) is tuple assert ref[0] == "ref" o = frame.vm.heap[ref[1]] klass = o.java_class method = klass.find_method("hashCode", "()I") if method[0] & 0x0100 > 0: # assuming native call to object's hashCode, get heap id frame.stack.append(ref[1]) return pvm_thread = Thread(frame.vm, frame.vm.top_thread_ref) pvm_thread.is_alive = True m_args = [None] * method[1] m_args[0] = ref sub = Frame(pvm_thread, klass, method, m_args, "call get hashCode") pvm_thread.frame_stack.append(sub) frame.vm.run_thread(pvm_thread) assert sub.has_result frame.stack.append(sub.ret)
def __init__(self, _class_path="."): logger.debug("Creating VM") # Major memory structures self.perm_gen = {} self.heap = {} self.heap_next_id = 1 # todo clean up self.cache_klass_klass = {} self.global_strings = {} # Handle for linked list of threads self.threads_queue = deque() self.threads = [] self.non_daemons = 0 self.top_group = None self.top_thread = None self.top_group_ref = None self.top_thread_ref = None self.class_path = read_class_path(_class_path) self.init_default_thread() # Load System and init major fields system_class = self.get_class("java/lang/System") # Set System.props to vm owned object system_class.static_fields["props"][1] = ( "vm_ref", VM_OBJECTS["System.Properties"]) # STDout initialization using vm owned object ps_class = self.get_class("java/io/PrintStream") ps_object = ps_class.get_instance(self) ps_ref = self.add_to_heap(ps_object) method = ps_class.find_method("<init>", "(Ljava/io/OutputStream;)V") std_out_ref = ("vm_ref", VM_OBJECTS["Stdout.OutputStream"]) thread = Thread(self, None) frame = Frame(thread, ps_class, method, [ps_ref, std_out_ref], "PrintStream init") thread.frame_stack.append(frame) logger.debug("Run PrintStream init") self.run_thread(thread) # Run exclusive thread # <--thread added to the VM at this point system_class.static_fields["out"][1] = ps_ref system_class.static_fields["in"][1] = \ ("vm_ref", VM_OBJECTS["Stdin.InputputStream"]) # Additional parameters system_class.static_fields["lineSeparator"][1] = \ self.make_heap_string("\n") # Load additional classes to speed up booting self.touch_classes() self.initialized = True logger.debug("VM created")
def initialize_vm(self, main_klass, method, m_args): """ Run initialized vm with specific method of a class. This is class entered from command line. Method is looked up void main(String args[]). For more details see methods.txt in docs. :param main_klass: :param method: :param m_args: :return: """ t_klass = self.get_class("java/lang/Thread") t = t_klass.get_instance(self) t.fields["priority"] = 5 t.fields["name"] = self.make_heap_string("main") t.fields["blockerLock"] = self.add_to_heap( self.get_class("java/lang/Object").get_instance(self)) t_ref = self.add_to_heap(t) t.fields["group"] = self.top_group_ref pvm_thread = Thread(self, t_ref) pvm_thread.is_alive = True frame = Frame(pvm_thread, main_klass, method, m_args, "main") pvm_thread.frame_stack.append(frame) self.add_thread(pvm_thread) logger.debug("run thread pool")
def init_default_thread(self): '''Create initial thread group and thread. Both are java's objects ''' tg_klass = self.get_class("java/lang/ThreadGroup") t_klass = self.get_class("java/lang/Thread") tg = tg_klass.get_instance(self) t = t_klass.get_instance(self) tg.fields["name"] = self.make_heap_string("system") tg.fields["maxPriority"] = 10 t.fields["priority"] = 5 t.fields["name"] = self.make_heap_string("system-main") t.fields["blockerLock"] = self.add_to_heap( self.get_class("java/lang/Object").get_instance(self)) tg_ref = self.add_to_heap(tg) t_ref = self.add_to_heap(t) t.fields["group"] = tg_ref # Add thread to threadgroup; call byte code of void add(Thread) pvm_thread = Thread(self, t_ref) pvm_thread.is_alive = True method = tg_klass.find_method("add", "(Ljava/lang/Thread;)V") args = [None] * method[1] args[0] = tg_ref args[1] = t_ref frame = Frame(pvm_thread, tg_klass, method, args, "system tg init") pvm_thread.frame_stack.append(frame) self.run_thread(pvm_thread) self.top_group = tg self.top_thread = t self.top_group_ref = tg_ref self.top_thread_ref = t_ref
def java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction__Ljava_lang_Object_( frame, args): ref = args[0] assert type(ref) is tuple and ref[0] == "ref" o = frame.vm.heap[ref[1]] klass = o.java_class method = klass.find_method("run", "()Ljava/lang/Object;") args = [None] * method[1] args[0] = ref sub = Frame(frame.thread, klass, method, args, "RUN call in java_security_AccessController_doPrivileged") frame.thread.frame_stack.append(sub)
def java_lang_Thread_start0___V(frame, args): '''Create new thread with one's void run() see thread.txt for details ''' t_ref = args[0] o = frame.vm.heap[t_ref[1]] run = o.java_class.find_method("run", "()V") assert run is not None pvm_thread = Thread(frame.vm, t_ref) pvm_thread.is_alive = True m_args = [None] * run[1] m_args[0] = t_ref sub = Frame(pvm_thread, o.java_class, run, m_args, "Thread") pvm_thread.frame_stack.append(sub) frame.vm.add_thread(pvm_thread)
def run_static_constructor(self, java_class): '''Static constructor is run for every class loaded by class loader. It is executed in thread exclusive mode. ''' logger.debug("Running static constructor for %s", java_class.this_name) method = java_class.static_contructor() if method is None: logger.debug("No static constructor for %s", java_class.this_name) return pvm_thread = Thread(self, self.top_thread_ref) pvm_thread.is_alive = True frame = Frame(pvm_thread, java_class, method, [None] * method[1], "<clinit:{0}>".format(java_class.this_name)) pvm_thread.frame_stack.append(frame) self.run_thread(pvm_thread) logger.debug("Finished with static constructor for %s", java_class.this_name)
def raise_exception(self, frame, name): '''Util method to raise an exception based on name. e.g. java.lang.NullPointerException Exception is created on heap and throw op is called ''' ex_klass = self.get_class(name) ex = ex_klass.get_instance(self) ref = self.add_to_heap(ex) method = ex_klass.find_method("<init>", "()V") m_args = [None] * method[1] m_args[0] = ref pvm_thread = Thread(self, None) pvm_thread.is_alive = True sub = Frame(pvm_thread, ex_klass, method, m_args, "exinit") pvm_thread.frame_stack.append(sub) self.run_thread(pvm_thread) frame.stack.append(ref) get_operation('0xbf')(frame)
def sun_reflect_NativeConstructorAccessorImpl_newInstance0__Ljava_lang_reflect_Constructor__Ljava_lang_Object__Ljava_lang_Object_(frame, args): '''Create instance of a class, with constructor call''' ref = args[0] params = args[1] assert type(ref) is tuple and ref[0] == "ref" assert params is None or len(params) == 0 o = frame.vm.heap[ref[1]] klass_klass = frame.vm.heap[o.fields["clazz"][1]] clazz = frame.vm.get_class(klass_klass.fields["@CLASS_NAME"]) signature = str_to_string(frame.vm, o.fields["signature"]) assert signature == "()V" instance = clazz.get_instance(frame.vm) iref = frame.vm.add_to_heap(instance) frame.stack.append(iref) method = clazz.find_method("<init>", signature) # actully running constructor in exclusive mode pvm_thread = Thread(frame.vm, frame.vm.top_thread_ref) pvm_thread.is_alive = True m_args = [None]*method[1] m_args[0] = iref sub = Frame(pvm_thread, clazz, method, m_args, "nativ instance0") pvm_thread.frame_stack.append(sub) frame.vm.run_thread(pvm_thread)
def invokespecial(frame): index = (ord(frame.code[frame.pc]) << 8) + ord(frame.code[frame.pc + 1]) frame.pc += 2 cp_item = frame.this_class.constant_pool[index] assert cp_item[0] == 10 # CONSTANT_Methodref klass_info = frame.this_class.constant_pool[cp_item[1]] assert klass_info[0] == 7 # CONSTANT_Class_info name_and_type = frame.this_class.constant_pool[cp_item[2]] assert name_and_type[0] == 12 # name_and_type_index klass_name = frame.this_class.constant_pool[klass_info[1]][1] klass = frame.vm.get_class(klass_name) method_name = frame.this_class.constant_pool[name_and_type[1]][1] method_signature = frame.this_class.constant_pool[name_and_type[2]][1] method = klass.find_method(method_name, method_signature) logger.debug(klass_name) logger.debug(method_name) logger.debug(method_signature) logger.debug(frame.stack) if is_spec_lookup(frame.this_class, klass, method_name): method = None c = frame.this_class.super_class while method is None: if c is None: break if (method_name in c.methods and method_signature in c.methods[method_name]): method = c.methods[method_name][method_signature] klass = c break c = c.super_class assert method is not None nargs = args_count(method_signature) + 1 args = [None] * nargs while nargs > 0: value = frame.stack.pop() if type(value) is tuple and value[0] in ('long', 'double'): nargs -= 1 args[nargs - 1] = value nargs -= 1 assert len(args[0]) > 0 jassert_ref(args[0]) if args[0] is None: frame.vm.raise_exception(frame, "java/lang/NullPointerException") return if method[0] & 0x0100 > 0: # is native? exec_native(frame, args, klass, method_name, method_signature) return obj_mon = None if method[0] & 0x0020 > 0: # is sync obj_mon = frame.vm.heap[args[0][1]] if "@monitor" in obj_mon.fields: if obj_mon.fields["@monitor"] == frame.thread: obj_mon.fields["@monitor_count"] += 1 else: index = 0 while index < len(args): a = args[index] if type(a) is tuple and a[0] in ('long', 'double'): index += 1 else: frame.stack.append(a) index += 1 raise SkipThreadCycle() else: obj_mon.fields["@monitor"] = frame.thread obj_mon.fields["@monitor_count"] = 1 m_args = [''] * method[1] m_args[0:len(args)] = args[0:len(args)] instance = frame.vm.heap[args[0][1]] logger.debug("InvokeSpec: %s:%s %s", method_name, method_signature, instance) sub = Frame(frame.thread, klass, method, m_args, "%s:%s %s" % (method_name, method_signature, instance)) if obj_mon is not None: sub.monitor = obj_mon frame.thread.frame_stack.append(sub)
def invokevirtual(frame): index = (ord(frame.code[frame.pc]) << 8) + ord(frame.code[frame.pc + 1]) frame.pc += 2 cp_item = frame.this_class.constant_pool[index] assert cp_item[0] == 10 # CONSTANT_Methodref klass_info = frame.this_class.constant_pool[cp_item[1]] assert klass_info[0] == 7 # CONSTANT_Class_info name_and_type = frame.this_class.constant_pool[cp_item[2]] assert name_and_type[0] == 12 # name_and_type_index klass_name = frame.this_class.constant_pool[klass_info[1]][1] method_name = frame.this_class.constant_pool[name_and_type[1]][1] method_signature = frame.this_class.constant_pool[name_and_type[2]][1] logger.debug("%s %s %s", klass_name, method_name, method_signature) klass = frame.vm.get_class(klass_name) method = klass.find_method(method_name, method_signature) nargs = args_count(method_signature) + 1 args = [None] * nargs while nargs > 0: value = frame.stack.pop() if type(value) is tuple and value[0] in ('long', 'double'): nargs -= 1 args[nargs - 1] = value nargs -= 1 logger.debug(frame.id) logger.debug(args) logger.debug(method_signature) jassert_ref(args[0]) if args[0] is None: frame.vm.raise_exception(frame, "java/lang/NullPointerException") return if args[0][0] == "vm_ref": # vm owned object call vm_obj_call(frame, args, method_name, method_signature) return # ignore signute polimorphic method instance = frame.vm.heap[args[0][1]] klass = instance.java_class method = None while method is None and klass is not None: if method_name in klass.methods: if method_signature in klass.methods[method_name]: method = klass.methods[method_name][method_signature] break klass = klass.super_class assert method is not None assert klass is not None if method[0] & 0x0100 > 0: # is native? exec_native(frame, args, klass, method_name, method_signature) return obj_mon = None if method[0] & 0x0020 > 0: # is sync obj_mon = frame.vm.heap[args[0][1]] if "@monitor" in obj_mon.fields: if obj_mon.fields["@monitor"] == frame.thread: obj_mon.fields["@monitor_count"] += 1 else: index = 0 while index < len(args): a = args[index] if type(a) is tuple and a[0] in ('long', 'double'): index += 1 else: frame.stack.append(a) index += 1 raise SkipThreadCycle() else: obj_mon.fields["@monitor"] = frame.thread obj_mon.fields["@monitor_count"] = 1 m_args = [''] * method[1] m_args[0:len(args)] = args[0:len(args)] sub = Frame( frame.thread, klass, method, m_args, "InvVirt: %s %s in %s" % (method_name, method_signature, instance.java_class.this_name)) if obj_mon is not None: sub.monitor = obj_mon frame.thread.frame_stack.append(sub)
def op_0xb9(frame): # invokeinterface index = (ord(frame.code[frame.pc]) << 8) + ord(frame.code[frame.pc + 1]) frame.pc += 2 count = ord(frame.code[frame.pc]) assert count > 0 frame.pc += 1 zero = ord(frame.code[frame.pc]) assert zero == 0 frame.pc += 1 cp_item = frame.this_class.constant_pool[index] assert cp_item[0] == 11 # CONSTANT_Methodref klass_info = frame.this_class.constant_pool[cp_item[1]] assert klass_info[0] == 7 # CONSTANT_Class_info name_and_type = frame.this_class.constant_pool[cp_item[2]] assert name_and_type[0] == 12 # name_and_type_index klass_name = frame.this_class.constant_pool[klass_info[1]][1] method_name = frame.this_class.constant_pool[name_and_type[1]][1] method_signature = frame.this_class.constant_pool[name_and_type[2]][1] logger.debug("%s %s %s", klass_name, method_name, method_signature) frame.vm.get_class(klass_name) nargs = args_count(method_signature) + 1 args = [None] * nargs while nargs > 0: value = frame.stack.pop() if type(value) is tuple and value[0] in ('long', 'double'): nargs -= 1 args[nargs - 1] = value nargs -= 1 logger.debug(args) logger.debug(method_signature) assert len(args[0]) > 0 jassert_ref(args[0]) if args[0] is None: frame.vm.raise_exception(frame, "java/lang/NullPointerException") return if args[0][0] == "vm_ref": # vm owned object call vm_obj_call(frame, args, method_name, method_signature) return # ignore signute polimorphic method instance = frame.vm.heap[args[0][1]] klass = instance.java_class method = None while method is None and klass is not None: if method_name in klass.methods: if method_signature in klass.methods[method_name]: method = klass.methods[method_name][method_signature] break klass = klass.super_class assert method is not None if method[0] & 0x0100 > 0: # is native? exec_native(frame, args, klass, method_name, method_signature) return obj_mon = None if method[0] & 0x0020 > 0: # is sync obj_mon = frame.vm.heap[args[0][1]] if "@monitor" in obj_mon.fields: if obj_mon.fields["@monitor"] == frame.thread: obj_mon.fields["@monitor_count"] += 1 else: index = 0 while index < len(args): a = args[index] if type(a) is tuple and a[0] in ('long', 'double'): index += 1 else: frame.stack.append(a) index += 1 raise SkipThreadCycle() else: obj_mon.fields["@monitor"] = frame.thread obj_mon.fields["@monitor_count"] = 1 m_args = [''] * method[1] m_args[0:len(args)] = args[0:len(args)] sub = Frame(frame.thread, klass, method, m_args, "InvInt: %s %s in %s" % (method_name, method_signature, instance.java_class.this_name)) if obj_mon is not None: sub.monitor = obj_mon frame.thread.frame_stack.append(sub) return
def invokestatic(frame): index = (ord(frame.code[frame.pc]) << 8) + ord(frame.code[frame.pc + 1]) frame.pc += 2 cp_methodref = frame.this_class.constant_pool[index] assert cp_methodref[0] == 10 # CONSTANT_Methodref klass_info = frame.this_class.constant_pool[cp_methodref[1]] assert klass_info[0] == 7 # CONSTANT_Class_info name_and_type = frame.this_class.constant_pool[cp_methodref[2]] assert name_and_type[0] == 12 # name_and_type_index klass_name = frame.this_class.constant_pool[klass_info[1]][1] method_name = frame.this_class.constant_pool[name_and_type[1]][1] method_signature = frame.this_class.constant_pool[name_and_type[2]][1] assert klass_name is not None assert method_name is not None assert method_signature is not None if klass_name == "sun/misc/VM" and method_name == "isBooted": # shortcut, to be remvoed frame.stack.append(1) return if (klass_name == "sun/reflect/Reflection" and method_name == "registerMethodsToFilter"): logger.debug("Ignoring registerMethodsToFilter") frame.stack.pop() frame.stack.pop() return if (klass_name == "sun/misc/SharedSecrets" and method_name == "getJavaLangAccess"): # use vm owned object instead of constructing real one frame.vm.get_class("sun/misc/JavaLangAccess") frame.stack.append(("vm_ref", VM_OBJECTS["JavaLangAccess"])) return logger.debug("%s %s %s", klass_name, method_name, method_signature) klass = frame.vm.get_class(klass_name) method = klass.find_method(method_name, method_signature) assert method is not None assert method[0] & 0x0008 > 0 # make sure this is static method obj_mon = None if method[0] & 0x0020: obj_mon = frame.vm.heap[klass.heap_ref[1]] if "@monitor" in obj_mon.fields: if obj_mon.fields["@monitor"] == frame.thread: obj_mon.fields["@monitor_count"] += 1 else: raise SkipThreadCycle() else: obj_mon.fields["@monitor"] = frame.thread obj_mon.fields["@monitor_count"] = 1 nargs = args_count(method_signature) args = [None] * nargs while nargs > 0: value = frame.stack.pop() if type(value) is tuple and value[0] in ('long', 'double'): nargs -= 1 args[nargs - 1] = value nargs -= 1 if method[0] & 0x0100 > 0: # is native? exec_native(frame, args, klass, method_name, method_signature) return m_args = [''] * method[1] m_args[0:len(args)] = args[0:len(args)] logger.debug("InvStatic: %s %s in %s", method_name, method_signature, klass_name) if method_name == "countBits": frame.stack.append(5) return sub = Frame(frame.thread, klass, method, m_args, "InvStatic: %s %s in %s" % (method_name, method_signature, klass_name)) if obj_mon is not None: sub.monitor = obj_mon frame.thread.frame_stack.append(sub)
def invokestatic(frame): index = (ord(frame.code[frame.pc]) << 8) + ord(frame.code[frame.pc + 1]) frame.pc += 2 cp_methodref = frame.this_class.constant_pool[index] assert cp_methodref[0] == 10 # CONSTANT_Methodref klass_info = frame.this_class.constant_pool[cp_methodref[1]] assert klass_info[0] == 7 # CONSTANT_Class_info name_and_type = frame.this_class.constant_pool[cp_methodref[2]] assert name_and_type[0] == 12 # name_and_type_index klass_name = frame.this_class.constant_pool[klass_info[1]][1] method_name = frame.this_class.constant_pool[name_and_type[1]][1] method_signature = frame.this_class.constant_pool[name_and_type[2]][1] assert klass_name is not None assert method_name is not None assert method_signature is not None if klass_name == "sun/misc/VM" and method_name == "isBooted": # shortcut, to be remvoed frame.stack.append(1) return if (klass_name == "sun/reflect/Reflection" and method_name == "registerMethodsToFilter"): logger.debug("Ignoring registerMethodsToFilter") frame.stack.pop() frame.stack.pop() return if (klass_name == "sun/misc/SharedSecrets" and method_name == "getJavaLangAccess"): # use vm owned object instead of constructing real one frame.vm.get_class("sun/misc/JavaLangAccess") frame.stack.append(("vm_ref", VM_OBJECTS["JavaLangAccess"])) return logger.debug("%s %s %s", klass_name, method_name, method_signature) klass = frame.vm.get_class(klass_name) method = klass.find_method(method_name, method_signature) assert method is not None assert method[0] & 0x0008 > 0 # make sure this is static method obj_mon = None if method[0] & 0x0020: obj_mon = frame.vm.heap[klass.heap_ref[1]] if "@monitor" in obj_mon.fields: if obj_mon.fields["@monitor"] == frame.thread: obj_mon.fields["@monitor_count"] += 1 else: raise SkipThreadCycle() else: obj_mon.fields["@monitor"] = frame.thread obj_mon.fields["@monitor_count"] = 1 nargs = args_count(method_signature) args = [None] * nargs while nargs > 0: value = frame.stack.pop() if type(value) is tuple and value[0] in ('long', 'double'): nargs -= 1 args[nargs - 1] = value nargs -= 1 if method[0] & 0x0100 > 0: # is native? exec_native(frame, args, klass, method_name, method_signature) return m_args = [''] * method[1] m_args[0:len(args)] = args[0:len(args)] logger.debug("InvStatic: %s %s in %s", method_name, method_signature, klass_name) if method_name == "countBits": frame.stack.append(5) return sub = Frame( frame.thread, klass, method, m_args, "InvStatic: %s %s in %s" % (method_name, method_signature, klass_name)) if obj_mon is not None: sub.monitor = obj_mon frame.thread.frame_stack.append(sub)