3 Commits

9 changed files with 152 additions and 25 deletions

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ iso_root
*/*.gch
*/*/*.gch
.gdb_history
symbols.map
symbols.S

View File

@@ -1,4 +1,4 @@
SOURCES = src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
SOURCES = src/debug/panic.c src/debug/stacktrace.c src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable
@@ -9,6 +9,10 @@ build:
nasm -f elf64 src/idt/idt.S -o idt_stub.o
nasm -f elf64 src/entry.S -o entry.o
x86_64-elf-ld -o pepperk -T linker.ld *.o
nm -n pepperk | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
python3 symbols.py
nasm -f elf64 symbols.S -o symbols.o
x86_64-elf-ld -o pepperk -T linker.ld *.o
limine/limine:
rm -rf limine
@@ -44,4 +48,4 @@ run: build-iso
/usr/bin/qemu-system-x86_64 -cdrom pepper.iso -serial stdio
clean:
rm -rf *.o pepperk iso_root pepper.iso limine
rm -rf *.o symbols.map symbols.S pepperk iso_root pepper.iso limine

View File

@@ -2,7 +2,7 @@
## Trying the kernel
First install the dependencies: `sudo apt install xorriso make qemu-system`
First install the dependencies: `sudo apt install python3 xorriso make qemu-system`
Then, to compile the kernel and make an ISO image file: `make build-iso`
To run it with QEMU, `make run`

View File

@@ -10,7 +10,7 @@
/* version */
#define PEPPEROS_VERSION_MAJOR "0"
#define PEPPEROS_VERSION_MINOR "0"
#define PEPPEROS_VERSION_PATCH "1"
#define PEPPEROS_VERSION_PATCH "58"
#define PEPPEROS_SPLASH "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n"
/* process */

23
src/debug/panic.c Normal file
View File

@@ -0,0 +1,23 @@
#include <stddef.h>
#include "idt/idt.h"
#include "io/serial/serial.h"
#include "kernel.h"
void panic(struct cpu_status_t* ctx, const char* str)
{
CLEAR_INTERRUPTS;
if (ctx == NULL)
{
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m Something went horribly wrong! (no cpu ctx)");
DIE_DEBUG(str);
skputc('\n');
DEBUG("\x1b[38;5;231m\x1b[48;5;196mend Kernel panic - halting...\x1b[0m");
hcf();
}
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\n\rrax=%p rbx=%p rcx=%p rdx=%p\n\rrsi=%p rdi=%p r8=%p r9=%p\n\rr10=%p r11=%p r12=%p r13=%p\n\rr14=%p r15=%p\n\n\rflags=%p\n\rHalting...",
ctx->iret_rip,
ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi,
ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags);
debug_stack_trace(100);
hcf();
}

75
src/debug/stacktrace.c Normal file
View File

@@ -0,0 +1,75 @@
#include <stdint.h>
#include "kernel.h"
void debug_stack_trace(unsigned int max_frames)
{
DEBUG("*** begin stack trace ***");
// Thanks GCC :)
uintptr_t* rbp = (uintptr_t*)__builtin_frame_address(0);
for (unsigned int frame=0; frame<max_frames && rbp != NULL; frame++)
{
// Return address, 1 word above saved rbp
uintptr_t rip = rbp[1];
uintptr_t offset = 0;
const char* name = debug_find_symbol(rip, &offset);
DEBUG("[%u] <0x%p> (%s+0x%x)", frame, (void*)rip, name, offset);
uintptr_t* next_rbp = (uintptr_t*)rbp[0];
// invalid rbp or we're at the end
if (next_rbp <= rbp || next_rbp == NULL)
{
break;
}
rbp = next_rbp;
}
DEBUG("*** end stack trace ***");
}
typedef struct
{
uint64_t addr;
const char *name;
} __attribute__((packed)) kernel_symbol_t;
__attribute__((weak)) extern kernel_symbol_t symbol_table[];
__attribute__((weak)) extern uint64_t symbol_count;
// binary search
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset)
{
if (!symbol_table || symbol_count == 0)
{
if (offset) *offset = 0;
return "???";
}
int low = 0, high = (int)symbol_count - 1;
int best = -1;
while (low <= high)
{
int mid = (low + high) / 2;
if (symbol_table[mid].addr <= rip)
{
best = mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
if (best != -1)
{
if (offset)
{
*offset = rip - symbol_table[best].addr;
}
return symbol_table[best].name;
}
if (offset) *offset = 0;
return "unknown";
}

View File

@@ -31,6 +31,10 @@ enum ErrorCodes
void panic(struct cpu_status_t* ctx, const char* str);
void hcf();
void idle();
void debug_stack_trace(unsigned int max_frames);
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
#define assert(check) do { if(!(check)) hcf(); } while(0)
struct boot_context

View File

@@ -39,25 +39,6 @@ void idle() {SET_INTERRUPTS; for(;;)asm("hlt");}
uint8_t kernel_stack[KERNEL_STACK_SIZE] __attribute__((aligned(16)));
void panic(struct cpu_status_t* ctx, const char* str)
{
CLEAR_INTERRUPTS;
if (ctx == NULL)
{
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m Something went horribly wrong! (no cpu ctx)");
DIE_DEBUG(str);
skputc('\n');
DEBUG("\x1b[38;5;231m\x1b[48;5;196mend Kernel panic - halting...\x1b[0m");
hcf();
}
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\n\rrax=%p rbx=%p rcx=%p rdx=%p\n\rrsi=%p rdi=%p r8=%p r9=%p\n\rr10=%p r11=%p r12=%p r13=%p\n\rr14=%p r15=%p\n\n\rflags=%p\n\rstack at rbp=%p\n\rHalting...",
ctx->iret_rip,
ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi,
ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags,
ctx->rbp);
hcf();
}
struct boot_context boot_ctx;
extern volatile struct limine_framebuffer_request framebuffer_request;
@@ -71,7 +52,11 @@ extern struct process_t* current_process;
void pedicel_main(void* arg)
{
printf("Hello, world from a KERNEL PROCESS!");
//panic(NULL, "WE DID IT! Hello, world from a PROCESS!!!!");
}
void two_main(void* arg)
{
printf("...process 2 speaking!!!");
}
void idle_main(void* arg)
@@ -112,6 +97,7 @@ void kmain()
struct process_t* idle_proc = process_create("idle", (void*)idle_main, 0);
struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0);
struct process_t* two = process_create("two", (void*)two_main, 0);
process_display_list(processes_list);

33
symbols.py Normal file
View File

@@ -0,0 +1,33 @@
# Make assembly file from ELF symbols map
# Then link it to kernel so it's aware of symbol names
# then we can use that for the stack trace.
print("Extracting symbols from map file to assembly...")
with open("symbols.map", "r") as f:
lines = f.readlines()
symbols = []
for line in lines:
parts = line.split()
# output is formed like "address name"
symbols.append((parts[0], parts[1]))
with open("symbols.S", "w") as f:
f.write("section .rodata\n")
f.write("global symbol_table\n")
f.write("global symbol_count\n")
f.write("symbol_table:\n")
for i, (addr, name) in enumerate(symbols):
f.write(f" dq 0x{addr}\n")
f.write(f" dq sym_name_{i}\n")
f.write("\nsymbol_count: dq " + str(len(symbols)) + "\n\n")
for i, (addr, name) in enumerate(symbols):
# escaping quotes
safe_name = name.replace('"', '\\"')
f.write(f'sym_name_{i}: db "{safe_name}", 0\n')
print("Done!")