From 11b403cb230f7f447fa7b988412b9f07b89ac3b6 Mon Sep 17 00:00:00 2001 From: Zach Shaftel Date: Wed, 29 Apr 2020 13:13:44 -0400 Subject: [PATCH] Print byte offset of error in backtrace --- lisp/emacs-lisp/debug.el | 6 ++++-- src/bytecode.c | 5 +++-- src/eval.c | 14 +++++++++++++- src/lisp.h | 1 + 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index ed28997292f..db2943b6e73 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -335,8 +335,10 @@ That buffer should be current already and in debugger-mode." nil)) (setq backtrace-view (plist-put backtrace-view :show-flags t) - backtrace-insert-header-function (lambda () - (debugger--insert-header args)) + backtrace-insert-header-function + (lambda () + (insert (format "Byte-code offset of error: %d\n" (car (last args)))) + (debugger--insert-header args)) backtrace-print-function debugger-print-function) (backtrace-print) ;; Place point on "stack frame 0" (bug#15101). diff --git a/src/bytecode.c b/src/bytecode.c index 8ef84682035..1c98a516dbb 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -424,13 +424,14 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, Threading provides a performance boost. These macros are how we allow the code to be compiled both ways. */ #ifdef BYTE_CODE_THREADED +#define UPDATE_OFFSET (backtrace_byte_offset = pc - bytestr_data); /* The CASE macro introduces an instruction's body. It is either a label or a case label. */ #define CASE(OP) insn_ ## OP /* NEXT is invoked at the end of an instruction to go to the next instruction. It is either a computed goto, or a plain break. */ -#define NEXT goto *(targets[op = FETCH]) +#define NEXT UPDATE_OFFSET goto *(targets[op = FETCH]) /* FIRST is like NEXT, but is only used at the start of the interpreter body. In the switch-based interpreter it is the switch, so the threaded definition must include a semicolon. */ @@ -1448,7 +1449,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, unbind_to (count, Qnil); error ("binding stack not balanced (serious byte compiler bug)"); } - + backtrace_byte_offset = -1; Lisp_Object result = TOP; SAFE_FREE (); return result; diff --git a/src/eval.c b/src/eval.c index 4251c3e3304..82463c41747 100644 --- a/src/eval.c +++ b/src/eval.c @@ -56,6 +56,8 @@ Lisp_Object Vrun_hooks; /* FIXME: We should probably get rid of this! */ Lisp_Object Vsignaling_function; +int backtrace_byte_offset = -1; + /* These would ordinarily be static, but they need to be visible to GDB. */ bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; @@ -335,7 +337,10 @@ call_debugger (Lisp_Object arg) redisplay, which necessarily leads to display problems. */ specbind (Qinhibit_eval_during_redisplay, Qt); #endif - + if (backtrace_byte_offset >= 0) { + arg = CALLN(Fappend, arg, list1(make_fixnum(backtrace_byte_offset))); + backtrace_byte_offset = -1; + } val = apply1 (Vdebugger, arg); /* Interrupting redisplay and resuming it later is not safe under @@ -1695,6 +1700,13 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) /* Like xsignal, but takes 0, 1, 2, or 3 args instead of a list. */ +void +xsignal_with_offset (Lisp_Object error_symbol, Lisp_Object data, int bytecode_offset) +{ + backtrace_byte_offset = bytecode_offset; + xsignal(error_symbol, data); +} + void xsignal0 (Lisp_Object error_symbol) { diff --git a/src/lisp.h b/src/lisp.h index c9b069b56ca..ff60dfa8f0d 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4089,6 +4089,7 @@ extern Lisp_Object Vautoload_queue; extern Lisp_Object Vrun_hooks; extern Lisp_Object Vsignaling_function; extern Lisp_Object inhibit_lisp_code; +extern int backtrace_byte_offset; /* To run a normal hook, use the appropriate function from the list below. The calling convention: -- 2.39.5