feat: ported debug logging

This commit is contained in:
2023-09-27 22:26:50 +02:00
parent 7411fb55ea
commit 0567926814
10 changed files with 342 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ if (NOT ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
endif () endif ()
# Define global options # Define global options
option(USE_DEBUG "Enable debug code" ON)
option(USE_LIMINE "Enable support for the limine boot protocol" ON) option(USE_LIMINE "Enable support for the limine boot protocol" ON)
# Find builtins # Find builtins
@@ -57,10 +58,17 @@ if (NOT ${USE_LIMINE})
endif () endif ()
# Find sources # Find sources
file(GLOB KERNEL_SOURCES src/rt/*.c src/ulibc/*.c) file(GLOB KERNEL_SOURCES
src/rt/*.c
src/ulibc/*.c)
file(GLOB PLATFORM_GENERIC_SOURCES src/platform/generic/*.c) file(GLOB PLATFORM_GENERIC_SOURCES src/platform/generic/*.c)
if (${USE_DEBUG})
add_definitions(-DUSE_DEBUG)
file(GLOB DEBUG_KERNEL_SOURCES src/rt/debug/*.c)
endif ()
if (${USE_LIMINE}) if (${USE_LIMINE})
add_definitions(-DUSE_LIMINE)
file(GLOB LIMINE_KERNEL_SOURCES src/rt/limine/*.c) file(GLOB LIMINE_KERNEL_SOURCES src/rt/limine/*.c)
endif () endif ()
if (NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/${CMAKE_SYSTEM_PROCESSOR}) if (NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/${CMAKE_SYSTEM_PROCESSOR})
@@ -77,6 +85,7 @@ file(GLOB CRTN src/platform/generic/crt/crtn.c)
set(KERNEL_SOURCE_FILES set(KERNEL_SOURCE_FILES
${KERNEL_SOURCES} ${KERNEL_SOURCES}
${LIMINE_KERNEL_SOURCES} ${LIMINE_KERNEL_SOURCES}
${DEBUG_KERNEL_SOURCES}
${PLATFORM_GENERIC_SOURCES} ${PLATFORM_GENERIC_SOURCES}
${PLATFORM_SPECIFIC_SOURCES} ${PLATFORM_SPECIFIC_SOURCES}
${PLATFORM_SPECIFIC_ASM_SOURCES} ${PLATFORM_SPECIFIC_ASM_SOURCES}

167
yak-kernel/include/elf.h Normal file
View File

@@ -0,0 +1,167 @@
//
// Created by rick on 07-03-21.
//
#ifndef NEW_KERNEL_ELF_H
#define NEW_KERNEL_ELF_H
#include <sys/types.h>
// \x7FELF (little endian)
#define ELF_MAGIC 0x464C457F
#define ELF_CLASS_32 1
#define ELF_CLASS_64 2
#define ELF_ENDIAN_LITTLE 1
#define ELF_ENDIAN_BIG 2
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MASKPROC 0xf0000000
#define ELF32_ST_BIND(i) ((i)>>4)
#define ELF32_ST_TYPE(i) ((i)&0xf)
#define ELF32_ST_INFO(b, t) (((b)<<4)+((t)&0xf))
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15
struct elf_file_header {
uint32_t ei_magic;
uint8_t ei_class;
uint8_t ei_data;
uint8_t ei_version;
uint8_t ei_osabi;
uint8_t ei_abiversion;
uint64_t: 56; // 7 bytes padding
union {
struct {
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf32 __attribute((packed));
struct {
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf64 __attribute((packed));
};
} __attribute((packed));
struct elf32_program_header {
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} __attribute((packed));
struct elf64_program_header {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} __attribute((packed));
struct elf32_section_header {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
uint32_t sh_addr;
uint32_t sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addr_align;
uint32_t sh_ent_size;
} __attribute((packed));
struct elf64_section_header {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addr_align;
uint64_t sh_ent_size;
} __attribute((packed));
struct elf32_symtab_entry {
uint32_t st_name;
uint32_t st_value;
uint32_t st_size;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
} __attribute((packed));
struct elf64_symtab_entry {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
} __attribute((packed));
#endif //NEW_KERNEL_ELF_H

View File

@@ -0,0 +1,14 @@
//
// Created by rick on 08-03-21.
//
#ifndef NEW_KERNEL_DEBUG_H
#define NEW_KERNEL_DEBUG_H
#include <stdbool.h>
void debug_store_info(void *kernel);
void debug_backtrace(bool do_sync);
#endif //NEW_KERNEL_DEBUG_H

View File

@@ -7,7 +7,9 @@
typedef void (*print_function)(char c); typedef void (*print_function)(char c);
void kprint_now(char* msg); void kprint(const char* msg);
void kprint_now(const char* msg);
void kprint_putc_now(char c); void kprint_putc_now(char c);

View File

@@ -5,7 +5,7 @@
#include <yak/platform/generic/platform.h> #include <yak/platform/generic/platform.h>
void platform_init() { void platform_init() {
printf("Init X86_64"); printf("Init X86_64\n");
} }
void __attribute__((noreturn)) halt_forever() { void __attribute__((noreturn)) halt_forever() {

View 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");
}

View File

@@ -1,6 +1,6 @@
#include <yak/rt/kmain.h> #include <yak/rt/kmain.h>
#include <yak/rt/panic.h> #include <yak/rt/panic.h>
#include "yak/platform/generic/platform.h" #include <yak/platform/generic/platform.h>
void kmain() { void kmain() {
_init(); _init();

View File

@@ -9,8 +9,13 @@
print_function print_functions[MAX_PRINT_FUNCTIONS] = {0}; print_function print_functions[MAX_PRINT_FUNCTIONS] = {0};
void kprint_now(char* msg) { void kprint(const char* msg) {
char* m = msg; // todo async
kprint_now(msg);
}
void kprint_now(const char* msg) {
const char* m = msg;
while (*m != 0) { while (*m != 0) {
kprint_putc_now(*m); kprint_putc_now(*m);
m++; m++;

View File

@@ -5,8 +5,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <limine.h> #include <limine.h>
#include <yak/rt/kprint.h>
#include <yak/rt/debug/debug.h>
#include <yak/rt/kmain.h> #include <yak/rt/kmain.h>
#include <yak/rt/kprint.h>
static struct limine_bootloader_info_request limine_bootloader_info_request = { static struct limine_bootloader_info_request limine_bootloader_info_request = {
.id = 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"); 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(); kmain();
} }

View File

@@ -3,13 +3,18 @@
// //
#include <yak/rt/panic.h> #include <yak/rt/panic.h>
#include "yak/rt/kprint.h" #include <yak/rt/kprint.h>
#include "yak/platform/generic/platform.h" #include <yak/platform/generic/platform.h>
#ifdef USE_DEBUG
#include <yak/rt/debug/debug.h>
#endif
void __attribute__((__noreturn__)) panic(char *reason) { void __attribute__((__noreturn__)) panic(char *reason) {
kprint_now(reason); #ifdef USE_DEBUG
debug_backtrace(true);
#endif
// todo stack trace kprint_now(reason);
halt_forever(); halt_forever();
} }