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 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 run_thread(self, thread, quota=-1): '''Run single thread according to quota. Quota is number of byte codes to be executed. Quota -1 runs entire thread in exclusive mode. For each byte code specific operation function is called. Operation can throw exception. Thread may be busy (e.g. monitor is not available). Returns from syncronized methods are handled. ''' frame_stack = thread.frame_stack while len(frame_stack) > 0: frame = frame_stack[-1] # get current if frame.pc < len(frame.code): op = frame.code[frame.pc] frame.cpc = frame.pc frame.pc += 1 # Make function name to be called op_call = hex(ord(op)) logger.debug("About to execute {2}: op_{0} ({3}) in {1}".format( op_call, frame.id, frame.pc - 1, get_operation_name(op_call))) opt = get_operation(op_call) if opt is None: raise Exception("Op ({0}) is not yet supported".format( op_call)) try: try: opt(frame) logger.debug("Stack:" + str(frame.stack)) except SkipThreadCycle: # Thread is busy, call the same operation later frame.pc = frame.cpc break except JavaException as jexc: # Exception handling ref = jexc.ref exc = self.heap[ref[1]] handled = False while not handled: for (start_pc, end_pc, handler_pc, catch_type, type_name) in frame.method[3]: if start_pc <= frame.cpc < end_pc and \ self.object_of_klass(exc, type_name): frame.pc = handler_pc frame.stack.append(ref) handled = True break if handled: break frame_stack.pop() if len(frame_stack) == 0: raise frame = frame_stack[-1] else: # Frame is done frame_stack.pop() if frame.monitor is not None: assert frame.monitor.fields["@monitor"] == frame.thread frame.monitor.fields["@monitor_count"] -= 1 if frame.monitor.fields["@monitor_count"] == 0: del frame.monitor.fields["@monitor"] del frame.monitor.fields["@monitor_count"] frame.monitor = None # handle possible return VALUE if frame.has_result: if len(frame_stack) > 0: frame_stack[-1].stack.append(frame.ret) if quota != -1: quota -= 1 if quota == 0: break
def run_thread(self, thread, quota=-1): '''Run single thread according to quota. Quota is number of byte codes to be executed. Quota -1 runs entire thread in exclusive mode. For each byte code specific operation function is called. Operation can throw exception. Thread may be busy (e.g. monitor is not available). Returns from syncronized methods are handled. ''' frame_stack = thread.frame_stack while len(frame_stack) > 0: frame = frame_stack[-1] # get current if frame.pc < len(frame.code): op = frame.code[frame.pc] frame.cpc = frame.pc frame.pc += 1 # Make function name to be called op_call = hex(ord(op)) logger.debug( "About to execute {2}: op_{0} ({3}) in {1}".format( op_call, frame.id, frame.pc - 1, get_operation_name(op_call))) opt = get_operation(op_call) if opt is None: raise Exception( "Op ({0}) is not yet supported".format(op_call)) try: try: opt(frame) logger.debug("Stack:" + str(frame.stack)) except SkipThreadCycle: # Thread is busy, call the same operation later frame.pc = frame.cpc break except JavaException as jexc: # Exception handling ref = jexc.ref exc = self.heap[ref[1]] handled = False while not handled: for (start_pc, end_pc, handler_pc, catch_type, type_name) in frame.method[3]: if start_pc <= frame.cpc < end_pc and \ self.object_of_klass(exc, type_name): frame.pc = handler_pc frame.stack.append(ref) handled = True break if handled: break frame_stack.pop() if len(frame_stack) == 0: raise frame = frame_stack[-1] else: # Frame is done frame_stack.pop() if frame.monitor is not None: assert frame.monitor.fields["@monitor"] == frame.thread frame.monitor.fields["@monitor_count"] -= 1 if frame.monitor.fields["@monitor_count"] == 0: del frame.monitor.fields["@monitor"] del frame.monitor.fields["@monitor_count"] frame.monitor = None # handle possible return VALUE if frame.has_result: if len(frame_stack) > 0: frame_stack[-1].stack.append(frame.ret) if quota != -1: quota -= 1 if quota == 0: break