feat: added debug traces and added support for booting using grub and
tftp
This commit is contained in:
113
kernel/debug/debug.c
Normal file
113
kernel/debug/debug.c
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// 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");
|
||||
}
|
||||
Reference in New Issue
Block a user