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@nvidia.com>
This commit is contained in:
parent
a73641937a
commit
dc8162d5f0
|
@ -40,15 +40,73 @@
|
||||||
#endif
|
#endif
|
||||||
#include <dlfcn.h>
|
#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
|
void
|
||||||
xorg_backtrace(void)
|
xorg_backtrace(void)
|
||||||
{
|
{
|
||||||
unw_cursor_t cursor;
|
unw_cursor_t cursor, signal_cursor;
|
||||||
unw_context_t context;
|
unw_context_t context;
|
||||||
unw_word_t ip;
|
unw_word_t ip;
|
||||||
unw_word_t off;
|
unw_word_t off;
|
||||||
unw_proc_info_t pip;
|
unw_proc_info_t pip;
|
||||||
int ret, i = 0;
|
int ret, i = 0, signal_frame = -1;
|
||||||
char procname[256];
|
char procname[256];
|
||||||
const char *filename;
|
const char *filename;
|
||||||
Dl_info dlinfo;
|
Dl_info dlinfo;
|
||||||
|
@ -99,6 +157,9 @@ xorg_backtrace(void)
|
||||||
|
|
||||||
|
|
||||||
if (unw_is_signal_frame(&cursor)) {
|
if (unw_is_signal_frame(&cursor)) {
|
||||||
|
signal_cursor = cursor;
|
||||||
|
signal_frame = i;
|
||||||
|
|
||||||
ErrorFSigSafe("%u: <signal handler called>\n", i++);
|
ErrorFSigSafe("%u: <signal handler called>\n", i++);
|
||||||
} else {
|
} else {
|
||||||
ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
|
ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
|
||||||
|
@ -110,6 +171,10 @@ xorg_backtrace(void)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret);
|
ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signal_frame >= 0)
|
||||||
|
print_registers(signal_frame, signal_cursor);
|
||||||
|
|
||||||
ErrorFSigSafe("\n");
|
ErrorFSigSafe("\n");
|
||||||
}
|
}
|
||||||
#else /* HAVE_LIBUNWIND */
|
#else /* HAVE_LIBUNWIND */
|
||||||
|
|
Loading…
Reference in New Issue