printf("Pending handler = %p\n", data->pending_handler);
}
+void print_backtrace_frame(void *pc, void *fp)
+{
+ struct code *code = (struct code *) component_ptr_from_pc((lispobj *) pc);
+ if (code) {
+ struct compiled_debug_fun *df = debug_function_from_pc(code, pc);
+ if (df) {
+ print_entry_name(df->name);
+ } else {
+ print_entry_points(code);
+ }
+ } else {
+#ifdef LISP_FEATURE_OS_PROVIDES_DLADDR
+ Dl_info info;
+ if (dladdr(pc, &info)) {
+ printf("foreign function %s, fp = 0x%lx, pc = 0x%lx",
+ info.dli_sname,
+ (unsigned long) fp,
+ (unsigned long) pc);
+ } else
+#endif
+ printf("foreign fp = 0x%lx, pc = 0x%lx",
+ (unsigned long) fp,
+ (unsigned long) pc);
+ }
+ putchar('\n');
+}
+
/* This function has been split from backtrace() to enable Lisp
* backtraces from gdb with call backtrace_from_fp(...). Useful for
* example when debugging threading deadlocks.
int i;
for (i = 0; i < nframes; ++i) {
- lispobj *p;
void *ra;
void *next_fp;
break;
printf("%4d: ", i);
+ print_backtrace_frame(ra, next_fp);
- p = (lispobj *) component_ptr_from_pc((lispobj *) ra);
- if (p) {
- struct code *cp = (struct code *) p;
- struct compiled_debug_fun *df = debug_function_from_pc(cp, ra);
- if (df)
- print_entry_name(df->name);
- else
- print_entry_points(cp);
- } else {
-#ifdef LISP_FEATURE_OS_PROVIDES_DLADDR
- Dl_info info;
- if (dladdr(ra, &info)) {
- printf("Foreign function %s, fp = 0x%lx, ra = 0x%lx",
- info.dli_sname,
- (unsigned long) next_fp,
- (unsigned long) ra);
- } else
-#endif
- printf("Foreign fp = 0x%lx, ra = 0x%lx",
- (unsigned long) next_fp,
- (unsigned long) ra);
- }
-
- putchar('\n');
fp = next_fp;
}
}
backtrace_from_fp(fp, nframes);
}
+void
+backtrace_from_context(os_context_t *context, int nframes)
+{
+ void *fp = *(void **)os_context_register_addr(context, reg_FP);
+ void *pc = *(void **)os_context_pc_addr(context);
+
+ printf("interrupted in ");
+ print_backtrace_frame(pc, fp);
+
+ backtrace_from_fp(fp, nframes);
+}
+
#endif
static cmd backtrace_cmd, purify_cmd, catchers_cmd;
static cmd grab_sigs_cmd;
static cmd kill_cmd;
+static cmd backtrace_context_cmd;
static struct cmd {
char *cmd, *help;
{"help", "Display this help information.", help_cmd},
{"?", "(an alias for help)", help_cmd},
{"backtrace", "Backtrace up to N frames.", backtrace_cmd},
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+ {"cback", "Backtrace from interrupt context number I for up to N frames.", backtrace_context_cmd},
+#endif
{"catchers", "Print a list of all the active catchers.", catchers_cmd},
{"context", "Print interrupt context number I.", print_context_cmd},
{"dump", "Dump memory starting at ADDRESS for COUNT words.", dump_cmd},
#endif
printf("PC:\t\t 0x%08lx\n",
(unsigned long)(*os_context_pc_addr(context)));
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+ printf("interrupted in ");
+ print_backtrace_frame(*os_context_pc_addr(context),
+ *os_context_register_addr(context, reg_FP));
+#endif
}
static void
backtrace(n);
}
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+static void
+backtrace_context_cmd(char **ptr)
+{
+ void backtrace_from_context(os_context_t *context, int nframes);
+ int i;
+ int n;
+ int free_ici;
+ struct thread *thread=arch_os_get_current_thread();
+
+ free_ici = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread));
+
+ if (!free_ici) {
+ printf("There are no interrupt contexts!\n");
+ return;
+ }
+
+ if (more_p(ptr))
+ i = parse_number(ptr);
+ else
+ i = free_ici - 1;
+
+ if (more_p(ptr))
+ n = parse_number(ptr);
+ else
+ n = 100;
+
+ if ((i >= 0) && (i < free_ici)) {
+ printf("There are %d interrupt contexts.\n", free_ici);
+ } else {
+ printf("There aren't that many/few contexts.\n");
+ printf("There are %d interrupt contexts.\n", free_ici);
+ return;
+ }
+
+ printf("Backtrace from context %d:\n", i);
+ backtrace_from_context(thread->interrupt_contexts[i], n);
+}
+#endif
+
static void
catchers_cmd(char **ptr)
{