Commit 74f46bd4 authored by Yong Cong Sin's avatar Yong Cong Sin Committed by Anas Nashif
Browse files

arch: riscv: stacktrace: print additional arg when fatal error



Print `sp`/`fp` in traces.

Signed-off-by: default avatarYong Cong Sin <ycsin@meta.com>
Signed-off-by: default avatarYong Cong Sin <yongcong.sin@gmail.com>
parent 07493105
Loading
Loading
Loading
Loading
+22 −12
Original line number Diff line number Diff line
@@ -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);

typedef bool (*riscv_stacktrace_cb)(void *cookie, unsigned long addr, unsigned long sfp);

#define MAX_STACK_FRAMES CONFIG_ARCH_STACKWALK_MAX_FRAMES

struct stackframe {
@@ -94,7 +96,7 @@ static inline bool in_text_region(uintptr_t addr)
}

#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 _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++) {
		if (in_text_region(ra) && !cb(cookie, ra)) {
		if (in_text_region(ra) && !cb(cookie, ra, fp)) {
			break;
		}
		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)) {
			/* 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;
			}
			/**
@@ -167,7 +169,7 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru
}
#else  /* !CONFIG_FRAME_POINTER */
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 _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 */
		sp = csf->sp;
		ra = csf->ra;

	}

	ksp = (uintptr_t *)sp;
	for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy((uintptr_t)ksp, thread, esf) &&
			((uintptr_t)ksp > last_ksp);) {
		if (in_text_region(ra)) {
			if (!cb(cookie, ra)) {
			if (!cb(cookie, ra, POINTER_TO_UINT(ksp))) {
				break;
			}
			/*
@@ -218,7 +219,8 @@ void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie,
		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
@@ -248,14 +250,22 @@ static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const th
#define PR_REG "%016" PRIxPTR
#endif

#ifdef CONFIG_FRAME_POINTER
#define SFP "fp"
#else
#define SFP "sp"
#endif /* CONFIG_FRAME_POINTER */

#ifdef CONFIG_SYMTAB
#define LOG_STACK_TRACE(idx, ra, name, offset)                                                     \
	LOG_ERR("     %2d: ra: " PR_REG " [%s+0x%x]", idx, ra, name, offset)
#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, ra, name, offset) LOG_ERR("     %2d: ra: " PR_REG, idx, ra)
#define LOG_STACK_TRACE(idx, sfp, ra, name, offset)                                                \
	LOG_ERR("     %2d: " SFP ": " PR_REG " ra: " PR_REG, idx, sfp, ra)
#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;
#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);
#endif /* CONFIG_SYMTAB */

	LOG_STACK_TRACE((*i)++, ra, name, offset);
	LOG_STACK_TRACE((*i)++, sfp, ra, name, offset);

	return true;
}
+4 −4
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@ tests:
      type: multi_line
      regex:
        - "E: call trace:"
        - "E:       0: ra: \\w+"
        - "E:       1: ra: \\w+"
        - "E:       0: fp: \\w+ ra: \\w+"
        - "E:       1: fp: \\w+ ra: \\w+"
  arch.common.stack_unwind.riscv_sp:
    arch_allow: riscv
    integration_platforms:
@@ -28,8 +28,8 @@ tests:
      type: multi_line
      regex:
        - "E: call trace:"
        - "E:       0: ra: \\w+"
        - "E:       1: ra: \\w+"
        - "E:       0: sp: \\w+ ra: \\w+"
        - "E:       1: sp: \\w+ ra: \\w+"
  arch.common.stack_unwind.x86:
    arch_allow: x86
    extra_configs: