Author: Armin Rigo <ar...@tunes.org> Branch: reverse-debugger Changeset: r85442:1e8833dfdd80 Date: 2016-06-29 08:20 +0200 http://bitbucket.org/pypy/pypy/changeset/1e8833dfdd80/
Log: in-progress diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py --- a/pypy/interpreter/pyframe.py +++ b/pypy/interpreter/pyframe.py @@ -813,9 +813,11 @@ def fget_f_builtins(self, space): return self.get_builtin().getdict(space) + def get_f_back(self): + return ExecutionContext.getnextframe_nohidden(self) + def fget_f_back(self, space): - f_back = ExecutionContext.getnextframe_nohidden(self) - return self.space.wrap(f_back) + return self.space.wrap(self.get_f_back()) def fget_f_lasti(self, space): return self.space.wrap(self.last_instr) diff --git a/pypy/interpreter/reverse_debugging.py b/pypy/interpreter/reverse_debugging.py --- a/pypy/interpreter/reverse_debugging.py +++ b/pypy/interpreter/reverse_debugging.py @@ -1,7 +1,9 @@ import sys from rpython.rlib import revdb from rpython.rlib.debug import make_sure_not_resized -from pypy.interpreter.error import oefmt +from pypy.interpreter.error import OperationError, oefmt +from pypy.interpreter.baseobjspace import W_Root +from pypy.interpreter import gateway, typedef class DBState: @@ -17,8 +19,8 @@ #make_sure_not_resized(dbstate.breakpoint_funcnames) #make_sure_not_resized(dbstate.watch_progs) make_sure_not_resized(dbstate.metavars) - #revdb.register_debug_command(revdb.CMD_PRINT, lambda_print) - #revdb.register_debug_command(revdb.CMD_BACKTRACE, lambda_backtrace) + revdb.register_debug_command(revdb.CMD_PRINT, lambda_print) + revdb.register_debug_command(revdb.CMD_BACKTRACE, lambda_backtrace) #revdb.register_debug_command(revdb.CMD_LOCALS, lambda_locals) #revdb.register_debug_command(revdb.CMD_BREAKPOINTS, lambda_breakpoints) #revdb.register_debug_command(revdb.CMD_MOREINFO, lambda_moreinfo) @@ -39,3 +41,103 @@ "'$%d' refers to an object created later in time", oparg) return w_var + +def fetch_cur_frame(): + ec = dbstate.space.getexecutioncontext() + frame = ec.topframeref() + if frame is None: + revdb.send_output("No stack.\n") + return frame + +def compile(source, mode): + space = dbstate.space + compiler = space.createcompiler() + code = compiler.compile(source, '<revdb>', mode, 0, + hidden_applevel=True) + return code + + +class W_RevDBOutput(W_Root): + softspace = 0 + + def __init__(self, space): + self.space = space + + def descr_write(self, w_buffer): + space = self.space + if space.isinstance_w(w_buffer, space.w_unicode): + w_buffer = space.call_method(w_buffer, 'encode', + space.wrap('utf-8')) # safe? + revdb.send_output(space.str_w(w_buffer)) + +W_RevDBOutput.typedef = typedef.TypeDef( + "revdb_output", + write = gateway.interp2app(W_RevDBOutput.descr_write), + softspace = typedef.interp_attrproperty("softspace", W_RevDBOutput), + ) + + +def command_print(cmd, expression): + frame = fetch_cur_frame() + if frame is None: + return + space = dbstate.space + try: + code = compile(expression, 'exec') + w_revdb_output = space.wrap(W_RevDBOutput(space)) + space.sys.setdictvalue(space, 'stdout', w_revdb_output) + space.sys.setdictvalue(space, 'stderr', w_revdb_output) + try: + code.exec_code(space, + frame.get_w_globals(), + frame.getdictscope()) + + except OperationError as operationerr: + w_type = operationerr.w_type + w_value = operationerr.get_w_value(space) + w_traceback = space.wrap(operationerr.get_traceback()) + + # set the sys.last_xxx attributes + space.setitem(space.sys.w_dict, space.wrap('last_type'), w_type) + space.setitem(space.sys.w_dict, space.wrap('last_value'), w_value) + space.setitem(space.sys.w_dict, space.wrap('last_traceback'), + w_traceback) + + # call sys.excepthook if present + w_hook = space.sys.getdictvalue(space, 'excepthook') + if w_hook is None: + raise + space.call_function(w_hook, w_type, w_value, w_traceback) + return + + except OperationError as e: + revdb.send_output('%s\n' % e.errorstr(space, use_repr=True)) + return +lambda_print = lambda: command_print + + +def show_frame(frame, indent=''): + code = frame.getcode() + lineno = frame.get_last_lineno() + revdb.send_output('%sFile "%s", line %d in %s\n%s ' % ( + indent, code.co_filename, lineno, code.co_name, indent)) + revdb.send_linecache(code.co_filename, lineno) + +def command_backtrace(cmd, extra): + frame = fetch_cur_frame() + if frame is None: + return + if cmd.c_arg1 == 0: + show_frame(frame) + else: + revdb.send_output("Traceback (most recent call last):\n") + frames = [] + while frame is not None: + frames.append(frame) + if len(frames) == 200: + revdb.send_output(" ...\n") + break + frame = frame.get_f_back() + while len(frames) > 0: + show_frame(frames.pop(), indent=' ') +lambda_backtrace = lambda: command_backtrace diff --git a/rpython/rlib/revdb.py b/rpython/rlib/revdb.py --- a/rpython/rlib/revdb.py +++ b/rpython/rlib/revdb.py @@ -18,6 +18,7 @@ CMD_ATTACHID = 6 CMD_CHECKWATCH = 7 CMD_WATCHVALUES = 8 +ANSWER_LINECACHE= 19 ANSWER_TEXT = 20 ANSWER_MOREINFO = 21 ANSWER_NEXTNID = 22 @@ -49,6 +50,9 @@ def send_watch(text, ok_flag): send_answer(ANSWER_WATCH, ok_flag, extra=text) +def send_linecache(filename, linenum): + send_answer(ANSWER_LINECACHE, linenum, extra=filename) + def current_time(): """For RPython debug commands: returns the current time.""" return llop.revdb_get_value(lltype.SignedLongLong, 'c') diff --git a/rpython/translator/revdb/message.py b/rpython/translator/revdb/message.py --- a/rpython/translator/revdb/message.py +++ b/rpython/translator/revdb/message.py @@ -47,6 +47,10 @@ # if breakpoint_mode=='i': ignored, never sent ANSWER_BREAKPOINT = -24 +# print one line of a file to the console, for CMD_PRINT +# Message(ANSWER_LINECACHE, linenum, extra=filename) +ANSWER_LINECACHE = 19 + # print text to the console, for CMD_PRINT and others # Message(ANSWER_TEXT, extra=text) ANSWER_TEXT = 20 diff --git a/rpython/translator/revdb/process.py b/rpython/translator/revdb/process.py --- a/rpython/translator/revdb/process.py +++ b/rpython/translator/revdb/process.py @@ -1,4 +1,5 @@ import sys, os, struct, socket, errno, subprocess +import linecache from rpython.translator.revdb import ancillary from rpython.translator.revdb.message import * @@ -170,6 +171,12 @@ elif msg.cmd == ANSWER_READY: self.update_times(msg) break + elif msg.cmd == ANSWER_LINECACHE: + line = linecache.getline(msg.extra, msg.arg1) + if not line.endswith('\n'): + line += '\n' + sys.stdout.write(line) + sys.stdout.flush() elif msg.cmd == ANSWER_NEXTNID and pgroup is not None: uid = msg.arg1 if uid < pgroup.initial_uid: @@ -507,6 +514,8 @@ def show_backtrace(self, complete=1): """Show the backtrace. """ + if complete: + self.active.tainted = True self.active.send(Message(CMD_BACKTRACE, complete)) self.active.print_text_answer() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit