mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-25 08:10:02 +00:00
improved debugger, refactored
This commit is contained in:
parent
72df91d99b
commit
6d7a563d36
9 changed files with 276 additions and 208 deletions
|
@ -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, ...);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
char ch = serial_in();
|
||||||
|
switch (ch) {
|
||||||
|
case '\r':
|
||||||
|
goto end;
|
||||||
|
case '\x7f':
|
||||||
|
if (p > buf) {
|
||||||
|
p--;
|
||||||
|
kputs("\x08 \x08");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
static void dbg_puts(char *msg) {
|
default:
|
||||||
serial_out_str(msg);
|
kputc(ch);
|
||||||
|
*p++ = ch;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
static char dbg_getc() {
|
end:
|
||||||
return serial_in();
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
// TODO set breakpoints
|
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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -372,6 +372,12 @@ static void print_unum(
|
||||||
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');
|
||||||
serial_out('0');
|
serial_out('0');
|
||||||
|
|
Loading…
Reference in a new issue