Files
my-kern/kernel/debug/debug.c

114 lines
3.2 KiB
C

//
// Created by rick on 08-03-21.
//
#include "debug.h"
#include <elf.h>
#include <libk/libk.h>
#include <libc/libc.h>
#include <libc/kprintf.h>
#include <libc/string.h>
#include <libk/kprint.h>
static struct elf32_section_header* elf_headers = NULL;
static struct elf32_section_header* elf_shstrtab = NULL;
static struct elf32_section_header* elf_symtab = NULL;
static struct elf32_section_header* elf_strtab = NULL;
static uint32_t elf_header_cnt;
static const char* elf_name_symtab = ".symtab";
static const char* elf_name_strtab = ".strtab";
struct stackframe {
struct stackframe* ebp;
uint32_t eip;
};
char *debug_get_shstrtab_entry(uint32_t ndx) {
if (elf_shstrtab == NULL) {
return NULL;
}
if (ndx > elf_shstrtab->sh_size) {
return NULL;
}
return ((char*)elf_shstrtab->sh_addr + ndx);
}
char *debug_get_strtab_entry(uint32_t ndx) {
if (elf_strtab == NULL) {
return NULL;
}
if (ndx > elf_strtab->sh_size) {
return NULL;
}
return ((char*)elf_strtab->sh_addr + ndx);
}
void debug_find_sections(uint32_t shndx) {
elf_shstrtab = &elf_headers[shndx];
for (uint32_t i = 0; i < elf_header_cnt; ++i) {
struct elf32_section_header *current = &elf_headers[i];
char *name = debug_get_shstrtab_entry(current->sh_name);
if (name == NULL) {
printf("Name was NULL\n");
continue;
}
if (strcmp(name, elf_name_symtab) == 0) {
elf_symtab = current;
continue;
}
if (strcmp(name, elf_name_strtab) == 0) {
elf_strtab = current;
continue;
}
}
}
void debug_store_info(struct multiboot_info *info) {
if (!(info->flags & MULTIBOOT_INFO_ELF_SHDR)) {
return;
}
if (sizeof(struct elf32_section_header) != info->u.elf_sec.size) {
k_panics("ELF size not correct");
}
elf_headers = (struct elf32_section_header *) info->u.elf_sec.addr;
elf_header_cnt = info->u.elf_sec.num;
debug_find_sections(info->u.elf_sec.shndx);
}
struct elf32_symtab_entry* debug_get_entry_for_addr(uint32_t addr) {
if (elf_symtab == NULL) {
return NULL;
}
struct elf32_symtab_entry* first = (struct elf32_symtab_entry *) elf_symtab->sh_addr;
uint32_t num = elf_symtab->sh_size / sizeof(struct elf32_symtab_entry);
for (uint32_t i = 0; i < num; ++i) {
// only functions for now
if (ELF32_ST_TYPE(first[i].st_info) != STT_FUNC) {
continue;
}
if (addr >= first[i].st_value && addr < (first[i].st_value + first[i].st_size)) {
return &first[i];
}
}
return NULL;
}
void debug_backtrace(bool do_sync) {
struct stackframe *frame = __builtin_frame_address(0);
void (*printer)(const char*) = do_sync ? kprint_sync : kprint;
printer("\n\n## Stack Trace ##\n");
char msg[1024] = {0};
while (frame->ebp != NULL) {
struct elf32_symtab_entry *entry = debug_get_entry_for_addr(frame->eip);
if (entry == NULL) {
sprintf(msg, "#unknown (%x)\n", frame->eip);
} else {
sprintf(msg, "%s (%x)\n", debug_get_strtab_entry(entry->st_name), frame->eip);
};
printer(msg);
frame = frame->ebp;
}
printer("\n");
}