xserver: Branch 'master' - 2 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 3 16:45:00 UTC 2022


 os/backtrace.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 75 insertions(+), 5 deletions(-)

New commits:
commit dc8162d5f0552ed1ab7c21692bcabf45b48c6467
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Thu May 27 17:06:16 2021 -0700

    os: print registers in the libunwind version of xorg_backtrace()
    
    If the stack walker finds a signal frame, record the cursor at that point and
    then use unw_get_reg() to query the values of the architecture-specific
    registers at the frame that triggered the signal.
    
    Example output:
    
     (EE) Backtrace:
     (EE) 0: hw/xfree86/Xorg (OsSigHandler+0x25) [0x561458bb8195]
     (EE) 1: <signal handler called>
     (EE) 2: hw/xfree86/Xorg (dix_main+0x9c) [0x561458aead6c]
     (EE) 3: /usr/lib/libc.so.6 (__libc_start_main+0xd5) [0x7f2d23170b25]
     (EE) 4: hw/xfree86/Xorg (_start+0x2e) [0x561458aad8be]
     (EE)
     (EE) Registers at frame #2:
     (EE)   rax: 0x0
     (EE)   rbx: 0x561458c3ae60
     (EE)   rcx: 0x7f2d23328943
     (EE)   rdx: 0x0
     (EE)   rsi: 0x7ffcb6025030
     (EE)   rdi: 0xe
     (EE)   rbp: 0x0
     (EE)   rsp: 0x7ffcb6026430
     (EE)    r8: 0x0
     (EE)    r9: 0x0
     (EE)   r10: 0x8
     (EE)   r11: 0x246
     (EE)   r12: 0x561458aad890
     (EE)   r13: 0x0
     (EE)   r14: 0x0
     (EE)   r15: 0x0
     (EE)
     (EE) Segmentation fault at address 0x0
    
    Signed-off-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/os/backtrace.c b/os/backtrace.c
index bf7ee68e2..8025bffae 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -40,15 +40,73 @@
 #endif
 #include <dlfcn.h>
 
+static void
+print_registers(int frame, unw_cursor_t cursor)
+{
+    const struct {
+        const char *name;
+        int regnum;
+    } regs[] = {
+#if UNW_TARGET_X86_64
+        { "rax", UNW_X86_64_RAX },
+        { "rbx", UNW_X86_64_RBX },
+        { "rcx", UNW_X86_64_RCX },
+        { "rdx", UNW_X86_64_RDX },
+        { "rsi", UNW_X86_64_RSI },
+        { "rdi", UNW_X86_64_RDI },
+        { "rbp", UNW_X86_64_RBP },
+        { "rsp", UNW_X86_64_RSP },
+        { " r8", UNW_X86_64_R8  },
+        { " r9", UNW_X86_64_R9  },
+        { "r10", UNW_X86_64_R10 },
+        { "r11", UNW_X86_64_R11 },
+        { "r12", UNW_X86_64_R12 },
+        { "r13", UNW_X86_64_R13 },
+        { "r14", UNW_X86_64_R14 },
+        { "r15", UNW_X86_64_R15 },
+#endif
+    };
+    const int num_regs = sizeof(regs) / sizeof(*regs);
+    int ret, i;
+
+    if (num_regs == 0)
+        return;
+
+    /*
+     * Advance the cursor from the signal frame to the one that triggered the
+     * signal.
+     */
+    frame++;
+    ret = unw_step(&cursor);
+    if (ret < 0) {
+        ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret);
+        return;
+    }
+
+    ErrorFSigSafe("\n");
+    ErrorFSigSafe("Registers at frame #%d:\n", frame);
+
+    for (i = 0; i < num_regs; i++) {
+        uint64_t val;
+        ret = unw_get_reg(&cursor, regs[i].regnum, &val);
+        if (ret < 0) {
+            ErrorFSigSafe("unw_get_reg(%s) failed: %s [%d]\n",
+                          regs[i].name, unw_strerror(ret), ret);
+        } else {
+            ErrorFSigSafe("  %s: 0x%" PRIx64 "\n", regs[i].name, val);
+        }
+    }
+}
+
 void
 xorg_backtrace(void)
 {
-    unw_cursor_t cursor;
+    unw_cursor_t cursor, signal_cursor;
     unw_context_t context;
     unw_word_t ip;
     unw_word_t off;
     unw_proc_info_t pip;
-    int ret, i = 0;
+    int ret, i = 0, signal_frame = -1;
     char procname[256];
     const char *filename;
     Dl_info dlinfo;
@@ -99,6 +157,9 @@ xorg_backtrace(void)
 
 
         if (unw_is_signal_frame(&cursor)) {
+            signal_cursor = cursor;
+            signal_frame = i;
+
             ErrorFSigSafe("%u: <signal handler called>\n", i++);
         } else {
             ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
@@ -110,6 +171,10 @@ xorg_backtrace(void)
         if (ret < 0)
             ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret);
     }
+
+    if (signal_frame >= 0)
+        print_registers(signal_frame, signal_cursor);
+
     ErrorFSigSafe("\n");
 }
 #else /* HAVE_LIBUNWIND */
commit a73641937a9e0df3a5d32f0dac7114d971abcd21
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Thu May 27 16:58:56 2021 -0700

    os: print <signal handler called> if unw_is_signal_frame()
    
    libunwind has a function to query whether the cursor points to a signal frame.
    Use this to print
    
     1: <signal handler called>
    
    like GDB does, rather than printing something less useful such as
    
     1: /usr/lib/libpthread.so.0 (funlockfile+0x60) [0x7f679838b870]
    
    Signed-off-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/os/backtrace.c b/os/backtrace.c
index 99d776950..bf7ee68e2 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -97,9 +97,14 @@ xorg_backtrace(void)
         else
             filename = "?";
 
-        ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
-            ret == -UNW_ENOMEM ? "..." : "", (int)off,
-            (void *)(uintptr_t)(ip));
+
+        if (unw_is_signal_frame(&cursor)) {
+            ErrorFSigSafe("%u: <signal handler called>\n", i++);
+        } else {
+            ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
+                ret == -UNW_ENOMEM ? "..." : "", (int)off,
+                (void *)(uintptr_t)(ip));
+        }
 
         ret = unw_step(&cursor);
         if (ret < 0)


More information about the xorg-commit mailing list