Add symbol table handling and debug backtrace

This commit is contained in:
Mark
2020-01-29 20:12:52 +02:00
parent 977ca16f82
commit bccd620eec
7 changed files with 148 additions and 5 deletions
+4
View File
@@ -5,6 +5,10 @@
struct amd64_loader_data {
uint32_t multiboot_info_ptr;
uint32_t symtab_ptr;
uint32_t symtab_size;
uint32_t strtab_ptr;
uint32_t strtab_size;
uint32_t initrd_ptr;
uint32_t initrd_len;
char cmdline[KERNEL_CMDLINE_MAX];
+4
View File
@@ -38,6 +38,10 @@
#define kfatal(f, ...) debugf(DEBUG_FATAL, "\033[41m" DEBUG_BASE_FMT f "\033[0m", DEBUG_BASE_ARGS, ##__VA_ARGS__)
#define kprint(l, f, ...) debugf(l, DEBUG_BASE_FMT f, DEBUG_BASE_ARGS, ##__VA_ARGS__)
void debug_symbol_table_set(uintptr_t symtab, uintptr_t strtab, size_t symtab_size, size_t strtab_size);
int debug_symbol_find(uintptr_t addr, const char **name, uintptr_t *base);
void debug_backtrace(uintptr_t rbp, int depth, int limit);
void fmtsiz(char *buf, size_t sz);
void debugc(int level, char c);
+4
View File
@@ -1,6 +1,7 @@
.section .text
// Args:
// %rdi - Address of loader's information struct
.type _start, %function
.global _start
_start:
cli
@@ -11,12 +12,15 @@ _start:
call _init
movq %rbx, %rdi
xorq %rbp, %rbp
pushq %rbp
call kernel_main
1:
cli
hlt
jmp 1b
.size _start, . - _start
// Entrypoint for AP bootstrap code
.global kernel_stacks_top
+39
View File
@@ -2,6 +2,13 @@
#include "sys/debug.h"
#include "sys/panic.h"
#define X86_EXCEPTION_PF 14
#define X86_PF_EXEC (1 << 5)
#define X86_PF_USER (1 << 2)
#define X86_PF_WRITE (1 << 1)
#define X86_PF_PRESENT (1 << 0)
#define X86_FLAGS_CF (1 << 0)
#define X86_FLAGS_PF (1 << 2)
#define X86_FLAGS_AF (1 << 4)
@@ -56,5 +63,37 @@ void amd64_exception(struct amd64_exception_frame *frame) {
(frame->rflags & X86_FLAGS_IF) ? 'I' : '-',
(frame->rflags & X86_FLAGS_TF) ? 'T' : '-');
if (frame->exc_no == X86_EXCEPTION_PF) {
uintptr_t cr2;
asm volatile ("movq %%cr2, %0":"=r"(cr2));
kfatal("Page fault info:\n");
kfatal("Fault address: %p\n", cr2);
if (frame->exc_code & X86_PF_EXEC) {
kfatal(" - Instruction fetch\n");
} else {
if (frame->exc_code & X86_PF_WRITE) {
kfatal(" - Write operation\n");
} else {
kfatal(" - Read operation\n");
}
}
if (frame->exc_code & X86_PF_PRESENT) {
kfatal(" - Refers to non-present page\n");
}
if (frame->exc_code & X86_PF_USER) {
kfatal(" - Userspace\n");
}
}
uintptr_t sym_base;
const char *sym_name;
if (debug_symbol_find(frame->rip, &sym_name, &sym_base) == 0) {
kfatal(" Backtrace:\n");
kfatal("0: %p <%s + %04x>\n", frame->rip, sym_name, frame->rip - sym_base);
debug_backtrace(frame->rbp, 1, 10);
}
panic("Exception without resolution\n");
}
+5 -5
View File
@@ -35,6 +35,11 @@ void kernel_main(struct amd64_loader_data *data) {
data = (struct amd64_loader_data *) MM_VIRTUALIZE(data);
multiboot_info = (multiboot_info_t *) MM_VIRTUALIZE(data->multiboot_info_ptr);
if (data->symtab_ptr) {
kinfo("Kernel symbol table at %p\n", MM_VIRTUALIZE(data->symtab_ptr));
debug_symbol_table_set(MM_VIRTUALIZE(data->symtab_ptr), MM_VIRTUALIZE(data->strtab_ptr), data->symtab_size, data->strtab_size);
}
// Parse kernel command line
kernel_set_cmdline(data->cmdline);
@@ -56,11 +61,6 @@ void kernel_main(struct amd64_loader_data *data) {
amd64_apic_init();
//#pragma GCC diagnostic ignored "-Wdiv-by-zero"
// uint32_t *addr = (uint32_t *) 0x110000000;
// *addr = 1;
//#pragma GCC diagnostic pop
while (1) {
asm volatile ("sti; hlt");
}
+19
View File
@@ -45,10 +45,29 @@ static uint64_t elf_load(uintptr_t src) {
Elf64_Shdr *shdrs = (Elf64_Shdr *) (src + (uintptr_t) ehdr->e_shoff);
const char *shstrtabd = (const char *) (src + (uintptr_t) shdrs[ehdr->e_shstrndx].sh_offset);
loader_data.strtab_ptr = 0;
loader_data.strtab_size = 0;
loader_data.symtab_ptr = 0;
loader_data.symtab_size = 0;
for (size_t i = 0; i < (size_t) ehdr->e_shnum; ++i) {
Elf64_Shdr *shdr = &shdrs[i];
const char *name = &shstrtabd[shdr->sh_name];
if (shdr->sh_type == SHT_SYMTAB && !strcmp(name, ".symtab")) {
loader_data.symtab_ptr = (uint32_t) shdr->sh_offset + src;
loader_data.symtab_size = (uint32_t) shdr->sh_size;
}
if (shdr->sh_type == SHT_STRTAB && !strcmp(name, ".strtab")) {
puts("Strtab section: ");
puts(name);
putc('\n');
loader_data.strtab_ptr = (uint32_t) shdr->sh_offset + src;
loader_data.strtab_size = (uint32_t) shdr->sh_size;
}
if (shdr->sh_flags & SHF_ALLOC) {
if (!strcmp(name, ".note.gnu.property")) {
// Fuck you, gcc
+73
View File
@@ -4,6 +4,7 @@
#include "sys/attr.h"
#include "sys/spin.h"
#include "sys/config.h"
#include "sys/elf.h"
#include <stdint.h>
#if defined(ARCH_AMD64)
@@ -11,6 +12,78 @@
#include "sys/amd64/hw/rs232.h"
#endif
////
static uintptr_t g_symtab_ptr = 0;
static uintptr_t g_strtab_ptr = 0;
static size_t g_symtab_size = 0;
static size_t g_strtab_size = 0;
void debug_symbol_table_set(uintptr_t s0, uintptr_t s1, size_t z0, size_t z1) {
g_symtab_ptr = s0;
g_symtab_size = z0;
g_strtab_ptr = s1;
g_strtab_size = z1;
}
int debug_symbol_find(uintptr_t addr, const char **name, uintptr_t *base) {
if (g_symtab_ptr && g_strtab_ptr) {
size_t offset = 0;
Elf64_Sym *sym;
while (offset < g_symtab_size) {
sym = (Elf64_Sym *) (g_symtab_ptr + offset);
if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) {
if (sym->st_value <= addr && sym->st_value + sym->st_size >= addr) {
*base = sym->st_value;
if (sym->st_name < g_strtab_size) {
*name = (const char *) (g_strtab_ptr + sym->st_name);
} else {
*name = "<invalid>";
}
return 0;
}
}
offset += sizeof(Elf64_Sym);
}
}
return -1;
}
void debug_backtrace(uintptr_t rbp, int depth, int limit) {
// Typical layout:
// rbp + 08 == rip
// rbp + 00 == rbp_1
if (!limit) {
return;
}
uintptr_t rip = ((uintptr_t *) rbp)[1];
uintptr_t rbp_next = ((uintptr_t *) rbp)[0];
uintptr_t base;
const char *name;
if (debug_symbol_find(rip, &name, &base) == 0) {
kfatal("%d: %p <%s + %04x>\n", depth, rip, name, rip - base);
} else {
kfatal("%d: %p (unknown)\n", depth, rip);
}
if (rbp_next == 0) {
kfatal("-- End of frame chain\n");
return;
}
debug_backtrace(rbp_next, depth + 1, limit - 1);
}
////
static const char *s_debug_xs_set0 = "0123456789abcdef";
static const char *s_debug_xs_set1 = "0123456789ABCDEF";