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

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

View File

@@ -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 &regs)
{
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;
}
}

View File

@@ -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 &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));

View File

@@ -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

View File

@@ -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<const gdt_descriptor *>(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<const idt_descriptor *>(table.base);
for (int i = 0; i < count; ++i) {
for (int i = start; i < start+count; ++i) {
uint64_t base =
(static_cast<uint64_t>(idt[i].base_high) << 32) |
(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);
/// 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);

View File

@@ -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:

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
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<cpu_state *>(sp0) - 1;