Author: Armin Rigo <[email protected]>
Branch: reverse-debugger
Changeset: r85224:31c1d222566e
Date: 2016-06-18 09:05 +0200
http://bitbucket.org/pypy/pypy/changeset/31c1d222566e/
Log: Start the Python-side command-line reverse debugger
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -399,8 +399,8 @@
line += '\nPYPY_INHIBIT_TAIL_CALL();'
break
elif self.db.reverse_debugger:
- from rpython.translator.revdb import revdb_genc
- line = revdb_genc.emit(line, self.lltypename(v_result), r)
+ from rpython.translator.revdb import gencsupp
+ line = gencsupp.emit(line, self.lltypename(v_result), r)
return line
def OP_DIRECT_CALL(self, op):
@@ -441,9 +441,9 @@
if (S._gckind != 'gc' and not S._hints.get('is_excdata')
and not S._hints.get('static_immutable')
and not S._hints.get('ignore_revdb')):
- from rpython.translator.revdb import revdb_genc
- result = revdb_genc.emit(result, self.lltypename(op.result),
- newvalue)
+ from rpython.translator.revdb import gencsupp
+ result = gencsupp.emit(result, self.lltypename(op.result),
+ newvalue)
return result
def generic_set(self, op, targetexpr):
@@ -455,8 +455,8 @@
if self.db.reverse_debugger:
S = self.lltypemap(op.args[0]).TO
if S._gckind != 'gc' and not S._hints.get('is_excdata'):
- from rpython.translator.revdb import revdb_genc
- result = revdb_genc.emit_void(result)
+ from rpython.translator.revdb import gencsupp
+ result = gencsupp.emit_void(result)
return result
def OP_GETFIELD(self, op, ampersand=''):
@@ -586,8 +586,8 @@
expr_result,
is_atomic)
if self.db.reverse_debugger:
- from rpython.translator.revdb import revdb_genc
- res += revdb_genc.record_malloc_uid(expr_result)
+ from rpython.translator.revdb import gencsupp
+ res += gencsupp.record_malloc_uid(expr_result)
return res
def OP_BOEHM_MALLOC(self, op):
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -160,8 +160,8 @@
self.c_entrypoint_name = pfname
if self.config.translation.reverse_debugger:
- from rpython.translator.revdb import revdb_genc
- revdb_genc.prepare_database(db)
+ from rpython.translator.revdb import gencsupp
+ gencsupp.prepare_database(db)
for obj in exports.EXPORTS_obj2name.keys():
db.getcontainernode(obj)
@@ -855,8 +855,8 @@
if _CYGWIN:
files.append(srcdir / 'cygwin_wait.c')
if database.reverse_debugger:
- from rpython.translator.revdb import revdb_genc
- files += revdb_genc.extra_files()
+ from rpython.translator.revdb import gencsupp
+ files += gencsupp.extra_files()
return eci.merge(ExternalCompilationInfo(separate_module_files=files))
diff --git a/rpython/translator/revdb/ancillary.py
b/rpython/translator/revdb/ancillary.py
--- a/rpython/translator/revdb/ancillary.py
+++ b/rpython/translator/revdb/ancillary.py
@@ -1,5 +1,5 @@
+import py
import os, sys
-from rpython.tool.udir import udir
def build(tmpdir):
@@ -22,8 +22,12 @@
ffibuilder.compile(tmpdir=tmpdir, verbose=True)
-def import_():
- tmpdir = str(udir.ensure('ancillary', dir=1))
+def import_(verbose=False):
+ import rpython
+ basedir = py.path.local(rpython.__file__).dirpath()
+ tmpdir = str(basedir.ensure('_cache', 'ancillary', dir=1))
+ if verbose:
+ print tmpdir
old_sys_path = sys.path[:]
sys.path.insert(0, tmpdir)
try:
@@ -50,4 +54,4 @@
if __name__ == '__main__':
- import_()
+ import_(verbose=True)
diff --git a/rpython/translator/revdb/revdb_genc.py
b/rpython/translator/revdb/gencsupp.py
rename from rpython/translator/revdb/revdb_genc.py
rename to rpython/translator/revdb/gencsupp.py
diff --git a/rpython/translator/revdb/interact.py
b/rpython/translator/revdb/interact.py
new file mode 100644
--- /dev/null
+++ b/rpython/translator/revdb/interact.py
@@ -0,0 +1,76 @@
+import sys, re
+import subprocess, socket
+import traceback
+from rpython.translator.revdb.message import *
+
+r_cmdline = re.compile(r"(\S+)\s*(.*)")
+
+
+class RevDebugControl(object):
+
+ def __init__(self, revdb_log_filename, executable=None):
+ with open(revdb_log_filename, 'rb') as f:
+ header = f.readline()
+ fields = header.split('\t')
+ if len(fields) < 2 or fields[0] != 'RevDB:':
+ raise ValueError("file %r is not a RevDB log" % (
+ revdb_log_filename,))
+ if executable is None:
+ executable = fields[1]
+ #
+ s1, s2 = socket.socketpair()
+ subproc = subprocess.Popen(
+ [executable, '--revdb-replay', revdb_log_filename,
+ str(s2.fileno())])
+ s2.close()
+ self.subproc = subproc
+ child = ReplayProcess(subproc.pid, s1)
+ msg = child.expect(ANSWER_INIT, INIT_VERSION_NUMBER, Ellipsis)
+ self.total_stop_points = msg.arg2
+ child.expect(ANSWER_STD, 1, Ellipsis)
+ self.active_child = child
+ self.paused_children = {}
+
+ def interact(self):
+ last_command = ''
+ while True:
+ prompt = '(%d)$ ' % self.active_child.current_time()
+ try:
+ cmdline = raw_input(prompt).strip()
+ except EOFError:
+ print
+ cmdline = 'quit'
+ if not cmdline:
+ cmdline = last_command
+ match = r_cmdline.match(cmdline)
+ if not match:
+ continue
+ command, argument = match.groups()
+ try:
+ runner = getattr(self, 'command_' + command)
+ except AttributeError:
+ print >> sys.stderr, "no command '%s', try 'help'" % (command,)
+ else:
+ try:
+ runner(argument)
+ except Exception as e:
+ for line in traceback.format_exception_only(type(e), e):
+ sys.stderr.write(line)
+ last_command = cmdline
+
+ def command_help(self, argument):
+ """Display commands summary"""
+ print 'Available commands:'
+ for name in dir(self):
+ if name.startswith('command_'):
+ command = name[len('command_'):]
+ docstring = getattr(self, name).__doc__ or 'undocumented'
+ print '\t%s\t%s' % (command, docstring)
+
+ def command_quit(self, argument):
+ """Exit the reverse debugger"""
+ sys.exit(0)
+
+ def command_go(self, argument):
+ """Go to time ARG"""
+ target_time = int(argument)
diff --git a/rpython/translator/revdb/revmsg.py
b/rpython/translator/revdb/message.py
rename from rpython/translator/revdb/revmsg.py
rename to rpython/translator/revdb/message.py
--- a/rpython/translator/revdb/revmsg.py
+++ b/rpython/translator/revdb/message.py
@@ -88,3 +88,13 @@
def close(self):
self.send(Message(CMD_QUIT))
+
+ def forward(self, steps):
+ self.send(Message(CMD_FORWARD, steps))
+ return self.expect(ANSWER_STD, Ellipsis, Ellipsis)
+
+ def current_time(self):
+ return self.forward(0).arg1
+
+ def currently_created_objects(self):
+ return self.forward(0).arg2
diff --git a/rpython/translator/revdb/revdb.py
b/rpython/translator/revdb/revdb.py
new file mode 100755
--- /dev/null
+++ b/rpython/translator/revdb/revdb.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+import sys, os
+
+
+if __name__ == '__main__':
+ import argparse
+ parser = argparse.ArgumentParser(description='Reverse debugger')
+ parser.add_argument('log', metavar='LOG', help='log file name')
+ parser.add_argument('-x', '--executable', dest='executable',
+ help='name of the executable file '
+ 'that recorded the log')
+ options = parser.parse_args(sys.argv[1:])
+
+ sys.path.insert(0, os.path.abspath(
+ os.path.join(__file__, '..', '..', '..', '..')))
+
+ from rpython.translator.revdb.interact import RevDebugControl
+ ctrl = RevDebugControl(options.log, executable=options.executable)
+ ctrl.interact()
diff --git a/rpython/translator/revdb/src-revdb/revdb.c
b/rpython/translator/revdb/src-revdb/revdb.c
--- a/rpython/translator/revdb/src-revdb/revdb.c
+++ b/rpython/translator/revdb/src-revdb/revdb.c
@@ -120,7 +120,7 @@
write_all(RDB_SIGNATURE, strlen(RDB_SIGNATURE));
for (i = 0; i < argc; i++) {
- write_all(" ", 1);
+ write_all("\t", 1);
write_all(argv[i], strlen(argv[i]));
}
write_all("\n\0", 2);
@@ -336,7 +336,7 @@
}
fprintf(stderr, "%s", RDB_SIGNATURE);
while ((read_all(input, 1), input[0] != 0))
- fputc(input[0], stderr);
+ fputc(input[0] == '\t' ? ' ' : input[0], stderr);
read_all(&h, sizeof(h));
if (h.version != RDB_VERSION) {
diff --git a/rpython/translator/revdb/test/test_basic.py
b/rpython/translator/revdb/test/test_basic.py
--- a/rpython/translator/revdb/test/test_basic.py
+++ b/rpython/translator/revdb/test/test_basic.py
@@ -9,7 +9,7 @@
from rpython.rtyper.annlowlevel import cast_gcref_to_instance
from rpython.rtyper.lltypesystem import lltype, llmemory
-from rpython.translator.revdb.revmsg import *
+from rpython.translator.revdb.message import *
class RDB(object):
@@ -17,7 +17,7 @@
with open(filename, 'rb') as f:
header = f.readline()
self.buffer = f.read()
- assert header == 'RevDB: ' + ' '.join(expected_argv) + '\n'
+ assert header == 'RevDB:\t' + '\t'.join(expected_argv) + '\n'
#
self.cur = 0
x = self.next('c'); assert x == '\x00'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit