Improve debugging functions

- More sensible stack tracer, in C++ (no symbols yet)
- Was forgetting to add null frame to new kernel stacks
- __kernel_assert was using an old vector
- A GP fault will only print its associated table entry
This commit is contained in:
Justin C. Miller
2019-03-15 00:47:46 -07:00
parent 6410c898c5
commit bf8286d15f
9 changed files with 81 additions and 66 deletions

View File

@@ -136,6 +136,10 @@ rule strip
strip -g $out; $ strip -g $out; $
objcopy --add-gnu-debuglink=$out.debug $out objcopy --add-gnu-debuglink=$out.debug $out
rule dump
description = Dumping decompiled $name
command = objdump -DS $in > $out
{% for target in targets %} {% for target in targets %}
subninja {{ target }}/target.ninja 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 build $builddir/popcorn.elf | $builddir/popcorn.elf.debug : strip $builddir/host/popcorn.elf
name = kernel 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 build $builddir/popcorn.elf-gdb.py : cp ${srcroot}/assets/debugging/popcorn.elf-gdb.py
name = kernel debug python scripts name = kernel debug python scripts

View File

@@ -8,13 +8,14 @@ __kernel_assert(const char *file, unsigned line, const char *message)
if (cons) { if (cons) {
cons->set_color(9 , 0); cons->set_color(9 , 0);
cons->puts("\n\n ERROR: "); cons->puts("\n\n ERROR: ");
cons->puts(message);
cons->puts("\n ");
cons->puts(file); cons->puts(file);
cons->puts(":"); cons->puts(":");
cons->put_dec(line); cons->put_dec(line);
cons->puts(": "); cons->puts("\n");
cons->puts(message);
} }
__asm__ ( "int $0e7h" ); __asm__ ( "int $0e4h" );
while (1) __asm__ ("hlt"); while (1) __asm__ ("hlt");
} }

View File

@@ -4,7 +4,9 @@
#include "gdt.h" #include "gdt.h"
#include "page_manager.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_enter = 0;
size_t __counter_syscall_sysret = 0; size_t __counter_syscall_sysret = 0;
@@ -14,48 +16,52 @@ print_regs(const cpu_state &regs)
{ {
console *cons = console::get(); console *cons = console::get();
print_reg("rax", regs.rax); print_regL("rax", regs.rax);
print_reg("rbx", regs.rbx); print_regM("rbx", regs.rbx);
print_reg("rcx", regs.rcx); print_regR("rcx", regs.rcx);
print_reg("rdx", regs.rdx); print_regL("rdx", regs.rdx);
print_reg("rdi", regs.rdi); print_regM("rdi", regs.rdi);
print_reg("rsi", regs.rsi); print_regR("rsi", regs.rsi);
cons->puts("\n"); cons->puts("\n");
print_reg(" r8", regs.r8); print_regL(" r8", regs.r8);
print_reg(" r9", regs.r9); print_regM(" r9", regs.r9);
print_reg("r10", regs.r10); print_regR("r10", regs.r10);
print_reg("r11", regs.r11); print_regL("r11", regs.r11);
print_reg("r12", regs.r12); print_regM("r12", regs.r12);
print_reg("r13", regs.r13); print_regR("r13", regs.r13);
print_reg("r14", regs.r14); print_regL("r14", regs.r14);
print_reg("r15", regs.r15); print_regM("r15", regs.r15);
cons->puts("\n"); cons->puts("\n\n");
print_reg("rbp", regs.rbp); print_regL("rbp", regs.rbp);
print_reg("rsp", regs.user_rsp); print_regM("rsp", regs.user_rsp);
print_reg("sp0", tss_get_stack(0)); print_regR("sp0", tss_get_stack(0));
cons->puts("\n"); print_regL("rip", regs.rip);
print_reg(" cs", regs.cs); print_regM("cr3", page_manager::get()->get_pml4());
print_reg(" ss", regs.ss); cons->puts("\n\n");
cons->puts("\n");
print_reg("rip", regs.rip);
cons->puts("\n");
print_reg("cr3", page_manager::get()->get_pml4());
} }
struct frame
{
frame *prev;
uintptr_t return_addr;
};
void void
print_stacktrace(int skip) print_stacktrace(int skip)
{ {
console *cons = console::get(); console *cons = console::get();
int frame = 0;
uint64_t bp = get_frame(skip); frame *fp = nullptr;
while (bp) { int fi = -skip;
cons->printf(" frame %2d: %lx\n", frame, bp); __asm__ __volatile__ ( "mov %%rbp, %0" : "=r" (fp) );
bp = get_frame(++frame + skip);
while (fp) {
if (fi++ >= 0)
cons->printf(" frame %2d: %lx\n", fi-1, fp->return_addr);
fp = fp->prev;
} }
} }

View File

@@ -9,7 +9,6 @@ extern "C" {
uintptr_t get_rip(); uintptr_t get_rip();
uintptr_t get_frame(int frame); uintptr_t get_frame(int frame);
uintptr_t get_gsbase(); uintptr_t get_gsbase();
} }
extern size_t __counter_syscall_enter; extern size_t __counter_syscall_enter;
@@ -17,7 +16,7 @@ extern size_t __counter_syscall_sysret;
void print_regs(const cpu_state &regs); void print_regs(const cpu_state &regs);
void print_stack(const cpu_state &regs); void print_stack(const cpu_state &regs);
void print_stacktrace(int skip = 0); void print_stacktrace(int skip);
#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value)); #define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value));

View File

@@ -18,19 +18,3 @@ _halt:
hlt hlt
jmp _halt 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

View File

@@ -184,18 +184,25 @@ gdt_init()
} }
void void
gdt_dump() gdt_dump(int index)
{ {
const table_ptr &table = g_gdtr; const table_ptr &table = g_gdtr;
console *cons = console::get(); 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); 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 = const gdt_descriptor *gdt =
reinterpret_cast<const gdt_descriptor *>(table.base); reinterpret_cast<const gdt_descriptor *>(table.base);
for (int i = 0; i < count; ++i) { for (int i = start; i < start+count; ++i) {
uint32_t base = uint32_t base =
(gdt[i].base_high << 24) | (gdt[i].base_high << 24) |
(gdt[i].base_mid << 16) | (gdt[i].base_mid << 16) |
@@ -233,17 +240,25 @@ gdt_dump()
} }
void void
idt_dump() idt_dump(int index)
{ {
const table_ptr &table = g_idtr; 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); 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 = const idt_descriptor *idt =
reinterpret_cast<const idt_descriptor *>(table.base); reinterpret_cast<const idt_descriptor *>(table.base);
for (int i = 0; i < count; ++i) { for (int i = start; i < start+count; ++i) {
uint64_t base = uint64_t base =
(static_cast<uint64_t>(idt[i].base_high) << 32) | (static_cast<uint64_t>(idt[i].base_high) << 32) |
(static_cast<uint64_t>(idt[i].base_mid) << 16) | (static_cast<uint64_t>(idt[i].base_mid) << 16) |

View File

@@ -25,7 +25,9 @@ void tss_set_stack(int ring, uintptr_t rsp);
uintptr_t tss_get_stack(int ring); uintptr_t tss_get_stack(int ring);
/// Dump information about the current GDT to the screen /// 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 /// 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);

View File

@@ -124,13 +124,13 @@ isr_handler(uintptr_t return_rsp, cpu_state *regs)
switch ((regs->errorcode & 0x07) >> 1) { switch ((regs->errorcode & 0x07) >> 1) {
case 0: case 0:
cons->printf(" GDT[%x]\n", index); cons->printf(" GDT[%x]\n", index);
gdt_dump(); gdt_dump(index);
break; break;
case 1: case 1:
case 3: case 3:
cons->printf(" IDT[%x]\n", index); cons->printf(" IDT[%x]\n", index);
idt_dump(); idt_dump(index);
break; break;
default: default:

View File

@@ -143,8 +143,9 @@ scheduler::load_process(const char *name, const void *data, size_t size)
// Create a one-page kernel stack space // Create a one-page kernel stack space
void *stack0 = proc->setup_kernel_stack(stack_size, 0); void *stack0 = proc->setup_kernel_stack(stack_size, 0);
// Stack grows down, point to the end // Stack grows down, point to the end, resere space for initial null frame
void *sp0 = kutil::offset_pointer(stack0, stack_size); static const size_t null_frame = sizeof(uint64_t);
void *sp0 = kutil::offset_pointer(stack0, stack_size - null_frame);
cpu_state *state = reinterpret_cast<cpu_state *>(sp0) - 1; cpu_state *state = reinterpret_cast<cpu_state *>(sp0) - 1;