[pypy-commit] pypy reverse-debugger: push and pull to get it to shape for the next step (which involves fork)

arigo pypy.commits at gmail.com
Tue Jun 7 15:19:33 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r85009:9734700e55f1
Date: 2016-06-07 21:20 +0200
http://bitbucket.org/pypy/pypy/changeset/9734700e55f1/

Log:	push and pull to get it to shape for the next step (which involves
	fork)

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
@@ -15,14 +15,10 @@
 static char rpy_rev_buffer[16384];
 static int rpy_rev_fileno = -1;
 
-#ifndef rpy_rdb_replay
-bool_t rpy_rdb_replay;
-#endif
-
 
 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(int exitcode, int *exitcode_p);
+static void check_at_end(int exitcode, int *exitcode_p, uint64_t stop_points);
 
 RPY_EXTERN
 void rpy_reverse_db_setup(int *argc_p, char **argv_p[])
@@ -31,17 +27,17 @@
 
     int replay_asked = (*argc_p >= 2 && !strcmp((*argv_p)[1], "--replay"));
 
-#ifdef rpy_rdb_replay
-    if (replay_asked != rpy_rdb_replay) {
+#ifdef RPY_RDB_DYNAMIC_REPLAY
+    RPY_RDB_REPLAY = replay_asked;
+#else
+    if (replay_asked != RPY_RDB_REPLAY) {
         fprintf(stderr, "This executable was only compiled for %s mode.",
-                rpy_rdb_replay ? "replay" : "record");
+                RPY_RDB_REPLAY ? "replay" : "record");
         exit(1);
     }
-#else
-    rpy_rdb_replay = replay_asked;
 #endif
 
-    if (rpy_rdb_replay)
+    if (RPY_RDB_REPLAY)
         setup_replay_mode(argc_p, argv_p);
     else
         setup_record_mode(*argc_p, *argv_p);
@@ -51,12 +47,15 @@
 void rpy_reverse_db_teardown(int *exitcode_p)
 {
     int exitcode;
+    uint64_t stop_points;
     RPY_REVDB_EMIT(exitcode = *exitcode_p; , int _e, exitcode);
+    RPY_REVDB_EMIT(stop_points = rpy_revdb.stop_point_seen; ,
+                   uint64_t _e, stop_points);
 
-    if (!rpy_rdb_replay)
+    if (!RPY_RDB_REPLAY)
         rpy_reverse_db_flush();
     else
-        check_at_end(exitcode, exitcode_p);
+        check_at_end(exitcode, exitcode_p, stop_points);
 }
 
 
@@ -70,7 +69,7 @@
     char *filename = getenv("PYPYREVDB");
     Signed x;
 
-    assert(!rpy_rdb_replay);
+    assert(RPY_RDB_REPLAY == 0);
     rpy_revdb.buf_p = rpy_rev_buffer;
     rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
 
@@ -132,19 +131,23 @@
 static void setup_replay_mode(int *argc_p, char **argv_p[])
 {
     Signed x;
-    char *filename = (*argc_p) <= 2 ? "-" : (*argv_p)[2];
+    int argc = *argc_p;
+    char **argv = *argv_p;
+    char *filename;
 
-    if (!strcmp(filename, "-")) {
-        rpy_rev_fileno = 0;   /* stdin */
+    if (argc != 3) {
+        fprintf(stderr, "syntax: %s --replay <RevDB-file>\n", argv[0]);
+        exit(2);
     }
-    else {
-        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);
-        }
+    filename = argv[2];
+
+    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);
+
+    assert(RPY_RDB_REPLAY == 1);
     rpy_revdb.buf_p = rpy_rev_buffer;
     rpy_revdb.buf_limit = rpy_rev_buffer;
 
@@ -171,13 +174,15 @@
 
     RPY_REVDB_EMIT(abort();, Signed _e, x);
     *argv_p = (char **)x;
+
+    rpy_revdb.stop_point_break = 1;
 }
 
-static void check_at_end(int exitcode, int *exitcode_p)
+static void check_at_end(int exitcode, int *exitcode_p, uint64_t stop_points)
 {
     char dummy[1];
-    if (*exitcode_p != exitcode) {
-        fprintf(stderr, "Bogus exit code\n");
+    if (stop_points != rpy_revdb.stop_point_seen) {
+        fprintf(stderr, "Bad number of stop points\n");
         exit(1);
     }
     if (rpy_revdb.buf_p != rpy_revdb.buf_limit ||
@@ -185,8 +190,12 @@
         fprintf(stderr, "RevDB file error: corrupted file (too much data?)\n");
         exit(1);
     }
-    printf("Replaying finished.\n");
-    rpy_reverse_db_stop_point(0);
+    if (*exitcode_p != exitcode) {
+        fprintf(stderr, "Bogus exit code\n");
+        exit(1);
+    }
+    printf("Replaying finished (exit code %d)\n", exitcode);
+    rpy_reverse_db_break(0);
     *exitcode_p = 0;
 }
 
@@ -219,9 +228,10 @@
 }
 
 RPY_EXTERN
