/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include /* * amd64 stack frame layout: * * 24(%rbp) ... * 16(%rbp) argument 7 (if applicable, args 1-6 are passed in registers) * 8(%rbp) caller %rip (after the call instruction, pushed by hardware) * ------------------------------------------------------------ * (%rbp) caller %rbp (pushed in callee prologue) * -8(%rbp) local variable 1 * -16(%rbp) local variable 2 * -24(%rbp) ... */ __naked void ktrace_print(void) { __asm__ volatile( " movq %rbp, %rdi \n" " jmp ktrace_print_from \n" ); } void ktrace_print_from(void *frame) { void **rbp = (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 (rbp >= (void **)image_start && rbp < (void **)image_end) { /* arch/x86/boot/setup64.S pushes two `nil's as the initial stack frame */ if (rbp[1] == nil) break; /* Caller return address is immediately above the stack frame. * XXX This prints the position *after* the call instruction. */ kprintf(" %p\n", rbp[1]); if (rbp[1] >= isr_start && rbp[1] < isr_end) break; rbp = *rbp; } } __naked void *ktrace_return_addr(void) { __asm__ volatile( " movq 8(%rbp), %rax \n" " ret \n" ); }