arch: riscv: use symtab to print function name in stack trace

Selecting `CONFIG_EXCEPTION_STACK_TRACE_SYMTAB` will
enable the symtab generation which will be used in the
stack trace to print the function name of the return
address.

Updated the `stack_unwind` test to test the symbols in a
stack trace.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
This commit is contained in:
Yong Cong Sin 2024-05-18 16:49:42 +08:00 committed by Anas Nashif
commit c1a925de98
4 changed files with 57 additions and 4 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/debug/symtab.h>
#include <zephyr/kernel.h>
#include <zephyr/kernel_structs.h>
#include <kernel_internal.h>
@ -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

View file

@ -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

View file

@ -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
#

View file

@ -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+]"