aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Norris <[email protected]>2024-10-15 22:18:19 +1100
committerBrian Behlendorf <[email protected]>2024-10-20 09:35:43 -0700
commit0a001f30888f68f63078f9763c98ee727d96bf29 (patch)
treefb75cd073869e8b0b7583adad5fc442d5ace2380
parent27e8f5610262177567b9aaebc6c9448d783aadd7 (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.c44
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