arch: arm64: implement arch_stack_walk()
Currently it supports `esf` based unwinding only. Then, update the exception stack unwinding to use `arch_stack_walk()`, and update the Kconfigs & testcase accordingly. Also, `EXCEPTION_STACK_TRACE_MAX_FRAMES` is unused and made redundant after this change, so remove it. 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
06a8c35316
commit
ab676fdb86
4 changed files with 66 additions and 31 deletions
|
@ -161,6 +161,14 @@ config ARM64_EXCEPTION_STACK_TRACE
|
||||||
help
|
help
|
||||||
Internal config to enable runtime stack traces on fatal exceptions.
|
Internal config to enable runtime stack traces on fatal exceptions.
|
||||||
|
|
||||||
|
config ARCH_HAS_STACKWALK
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
depends on FRAME_POINTER
|
||||||
|
help
|
||||||
|
Internal config to indicate that the arch_stack_walk() API is implemented
|
||||||
|
and it can be enabled.
|
||||||
|
|
||||||
config ARM64_SAFE_EXCEPTION_STACK_SIZE
|
config ARM64_SAFE_EXCEPTION_STACK_SIZE
|
||||||
int "The stack size of the safe exception stack"
|
int "The stack size of the safe exception stack"
|
||||||
default 4096
|
default 4096
|
||||||
|
|
|
@ -194,9 +194,13 @@ static void esf_dump(const struct arch_esf *esf)
|
||||||
LOG_ERR("x16: 0x%016llx x17: 0x%016llx", esf->x16, esf->x17);
|
LOG_ERR("x16: 0x%016llx x17: 0x%016llx", esf->x16, esf->x17);
|
||||||
LOG_ERR("x18: 0x%016llx lr: 0x%016llx", esf->x18, esf->lr);
|
LOG_ERR("x18: 0x%016llx lr: 0x%016llx", esf->x18, esf->lr);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||||
|
|
||||||
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
#ifdef CONFIG_ARCH_STACKWALK
|
||||||
static void esf_unwind(const struct arch_esf *esf)
|
typedef bool (*arm64_stacktrace_cb)(void *cookie, unsigned long addr, void *fp);
|
||||||
|
|
||||||
|
static void walk_stackframe(arm64_stacktrace_cb cb, void *cookie, const struct arch_esf *esf,
|
||||||
|
int max_frames)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* For GCC:
|
* For GCC:
|
||||||
|
@ -218,30 +222,61 @@ static void esf_unwind(const struct arch_esf *esf)
|
||||||
* + +-----------------+
|
* + +-----------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint64_t *fp = (uint64_t *) esf->fp;
|
uint64_t *fp;
|
||||||
unsigned int count = 0;
|
|
||||||
uint64_t lr;
|
uint64_t lr;
|
||||||
|
|
||||||
LOG_ERR("");
|
if (esf != NULL) {
|
||||||
for (int i = 0; (fp != NULL) && (i < CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES); i++) {
|
fp = (uint64_t *) esf->fp;
|
||||||
lr = fp[1];
|
} else {
|
||||||
#ifdef CONFIG_SYMTAB
|
return;
|
||||||
uint32_t offset = 0;
|
}
|
||||||
const char *name = symtab_find_symbol_name(lr, &offset);
|
|
||||||
|
|
||||||
LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx [%s+0x%x]",
|
for (int i = 0; (fp != NULL) && (i < max_frames); i++) {
|
||||||
count++, (uint64_t) fp, lr, name, offset);
|
lr = fp[1];
|
||||||
#else
|
if (!cb(cookie, lr, fp)) {
|
||||||
LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx",
|
break;
|
||||||
count++, (uint64_t) fp, lr);
|
}
|
||||||
#endif
|
|
||||||
fp = (uint64_t *) fp[0];
|
fp = (uint64_t *) fp[0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie,
|
||||||
|
const struct k_thread *thread, const struct arch_esf *esf)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(thread);
|
||||||
|
|
||||||
|
walk_stackframe((arm64_stacktrace_cb)callback_fn, cookie, esf,
|
||||||
|
CONFIG_ARCH_STACKWALK_MAX_FRAMES);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ARCH_STACKWALK */
|
||||||
|
|
||||||
|
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
||||||
|
static bool print_trace_address(void *arg, unsigned long lr, void *fp)
|
||||||
|
{
|
||||||
|
int *i = arg;
|
||||||
|
#ifdef CONFIG_SYMTAB
|
||||||
|
uint32_t offset = 0;
|
||||||
|
const char *name = symtab_find_symbol_name(lr, &offset);
|
||||||
|
|
||||||
|
LOG_ERR(" %d: fp: 0x%016llx lr: 0x%016lx [%s+0x%x]", (*i)++, (uint64_t)fp, lr, name,
|
||||||
|
offset);
|
||||||
|
#else
|
||||||
|
LOG_ERR(" %d: fp: 0x%016llx lr: 0x%016lx", (*i)++, (uint64_t)fp, lr);
|
||||||
|
#endif /* CONFIG_SYMTAB */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esf_unwind(const struct arch_esf *esf)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
LOG_ERR("");
|
||||||
|
LOG_ERR("call trace:");
|
||||||
|
walk_stackframe(print_trace_address, &i, esf, CONFIG_ARCH_STACKWALK_MAX_FRAMES);
|
||||||
LOG_ERR("");
|
LOG_ERR("");
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_EXCEPTION_STACK_TRACE */
|
||||||
|
|
||||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_STACK_PROTECTION
|
#ifdef CONFIG_ARM64_STACK_PROTECTION
|
||||||
static bool z_arm64_stack_corruption_check(struct arch_esf *esf, uint64_t esr, uint64_t far)
|
static bool z_arm64_stack_corruption_check(struct arch_esf *esf, uint64_t esr, uint64_t far)
|
||||||
|
|
|
@ -381,21 +381,12 @@ config DEBUG_INFO
|
||||||
config EXCEPTION_STACK_TRACE
|
config EXCEPTION_STACK_TRACE
|
||||||
bool "Attempt to print stack traces upon exceptions"
|
bool "Attempt to print stack traces upon exceptions"
|
||||||
default y
|
default y
|
||||||
depends on ARM64_EXCEPTION_STACK_TRACE || ARCH_STACKWALK
|
depends on ARCH_STACKWALK
|
||||||
help
|
help
|
||||||
If the architecture fatal handling code supports it, attempt to
|
If the architecture fatal handling code supports it, attempt to
|
||||||
print a stack trace of function memory addresses when an
|
print a stack trace of function memory addresses when an
|
||||||
exception is reported.
|
exception is reported.
|
||||||
|
|
||||||
config EXCEPTION_STACK_TRACE_MAX_FRAMES
|
|
||||||
int "Configures the depth of stack trace"
|
|
||||||
default ARCH_STACKWALK_MAX_FRAMES if ARCH_STACKWALK
|
|
||||||
default 8
|
|
||||||
depends on EXCEPTION_STACK_TRACE
|
|
||||||
help
|
|
||||||
In the event of a stack trace, this place a limit on the depths
|
|
||||||
of the stack to examine.
|
|
||||||
|
|
||||||
config EXCEPTION_STACK_TRACE_SYMTAB
|
config EXCEPTION_STACK_TRACE_SYMTAB
|
||||||
bool "Print function names in the stack trace"
|
bool "Print function names in the stack trace"
|
||||||
select SYMTAB
|
select SYMTAB
|
||||||
|
|
|
@ -54,8 +54,9 @@ tests:
|
||||||
harness_config:
|
harness_config:
|
||||||
type: multi_line
|
type: multi_line
|
||||||
regex:
|
regex:
|
||||||
- "E: backtrace 0: fp: \\w+ lr: \\w+"
|
- "E: call trace:"
|
||||||
- "E: backtrace 1: fp: \\w+ lr: \\w+"
|
- "E: 0: fp: \\w+ lr: \\w+"
|
||||||
|
- "E: 1: fp: \\w+ lr: \\w+"
|
||||||
arch.common.stack_unwind.symtab:
|
arch.common.stack_unwind.symtab:
|
||||||
arch_allow:
|
arch_allow:
|
||||||
- riscv
|
- riscv
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue