improved debugger, refactored

This commit is contained in:
trimill 2024-02-03 00:37:02 -05:00
parent 72df91d99b
commit 6d7a563d36
No known key found for this signature in database
GPG key ID: 4F77A16E17E10BCB
9 changed files with 276 additions and 208 deletions

View file

@ -3,11 +3,11 @@
#define _PANIC_STR(x) _PANIC_STR2(x) #define _PANIC_STR(x) _PANIC_STR2(x)
#define _PANIC_STR2(x) #x #define _PANIC_STR2(x) #x
#define panic(msg, ...) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg, ## __VA_ARGS__) #define panic(...) _panic_impl(_PANIC_STR(__LINE__), __FILE__, __VA_ARGS__)
#define kassert(val, msg, ...) do { if (!(val)) { panic(msg, ## __VA_ARGS__); } } while(0) #define kassert(val, ...) do { if (!(val)) { panic(__VA_ARGS__); } } while(0)
__attribute__((noreturn,format(printf, 3, 4))) __attribute__((format(printf, 3, 4)))
void _panic_impl(char *line, char *file, char *msg, ...); _Noreturn void _panic_impl(char *line, char *file, char *format, ...);
__attribute__((noreturn,format(printf, 3, 4))) __attribute__((format(printf, 3, 4)))
void _panic_interrupt(void *ip, void *bp, char *msg, ...); _Noreturn void panic_interrupt(void *ip, void *bp, char *format, ...);

View file

@ -6,7 +6,6 @@
#include "bindings.h" #include "bindings.h"
#include "memory.h" #include "memory.h"
#include "serial.h"
/* global state, idk a better way rn */ /* global state, idk a better way rn */
struct acpi_state state; struct acpi_state state;
@ -208,7 +207,7 @@ static void *acpi_find_table_rsdt(struct rsdt *rsdt, const char *identifier, int
memcpy(buf, h->signature, 4); memcpy(buf, h->signature, 4);
buf[4] = '\n'; buf[4] = '\n';
buf[5] = '\0'; buf[5] = '\0';
serial_out_str(buf); kputs(buf);
if (!strncmp(h->signature, identifier, ident_len)) if (!strncmp(h->signature, identifier, ident_len))
return (void *)h; return (void *)h;
} }

View file

@ -1,6 +1,5 @@
#include <backtrace.h> #include <backtrace.h>
#include <lib.h> #include <lib.h>
#include "serial.h"
struct stackframe { struct stackframe {
struct stackframe *rbp; struct stackframe *rbp;
@ -36,17 +35,10 @@ void log_backtrace() {
void log_backtrace_ex(void *ip, void *bp) { void log_backtrace_ex(void *ip, void *bp) {
struct stackframe *frame = bp; struct stackframe *frame = bp;
char buf[20]; kputs("Stack trace:\n");
serial_out_str("Stack trace:\n"); kprintf(" %#lx\n", (size_t)ip);
ultoa((size_t)ip, buf, 16);
serial_out_str(" 0x");
serial_out_str(buf);
serial_out_str("\n");
while (frame) { while (frame) {
ultoa((size_t)frame->rip, buf, 16); kprintf(" %#lx\n", (size_t)frame->rip);
serial_out_str(" 0x");
serial_out_str(buf);
serial_out_str("\n");
frame = frame->rbp; frame = frame->rbp;
} }

View file

@ -1,7 +1,7 @@
#include <lib.h> #include <lib.h>
#include <stddef.h> #include <stddef.h>
#include <serial.h>
#include <backtrace.h> #include <backtrace.h>
#include <serial.h>
#include "debugger.h" #include "debugger.h"
struct dr6 { struct dr6 {
@ -73,183 +73,217 @@ struct breakpoint {
uint8_t rw; uint8_t rw;
uint8_t used; uint8_t used;
uint8_t enable; uint8_t enable;
uint8_t instr_len;
}; };
static size_t dbg_steps = 0; static int dbg_steps = 0;
static int dbg_continue = 0; static int dbg_continue = 0;
static struct breakpoint bkps[4] = {{0}, {0}, {0}, {0}}; static struct breakpoint bkps[4] = {{0}, {0}, {0}, {0}};
static void dbg_putc(char c) { static size_t debugger_read(char *buf, size_t len) {
serial_out(c); char *p = buf;
} size_t result;
while (p < buf + len - 1) {
static void dbg_puts(char *msg) { char ch = serial_in();
serial_out_str(msg); switch (ch) {
} case '\r':
goto end;
static char dbg_getc() { case '\x7f':
return serial_in(); if (p > buf) {
p--;
kputs("\x08 \x08");
}
break;
default:
kputc(ch);
*p++ = ch;
}
}
end:
result = p - buf;
kputc('\n');
for(; p < buf + len; p++) {
*p = 0;
}
return result;
} }
static void debugger_msg(int cause, struct dr6 dr6) { static void debugger_msg(int cause, struct dr6 dr6) {
char buf[24];
switch (cause) { switch (cause) {
case DEBUG_INT3: case DEBUG_INT3:
dbg_puts("dbg: reached int3"); kputs("dbg: reached int3");
break; break;
case DEBUG_FAULT: case DEBUG_FAULT:
dbg_puts("dbg: a fault occured"); kputs("dbg: a fault occured");
break; break;
case DEBUG_DBG: case DEBUG_DBG:
if (dr6.bs) if (dr6.bs)
dbg_puts("dbg: finished steps"); kputs("dbg: finished steps");
else if (dr6.b0) if (dr6.b0)
dbg_puts("dbg: reached breakpoint 0"); kputs("dbg: reached breakpoint 0");
else if (dr6.b1) else if (dr6.b1)
dbg_puts("dbg: reached breakpoint 1"); kputs("dbg: reached breakpoint 1");
else if (dr6.b2) else if (dr6.b2)
dbg_puts("dbg: reached breakpoint 2"); kputs("dbg: reached breakpoint 2");
else if (dr6.b3) else if (dr6.b3)
dbg_puts("dbg: reached breakpoint 3"); kputs("dbg: reached breakpoint 3");
} }
if (dbg_steps > 0) { if (dbg_steps > 0) {
ultoa(dbg_steps, buf, 10); kprintf(" (%d steps left)", dbg_steps);
dbg_puts(" (");
dbg_puts(buf);
dbg_puts(" steps left)");
} }
if (dbg_continue > 0) { if (dbg_continue > 0) {
dbg_puts(" (paused continue)"); kputs(" (paused continue)");
} }
dbg_puts("\n"); kputs("\n");
}
static void debugger_print_reg(char *name, uint64_t val) {
char buf[24];
char *end;
dbg_puts(name);
dbg_puts(": 0x");
end = ultoa(val, buf, 16);
for (int i = 0; i < 16 - (end - buf); i++) {
dbg_putc('0');
}
dbg_puts(buf);
dbg_puts(" (");
end = ultoa(val, buf, 10);
dbg_puts(buf);
dbg_puts(")\n");
} }
static void debugger_print_regs(struct isr_regs *state) { static void debugger_print_regs(struct isr_regs *state) {
debugger_print_reg("rax", state->rax); kprintf("rax: %#016lx (%lu)\n", state->rax, state->rax);
debugger_print_reg("rbx", state->rbx); kprintf("rbx: %#016lx (%lu)\n", state->rbx, state->rbx);
debugger_print_reg("rcx", state->rcx); kprintf("rcx: %#016lx (%lu)\n", state->rcx, state->rcx);
debugger_print_reg("rdx", state->rdx); kprintf("rdx: %#016lx (%lu)\n", state->rdx, state->rdx);
debugger_print_reg("rsi", state->rsi); kprintf("rsi: %#016lx (%lu)\n", state->rsi, state->rsi);
debugger_print_reg("rdi", state->rdi); kprintf("rdi: %#016lx (%lu)\n", state->rdi, state->rdi);
debugger_print_reg("rsp", state->rsp); kprintf("rsp: %#016lx (%lu)\n", state->rsp, state->rsp);
debugger_print_reg("rbp", state->rbp); kprintf("rbp: %#016lx (%lu)\n", state->rbp, state->rbp);
debugger_print_reg("r8 ", state->r8 ); kprintf("r8 : %#016lx (%lu)\n", state->r8 , state->r8 );
debugger_print_reg("r9 ", state->r9 ); kprintf("r9 : %#016lx (%lu)\n", state->r9 , state->r9 );
debugger_print_reg("r10", state->r10); kprintf("r10: %#016lx (%lu)\n", state->r10, state->r10);
debugger_print_reg("r11", state->r11); kprintf("r11: %#016lx (%lu)\n", state->r11, state->r11);
debugger_print_reg("r12", state->r12); kprintf("r12: %#016lx (%lu)\n", state->r12, state->r12);
debugger_print_reg("r13", state->r13); kprintf("r13: %#016lx (%lu)\n", state->r13, state->r13);
debugger_print_reg("r14", state->r14); kprintf("r14: %#016lx (%lu)\n", state->r14, state->r14);
debugger_print_reg("r15", state->r15); kprintf("r15: %#016lx (%lu)\n", state->r15, state->r15);
dbg_puts("---\n"); kputs("---\n");
debugger_print_reg("rip", state->rip); kprintf("rip: %#016lx (%lu)\n", state->rip, state->rip);
dbg_puts("---\n"); kputs("---\n");
debugger_print_reg("rflags", state->rflags); kprintf("rflags: %#016lx (%lu)\n", state->rflags, state->rflags);
struct rflags *rflags = (struct rflags *)state->rflags; struct rflags *rflags = (struct rflags *)state->rflags;
dbg_puts("rflags: "); kputs("rflags: ");
if(rflags->cf) dbg_puts("CF "); if(rflags->cf) kputs("CF ");
if(rflags->pf) dbg_puts("PF "); if(rflags->pf) kputs("PF ");
if(rflags->af) dbg_puts("AF "); if(rflags->af) kputs("AF ");
if(rflags->zf) dbg_puts("ZF "); if(rflags->zf) kputs("ZF ");
if(rflags->sf) dbg_puts("SF "); if(rflags->sf) kputs("SF ");
if(rflags->tf) dbg_puts("TF "); if(rflags->tf) kputs("TF ");
if(rflags->if_) dbg_puts("IF "); if(rflags->if_) kputs("IF ");
if(rflags->df) dbg_puts("DF "); if(rflags->df) kputs("DF ");
if(rflags->of) dbg_puts("OF "); if(rflags->of) kputs("OF ");
if(rflags->iopl) dbg_puts("IOPL "); if(rflags->iopl) kputs("IOPL ");
if(rflags->nt) dbg_puts("NT "); if(rflags->nt) kputs("NT ");
if(rflags->md) dbg_puts("MD "); if(rflags->md) kputs("MD ");
if(rflags->rf) dbg_puts("RF "); if(rflags->rf) kputs("RF ");
if(rflags->vm) dbg_puts("VM "); if(rflags->vm) kputs("VM ");
if(rflags->ac) dbg_puts("AC "); if(rflags->ac) kputs("AC ");
if(rflags->vif) dbg_puts("VIF "); if(rflags->vif) kputs("VIF ");
if(rflags->vip) dbg_puts("VIP "); if(rflags->vip) kputs("VIP ");
if(rflags->id) dbg_puts("ID "); if(rflags->id) kputs("ID ");
dbg_putc('\n'); kputs("\n");
} }
#define PROMPT_LEN 60 #define PROMPT_LEN 60
static int debugger_handle_bkp_cmd(char *buf) { static int debugger_handle_bkp_cmd(char *msg) {
if (buf[0] == 'l') { if (msg[0] == 'l') {
// list breakpoints // list breakpoints
char buf[20];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
dbg_puts("breakpoint ");
dbg_putc('0' + i);
dbg_puts(": ");
struct breakpoint bkp = bkps[i]; struct breakpoint bkp = bkps[i];
if(!bkp.used) { if(!bkp.used) {
dbg_puts("unset\n"); kprintf("breakpoint %d: unset\n", i);
continue; continue;
} }
dbg_puts(" 0x"); const char *lenstrs[] = {"1", "2", "8", "4"};
ultoa(bkp.addr, buf, 16); const char *rwstrs[] = {"x ", "w ", "io", "rw"};
dbg_puts(buf); kprintf(
dbg_puts(" len="); "breakpoint %d: %#016lx len=%s trigger=%s instrlen=%01d %s\n",
switch (bkp.len) { i,
case 0x0: dbg_putc('1'); break; bkp.addr,
case 0x1: dbg_putc('2'); break; lenstrs[bkp.len],
case 0x2: dbg_putc('8'); break; rwstrs[bkp.rw],
case 0x3: dbg_putc('4'); break; bkp.instr_len,
} bkp.enable ? " enabled" : " disabled"
dbg_puts(" trigger="); );
switch (bkp.rw) {
case 0x0: dbg_puts("x "); break;
case 0x1: dbg_puts("w "); break;
case 0x2: dbg_puts("io"); break;
case 0x3: dbg_puts("rw"); break;
}
dbg_puts(bkp.enable ? " enabled" : " disabled");
} }
return 1; return 1;
} else if (buf[0] == 'd') { } else if (msg[0] == 'd') {
// disable breakpoints // disable breakpoints
bkps[0].enable = 0; bkps[0].enable = 0;
bkps[1].enable = 0; bkps[1].enable = 0;
bkps[2].enable = 0; bkps[2].enable = 0;
bkps[3].enable = 0; bkps[3].enable = 0;
kputs("disabled breakpoints\n");
return 1; return 1;
} else if (buf[0] == 'c') { } else if (msg[0] == 'c') {
// clear breakpoints // clear breakpoints
bkps[0].used = 0; bkps[0].used = 0;
bkps[1].used = 0; bkps[1].used = 0;
bkps[2].used = 0; bkps[2].used = 0;
bkps[3].used = 0; bkps[3].used = 0;
kputs("cleared breakpoints\n");
return 1; return 1;
} else if (buf[0] <= '0' && buf[0] >= '3') { } else if (msg[0] <= '0' && msg[0] >= '3') {
dbg_puts("invalid breakpoint command\n"); kputs("invalid breakpoint command\n");
return 1;
}
char buf[64];
int id = msg[0] - '0';
switch (msg[1]) {
case 'e':
bkps[id].enable = bkps[id].used;
kprintf("enabled breakpoint %d\n", id);
return 1;
case 'd':
bkps[id].enable = 0;
kprintf("disabled breakpoint %d\n", id);
return 1;
case 'c':
bkps[id].used = 0;
kprintf("cleared breakpoint %d\n", id);
return 1;
case 'a':
kputs("addr> 0x");
debugger_read(buf, 64);
bkps[id].addr = strtoll(buf, NULL, 16);
kputs("len (1/2/4/8)> ");
debugger_read(buf, 64);
switch (buf[0]) {
case '1': bkps[id].len = 0x0; break;
case '2': bkps[id].len = 0x1; break;
case '8': bkps[id].len = 0x2; break;
case '4': bkps[id].len = 0x3; break;
default: bkps[id].len = 0x0; break;
}
kputs("cond (x/w/io/rw)> ");
debugger_read(buf, 64);
switch ((int)buf[0] * 256 + (int)buf[1]) {
case (int)'x'*256 + (int)0: bkps[id].rw = 0x0; break;
case (int)'w'*256 + (int)0: bkps[id].rw = 0x1; break;
case (int)'i'*256 + (int)'o': bkps[id].rw = 0x2; break;
case (int)'r'*256 + (int)'w': bkps[id].rw = 0x3; break;
default: bkps[id].len = 0x0; break;
}
kputs("instr len (1..15)> ");
debugger_read(buf, 64);
bkps[id].instr_len = strtoi(buf, NULL, 10);
kputs("enable (y/n)> ");
debugger_read(buf, 64);
bkps[id].used = 1;
bkps[id].enable = !(buf[0] == 'n' || buf[0] == 'N');
kprintf("added breakpoint %d\n", id);
return 1;
default:
kputs("invalid breakpoint command\n");
return 1; return 1;
} }
// TODO set breakpoints
return 1;
} }
static void debugger_load_bkps() { static void debugger_load_bkps() {
struct dr7 dr7; struct dr7 dr7;
__asm__ volatile ("mov %%dr7, %0" : "=r"(dr7)); __asm__ volatile ("mov %%dr7, %0" : "=r"(dr7));
dr7.g0 = bkps[0].enable & bkps[0].used; dr7.g0 = bkps[0].enable & bkps[0].used;
dr7.g1 = bkps[1].enable & bkps[0].used; dr7.g1 = bkps[1].enable & bkps[1].used;
dr7.g2 = bkps[2].enable & bkps[0].used; dr7.g2 = bkps[2].enable & bkps[2].used;
dr7.g3 = bkps[3].enable & bkps[0].used; dr7.g3 = bkps[3].enable & bkps[3].used;
dr7.l0 = 0; dr7.l0 = 0;
dr7.l1 = 0; dr7.l1 = 0;
dr7.l2 = 0; dr7.l2 = 0;
@ -263,19 +297,16 @@ static void debugger_load_bkps() {
dr7.len2 = bkps[2].len; dr7.len2 = bkps[2].len;
dr7.len3 = bkps[3].len; dr7.len3 = bkps[3].len;
__asm__ volatile ("mov %0, %%dr7" : : "r"(dr7)); __asm__ volatile ("mov %0, %%dr7" : : "r"(dr7));
__asm__ volatile ("mov %0, %%dr0" : : "r"(bkps[0].addr));
__asm__ volatile ("mov %0, %%dr1" : : "r"(bkps[1].addr));
__asm__ volatile ("mov %0, %%dr2" : : "r"(bkps[2].addr));
__asm__ volatile ("mov %0, %%dr3" : : "r"(bkps[3].addr));
} }
static int debugger_prompt(struct isr_regs *state) { static int debugger_prompt(struct isr_regs *state) {
char buf[PROMPT_LEN]; kputs("dbg> ");
char *p = buf; char buf[64];
dbg_puts("dbg> "); debugger_read(buf, 64);
while ((*p = dbg_getc()) != '\r' && p < buf + PROMPT_LEN - 1) {
dbg_putc(*p++);
}
dbg_putc('\n');
for(; p < buf + PROMPT_LEN; p++) {
*p = 0;
}
struct rflags *rflags = (struct rflags *)&state->rflags; struct rflags *rflags = (struct rflags *)&state->rflags;
@ -283,7 +314,7 @@ static int debugger_prompt(struct isr_regs *state) {
case '\0': // nothing entered case '\0': // nothing entered
return 1; return 1;
case 'h': // help case 'h': // help
dbg_puts("see debugger.c for help information\n"); kputs("see debugger.c for help information\n");
return 1; return 1;
case 'q': // quit case 'q': // quit
return 0; return 0;
@ -302,6 +333,36 @@ static int debugger_prompt(struct isr_regs *state) {
dbg_steps = atol(buf + 1) - 1; dbg_steps = atol(buf + 1) - 1;
//if (dbg_steps < 0) dbg_steps = 0; //if (dbg_steps < 0) dbg_steps = 0;
return 0; return 0;
case 'm': // memory
{
kputs("addr> 0x");
debugger_read(buf, 64);
uint64_t start = (~0xF) & strtoll(buf, NULL, 16);
kputs("len> 0x");
debugger_read(buf, 64);
uint64_t len = (~0xF) & strtoll(buf, NULL, 16);
for (uint64_t a = start; a <= start + len; a += 0x10) {
kprintf("%08lx: ", a);
for (uint64_t b = 0; b < 0x10; b++) {
kprintf("%02x ", *(uint8_t *)(a + b));
if (b % 0x08 == 7) {
kputc(' ');
}
}
kputs("|");
for (uint64_t b = 0; b < 0x10; b++) {
uint8_t ch = *(uint8_t *)(a + b);
if (ch < 0x20 || ch >= 0x7f) {
ch = '.';
}
kputc(ch);
}
kputs("|\n");
}
return 1;
}
case 'b': // breakpoints case 'b': // breakpoints
{ {
int res = debugger_handle_bkp_cmd(buf+1); int res = debugger_handle_bkp_cmd(buf+1);
@ -309,7 +370,7 @@ static int debugger_prompt(struct isr_regs *state) {
return res; return res;
} }
default: default:
dbg_puts("unknown command\n"); kputs("unknown command\n");
return 1; return 1;
} }
} }
@ -318,9 +379,7 @@ void debugger(struct isr_regs *state, int cause) {
struct dr6 dr6; struct dr6 dr6;
__asm__ volatile ("mov %%dr6, %0" : "=r"(dr6)); __asm__ volatile ("mov %%dr6, %0" : "=r"(dr6));
if (dr6.b0 || dr6.b1 || dr6.b2 || dr6.b3) { if (!(dr6.b0 || dr6.b1 || dr6.b2 || dr6.b3)) {
} else {
if (dr6.bs && dbg_steps > 0) { if (dr6.bs && dbg_steps > 0) {
dbg_steps--; dbg_steps--;
return; return;
@ -333,11 +392,22 @@ void debugger(struct isr_regs *state, int cause) {
debugger_msg(cause, dr6); debugger_msg(cause, dr6);
kputs("hi\n");
dbg_steps = 0; dbg_steps = 0;
dbg_continue = 0; dbg_continue = 0;
struct rflags *rflags = (struct rflags *)&state->rflags; ((struct rflags *)&state->rflags)->tf = 0;
rflags->tf = 0;
if (dr6.b0) {
state->rip += bkps[0].instr_len;
} else if (dr6.b1) {
state->rip += bkps[1].instr_len;
} else if (dr6.b2) {
state->rip += bkps[2].instr_len;
} else if (dr6.b3) {
state->rip += bkps[3].instr_len;
}
while (debugger_prompt(state)); while (debugger_prompt(state));
} }

View file

@ -1,6 +1,5 @@
#include <lib.h> #include <lib.h>
#include <memory.h> #include <memory.h>
#include <serial.h>
#include <stdint.h> #include <stdint.h>
#include <panic.h> #include <panic.h>
#include <pci.h> #include <pci.h>

View file

@ -1,7 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <lib.h> #include <lib.h>
#include <serial.h>
#include <panic.h> #include <panic.h>
#include "debugger.h" #include "debugger.h"
@ -74,48 +73,48 @@ void idt_init(void) {
// Intel manual vol 3 ch 6.3.1 // Intel manual vol 3 ch 6.3.1
char *EXCEPTIONS[] = { char *EXCEPTIONS[] = {
"0x00 Division Error", "Division Error",
"0x01 Debug", "Debug",
"0x02 NMI", "NMI",
"0x03 Breakpoint", "Breakpoint",
"0x04 Overflow", "Overflow",
"0x05 BOUND Range Exceeded", "BOUND Range Exceeded",
"0x06 Invalid Opcode", "Invalid Opcode",
"0x07 Device Not Available", "Device Not Available",
"0x08 Double Fault", "Double Fault",
"0x09 Coprocessor Segment Overrun", "Coprocessor Segment Overrun",
"0x0A Invalid TSS", "Invalid TSS",
"0x0B Segment Not Present", "Segment Not Present",
"0x0C Stack-Segment Fault", "Stack-Segment Fault",
"0x0D General Protection Fault", "General Protection Fault",
"0x0E Page Fault", "Page Fault",
"0x0F Reserved", "Reserved",
"0x10 x87 Floating-Point Error", "x87 Floating-Point Error",
"0x11 Alignment Check", "Alignment Check",
"0x12 Machine Check", "Machine Check",
"0x13 SIMD Floaing-Point Exception", "SIMD Floaing-Point Exception",
"0x14 Virtualization Exception", "Virtualization Exception",
"0x15 Control Protection Exception", "Control Protection Exception",
"0x16 Reserved", "Reserved",
"0x17 Reserved", "Reserved",
"0x18 Reserved", "Reserved",
"0x19 Reserved", "Reserved",
"0x1A Reserved", "Reserved",
"0x1B Reserved", "Reserved",
"0x1C Hypervisor Injection Exception", "Hypervisor Injection Exception",
"0x1D VMM Communication Exception", "VMM Communication Exception",
"0x1E Security Exception", "Security Exception",
"0x1F Reserved", "Reserved",
}; };
void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) { void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) {
// breakpoint interrupt switch (exception) {
if (exception == 0x03) { case 0x01: // debug
debugger(state, DEBUG_INT3);
return;
} else if (exception == 0x01) {
debugger(state, DEBUG_DBG); debugger(state, DEBUG_DBG);
return; return;
case 0x03: // breakpoint
debugger(state, DEBUG_INT3);
return;
} }
char custom[64]; char custom[64];
@ -124,12 +123,12 @@ void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *s
// page faults store the offending address in cr2 // page faults store the offending address in cr2
if (exception == 0x0E) { if (exception == 0x0E) {
strcat(custom, "\nPage fault address: 0x"); strcat(custom, "\nPage fault address: 0x");
void *addr; uint64_t cr2;
__asm__ volatile ("mov %%cr2, %0" : "=r"(addr)); __asm__ volatile ("mov %%cr2, %0" : "=r"(cr2));
ultoa((size_t)addr, custom + 23, 16); ultoa((size_t)cr2, custom + 23, 16);
} }
_panic_interrupt( panic_interrupt(
(void *)state->rip, (void *)state->rip,
(void *)state->rbp, (void *)state->rbp,
"Exception %s\nError code 0x%lu%s", "Exception %s\nError code 0x%lu%s",
@ -149,7 +148,7 @@ void idt_pic_timer(void) {
// print a message once we know the timer works // print a message once we know the timer works
// but avoid spamming the logs // but avoid spamming the logs
if (counter == 3) { if (counter == 3) {
serial_out_str("pic timer!\n"); kputs("pic timer!\n");
} }
if (counter <= 3) { if (counter <= 3) {
counter++; counter++;

View file

@ -1,31 +1,34 @@
#include <panic.h> #include <panic.h>
#include <backtrace.h> #include <backtrace.h>
#include <stdarg.h> #include <stdarg.h>
#include <lib.h> #include <lib.h>
#include "bindings.h" #include "bindings.h"
void _panic_impl(char *line, char *file, char *format, ...) { _Noreturn void _panic_impl(char *line, char *file, char *format, ...) {
cli(); cli();
va_list list; va_list list;
va_start(list, msg); va_start(list, format);
kprintf("\n\n!!! PANIC !!!\n"); kprintf("\n\n!!! PANIC !!!\n");
kprintf("In file %s at line %s:\n", file, line); kprintf("In file %s at line %s:\n", file, line);
kvprintf(format, list); kvprintf(format, list);
kprintf("\n\n"); kprintf("\n\n");
log_backtrace(); log_backtrace();
while (1) { while (1) {
halt(); halt();
} }
} }
void _panic_interrupt(void *ip, void *bp, char *format, ...) { _Noreturn void panic_interrupt(void *ip, void *bp, char *msg, ...) {
cli();
va_list list; va_list list;
va_start(list, msg); va_start(list, msg);
kprintf("\n\n!!! PANIC !!!\n"); cli();
kvprintf(format, list); kputs("\n\n!!! PANIC !!!\n");
kprintf("\n\n"); kvprintf(msg, list);
kputs("\n\n");
log_backtrace_ex(ip, bp); log_backtrace_ex(ip, bp);
while (1) { while (1) {
halt(); halt();

View file

@ -2,7 +2,6 @@
#include <acpi.h> #include <acpi.h>
#include <memory.h> #include <memory.h>
#include <lib.h> #include <lib.h>
#include <serial.h>
#include <fb.h> #include <fb.h>
#include <shim.h> #include <shim.h>
#include <panic.h> #include <panic.h>
@ -20,6 +19,7 @@ void kmain(struct boot_info *info) {
*(char *)(0xB8000 + 0x144) = 'h'; *(char *)(0xB8000 + 0x144) = 'h';
*(char *)(0xB8000 + 0x146) = 'i'; *(char *)(0xB8000 + 0x146) = 'i';
while (1) { while (1) {
__asm__("hlt;"); __asm__("hlt;");
// loop so we dont halt // loop so we dont halt

View file

@ -344,7 +344,7 @@ static void print_unum(
bool space_pre = (flag & FLG_LEFT_ALIGN) || !(flag & FLG_ZERO); bool space_pre = (flag & FLG_LEFT_ALIGN) || !(flag & FLG_ZERO);
if (!space_pre && radix == 16 && flag & FLG_ALTERNATE) { if (!space_pre && radix == 16 && (flag & FLG_ALTERNATE)) {
char x = base + ('x' - 'a'); char x = base + ('x' - 'a');
serial_out('0'); serial_out('0');
serial_out(x); serial_out(x);
@ -371,6 +371,12 @@ static void print_unum(
if (flag & FLG_ZERO) if (flag & FLG_ZERO)
zero_padded = true; zero_padded = true;
} }
if (space_pre && radix == 16 && (flag & FLG_ALTERNATE)) {
char x = base + ('x' - 'a');
serial_out('0');
serial_out(x);
}
if (space_pre && radix == 16 && flag & FLG_ALTERNATE) { if (space_pre && radix == 16 && flag & FLG_ALTERNATE) {
char x = base + ('x' - 'a'); char x = base + ('x' - 'a');