[pypy-commit] pypy reverse-debugger: in-progress
arigo
pypy.commits at gmail.com
Wed Jun 29 02:19:15 EDT 2016
Author: Armin Rigo <arigo at 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()
More information about the pypy-commit
mailing list