diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index a85dcfbd82d..1f3676252c6 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -26,6 +27,21 @@ struct stackframe { uintptr_t ra; }; +#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER +#define SFP_FMT "fp: " +#else +#define SFP_FMT "sp: " +#endif + +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB +#define LOG_STACK_TRACE(idx, sfp, ra, name, offset) \ + LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG " [%s+0x%x]", idx, sfp, ra, name, \ + offset) +#else +#define LOG_STACK_TRACE(idx, sfp, ra, name, offset) \ + LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG, idx, sfp, ra) +#endif + static bool in_stack_bound(uintptr_t addr) { #ifdef CONFIG_THREAD_STACK_INFO @@ -82,7 +98,11 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) frame = (struct stackframe *)fp - 1; ra = frame->ra; if (in_text_region(ra)) { - LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, fp, ra); +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + LOG_STACK_TRACE(i, fp, ra, name, offset); /* * Increment the iterator only if `ra` is within the text region to get the * most out of it @@ -112,7 +132,11 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) ksp++) { ra = *ksp; if (in_text_region(ra)) { - LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra); +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + LOG_STACK_TRACE(i, (uintptr_t)ksp, ra, name, offset); /* * Increment the iterator only if `ra` is within the text region to get the * most out of it diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 2ca4126c6cb..d30186c7c73 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -73,10 +73,15 @@ Architectures * RISC-V - * Implemented frame-pointer based stack unwinding. - * The fatal error message triggered from a fault now contains the callee-saved-registers states. + * Implemented stack unwinding + + * Frame-pointer can be selected to enable precise stack traces at the expense of slightly + increased size and decreased speed. + + * Symbol names can be enabled by selecting :kconfig:option:`CONFIG_EXCEPTION_STACK_TRACE_SYMTAB` + * Xtensa Kernel diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 3721261e3d6..819d7034353 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -389,6 +389,15 @@ config EXCEPTION_STACK_TRACE print a stack trace of function memory addresses when an exception is reported. +config EXCEPTION_STACK_TRACE_SYMTAB + bool "Print function names in the stack trace" + select SYMTAB + depends on EXCEPTION_STACK_TRACE + help + Enable this if you want to print the function names in the + stack trace output. This will generate the symtab and + can consume a lot of ROM if there's a lot of functions. + # # Miscellaneous debugging options # diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index 9f29790f95c..84e00ecbf59 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -50,3 +50,18 @@ tests: regex: - "E: backtrace 0: fp: \\w+ lr: \\w+" - "E: backtrace 1: fp: \\w+ lr: \\w+" + arch.common.stack_unwind.symtab: + arch_allow: + - riscv + integration_platforms: + - qemu_riscv32 + - qemu_riscv64 + extra_args: OVERLAY_CONFIG="enable_fp.conf" + harness_config: + type: multi_line + regex: + - "[func1+\\w+]" + - "[func2+\\w+]" + - "[func1+\\w+]" + - "[func2+\\w+]" + - "[func1+\\w+]"