Skip to content

Commit 652a9bc

Browse files
committed
arch: x86: implement arch_stack_walk()
Currently it supports `esf` based unwinding only. The backtraces only prints the return address now, `frame->args` is no longer printed on 32-bit CPU. Signed-off-by: Yong Cong Sin <ycsin@meta.com>
1 parent 624362b commit 652a9bc

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

arch/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ config X86
9090
select ARCH_HAS_TIMING_FUNCTIONS
9191
select ARCH_HAS_THREAD_LOCAL_STORAGE
9292
select ARCH_HAS_DEMAND_PAGING if !X86_64
93+
select ARCH_HAS_STACKWALK
9394
select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
9495
select NEED_LIBC_MEM_PARTITION if USERSPACE && TIMING_FUNCTIONS \
9596
&& !BOARD_HAS_TIMING_FUNCTIONS \

arch/x86/core/fatal.c

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,44 @@ struct stack_frame {
140140
#endif
141141
};
142142

143-
#define MAX_STACK_FRAMES CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES
143+
static bool print_trace_address(void *arg, unsigned long addr)
144+
{
145+
ARG_UNUSED(arg);
144146

145-
__pinned_func
146-
static void unwind_stack(uintptr_t base_ptr, uint16_t cs)
147+
#ifdef CONFIG_X86_64
148+
LOG_ERR(" 0x%016lx", addr);
149+
#else
150+
LOG_ERR(" 0x%08lx", addr);
151+
#endif
152+
153+
return true;
154+
}
155+
156+
__pinned_func static void walk_stackframe(stack_trace_callback_fn cb, void *cookie,
157+
const struct arch_esf *esf, int max_frames)
147158
{
159+
uintptr_t base_ptr;
160+
uint16_t cs;
148161
struct stack_frame *frame;
149162
int i;
150163

164+
if (esf != NULL) {
165+
#ifdef CONFIG_X86_64
166+
base_ptr = esf->rbp;
167+
#else /* x86 32-bit */
168+
base_ptr = esf->ebp;
169+
#endif /* CONFIG_X86_64 */
170+
cs = esf->cs;
171+
} else {
172+
return;
173+
}
174+
151175
if (base_ptr == 0U) {
152176
LOG_ERR("NULL base ptr");
153177
return;
154178
}
155179

156-
for (i = 0; i < MAX_STACK_FRAMES; i++) {
180+
for (i = 0; i < max_frames; i++) {
157181
if (base_ptr % sizeof(base_ptr) != 0U) {
158182
LOG_ERR("unaligned frame ptr");
159183
return;
@@ -178,16 +202,40 @@ static void unwind_stack(uintptr_t base_ptr, uint16_t cs)
178202
if (frame->ret_addr == 0U) {
179203
break;
180204
}
181-
#ifdef CONFIG_X86_64
182-
LOG_ERR(" 0x%016lx", frame->ret_addr);
183-
#else
184-
LOG_ERR(" 0x%08lx (0x%lx)", frame->ret_addr, frame->args);
185-
#endif
205+
206+
if (!cb(cookie, frame->ret_addr)) {
207+
break;
208+
}
209+
186210
base_ptr = frame->next;
187211
}
188212
}
213+
214+
__pinned_func
215+
static void unwind_stack(const struct arch_esf *esf)
216+
{
217+
walk_stackframe(print_trace_address, NULL, esf,
218+
CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES);
219+
}
189220
#endif /* CONFIG_EXCEPTION_STACK_TRACE */
190221

222+
void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie,
223+
const struct k_thread *thread, const struct arch_esf *esf)
224+
{
225+
#ifdef CONFIG_EXCEPTION_STACK_TRACE
226+
ARG_UNUSED(thread);
227+
228+
walk_stackframe(callback_fn, cookie, esf, CONFIG_ARCH_STACKWALK_MAX_FRAMES);
229+
#else
230+
ARG_UNUSED(callback_fn);
231+
ARG_UNUSED(cookie);
232+
ARG_UNUSED(thread);
233+
ARG_UNUSED(esf);
234+
235+
LOG_DBG("Enable CONFIG_EXCEPTION_STACK_TRACE for %s()", __func__);
236+
#endif /* CONFIG_EXCEPTION_STACK_TRACE */
237+
}
238+
191239
static inline uintptr_t get_cr3(const struct arch_esf *esf)
192240
{
193241
#if defined(CONFIG_USERSPACE) && defined(CONFIG_X86_KPTI)
@@ -231,7 +279,7 @@ static void dump_regs(const struct arch_esf *esf)
231279
#endif
232280
LOG_ERR("RIP: 0x%016lx", esf->rip);
233281
#ifdef CONFIG_EXCEPTION_STACK_TRACE
234-
unwind_stack(esf->rbp, esf->cs);
282+
unwind_stack(esf);
235283
#endif
236284
}
237285
#else /* 32-bit */
@@ -250,7 +298,7 @@ static void dump_regs(const struct arch_esf *esf)
250298
#endif
251299
LOG_ERR("EIP: 0x%08x", esf->eip);
252300
#ifdef CONFIG_EXCEPTION_STACK_TRACE
253-
unwind_stack(esf->ebp, esf->cs);
301+
unwind_stack(esf);
254302
#endif
255303
}
256304
#endif /* CONFIG_X86_64 */

0 commit comments

Comments
 (0)