diff options
author | Rob Norris <[email protected]> | 2024-10-15 22:18:19 +1100 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2024-10-20 09:35:43 -0700 |
commit | 0a001f30888f68f63078f9763c98ee727d96bf29 (patch) | |
tree | fb75cd073869e8b0b7583adad5fc442d5ace2380 | |
parent | 27e8f5610262177567b9aaebc6c9448d783aadd7 (diff) |
libspl/backtrace: dump registers in libunwind backtraces
More useful stuff, especially when trying to follow a disassembly.
Sponsored-by: https://despairlabs.com/sponsor/
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Tino Reichardt <[email protected]>
Signed-off-by: Rob Norris <[email protected]>
Closes #16653
-rw-r--r-- | lib/libspl/backtrace.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/lib/libspl/backtrace.c b/lib/libspl/backtrace.c index d26d74210..e969823c2 100644 --- a/lib/libspl/backtrace.c +++ b/lib/libspl/backtrace.c @@ -65,32 +65,58 @@ libspl_backtrace(int fd) ssize_t ret __attribute__((unused)); unw_context_t uc; unw_cursor_t cp; - unw_word_t loc; + unw_word_t v; char buf[128]; - size_t n; + size_t n, c; - ret = write(fd, "Call trace:\n", 12); unw_getcontext(&uc); + unw_init_local(&cp, &uc); + ret = write(fd, "Registers:\n", 11); + c = 0; + for (uint_t regnum = 0; regnum <= UNW_TDEP_LAST_REG; regnum++) { + if (unw_get_reg(&cp, regnum, &v) < 0) + continue; + const char *name = unw_regname(regnum); + for (n = 0; name[n] != '\0' && name[n] != '?'; n++) {} + if (n == 0) { + buf[0] = '?'; + n = libspl_u64_to_hex_str(regnum, 2, + &buf[1], sizeof (buf)-1) + 1; + name = buf; + } + ret = write(fd, " ", 5-MIN(n, 3)); + ret = write(fd, name, n); + ret = write(fd, ": 0x", 4); + n = libspl_u64_to_hex_str(v, 18, buf, sizeof (buf)); + ret = write(fd, buf, n); + if (!(++c % 3)) + ret = write(fd, "\n", 1); + } + if (c % 3) + ret = write(fd, "\n", 1); + + unw_init_local(&cp, &uc); + ret = write(fd, "Call trace:\n", 12); while (unw_step(&cp) > 0) { - unw_get_reg(&cp, UNW_REG_IP, &loc); + unw_get_reg(&cp, UNW_REG_IP, &v); ret = write(fd, " [0x", 5); - n = libspl_u64_to_hex_str(loc, 10, buf, sizeof (buf)); + n = libspl_u64_to_hex_str(v, 18, buf, sizeof (buf)); ret = write(fd, buf, n); ret = write(fd, "] ", 2); - unw_get_proc_name(&cp, buf, sizeof (buf), &loc); + unw_get_proc_name(&cp, buf, sizeof (buf), &v); for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {} ret = write(fd, buf, n); ret = write(fd, "+0x", 3); - n = libspl_u64_to_hex_str(loc, 2, buf, sizeof (buf)); + n = libspl_u64_to_hex_str(v, 2, buf, sizeof (buf)); ret = write(fd, buf, n); #ifdef HAVE_LIBUNWIND_ELF ret = write(fd, " (in ", 5); - unw_get_elf_filename(&cp, buf, sizeof (buf), &loc); + unw_get_elf_filename(&cp, buf, sizeof (buf), &v); for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {} ret = write(fd, buf, n); ret = write(fd, " +0x", 4); - n = libspl_u64_to_hex_str(loc, 2, buf, sizeof (buf)); + n = libspl_u64_to_hex_str(v, 2, buf, sizeof (buf)); ret = write(fd, buf, n); ret = write(fd, ")", 1); #endif |