Backtrace and interrupt context display improvements for x86oids.
authorAlastair Bridgewater <nyef_sbcl@lisphacker.com>
Wed, 23 Dec 2009 03:03:08 +0000 (22:03 -0500)
committerAlastair Bridgewater <nyef_sbcl@lisphacker.com>
Sun, 27 Dec 2009 14:53:35 +0000 (09:53 -0500)
  * Refactored x86oid backtrace code.

  * Context display now shows current call site on x86oids.

  * New LDB command on x86oids, "cback", backtrace starting at given
interrupt context.

src/runtime/backtrace.c
src/runtime/monitor.c

index 996357e..dad9482 100644 (file)
@@ -523,6 +523,33 @@ describe_thread_state(void)
     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.
@@ -533,7 +560,6 @@ backtrace_from_fp(void *fp, int nframes)
   int i;
 
   for (i = 0; i < nframes; ++i) {
-    lispobj *p;
     void *ra;
     void *next_fp;
 
@@ -541,31 +567,8 @@ backtrace_from_fp(void *fp, int nframes)
       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;
   }
 }
@@ -586,4 +589,16 @@ backtrace(int nframes)
   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
index 5bc83c3..8c93d39 100644 (file)
@@ -65,6 +65,7 @@ static cmd print_context_cmd;
 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;
@@ -73,6 +74,9 @@ static struct cmd {
     {"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},
@@ -354,6 +358,11 @@ print_context(os_context_t *context)
 #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
@@ -403,6 +412,46 @@ backtrace_cmd(char **ptr)
     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)
 {