feat: ported debug logging
This commit is contained in:
@@ -11,6 +11,7 @@ if (NOT ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
|
||||
endif ()
|
||||
|
||||
# Define global options
|
||||
option(USE_DEBUG "Enable debug code" ON)
|
||||
option(USE_LIMINE "Enable support for the limine boot protocol" ON)
|
||||
|
||||
# Find builtins
|
||||
@@ -57,10 +58,17 @@ if (NOT ${USE_LIMINE})
|
||||
endif ()
|
||||
|
||||
# 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)
|
||||
|
||||
if (${USE_DEBUG})
|
||||
add_definitions(-DUSE_DEBUG)
|
||||
file(GLOB DEBUG_KERNEL_SOURCES src/rt/debug/*.c)
|
||||
endif ()
|
||||
if (${USE_LIMINE})
|
||||
add_definitions(-DUSE_LIMINE)
|
||||
file(GLOB LIMINE_KERNEL_SOURCES src/rt/limine/*.c)
|
||||
endif ()
|
||||
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
|
||||
${KERNEL_SOURCES}
|
||||
${LIMINE_KERNEL_SOURCES}
|
||||
${DEBUG_KERNEL_SOURCES}
|
||||
${PLATFORM_GENERIC_SOURCES}
|
||||
${PLATFORM_SPECIFIC_SOURCES}
|
||||
${PLATFORM_SPECIFIC_ASM_SOURCES}
|
||||
|
||||
167
yak-kernel/include/elf.h
Normal file
167
yak-kernel/include/elf.h
Normal 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
|
||||
14
yak-kernel/include/yak/rt/debug/debug.h
Normal file
14
yak-kernel/include/yak/rt/debug/debug.h
Normal 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
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <yak/platform/generic/platform.h>
|
||||
|
||||
void platform_init() {
|
||||
printf("Init X86_64");
|
||||
printf("Init X86_64\n");
|
||||
}
|
||||
|
||||
void __attribute__((noreturn)) halt_forever() {
|
||||
|
||||
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