From 0a001f30888f68f63078f9763c98ee727d96bf29 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Tue, 15 Oct 2024 22:18:19 +1100 Subject: [PATCH] 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 Reviewed-by: Tino Reichardt Signed-off-by: Rob Norris Closes #16653 --- lib/libspl/backtrace.c | 44 +++++++++++++++++++++++++++++++++--------- 1 file 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