Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit