diff --git a/scripts/templates/build.ninja.j2 b/scripts/templates/build.ninja.j2 index 6c94c3d..e2ee594 100644 --- a/scripts/templates/build.ninja.j2 +++ b/scripts/templates/build.ninja.j2 @@ -136,6 +136,10 @@ rule strip strip -g $out; $ objcopy --add-gnu-debuglink=$out.debug $out +rule dump + description = Dumping decompiled $name + command = objdump -DS $in > $out + {% for target in targets %} subninja {{ target }}/target.ninja @@ -161,6 +165,9 @@ build $builddir/ovmf_vars_d.fd : cp $srcroot/assets/ovmf/x64/ovmf_vars_d.fd build $builddir/popcorn.elf | $builddir/popcorn.elf.debug : strip $builddir/host/popcorn.elf name = kernel +build $builddir/popcorn.dump : dump $builddir/host/popcorn.elf + name = kernel + build $builddir/popcorn.elf-gdb.py : cp ${srcroot}/assets/debugging/popcorn.elf-gdb.py name = kernel debug python scripts diff --git a/src/kernel/assert.cpp b/src/kernel/assert.cpp index 263b953..1292bb8 100644 --- a/src/kernel/assert.cpp +++ b/src/kernel/assert.cpp @@ -8,13 +8,14 @@ __kernel_assert(const char *file, unsigned line, const char *message) if (cons) { cons->set_color(9 , 0); cons->puts("\n\n ERROR: "); + cons->puts(message); + cons->puts("\n "); cons->puts(file); cons->puts(":"); cons->put_dec(line); - cons->puts(": "); - cons->puts(message); + cons->puts("\n"); } - __asm__ ( "int $0e7h" ); + __asm__ ( "int $0e4h" ); while (1) __asm__ ("hlt"); } diff --git a/src/kernel/debug.cpp b/src/kernel/debug.cpp index f82f4b9..620b511 100644 --- a/src/kernel/debug.cpp +++ b/src/kernel/debug.cpp @@ -4,7 +4,9 @@ #include "gdt.h" #include "page_manager.h" -#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value)); +#define print_regL(name, value) cons->printf(" %s: %016lx", name, (value)); +#define print_regM(name, value) cons->printf(" %s: %016lx", name, (value)); +#define print_regR(name, value) cons->printf(" %s: %016lx\n", name, (value)); size_t __counter_syscall_enter = 0; size_t __counter_syscall_sysret = 0; @@ -14,48 +16,52 @@ print_regs(const cpu_state ®s) { console *cons = console::get(); - print_reg("rax", regs.rax); - print_reg("rbx", regs.rbx); - print_reg("rcx", regs.rcx); - print_reg("rdx", regs.rdx); - print_reg("rdi", regs.rdi); - print_reg("rsi", regs.rsi); + print_regL("rax", regs.rax); + print_regM("rbx", regs.rbx); + print_regR("rcx", regs.rcx); + print_regL("rdx", regs.rdx); + print_regM("rdi", regs.rdi); + print_regR("rsi", regs.rsi); cons->puts("\n"); - print_reg(" r8", regs.r8); - print_reg(" r9", regs.r9); - print_reg("r10", regs.r10); - print_reg("r11", regs.r11); - print_reg("r12", regs.r12); - print_reg("r13", regs.r13); - print_reg("r14", regs.r14); - print_reg("r15", regs.r15); + print_regL(" r8", regs.r8); + print_regM(" r9", regs.r9); + print_regR("r10", regs.r10); + print_regL("r11", regs.r11); + print_regM("r12", regs.r12); + print_regR("r13", regs.r13); + print_regL("r14", regs.r14); + print_regM("r15", regs.r15); - cons->puts("\n"); - print_reg("rbp", regs.rbp); - print_reg("rsp", regs.user_rsp); - print_reg("sp0", tss_get_stack(0)); + cons->puts("\n\n"); + print_regL("rbp", regs.rbp); + print_regM("rsp", regs.user_rsp); + print_regR("sp0", tss_get_stack(0)); - cons->puts("\n"); - print_reg(" cs", regs.cs); - print_reg(" ss", regs.ss); - - cons->puts("\n"); - print_reg("rip", regs.rip); - - cons->puts("\n"); - print_reg("cr3", page_manager::get()->get_pml4()); + print_regL("rip", regs.rip); + print_regM("cr3", page_manager::get()->get_pml4()); + cons->puts("\n\n"); } +struct frame +{ + frame *prev; + uintptr_t return_addr; +}; + void print_stacktrace(int skip) { console *cons = console::get(); - int frame = 0; - uint64_t bp = get_frame(skip); - while (bp) { - cons->printf(" frame %2d: %lx\n", frame, bp); - bp = get_frame(++frame + skip); + + frame *fp = nullptr; + int fi = -skip; + __asm__ __volatile__ ( "mov %%rbp, %0" : "=r" (fp) ); + + while (fp) { + if (fi++ >= 0) + cons->printf(" frame %2d: %lx\n", fi-1, fp->return_addr); + fp = fp->prev; } } diff --git a/src/kernel/debug.h b/src/kernel/debug.h index bd8624b..6779c41 100644 --- a/src/kernel/debug.h +++ b/src/kernel/debug.h @@ -9,7 +9,6 @@ extern "C" { uintptr_t get_rip(); uintptr_t get_frame(int frame); uintptr_t get_gsbase(); - } extern size_t __counter_syscall_enter; @@ -17,7 +16,7 @@ extern size_t __counter_syscall_sysret; void print_regs(const cpu_state ®s); void print_stack(const cpu_state ®s); -void print_stacktrace(int skip = 0); +void print_stacktrace(int skip); #define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value)); diff --git a/src/kernel/debug.s b/src/kernel/debug.s index 0fb0500..646dc0d 100644 --- a/src/kernel/debug.s +++ b/src/kernel/debug.s @@ -18,19 +18,3 @@ _halt: hlt jmp _halt - -global get_frame -get_frame: - mov rcx, rbp - -.loop: - mov rax, [rcx + 8] - mov rcx, [rcx] - cmp rdi, 0 - je .done - - sub rdi, 1 - jmp .loop - -.done: - ret diff --git a/src/kernel/gdt.cpp b/src/kernel/gdt.cpp index 6c6b526..7ff443b 100644 --- a/src/kernel/gdt.cpp +++ b/src/kernel/gdt.cpp @@ -184,18 +184,25 @@ gdt_init() } void -gdt_dump() +gdt_dump(int index) { const table_ptr &table = g_gdtr; console *cons = console::get(); - cons->printf(" GDT: loc:%lx size:%d\n", table.base, table.limit+1); + int start = 0; int count = (table.limit + 1) / sizeof(gdt_descriptor); + if (index != -1) { + start = index; + count = 1; + } else { + cons->printf(" GDT: loc:%lx size:%d\n", table.base, table.limit+1); + } + const gdt_descriptor *gdt = reinterpret_cast(table.base); - for (int i = 0; i < count; ++i) { + for (int i = start; i < start+count; ++i) { uint32_t base = (gdt[i].base_high << 24) | (gdt[i].base_mid << 16) | @@ -233,17 +240,25 @@ gdt_dump() } void -idt_dump() +idt_dump(int index) { const table_ptr &table = g_idtr; - log::info(logs::boot, "Loaded IDT at: %lx size: %d bytes", table.base, table.limit+1); + int start = 0; int count = (table.limit + 1) / sizeof(idt_descriptor); + if (index != -1) { + start = index; + count = 1; + log::info(logs::boot, "IDT FOR INDEX %02x", index); + } else { + log::info(logs::boot, "Loaded IDT at: %lx size: %d bytes", table.base, table.limit+1); + } + const idt_descriptor *idt = reinterpret_cast(table.base); - for (int i = 0; i < count; ++i) { + for (int i = start; i < start+count; ++i) { uint64_t base = (static_cast(idt[i].base_high) << 32) | (static_cast(idt[i].base_mid) << 16) | diff --git a/src/kernel/gdt.h b/src/kernel/gdt.h index 879e458..848175e 100644 --- a/src/kernel/gdt.h +++ b/src/kernel/gdt.h @@ -25,7 +25,9 @@ void tss_set_stack(int ring, uintptr_t rsp); uintptr_t tss_get_stack(int ring); /// Dump information about the current GDT to the screen -void gdt_dump(); +/// \arg index Which entry to print, or -1 for all entries +void gdt_dump(int index = -1); /// Dump information about the current IDT to the screen -void idt_dump(); +/// \arg index Which entry to print, or -1 for all entries +void idt_dump(int index = -1); diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 0358599..3f20d23 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -124,13 +124,13 @@ isr_handler(uintptr_t return_rsp, cpu_state *regs) switch ((regs->errorcode & 0x07) >> 1) { case 0: cons->printf(" GDT[%x]\n", index); - gdt_dump(); + gdt_dump(index); break; case 1: case 3: cons->printf(" IDT[%x]\n", index); - idt_dump(); + idt_dump(index); break; default: diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 0a62462..b837847 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -143,8 +143,9 @@ scheduler::load_process(const char *name, const void *data, size_t size) // Create a one-page kernel stack space void *stack0 = proc->setup_kernel_stack(stack_size, 0); - // Stack grows down, point to the end - void *sp0 = kutil::offset_pointer(stack0, stack_size); + // Stack grows down, point to the end, resere space for initial null frame + static const size_t null_frame = sizeof(uint64_t); + void *sp0 = kutil::offset_pointer(stack0, stack_size - null_frame); cpu_state *state = reinterpret_cast(sp0) - 1;