[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