limine/common/lib/trace.s2.c

86 lines
1.9 KiB
C
Raw Normal View History

2020-11-15 19:56:10 +03:00
#include <stddef.h>
#include <stdint.h>
#include <lib/trace.h>
2022-08-27 00:44:47 +03:00
#include <lib/misc.h>
2020-11-15 19:56:10 +03:00
#include <lib/config.h>
#include <lib/print.h>
#include <lib/uri.h>
#include <fs/file.h>
#include <mm/pmm.h>
#if defined (BIOS)
2021-04-08 02:15:35 +03:00
extern symbol stage2_map;
#elif defined (UEFI)
2022-04-20 05:00:00 +03:00
extern symbol __image_base;
2021-04-08 02:15:35 +03:00
#endif
2021-03-13 05:40:17 +03:00
2021-04-08 02:15:35 +03:00
extern symbol full_map;
2020-11-15 19:56:10 +03:00
2021-03-13 05:40:17 +03:00
static char *trace_address(size_t *off, size_t addr) {
char *limine_map;
#if defined (BIOS)
2021-02-25 03:24:54 +03:00
if (!stage3_loaded)
limine_map = stage2_map;
else
limine_map = full_map;
#elif defined (UEFI)
2021-04-08 02:15:35 +03:00
limine_map = full_map;
2022-04-20 05:00:00 +03:00
addr -= (size_t)__image_base;
2021-04-08 02:15:35 +03:00
#endif
2020-11-15 19:56:10 +03:00
2021-03-02 12:23:43 +03:00
uintptr_t prev_addr = 0;
char *prev_sym = NULL;
2020-11-15 19:56:10 +03:00
for (size_t i = 0;;) {
2021-03-02 12:23:43 +03:00
if (*((uintptr_t *)&limine_map[i]) >= addr) {
2020-11-15 19:56:10 +03:00
*off = addr - prev_addr;
return prev_sym;
}
2021-03-02 12:23:43 +03:00
prev_addr = *((uintptr_t *)&limine_map[i]);
i += sizeof(uintptr_t);
2021-02-25 03:24:54 +03:00
prev_sym = &limine_map[i];
while (limine_map[i++] != 0);
2020-11-15 19:56:10 +03:00
}
}
void print_stacktrace(size_t *base_ptr) {
if (base_ptr == NULL) {
asm volatile (
2021-07-20 14:35:43 +03:00
#if defined (__i386__)
"movl %%ebp, %0"
2021-07-20 14:35:43 +03:00
#elif defined (__x86_64__)
"movq %%rbp, %0"
#elif defined (__aarch64__)
"mov %0, x29"
#elif defined (__riscv64)
"mv %0, fp; addi %0, %0, -16"
2021-04-08 02:15:35 +03:00
#endif
: "=r"(base_ptr)
2020-11-15 19:56:10 +03:00
:: "memory"
);
}
print("Stacktrace:\n");
for (;;) {
size_t old_bp = base_ptr[0];
size_t ret_addr = base_ptr[1];
if (!ret_addr)
break;
size_t off;
char *name = trace_address(&off, ret_addr);
if (name)
print(" [%p] <%s+%p>\n", ret_addr, name, off);
2020-11-15 19:56:10 +03:00
else
print(" [%p]\n", ret_addr);
2020-11-15 19:56:10 +03:00
if (!old_bp)
break;
#if defined (__riscv)
base_ptr = (void *)(old_bp - 16);
#else
2020-11-15 19:56:10 +03:00
base_ptr = (void*)old_bp;
#endif
2020-11-15 19:56:10 +03:00
}
print("End of trace. ");
2020-11-15 19:56:10 +03:00
}