feat: ported debug logging
This commit is contained in:
123
yak-kernel/src/rt/debug/debug.c
Normal file
123
yak-kernel/src/rt/debug/debug.c
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Created by rick on 08-03-21.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <yak/rt/debug/debug.h>
|
||||
#include <yak/rt/kprint.h>
|
||||
|
||||
static uintptr_t kernel_start;
|
||||
static struct elf64_section_header *elf_headers = NULL;
|
||||
static struct elf64_section_header *elf_shstrtab = NULL;
|
||||
static struct elf64_section_header *elf_symtab = NULL;
|
||||
static struct elf64_section_header *elf_strtab = NULL;
|
||||
static uint32_t elf_header_cnt;
|
||||
|
||||
struct stackframe {
|
||||
struct stackframe *ebp;
|
||||
uintptr_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 *) kernel_start + elf_shstrtab->sh_offset + 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 *) kernel_start + elf_strtab->sh_offset + ndx);
|
||||
}
|
||||
|
||||
void debug_find_sections(uint32_t shndx) {
|
||||
elf_shstrtab = &elf_headers[shndx];
|
||||
for (uint32_t i = 0; i < elf_header_cnt; ++i) {
|
||||
struct elf64_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, ".symtab") == 0) {
|
||||
elf_symtab = current;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(name, ".strtab") == 0) {
|
||||
elf_strtab = current;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void debug_store_info(void *kernel) {
|
||||
struct elf_file_header* elf_header = (struct elf_file_header*)kernel;
|
||||
if (elf_header->ei_magic != ELF_MAGIC) {
|
||||
printf("Unsupported magic for kernel header\n");
|
||||
return;
|
||||
}
|
||||
// todo support other then 64 little
|
||||
if (elf_header->ei_class != ELF_CLASS_64 || elf_header->ei_data != ELF_ENDIAN_LITTLE) {
|
||||
printf("Kernel not a 64bit little endian elf\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (elf_header->elf64.e_shentsize != sizeof(struct elf64_section_header)) {
|
||||
printf("Elf section headers not correct size\n");
|
||||
}
|
||||
|
||||
kernel_start = (uintptr_t) kernel;
|
||||
elf_headers = (struct elf64_section_header *) (kernel_start + elf_header->elf64.e_shoff);
|
||||
elf_header_cnt = elf_header->elf64.e_shnum;
|
||||
debug_find_sections(elf_header->elf64.e_shstrndx);
|
||||
}
|
||||
|
||||
struct elf64_symtab_entry *debug_get_entry_for_addr(uintptr_t addr) {
|
||||
if (elf_symtab == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct elf64_symtab_entry *first = (struct elf64_symtab_entry *) (kernel_start + elf_symtab->sh_offset);
|
||||
uint32_t num = elf_symtab->sh_size / sizeof(struct elf64_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) {
|
||||
// todo support non-x86
|
||||
struct stackframe *frame = __builtin_frame_address(0);
|
||||
void (*printer)(const char *) = do_sync ? kprint_now : kprint;
|
||||
printer("\n\n## Stack Trace ##\n");
|
||||
char msg[1024] = {0};
|
||||
while (frame->ebp != NULL) {
|
||||
struct elf64_symtab_entry *entry = debug_get_entry_for_addr(frame->eip);
|
||||
if (entry == NULL) {
|
||||
snprintf(msg, 1024,"#unknown (%lx)\n", frame->eip);
|
||||
} else {
|
||||
snprintf(msg, 1024, "%s (%lx)\n", debug_get_strtab_entry(entry->st_name), frame->eip);
|
||||
};
|
||||
printer(msg);
|
||||
frame = frame->ebp;
|
||||
}
|
||||
printer("\n");
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <yak/rt/kmain.h>
|
||||
#include <yak/rt/panic.h>
|
||||
#include "yak/platform/generic/platform.h"
|
||||
#include <yak/platform/generic/platform.h>
|
||||
|
||||
void kmain() {
|
||||
_init();
|
||||
|
||||
@@ -9,8 +9,13 @@
|
||||
|
||||
print_function print_functions[MAX_PRINT_FUNCTIONS] = {0};
|
||||
|
||||
void kprint_now(char* msg) {
|
||||
char* m = msg;
|
||||
void kprint(const char* msg) {
|
||||
// todo async
|
||||
kprint_now(msg);
|
||||
}
|
||||
|
||||
void kprint_now(const char* msg) {
|
||||
const char* m = msg;
|
||||
while (*m != 0) {
|
||||
kprint_putc_now(*m);
|
||||
m++;
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <limine.h>
|
||||
#include <yak/rt/kprint.h>
|
||||
|
||||
#include <yak/rt/debug/debug.h>
|
||||
#include <yak/rt/kmain.h>
|
||||
#include <yak/rt/kprint.h>
|
||||
|
||||
static struct limine_bootloader_info_request limine_bootloader_info_request = {
|
||||
.id = LIMINE_BOOTLOADER_INFO_REQUEST,
|
||||
@@ -110,5 +112,9 @@ void limine_init() {
|
||||
printf("Booted using limine from an unknown bootloader\n");
|
||||
}
|
||||
|
||||
if (limine_kernel_file_request.response != NULL) {
|
||||
debug_store_info(limine_kernel_file_request.response->kernel_file->address);
|
||||
}
|
||||
|
||||
kmain();
|
||||
}
|
||||
|
||||
@@ -3,13 +3,18 @@
|
||||
//
|
||||
|
||||
#include <yak/rt/panic.h>
|
||||
#include "yak/rt/kprint.h"
|
||||
#include "yak/platform/generic/platform.h"
|
||||
#include <yak/rt/kprint.h>
|
||||
#include <yak/platform/generic/platform.h>
|
||||
#ifdef USE_DEBUG
|
||||
#include <yak/rt/debug/debug.h>
|
||||
#endif
|
||||
|
||||
void __attribute__((__noreturn__)) panic(char *reason) {
|
||||
kprint_now(reason);
|
||||
#ifdef USE_DEBUG
|
||||
debug_backtrace(true);
|
||||
#endif
|
||||
|
||||
// todo stack trace
|
||||
kprint_now(reason);
|
||||
|
||||
halt_forever();
|
||||
}
|
||||
Reference in New Issue
Block a user