-void rpy_reverse_db_stop_point(long stop_point)
+void rpy_reverse_db_break(long stop_point)
 {
-    printf("stop_point %ld\n", stop_point);
+    printf("break #%ld after %lld stop points\n", stop_point,
+           (long long)rpy_revdb.stop_point_seen);
 }
 
 
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
@@ -1,29 +1,36 @@
 #include <string.h>
+#include <stdint.h>
+
+/* 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 for it, which should be slightly faster (not tested so
+   far).
+*/
+
+typedef struct {
+#ifndef RPY_RDB_REPLAY
+    bool_t replay;
+#define RPY_RDB_REPLAY   rpy_revdb.replay
+#define RPY_RDB_DYNAMIC_REPLAY
+#endif
+    char *buf_p, *buf_limit;
+    uint64_t stop_point_seen, stop_point_break;
+} rpy_revdb_t;
+
+RPY_EXTERN rpy_revdb_t rpy_revdb;
+
+
+/* ------------------------------------------------------------ */
 
 RPY_EXTERN void rpy_reverse_db_setup(int *argc_p, char **argv_p[]);
 RPY_EXTERN void rpy_reverse_db_teardown(int *exitcode_p);
 
-typedef struct { char *buf_p, *buf_limit; } rpy_revdb_t;
-RPY_EXTERN rpy_revdb_t rpy_revdb;
-
-
-/* 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
-
-
-/* ------------------------------------------------------------ */
-
 
 #define RPY_REVDB_EMIT(normal_code, decl_e, variable)                   \
-    if (!rpy_rdb_replay) {                                              \
+    if (!RPY_RDB_REPLAY) {                                              \
         normal_code                                                     \
         {                                                               \
             decl_e = variable;                                          \
@@ -45,14 +52,15 @@
     }
 
 #define RPY_REVDB_EMIT_VOID(normal_code)                                \
-    if (!rpy_rdb_replay) { normal_code } else { }
+    if (!RPY_RDB_REPLAY) { normal_code } else { }
 
 #define OP_REVDB_STOP_POINT(stop_point, r)                              \
-    if (rpy_rdb_replay) rpy_reverse_db_stop_point(stop_point);
+    if (++rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break)      \
+        rpy_reverse_db_break(stop_point);
 
 RPY_EXTERN void rpy_reverse_db_flush(void);
 RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
-RPY_EXTERN void rpy_reverse_db_stop_point(long stop_point);
+RPY_EXTERN void rpy_reverse_db_break(long stop_point);
 
 
 /* ------------------------------------------------------------ */
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
@@ -25,6 +25,9 @@
         self.cur = p + struct.calcsize(mode)
         return struct.unpack_from(mode, self.buffer, p)[0]
 
+    def number_of_stop_points(self):
+        return struct.unpack_from("q", self.buffer, len(self.buffer) - 8)[0]
+
     def done(self):
         return self.cur == len(self.buffer)
 
@@ -91,6 +94,7 @@
         x = rdb.next(); assert x == len('[abc, d]\n')
         x = rdb.next('i'); assert x == 0      # errno
         x = rdb.next('i'); assert x == 9      # exitcode
+        x = rdb.next('q'); assert x == 0      # number of stop points
         # that's all that should get from this simple example
         assert rdb.done()
         #
@@ -98,8 +102,8 @@
         #
         # Now try the replay mode (just "doesn't crash" for now)
         out = replay()
-        assert out == ("Replaying finished.\n"
-                       "stop_point 0\n")
+        assert out == ("Replaying finished (exit code 9)\n"
+                       "break #0 after 0 stop points\n")
 
     def test_simple_interpreter(self):
         def main(argv):
@@ -108,9 +112,9 @@
                 print op
             return 9
         fn, replay = self.getcompiled(main, [], backendopt=False)
-        assert fn('abc d') == 'abc\nd\n'
+        assert fn('abc d ef') == 'abc\nd\nef\n'
+        assert self.fetch_rdb().number_of_stop_points() == 3
         out = replay()
-        assert out == ("stop_point 42\n"
-                       "stop_point 42\n"
-                       "Replaying finished.\n"
-                       "stop_point 0\n")
+        assert out == ("break #42 after 1 stop points\n"
+                       "Replaying finished (exit code 9)\n"
+                       "break #0 after 3 stop points\n")


More information about the pypy-commit mailing list