[pypy-commit] pypy reverse-debugger: By default, compile a single executable with both recording and
arigo
pypy.commits at gmail.com
Tue Jun 7 13:25:50 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r85003:5fd1d94677cf
Date: 2016-06-07 19:26 +0200
http://bitbucket.org/pypy/pypy/changeset/5fd1d94677cf/
Log: By default, compile a single executable with both recording and
replaying built in. Can compile a slightly faster single version by
#defining rpy_rdb_replay to either 0 or 1.
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
@@ -450,6 +450,11 @@
T = self.lltypemap(op.args[-1])
if T is Void:
result = '/* %s */' % result
+ 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)
return result
def OP_GETFIELD(self, op, ampersand=''):
diff --git a/rpython/translator/revdb/rdb-src/revdb.c b/rpython/translator/revdb/rdb-src/revdb.c
--- a/rpython/translator/revdb/rdb-src/revdb.c
+++ b/rpython/translator/revdb/rdb-src/revdb.c
@@ -1,5 +1,6 @@
#include "common_header.h"
#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
@@ -14,20 +15,59 @@
static char rpy_rev_buffer[16384];
static int rpy_rev_fileno = -1;
+#ifndef rpy_rdb_replay
+bool_t rpy_rdb_replay;
+#endif
-/* ------------------------------------------------------------ */
-#ifndef RPY_RDB_REPLAY
-/* ------------------------------------------------------------ */
+static void setup_record_mode(int argc, char *argv[]);
+static void setup_replay_mode(int *argc_p, char **argv_p[]);
+static void check_at_end(void);
RPY_EXTERN
void rpy_reverse_db_setup(int *argc_p, char **argv_p[])
{
/* init-time setup */
+ int replay_asked = (*argc_p >= 2 && !strcmp((*argv_p)[1], "--replay"));
+
+#ifdef rpy_rdb_replay
+ if (replay_asked != rpy_rdb_replay) {
+ fprintf(stderr, "This executable was only compiled for %s mode.",
+ rpy_rdb_replay ? "replay" : "record");
+ exit(1);
+ }
+#else
+ rpy_rdb_replay = replay_asked;
+#endif
+
+ if (rpy_rdb_replay)
+ setup_replay_mode(argc_p, argv_p);
+ else
+ setup_record_mode(*argc_p, *argv_p);
+}
+
+RPY_EXTERN
+void rpy_reverse_db_teardown(void)
+{
+ if (!rpy_rdb_replay)
+ rpy_reverse_db_flush();
+ else
+ check_at_end();
+}
+
+
+/* ------------------------------------------------------------ */
+/* Recording mode */
+/* ------------------------------------------------------------ */
+
+
+static void setup_record_mode(int argc, char *argv[])
+{
char *filename = getenv("PYPYREVDB");
Signed x;
+ assert(!rpy_rdb_replay);
rpy_revdb.buf_p = rpy_rev_buffer;
rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
@@ -43,18 +83,12 @@
atexit(rpy_reverse_db_flush);
}
- RPY_REVDB_EMIT(x = RDB_SIGNATURE;, Signed _e, x);
- RPY_REVDB_EMIT(x = RDB_VERSION;, Signed _e, x);
- RPY_REVDB_EMIT(x = 0;, Signed _e, x);
- RPY_REVDB_EMIT(x = 0;, Signed _e, x);
- RPY_REVDB_EMIT(x = *argc_p;, Signed _e, x);
- RPY_REVDB_EMIT(x = (Signed)*argv_p;, Signed _e, x);
-}
-
-RPY_EXTERN
-void rpy_reverse_db_teardown(void)
-{
- rpy_reverse_db_flush();
+ RPY_REVDB_EMIT(x = RDB_SIGNATURE; , Signed _e, x);
+ RPY_REVDB_EMIT(x = RDB_VERSION; , Signed _e, x);
+ RPY_REVDB_EMIT(x = 0; , Signed _e, x);
+ RPY_REVDB_EMIT(x = 0; , Signed _e, x);
+ RPY_REVDB_EMIT(x = argc; , Signed _e, x);
+ RPY_REVDB_EMIT(x = (Signed)argv; , Signed _e, x);
}
RPY_EXTERN
@@ -88,56 +122,55 @@
/* ------------------------------------------------------------ */
-#else
+/* Replaying mode */
/* ------------------------------------------------------------ */
-RPY_EXTERN
-void rpy_reverse_db_setup(int *argc_p, char **argv_p[])
+static void setup_replay_mode(int *argc_p, char **argv_p[])
{
Signed x;
+ char *filename = (*argc_p) <= 2 ? "-" : (*argv_p)[2];
- if (*argc_p <= 1) {
+ if (!strcmp(filename, "-")) {
rpy_rev_fileno = 0; /* stdin */
}
else {
- char *filename = (*argv_p)[1];
rpy_rev_fileno = open(filename, O_RDONLY | O_NOCTTY);
if (rpy_rev_fileno < 0) {
fprintf(stderr, "Can't open file '%s': %m\n", filename);
exit(1);
}
}
+ assert(rpy_rdb_replay);
rpy_revdb.buf_p = rpy_rev_buffer;
rpy_revdb.buf_limit = rpy_rev_buffer;
- RPY_REVDB_EMIT(*, Signed _e, x);
+ RPY_REVDB_EMIT(abort();, Signed _e, x);
if (x != RDB_SIGNATURE) {
fprintf(stderr, "stdin is not a RevDB file (or wrong platform)\n");
exit(1);
}
- RPY_REVDB_EMIT(*, Signed _e, x);
+ RPY_REVDB_EMIT(abort();, Signed _e, x);
if (x != RDB_VERSION) {
fprintf(stderr, "RevDB file version mismatch (got %lx, expected %lx)\n",
(long)x, (long)RDB_VERSION);
exit(1);
}
- RPY_REVDB_EMIT(*, Signed _e, x); /* ignored */
- RPY_REVDB_EMIT(*, Signed _e, x); /* ignored */
+ RPY_REVDB_EMIT(abort();, Signed _e, x); /* ignored */
+ RPY_REVDB_EMIT(abort();, Signed _e, x); /* ignored */
- RPY_REVDB_EMIT(*, Signed _e, x);
+ RPY_REVDB_EMIT(abort();, Signed _e, x);
if (x <= 0) {
fprintf(stderr, "RevDB file is bogus\n");
exit(1);
}
*argc_p = x;
- RPY_REVDB_EMIT(*, Signed _e, x);
+ RPY_REVDB_EMIT(abort();, Signed _e, x);
*argv_p = (char **)x;
}
-RPY_EXTERN
-void rpy_reverse_db_teardown(void)
+static void check_at_end(void)
{
char dummy[1];
if (rpy_revdb.buf_p != rpy_revdb.buf_limit ||
@@ -145,6 +178,7 @@
fprintf(stderr, "RevDB file error: corrupted file (too much data?)\n");
exit(1);
}
+ printf("Replaying finished.\n");
}
RPY_EXTERN
@@ -177,5 +211,3 @@
/* ------------------------------------------------------------ */
-#endif
-/* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/rdb-src/revdb_include.h b/rpython/translator/revdb/rdb-src/revdb_include.h
--- a/rpython/translator/revdb/rdb-src/revdb_include.h
+++ b/rpython/translator/revdb/rdb-src/revdb_include.h
@@ -7,51 +7,48 @@
RPY_EXTERN rpy_revdb_t rpy_revdb;
-/* ------------------------------------------------------------ */
-#ifndef RPY_RDB_REPLAY
+/* By default, this makes an executable which supports both recording
+ and replaying. It should help avoid troubles like using for
+ replaying an executable that is slightly different than the one
+ used for recording. In theory you can compile with
+ -Drpy_rdb_replay=0 or -Drpy_rdb_replay=1 to get only one version
+ compiled it (not tested so far).
+*/
+#ifndef rpy_rdb_replay
+RPY_EXTERN bool_t rpy_rdb_replay;
+#endif
+
+
/* ------------------------------------------------------------ */
-/* recording version of the macros */
#define RPY_REVDB_EMIT(normal_code, decl_e, variable) \
+ if (!rpy_rdb_replay) { \
normal_code \
- do { \
+ { \
decl_e = variable; \
memcpy(rpy_revdb.buf_p, &_e, sizeof(_e)); \
if ((rpy_revdb.buf_p += sizeof(_e)) > rpy_revdb.buf_limit) \
rpy_reverse_db_flush(); \
- } while (0)
+ } \
+ } else { \
+ decl_e; \
+ char *_src = rpy_revdb.buf_p; \
+ char *_end1 = _src + sizeof(_e); \
+ if (_end1 > rpy_revdb.buf_limit) { \
+ _src = rpy_reverse_db_fetch(sizeof(_e)); \
+ _end1 = _src + sizeof(_e); \
+ } \
+ rpy_revdb.buf_p = _end1; \
+ memcpy(&_e, _src, sizeof(_e)); \
+ variable = _e; \
+ }
+
#define RPY_REVDB_EMIT_VOID(normal_code) \
- normal_code
+ if (!rpy_rdb_replay) { normal_code } else { }
RPY_EXTERN void rpy_reverse_db_flush(void);
+RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
/* ------------------------------------------------------------ */
-#else
-/* ------------------------------------------------------------ */
-
-
-/* replaying version of the macros */
-#define RPY_REVDB_EMIT(normal_code, decl_e, variable) \
- do { \
- decl_e; \
- char *_src = rpy_revdb.buf_p; \
- char *_end1 = _src + sizeof(_e); \
- if (_end1 > rpy_revdb.buf_limit) { \
- _src = rpy_reverse_db_fetch(sizeof(_e)); \
- _end1 = _src + sizeof(_e); \
- } \
- rpy_revdb.buf_p = _end1; \
- memcpy(&_e, _src, sizeof(_e)); \
- variable = _e; \
- } while (0)
-#define RPY_REVDB_EMIT_VOID(normal_code) \
- /* nothing */
-
-RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
-
-
-/* ------------------------------------------------------------ */
-#endif
-/* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/revdb_genc.py b/rpython/translator/revdb/revdb_genc.py
--- a/rpython/translator/revdb/revdb_genc.py
+++ b/rpython/translator/revdb/revdb_genc.py
@@ -9,7 +9,10 @@
srcdir / 'revdb.c',
]
+def emit_void(normal_code):
+ return 'RPY_REVDB_EMIT_VOID(%s);' % (normal_code,)
+
def emit(normal_code, tp, value):
if tp == 'void @':
- return 'RPY_REVDB_EMIT_VOID(%s);' % (normal_code,)
+ return emit_void(normal_code)
return 'RPY_REVDB_EMIT(%s, %s, %s);' % (normal_code, cdecl(tp, '_e'), value)
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
@@ -87,5 +87,6 @@
#
assert got == [self.exename, 'abc', 'd']
#
- # Now try the replay mode
- xxx
+ # Now try the replay mode (just "doesn't crash" for now)
+ stdout = fn("--replay '%s'" % (self.rdbname,))
+ assert stdout == "Replaying finished.\n"
More information about the pypy-commit
mailing list