arch: riscv: stacktrace: print additional arg when fatal error
Print `sp`/`fp` in traces. Signed-off-by: Yong Cong Sin <ycsin@meta.com> Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
parent
074931057c
commit
74f46bd421
2 changed files with 27 additions and 17 deletions
|
@ -14,6 +14,8 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
|
||||||
|
|
||||||
uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf);
|
uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf);
|
||||||
|
|
||||||
|
typedef bool (*riscv_stacktrace_cb)(void *cookie, unsigned long addr, unsigned long sfp);
|
||||||
|
|
||||||
#define MAX_STACK_FRAMES CONFIG_ARCH_STACKWALK_MAX_FRAMES
|
#define MAX_STACK_FRAMES CONFIG_ARCH_STACKWALK_MAX_FRAMES
|
||||||
|
|
||||||
struct stackframe {
|
struct stackframe {
|
||||||
|
@ -94,7 +96,7 @@ static inline bool in_text_region(uintptr_t addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FRAME_POINTER
|
#ifdef CONFIG_FRAME_POINTER
|
||||||
static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread,
|
static void walk_stackframe(riscv_stacktrace_cb cb, void *cookie, const struct k_thread *thread,
|
||||||
const struct arch_esf *esf, stack_verify_fn vrfy,
|
const struct arch_esf *esf, stack_verify_fn vrfy,
|
||||||
const _callee_saved_t *csf)
|
const _callee_saved_t *csf)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +119,7 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy(fp, thread, esf) && (fp > last_fp); i++) {
|
for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy(fp, thread, esf) && (fp > last_fp); i++) {
|
||||||
if (in_text_region(ra) && !cb(cookie, ra)) {
|
if (in_text_region(ra) && !cb(cookie, ra, fp)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
last_fp = fp;
|
last_fp = fp;
|
||||||
|
@ -127,7 +129,7 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru
|
||||||
|
|
||||||
if ((i == 0) && (esf != NULL)) {
|
if ((i == 0) && (esf != NULL)) {
|
||||||
/* Print `esf->ra` if we are at the top of the stack */
|
/* Print `esf->ra` if we are at the top of the stack */
|
||||||
if (in_text_region(esf->ra) && !cb(cookie, esf->ra)) {
|
if (in_text_region(esf->ra) && !cb(cookie, esf->ra, fp)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -167,7 +169,7 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru
|
||||||
}
|
}
|
||||||
#else /* !CONFIG_FRAME_POINTER */
|
#else /* !CONFIG_FRAME_POINTER */
|
||||||
register uintptr_t current_stack_pointer __asm__("sp");
|
register uintptr_t current_stack_pointer __asm__("sp");
|
||||||
static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread,
|
static void walk_stackframe(riscv_stacktrace_cb cb, void *cookie, const struct k_thread *thread,
|
||||||
const struct arch_esf *esf, stack_verify_fn vrfy,
|
const struct arch_esf *esf, stack_verify_fn vrfy,
|
||||||
const _callee_saved_t *csf)
|
const _callee_saved_t *csf)
|
||||||
{
|
{
|
||||||
|
@ -187,14 +189,13 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru
|
||||||
/* Unwind the provided thread */
|
/* Unwind the provided thread */
|
||||||
sp = csf->sp;
|
sp = csf->sp;
|
||||||
ra = csf->ra;
|
ra = csf->ra;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ksp = (uintptr_t *)sp;
|
ksp = (uintptr_t *)sp;
|
||||||
for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy((uintptr_t)ksp, thread, esf) &&
|
for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy((uintptr_t)ksp, thread, esf) &&
|
||||||
((uintptr_t)ksp > last_ksp);) {
|
((uintptr_t)ksp > last_ksp);) {
|
||||||
if (in_text_region(ra)) {
|
if (in_text_region(ra)) {
|
||||||
if (!cb(cookie, ra)) {
|
if (!cb(cookie, ra, POINTER_TO_UINT(ksp))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -218,7 +219,8 @@ void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie,
|
||||||
thread = _current;
|
thread = _current;
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_stackframe(callback_fn, cookie, thread, esf, in_stack_bound, &thread->callee_saved);
|
walk_stackframe((riscv_stacktrace_cb)callback_fn, cookie, thread, esf, in_stack_bound,
|
||||||
|
&thread->callee_saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
||||||
|
@ -248,14 +250,22 @@ static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const th
|
||||||
#define PR_REG "%016" PRIxPTR
|
#define PR_REG "%016" PRIxPTR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SYMTAB
|
#ifdef CONFIG_FRAME_POINTER
|
||||||
#define LOG_STACK_TRACE(idx, ra, name, offset) \
|
#define SFP "fp"
|
||||||
LOG_ERR(" %2d: ra: " PR_REG " [%s+0x%x]", idx, ra, name, offset)
|
|
||||||
#else
|
#else
|
||||||
#define LOG_STACK_TRACE(idx, ra, name, offset) LOG_ERR(" %2d: ra: " PR_REG, idx, ra)
|
#define SFP "sp"
|
||||||
|
#endif /* CONFIG_FRAME_POINTER */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYMTAB
|
||||||
|
#define LOG_STACK_TRACE(idx, sfp, ra, name, offset) \
|
||||||
|
LOG_ERR(" %2d: " SFP ": " 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 ": " PR_REG " ra: " PR_REG, idx, sfp, ra)
|
||||||
#endif /* CONFIG_SYMTAB */
|
#endif /* CONFIG_SYMTAB */
|
||||||
|
|
||||||
static bool print_trace_address(void *arg, unsigned long ra)
|
static bool print_trace_address(void *arg, unsigned long ra, unsigned long sfp)
|
||||||
{
|
{
|
||||||
int *i = arg;
|
int *i = arg;
|
||||||
#ifdef CONFIG_SYMTAB
|
#ifdef CONFIG_SYMTAB
|
||||||
|
@ -263,7 +273,7 @@ static bool print_trace_address(void *arg, unsigned long ra)
|
||||||
const char *name = symtab_find_symbol_name(ra, &offset);
|
const char *name = symtab_find_symbol_name(ra, &offset);
|
||||||
#endif /* CONFIG_SYMTAB */
|
#endif /* CONFIG_SYMTAB */
|
||||||
|
|
||||||
LOG_STACK_TRACE((*i)++, ra, name, offset);
|
LOG_STACK_TRACE((*i)++, sfp, ra, name, offset);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ tests:
|
||||||
type: multi_line
|
type: multi_line
|
||||||
regex:
|
regex:
|
||||||
- "E: call trace:"
|
- "E: call trace:"
|
||||||
- "E: 0: ra: \\w+"
|
- "E: 0: fp: \\w+ ra: \\w+"
|
||||||
- "E: 1: ra: \\w+"
|
- "E: 1: fp: \\w+ ra: \\w+"
|
||||||
arch.common.stack_unwind.riscv_sp:
|
arch.common.stack_unwind.riscv_sp:
|
||||||
arch_allow: riscv
|
arch_allow: riscv
|
||||||
integration_platforms:
|
integration_platforms:
|
||||||
|
@ -28,8 +28,8 @@ tests:
|
||||||
type: multi_line
|
type: multi_line
|
||||||
regex:
|
regex:
|
||||||
- "E: call trace:"
|
- "E: call trace:"
|
||||||
- "E: 0: ra: \\w+"
|
- "E: 0: sp: \\w+ ra: \\w+"
|
||||||
- "E: 1: ra: \\w+"
|
- "E: 1: sp: \\w+ ra: \\w+"
|
||||||
arch.common.stack_unwind.x86:
|
arch.common.stack_unwind.x86:
|
||||||
arch_allow: x86
|
arch_allow: x86
|
||||||
extra_configs:
|
extra_configs:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue