diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-11-18 19:33:51 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-11-18 19:33:51 +1100 |
commit | c38c2e8d08e03e905b72334747a9f8795f3526c2 (patch) | |
tree | 94a7e5ec6124998eee1d1a27577370b03304c4e6 /core | |
parent | 94796c825b0708c8c86e7135d60c435fc3fd00a5 (diff) | |
download | skiboot-c38c2e8d08e03e905b72334747a9f8795f3526c2.zip skiboot-c38c2e8d08e03e905b72334747a9f8795f3526c2.tar.gz skiboot-c38c2e8d08e03e905b72334747a9f8795f3526c2.tar.bz2 |
Add symbolic backtraces and expose skiboot map to Linux
We use a double link technique, doing a first pass with a .o containing
a dummy symbol map, then re-linking with a new .o
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'core')
-rw-r--r-- | core/opal.c | 2 | ||||
-rw-r--r-- | core/stack.c | 51 | ||||
-rw-r--r-- | core/utils.c | 27 |
3 files changed, 57 insertions, 23 deletions
diff --git a/core/opal.c b/core/opal.c index 7e53486..345d619 100644 --- a/core/opal.c +++ b/core/opal.c @@ -119,6 +119,8 @@ static void add_opal_firmware_node(void) dt_add_property_string(firmware, "compatible", "ibm,opal-firmware"); dt_add_property_string(firmware, "name", "firmware"); dt_add_property_string(firmware, "git-id", gitid); + dt_add_property(firmware, "symbol-map", __sym_map_start, + __sym_map_end - __sym_map_start); } void add_opal_node(void) diff --git a/core/stack.c b/core/stack.c index 15c6e54..1341175 100644 --- a/core/stack.c +++ b/core/stack.c @@ -20,8 +20,9 @@ #include <cpu.h> #include <stack.h> #include <mem_region.h> +#include <unistd.h> -#define STACK_BUF_ENTRIES 20 +#define STACK_BUF_ENTRIES 60 static struct bt_entry bt_buf[STACK_BUF_ENTRIES]; extern uint32_t _stext, _etext; @@ -47,27 +48,27 @@ void __nomcount __backtrace(struct bt_entry *entries, unsigned int *count) void __print_backtrace(unsigned int pir, struct bt_entry *entries, unsigned int count, - char *out_buf, unsigned int *len) + char *out_buf, unsigned int *len, bool symbols) { + static char bt_text_buf[4096]; int i, l = 0, max; char *buf = out_buf; - unsigned long bottom, top, tbot, ttop; + unsigned long bottom, top, tbot, ttop, saddr = 0; + char *sym = NULL, *sym_end = NULL; char mark; - if (len) + if (!out_buf) { + buf = bt_text_buf; + max = sizeof(bt_text_buf) - 16; + } else max = *len - 1; - else - max = INT_MAX; bottom = cpu_stack_bottom(pir); top = cpu_stack_top(pir); - tbot = (unsigned long)&_stext; + tbot = SKIBOOT_BASE; ttop = (unsigned long)&_etext; - if (buf) - l += snprintf(buf, max, "CPU %04x Backtrace:\n", pir); - else - l += printf("CPU %04x Backtrace:\n", pir); + l += snprintf(buf, max, "CPU %04x Backtrace:\n", pir); for (i = 0; i < count && l < max; i++) { if (entries->sp < bottom || entries->sp > top) mark = '!'; @@ -75,19 +76,23 @@ void __print_backtrace(unsigned int pir, mark = '*'; else mark = ' '; - if (buf) - l += snprintf(buf + l, max - l, - " S: %016lx R: %016lx %c\n", - entries->sp, entries->pc, mark); + if (symbols) + saddr = get_symbol(entries->pc, &sym, &sym_end); + l += snprintf(buf + l, max - l, + " S: %016lx R: %016lx %c ", + entries->sp, entries->pc, mark); + while(sym < sym_end && l < max) + buf[l++] = *(sym++); + if (sym && l < max) + l += snprintf(buf + l, max - l, "+0x%lx\n", + entries->pc - saddr); else - l += printf(" S: %016lx R: %016lx %c\n", - entries->sp, entries->pc, mark); + l += snprintf(buf + l, max - l, "\n"); entries++; } - if (buf) - buf[l++] = 0; - else - l++; + if (!out_buf) + write(stdout->fd, bt_text_buf, l); + buf[l++] = 0; if (len) *len = l; } @@ -97,7 +102,7 @@ void backtrace(void) unsigned int ents = STACK_BUF_ENTRIES; __backtrace(bt_buf, &ents); - __print_backtrace(mfspr(SPR_PIR), bt_buf, ents, NULL, NULL); + __print_backtrace(mfspr(SPR_PIR), bt_buf, ents, NULL, NULL, true); } void __noreturn __nomcount __stack_chk_fail(void); @@ -189,7 +194,7 @@ void check_stacks(void) lowest->pir, lowest->stack_bot_mark, lowest->stack_bot_pc, lowest->stack_bot_tok); __print_backtrace(lowest->pir, lowest->stack_bot_bt, - lowest->stack_bot_bt_count, NULL, NULL); + lowest->stack_bot_bt_count, NULL, NULL, true); unlock(&stack_check_lock); } diff --git a/core/utils.c b/core/utils.c index 63046fc..1a81ae2 100644 --- a/core/utils.c +++ b/core/utils.c @@ -68,3 +68,30 @@ char __attrconst tohex(uint8_t nibble) return __tohex[nibble]; } +unsigned long get_symbol(unsigned long addr, char **sym, char **sym_end) +{ + unsigned long prev = 0, next; + char *psym = NULL, *p = __sym_map_start; + + *sym = *sym_end = NULL; + while(p < __sym_map_end) { + next = strtoul(p, &p, 16) | SKIBOOT_BASE; + if (next > addr && prev <= addr) { + p = psym + 3;; + if (p >= __sym_map_end) + return 0; + *sym = p; + while(p < __sym_map_end && *p != 10) + p++; + *sym_end = p; + return prev; + } + prev = next; + psym = p; + while(p < __sym_map_end && *p != 10) + p++; + p++; + } + return 0; +} + |