/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include /* * i386 stack frame layout: * * 12(%ebp) ... * 8(%ebp) argument 1 (if applicable) * 4(%ebp) caller %eip (after the call instruction, pushed by hardware) * ------------------------------------------------------------ * (%ebp) caller %ebp (pushed in callee prologue) * -4(%ebp) local variable 1 * -8(%ebp) local variable 2 * -12(%ebp) ... */ __naked void ktrace_print(void) { __asm__ volatile( " pushl %ebp \n" " call ktrace_print_from \n" " ret \n" ); } void ktrace_print_from(void *frame) { void **ebp = (void **)frame; kprintf("Stack trace:\n"); /* XXX Rather than spitting out raw addresses, parse the kernel image's * ELF sections to figure out what the address actually belongs to */ while (ebp >= (void **)image_start && ebp < (void **)image_end) { /* arch/x86/boot/setup32.S pushes two `nil's as the initial stack frame */ if (ebp[1] == nil) break; /* caller return address is immediately above the stack frame */ kprintf(" %p\n", ebp[1]); if (ebp[1] >= isr_start && ebp[1] < isr_end) break; ebp = *ebp; } } __naked void *ktrace_return_addr(void) { __asm__ volatile( " movl 4(%ebp), %eax \n" " ret \n" ); }