Author: Armin Rigo <[email protected]>
Branch: reverse-debugger
Changeset: r85093:9b64e55324a4
Date: 2016-06-11 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/9b64e55324a4/
Log: Debug commands written in RPython
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -1125,6 +1125,13 @@
exc_data.exc_value = lltype.typeOf(evalue)._defl()
return bool(etype)
+ def op_revdb_stop_point(self, *args):
+ pass
+
+ def op_revdb_send_output(self, ll_string):
+ from rpython.rtyper.annlowlevel import hlstr
+ sys.stdout.write(hlstr(ll_string))
+
class Tracer(object):
Counter = 0
diff --git a/rpython/rtyper/lltypesystem/lloperation.py
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -566,6 +566,7 @@
'instrument_count': LLOp(),
'revdb_stop_point': LLOp(),
+ 'revdb_send_output': LLOp(),
}
# ***** Run test_lloperation after changes. *****
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
@@ -159,6 +159,10 @@
self.c_entrypoint_name = pfname
+ if self.config.translation.reverse_debugger:
+ from rpython.translator.revdb import revdb_genc
+ revdb_genc.prepare_database(db)
+
for obj in exports.EXPORTS_obj2name.keys():
db.getcontainernode(obj)
exports.clear()
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
@@ -7,6 +7,9 @@
#include <unistd.h>
#include <ctype.h>
+#include "preimpl.h"
+#include "structdef.h"
+#include "src/rtyper.h"
#include "rdb-src/revdb_include.h"
#define RDB_SIGNATURE 0x0A424452 /* "RDB\n" */
@@ -292,12 +295,36 @@
return rpy_rev_buffer;
}
+/* generated by RPython */
+extern char *rpy_revdb_command_names[];
+extern void (*rpy_revdb_command_funcs[])(RPyString *);
+
+static void execute_rpy_command(long index, char *arguments)
+{
+ size_t length = strlen(arguments);
+ RPyString *s;
+
+ while (length > 0 && isspace(arguments[length - 1]))
+ length--;
+ s = malloc(sizeof(RPyString) + length);
+ if (s == NULL) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ /* xxx assumes Boehm here for now */
+ memset(s, 0, sizeof(RPyString));
+ RPyString_Size(s) = length;
+ memcpy(_RPyString_AsString(s), arguments, length);
+
+ rpy_revdb_command_funcs[index](s);
+}
+
struct action_s {
const char *name;
void (*act)(char *);
};
-static void process_input(char *input, const char *kind,
+static void process_input(char *input, const char *kind, int rpycmd,
struct action_s actions[])
{
char *p;
@@ -310,24 +337,37 @@
p++;
if (*p != 0) {
*p = 0;
- p++;
+ do {
+ p++;
+ } while (isspace(*p));
}
- a = actions;
- while (a->name != NULL && strcmp(a->name, input) != 0) {
- a++;
+
+ if (rpycmd) {
+ long i;
+ for (i = 0; rpy_revdb_command_names[i] != NULL; i++) {
+ if (strcmp(rpy_revdb_command_names[i], input) == 0) {
+ execute_rpy_command(i, p);
+ return;
+ }
+ }
}
- if (a->name != NULL) {
- while (isspace(*p))
- p++;
- a->act(p);
+
+ for (a = actions; a->name != NULL; a++) {
+ if (strcmp(a->name, input) == 0) {
+ a->act(p);
+ return;
+ }
}
- else if (strcmp(input, "help") == 0) {
- a = actions;
+ if (strcmp(input, "help") == 0) {
printf("select %s:\n", kind);
- while (a->name != NULL) {
+ if (rpycmd) {
+ char **p;
+ for (p = rpy_revdb_command_names; *p != NULL; p++)
+ printf("\t%s\n", *p);
+ }
+ for (a = actions; a->name != NULL; a++) {
if (*a->name != 0)
printf("\t%s\n", a->name);
- a++;
}
}
else {
@@ -552,7 +592,7 @@
{ "fork", act_info_fork },
{ NULL }
};
- process_input(p, "category", actions_info);
+ process_input(p, "category", 0, actions_info);
}
static void act_nop(char *p)
@@ -588,9 +628,10 @@
fflush(stdout);
if (fgets(input, sizeof(input), stdin) != input) {
fprintf(stderr, "\n");
- strcpy(input, "exit");
+ act_quit("");
+ abort(); /* unreachable */
}
- process_input(input, "command", actions_1);
+ process_input(input, "command", 1, actions_1);
}
}
@@ -606,5 +647,11 @@
run_debug_process();
}
+RPY_EXTERN
+void rpy_reverse_db_send_output(RPyString *output)
+{
+ fwrite(_RPyString_AsString(output), 1, RPyString_Size(output), stdout);
+}
+
/* ------------------------------------------------------------ */
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
@@ -56,11 +56,15 @@
#define OP_REVDB_STOP_POINT(stop_point, r) \
if (++rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break) \
- rpy_reverse_db_break(stop_point);
+ rpy_reverse_db_break(stop_point)
+
+#define OP_REVDB_SEND_OUTPUT(ll_string, r) \
+ rpy_reverse_db_send_output(ll_string)
RPY_EXTERN void rpy_reverse_db_flush(void);
RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
RPY_EXTERN void rpy_reverse_db_break(long stop_point);
+RPY_EXTERN void rpy_reverse_db_send_output(RPyString *output);
/* ------------------------------------------------------------ */
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
@@ -1,6 +1,7 @@
import py
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import lltype, rffi, rstr
from rpython.translator.c.support import cdecl
+from rpython.rlib import exports
def extra_files():
@@ -16,3 +17,26 @@
if tp == 'void @':
return emit_void(normal_code)
return 'RPY_REVDB_EMIT(%s, %s, %s);' % (normal_code, cdecl(tp, '_e'),
value)
+
+
+def prepare_database(db):
+ FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Ptr(rstr.STR)], lltype.Void))
+
+ bk = db.translator.annotator.bookkeeper
+ cmds = getattr(db.translator, 'revdb_commands', {}).items()
+
+ array_names = lltype.malloc(rffi.CArray(rffi.CCHARP), len(cmds) + 1,
+ flavor='raw', immortal=True, zero=True)
+ array_funcs = lltype.malloc(rffi.CArray(FUNCPTR), len(cmds),
+ flavor='raw', immortal=True, zero=True)
+
+ for i, (name, func) in enumerate(cmds):
+ fnptr = lltype.getfunctionptr(bk.getdesc(func).getuniquegraph())
+ assert lltype.typeOf(fnptr) == FUNCPTR
+ array_names[i] = rffi.str2charp(name)
+ array_funcs[i] = fnptr
+
+ exports.EXPORTS_obj2name[array_names._as_obj()] = 'rpy_revdb_command_names'
+ exports.EXPORTS_obj2name[array_funcs._as_obj()] = 'rpy_revdb_command_funcs'
+ db.get(array_names)
+ db.get(array_funcs)
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
@@ -181,3 +181,29 @@
child.expectx('(3)$ ')
child.sendline('info fork')
child.expectx('latest_fork=3\r\n')
+
+
+class TestDebugCommands(InteractiveTests):
+
+ def setup_class(cls):
+ #
+ def blip(cmdline):
+ revdb.send_output('<<<' + cmdline + '>>>\n')
+ revdb.send_output('blipped\n')
+ lambda_blip = lambda: blip
+ #
+ def main(argv):
+ revdb.register_debug_command('r', lambda_blip)
+ for op in argv[1:]:
+ revdb.stop_point(42)
+ print op
+ return 9
+ compile(cls, main, [], backendopt=False)
+ assert run(cls, 'abc d ef') == 'abc\nd\nef\n'
+
+ def test_run_blip(self):
+ child = self.replay()
+ child.expectx('(3)$ ')
+ child.sendline('r foo bar baz ')
+ child.expectx('<<<foo bar baz>>>\r\nblipped\r\n')
+ child.expectx('(3)$ ')
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit