unwind_stack() will walk the callstack and show the symbol names if available by using the architecture-specific framepointer implementation.
When available, call unwind_stack() during a panic to give more information about what caused the panic and help with debugging. Adjust the interrupt handlers to call panic_str() to avoid duplicating the backtrace. Signed-off-by: Casey Connolly <casey.conno...@linaro.org> --- arch/arm/lib/interrupts_64.c | 8 ++++---- include/symbols.h | 9 ++++++++- lib/panic.c | 7 +++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c index 0f8ca7d343156bd53688bf4a0acd9437f041f8f5..dcba82b560d3be73233674d9b657767d8641a76e 100644 --- a/arch/arm/lib/interrupts_64.c +++ b/arch/arm/lib/interrupts_64.c @@ -114,10 +114,10 @@ static void print_sym(unsigned long lr) symbol_lookup(lr, NULL, &offset, symname); /* Print the symbol address and the offset to the LR */ - printf("\t<%#016lx> %s+%#lx\n", lr - (gd->flags & GD_FLG_RELOC ? gd->reloc_off : 0), - symname, offset); + printf("\t<%#016lx> %pS\n", lr - (gd->flags & GD_FLG_RELOC ? gd->reloc_off : 0), + (void *)lr); } /** * show_backtrace - show backtrace using frame pointers @@ -233,9 +233,9 @@ static void except_msg(const char *msg, struct pt_regs *pt_regs) show_regs(pt_regs); if (CONFIG_IS_ENABLED(FRAMEPOINTER)) show_backtrace(pt_regs->elr, pt_regs->regs[30], pt_regs->regs[29]); show_efi_loaded_images(pt_regs); - panic("Resetting CPU ...\n"); + panic_str("Resetting CPU ...\n"); } /* * do_bad_sync handles the impossible case in the Synchronous Abort vector. @@ -284,9 +284,9 @@ void do_sync(struct pt_regs *pt_regs) show_regs(pt_regs); if (CONFIG_IS_ENABLED(FRAMEPOINTER)) show_backtrace(pt_regs->elr, pt_regs->regs[30], pt_regs->regs[29]); show_efi_loaded_images(pt_regs); - panic("Resetting CPU ...\n"); + panic_str("Resetting CPU ...\n"); } /* * do_irq handles the Irq exception. diff --git a/include/symbols.h b/include/symbols.h index c5267edbe768f304bc0f6235e71a39b6c3835a67..845f993060f042139df46bcc51a0180faadc35bc 100644 --- a/include/symbols.h +++ b/include/symbols.h @@ -4,9 +4,9 @@ #include <string.h> #define KSYM_NAME_LEN 127 -#if IS_ENABLED(CONFIG_SYMBOL_LOOKUP) +#if CONFIG_IS_ENABLED(SYMBOL_LOOKUP) const char * __attribute__((weak)) symbol_lookup(unsigned long addr, unsigned long *symaddr, unsigned long *offset, char *namebuf); #else static inline const char *symbol_lookup(unsigned long addr, unsigned long *symaddr, unsigned long *offset, @@ -21,4 +21,11 @@ static inline const char *symbol_lookup(unsigned long addr, unsigned long *symad namebuf[3] = '\0'; return namebuf; } #endif + +#if CONFIG_IS_ENABLED(FRAMEPOINTER) +/** + * unwind_stack - unwind the callstack and print a backtrace. + */ +void unwind_stack(void); +#endif diff --git a/lib/panic.c b/lib/panic.c index 0f578b5b5131589d215f5f4b16b95d9c9f3e8ce3..6f8bd7cc1eef7e5d97ba925bef65cc46924b4418 100644 --- a/lib/panic.c +++ b/lib/panic.c @@ -14,8 +14,9 @@ #include <command.h> #endif #include <linux/delay.h> #include <stdio.h> +#include <symbols.h> static void panic_finish(void) __attribute__ ((noreturn)); static void panic_finish(void) @@ -44,8 +45,14 @@ void panic(const char *fmt, ...) va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); + + if (CONFIG_IS_ENABLED(FRAMEPOINTER)) { + puts("\n"); + unwind_stack(); + } + #endif panic_finish(); } -- 2.50.0