mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-22 04:32:19 +00:00
debugger
This commit is contained in:
parent
b5b904cfc9
commit
c8c8d009f6
8 changed files with 411 additions and 16 deletions
|
@ -4,6 +4,7 @@
|
||||||
#define _PANIC_STR2(x) #x
|
#define _PANIC_STR2(x) #x
|
||||||
|
|
||||||
#define panic(msg) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg)
|
#define panic(msg) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg)
|
||||||
|
#define kassert(val, msg) do { if (!(val)) { panic(msg); } } while(0)
|
||||||
|
|
||||||
_Noreturn void _panic_impl(char *line, char *file, char *msg);
|
_Noreturn void _panic_impl(char *line, char *file, char *msg);
|
||||||
|
|
||||||
|
|
343
src/arch/amd64/debugger.c
Normal file
343
src/arch/amd64/debugger.c
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
#include <lib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <serial.h>
|
||||||
|
#include <backtrace.h>
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
|
struct dr6 {
|
||||||
|
uint64_t b0 : 1,
|
||||||
|
b1 : 1,
|
||||||
|
b2 : 1,
|
||||||
|
b3 : 1,
|
||||||
|
: 7,
|
||||||
|
bld : 1,
|
||||||
|
: 1,
|
||||||
|
bd : 1,
|
||||||
|
bs : 1,
|
||||||
|
bt : 1,
|
||||||
|
rtm : 1,
|
||||||
|
: 47;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dr7 {
|
||||||
|
uint64_t l0 : 1,
|
||||||
|
g0 : 1,
|
||||||
|
l1 : 1,
|
||||||
|
g1 : 1,
|
||||||
|
l2 : 1,
|
||||||
|
g2 : 1,
|
||||||
|
l3 : 1,
|
||||||
|
g3 : 1,
|
||||||
|
: 8,
|
||||||
|
rw0 : 2,
|
||||||
|
len0 : 2,
|
||||||
|
rw1 : 2,
|
||||||
|
len1 : 2,
|
||||||
|
rw2 : 2,
|
||||||
|
len2 : 2,
|
||||||
|
rw3 : 2,
|
||||||
|
len3 : 2,
|
||||||
|
: 32;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rflags {
|
||||||
|
uint64_t cf : 1,
|
||||||
|
: 1,
|
||||||
|
pf : 1,
|
||||||
|
: 1,
|
||||||
|
af : 1,
|
||||||
|
: 1,
|
||||||
|
zf : 1,
|
||||||
|
sf : 1,
|
||||||
|
|
||||||
|
tf : 1,
|
||||||
|
if_ : 1,
|
||||||
|
df : 1,
|
||||||
|
of : 1,
|
||||||
|
iopl : 2,
|
||||||
|
nt : 1,
|
||||||
|
md : 1,
|
||||||
|
|
||||||
|
rf : 1,
|
||||||
|
vm : 1,
|
||||||
|
ac : 1,
|
||||||
|
vif : 1,
|
||||||
|
vip : 1,
|
||||||
|
id : 1,
|
||||||
|
: 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct breakpoint {
|
||||||
|
uint64_t addr;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t rw;
|
||||||
|
uint8_t used;
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t dbg_steps = 0;
|
||||||
|
static int dbg_continue = 0;
|
||||||
|
static struct breakpoint bkps[4] = {{0}, {0}, {0}, {0}};
|
||||||
|
|
||||||
|
static void dbg_putc(char c) {
|
||||||
|
serial_out(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbg_puts(char *msg) {
|
||||||
|
serial_out_str(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char dbg_getc() {
|
||||||
|
return serial_in();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debugger_msg(int cause, struct dr6 dr6) {
|
||||||
|
char buf[24];
|
||||||
|
switch (cause) {
|
||||||
|
case DEBUG_INT3:
|
||||||
|
dbg_puts("dbg: reached int3");
|
||||||
|
break;
|
||||||
|
case DEBUG_FAULT:
|
||||||
|
dbg_puts("dbg: a fault occured");
|
||||||
|
break;
|
||||||
|
case DEBUG_DBG:
|
||||||
|
if (dr6.bs)
|
||||||
|
dbg_puts("dbg: finished steps");
|
||||||
|
else if (dr6.b0)
|
||||||
|
dbg_puts("dbg: reached breakpoint 0");
|
||||||
|
else if (dr6.b1)
|
||||||
|
dbg_puts("dbg: reached breakpoint 1");
|
||||||
|
else if (dr6.b2)
|
||||||
|
dbg_puts("dbg: reached breakpoint 2");
|
||||||
|
else if (dr6.b3)
|
||||||
|
dbg_puts("dbg: reached breakpoint 3");
|
||||||
|
}
|
||||||
|
if (dbg_steps > 0) {
|
||||||
|
ultoa(dbg_steps, buf, 10);
|
||||||
|
dbg_puts(" (");
|
||||||
|
dbg_puts(buf);
|
||||||
|
dbg_puts(" steps left)");
|
||||||
|
}
|
||||||
|
if (dbg_continue > 0) {
|
||||||
|
dbg_puts(" (paused continue)");
|
||||||
|
}
|
||||||
|
dbg_puts("\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) {
|
||||||
|
debugger_print_reg("rax", state->rax);
|
||||||
|
debugger_print_reg("rbx", state->rbx);
|
||||||
|
debugger_print_reg("rcx", state->rcx);
|
||||||
|
debugger_print_reg("rdx", state->rdx);
|
||||||
|
debugger_print_reg("rsi", state->rsi);
|
||||||
|
debugger_print_reg("rdi", state->rdi);
|
||||||
|
debugger_print_reg("rsp", state->rsp);
|
||||||
|
debugger_print_reg("rbp", state->rbp);
|
||||||
|
debugger_print_reg("r8 ", state->r8 );
|
||||||
|
debugger_print_reg("r9 ", state->r9 );
|
||||||
|
debugger_print_reg("r10", state->r10);
|
||||||
|
debugger_print_reg("r11", state->r11);
|
||||||
|
debugger_print_reg("r12", state->r12);
|
||||||
|
debugger_print_reg("r13", state->r13);
|
||||||
|
debugger_print_reg("r14", state->r14);
|
||||||
|
debugger_print_reg("r15", state->r15);
|
||||||
|
dbg_puts("---\n");
|
||||||
|
debugger_print_reg("rip", state->rip);
|
||||||
|
dbg_puts("---\n");
|
||||||
|
debugger_print_reg("rflags", state->rflags);
|
||||||
|
struct rflags *rflags = (struct rflags *)state->rflags;
|
||||||
|
dbg_puts("rflags: ");
|
||||||
|
if(rflags->cf) dbg_puts("CF ");
|
||||||
|
if(rflags->pf) dbg_puts("PF ");
|
||||||
|
if(rflags->af) dbg_puts("AF ");
|
||||||
|
if(rflags->zf) dbg_puts("ZF ");
|
||||||
|
if(rflags->sf) dbg_puts("SF ");
|
||||||
|
if(rflags->tf) dbg_puts("TF ");
|
||||||
|
if(rflags->if_) dbg_puts("IF ");
|
||||||
|
if(rflags->df) dbg_puts("DF ");
|
||||||
|
if(rflags->of) dbg_puts("OF ");
|
||||||
|
if(rflags->iopl) dbg_puts("IOPL ");
|
||||||
|
if(rflags->nt) dbg_puts("NT ");
|
||||||
|
if(rflags->md) dbg_puts("MD ");
|
||||||
|
if(rflags->rf) dbg_puts("RF ");
|
||||||
|
if(rflags->vm) dbg_puts("VM ");
|
||||||
|
if(rflags->ac) dbg_puts("AC ");
|
||||||
|
if(rflags->vif) dbg_puts("VIF ");
|
||||||
|
if(rflags->vip) dbg_puts("VIP ");
|
||||||
|
if(rflags->id) dbg_puts("ID ");
|
||||||
|
dbg_putc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PROMPT_LEN 60
|
||||||
|
|
||||||
|
static int debugger_handle_bkp_cmd(char *buf) {
|
||||||
|
if (buf[0] == 'l') {
|
||||||
|
// list breakpoints
|
||||||
|
char buf[20];
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
dbg_puts("breakpoint ");
|
||||||
|
dbg_putc('0' + i);
|
||||||
|
dbg_puts(": ");
|
||||||
|
struct breakpoint bkp = bkps[i];
|
||||||
|
if(!bkp.used) {
|
||||||
|
dbg_puts("unset\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dbg_puts(" 0x");
|
||||||
|
ultoa(bkp.addr, buf, 16);
|
||||||
|
dbg_puts(buf);
|
||||||
|
dbg_puts(" len=");
|
||||||
|
switch (bkp.len) {
|
||||||
|
case 0x0: dbg_putc('1'); break;
|
||||||
|
case 0x1: dbg_putc('2'); break;
|
||||||
|
case 0x2: dbg_putc('8'); break;
|
||||||
|
case 0x3: dbg_putc('4'); break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
} else if (buf[0] == 'd') {
|
||||||
|
// disable breakpoints
|
||||||
|
bkps[0].enable = 0;
|
||||||
|
bkps[1].enable = 0;
|
||||||
|
bkps[2].enable = 0;
|
||||||
|
bkps[3].enable = 0;
|
||||||
|
return 1;
|
||||||
|
} else if (buf[0] == 'c') {
|
||||||
|
// clear breakpoints
|
||||||
|
bkps[0].used = 0;
|
||||||
|
bkps[1].used = 0;
|
||||||
|
bkps[2].used = 0;
|
||||||
|
bkps[3].used = 0;
|
||||||
|
return 1;
|
||||||
|
} else if (buf[0] <= '0' && buf[0] >= '3') {
|
||||||
|
dbg_puts("invalid breakpoint command\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// TODO set breakpoints
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debugger_load_bkps() {
|
||||||
|
struct dr7 dr7;
|
||||||
|
__asm__ volatile ("mov %%dr7, %0" : "=r"(dr7));
|
||||||
|
dr7.g0 = bkps[0].enable & bkps[0].used;
|
||||||
|
dr7.g1 = bkps[1].enable & bkps[0].used;
|
||||||
|
dr7.g2 = bkps[2].enable & bkps[0].used;
|
||||||
|
dr7.g3 = bkps[3].enable & bkps[0].used;
|
||||||
|
dr7.l0 = 0;
|
||||||
|
dr7.l1 = 0;
|
||||||
|
dr7.l2 = 0;
|
||||||
|
dr7.l3 = 0;
|
||||||
|
dr7.rw0 = bkps[0].rw;
|
||||||
|
dr7.rw1 = bkps[1].rw;
|
||||||
|
dr7.rw2 = bkps[2].rw;
|
||||||
|
dr7.rw3 = bkps[3].rw;
|
||||||
|
dr7.len0 = bkps[0].len;
|
||||||
|
dr7.len1 = bkps[1].len;
|
||||||
|
dr7.len2 = bkps[2].len;
|
||||||
|
dr7.len3 = bkps[3].len;
|
||||||
|
__asm__ volatile ("mov %0, %%dr7" : : "r"(dr7));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int debugger_prompt(struct isr_regs *state) {
|
||||||
|
char buf[PROMPT_LEN];
|
||||||
|
char *p = buf;
|
||||||
|
dbg_puts("dbg> ");
|
||||||
|
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;
|
||||||
|
|
||||||
|
switch (buf[0]) {
|
||||||
|
case '\0': // nothing entered
|
||||||
|
return 1;
|
||||||
|
case 'h': // help
|
||||||
|
dbg_puts("see debugger.c for help information\n");
|
||||||
|
return 1;
|
||||||
|
case 'q': // quit
|
||||||
|
return 0;
|
||||||
|
case 'c': // continue
|
||||||
|
rflags->tf = 1;
|
||||||
|
dbg_continue = 1;
|
||||||
|
return 0;
|
||||||
|
case 'r': // print registers
|
||||||
|
debugger_print_regs(state);
|
||||||
|
return 1;
|
||||||
|
case 'k': // backtrace
|
||||||
|
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
|
||||||
|
return 1;
|
||||||
|
case 's': // step (n)
|
||||||
|
rflags->tf = 1;
|
||||||
|
dbg_steps = atol(buf + 1) - 1;
|
||||||
|
if (dbg_steps < 0) dbg_steps = 0;
|
||||||
|
return 0;
|
||||||
|
case 'b': // breakpoints
|
||||||
|
{
|
||||||
|
int res = debugger_handle_bkp_cmd(buf+1);
|
||||||
|
debugger_load_bkps();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
dbg_puts("unknown command\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void debugger(struct isr_regs *state, int cause) {
|
||||||
|
struct dr6 dr6;
|
||||||
|
__asm__ volatile ("mov %%dr6, %0" : "=r"(dr6));
|
||||||
|
|
||||||
|
if (dr6.b0 || dr6.b1 || dr6.b2 || dr6.b3) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (dr6.bs && dbg_steps > 0) {
|
||||||
|
dbg_steps--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dr6.bs && dbg_continue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugger_msg(cause, dr6);
|
||||||
|
|
||||||
|
dbg_steps = 0;
|
||||||
|
dbg_continue = 0;
|
||||||
|
|
||||||
|
struct rflags *rflags = (struct rflags *)&state->rflags;
|
||||||
|
rflags->tf = 0;
|
||||||
|
|
||||||
|
while (debugger_prompt(state));
|
||||||
|
}
|
9
src/arch/amd64/debugger.h
Normal file
9
src/arch/amd64/debugger.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "idt.h"
|
||||||
|
|
||||||
|
#define DEBUG_INT3 0x00
|
||||||
|
#define DEBUG_DBG 0x01
|
||||||
|
#define DEBUG_FAULT 0x02
|
||||||
|
|
||||||
|
void debugger(struct isr_regs *state, int cause);
|
|
@ -11,9 +11,9 @@ extern idt_pic_eoi
|
||||||
push rbx
|
push rbx
|
||||||
push rcx
|
push rcx
|
||||||
push rdx
|
push rdx
|
||||||
push rbp
|
|
||||||
push rdi
|
|
||||||
push rsi
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rbp
|
||||||
push r8
|
push r8
|
||||||
push r9
|
push r9
|
||||||
push r10
|
push r10
|
||||||
|
@ -33,9 +33,9 @@ extern idt_pic_eoi
|
||||||
pop r10
|
pop r10
|
||||||
pop r9
|
pop r9
|
||||||
pop r8
|
pop r8
|
||||||
pop rsi
|
|
||||||
pop rdi
|
|
||||||
pop rbp
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
pop rdx
|
pop rdx
|
||||||
pop rcx
|
pop rcx
|
||||||
pop rbx
|
pop rbx
|
||||||
|
@ -51,8 +51,7 @@ isr_stub_%+%1:
|
||||||
cld
|
cld
|
||||||
mov rdi, %1 ; exception number
|
mov rdi, %1 ; exception number
|
||||||
mov rsi, 0 ; placeholder error code
|
mov rsi, 0 ; placeholder error code
|
||||||
mov rdx, [rsp + 15 * 8] ; instruction pointer
|
mov rdx, rsp ; top of stack
|
||||||
mov rcx, rbp ; base pointer for stack trace
|
|
||||||
call idt_exception_handler
|
call idt_exception_handler
|
||||||
POPALL
|
POPALL
|
||||||
iretq
|
iretq
|
||||||
|
@ -64,15 +63,18 @@ isr_stub_%+%1:
|
||||||
%macro ISRExceptionCode 1
|
%macro ISRExceptionCode 1
|
||||||
align 8
|
align 8
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
|
; retrieve the error code without corrupting registers
|
||||||
|
mov [isr_tmp], rax
|
||||||
|
pop rax
|
||||||
|
mov [isr_err_code], rax
|
||||||
|
mov rax, [isr_tmp]
|
||||||
PUSHALL
|
PUSHALL
|
||||||
cld
|
cld
|
||||||
mov rdi, %1 ; exception number
|
mov rdi, %1 ; exception number
|
||||||
mov rsi, [rsp + 15 * 8] ; error code
|
mov rsi, [isr_err_code] ; error code
|
||||||
mov rdx, [rsp + 16 * 8] ; instruction pointer
|
mov rdx, rsp ; top of stack
|
||||||
mov rcx, rbp ; base pointer for stack trace
|
|
||||||
call idt_exception_handler
|
call idt_exception_handler
|
||||||
POPALL
|
POPALL
|
||||||
sub rsp, 8 ; discard error code
|
|
||||||
iretq
|
iretq
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
@ -188,6 +190,10 @@ PICGeneric 47 ; 15
|
||||||
%assign i i+1
|
%assign i i+1
|
||||||
%endrep
|
%endrep
|
||||||
|
|
||||||
|
section .data
|
||||||
|
isr_tmp: dq 0
|
||||||
|
isr_err_code: dq 0
|
||||||
|
|
||||||
; isr stub table
|
; isr stub table
|
||||||
section .rodata
|
section .rodata
|
||||||
bits 64
|
bits 64
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <panic.h>
|
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
#include <panic.h>
|
||||||
|
|
||||||
#include "backtrace.h"
|
#include "debugger.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
|
|
||||||
|
@ -108,7 +108,16 @@ char *EXCEPTIONS[] = {
|
||||||
"0x1F Reserved",
|
"0x1F Reserved",
|
||||||
};
|
};
|
||||||
|
|
||||||
void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *rbp) {
|
void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) {
|
||||||
|
// breakpoint interrupt
|
||||||
|
if (exception == 0x03) {
|
||||||
|
debugger(state, DEBUG_INT3);
|
||||||
|
return;
|
||||||
|
} else if (exception == 0x01) {
|
||||||
|
debugger(state, DEBUG_DBG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO don't just panic
|
// TODO don't just panic
|
||||||
char buf[24];
|
char buf[24];
|
||||||
char msg[256] = "Exception ";
|
char msg[256] = "Exception ";
|
||||||
|
@ -128,7 +137,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *r
|
||||||
strcat(msg, buf);
|
strcat(msg, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
panic_interrupt(rip, rbp, msg);
|
panic_interrupt((void *)state->rip, (void *)state->rbp, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_pic_eoi(uint8_t exception) {
|
void idt_pic_eoi(uint8_t exception) {
|
||||||
|
|
|
@ -1,3 +1,29 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct isr_regs {
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r12;
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r8;
|
||||||
|
uint64_t rbp;
|
||||||
|
uint64_t rdi;
|
||||||
|
uint64_t rsi;
|
||||||
|
uint64_t rdx;
|
||||||
|
uint64_t rcx;
|
||||||
|
uint64_t rbx;
|
||||||
|
uint64_t rax;
|
||||||
|
|
||||||
|
uint64_t rip;
|
||||||
|
uint64_t cs;
|
||||||
|
uint64_t rflags;
|
||||||
|
uint64_t rsp;
|
||||||
|
uint64_t ss;
|
||||||
|
};
|
||||||
|
|
||||||
void idt_init();
|
void idt_init();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
#include <shim.h>
|
#include <shim.h>
|
||||||
|
#include <panic.h>
|
||||||
|
|
||||||
void kmain(struct boot_info *info) {
|
void kmain(struct boot_info *info) {
|
||||||
memory_init(&info->map);
|
memory_init(&info->map);
|
||||||
|
|
|
@ -212,7 +212,7 @@ end:
|
||||||
if (n == 0) { \
|
if (n == 0) { \
|
||||||
buffer[0] = '0'; \
|
buffer[0] = '0'; \
|
||||||
buffer[1] = '\0'; \
|
buffer[1] = '\0'; \
|
||||||
return buffer; \
|
return buffer + 1; \
|
||||||
} \
|
} \
|
||||||
char *start = buffer; \
|
char *start = buffer; \
|
||||||
for (; n; n /= radix) { \
|
for (; n; n /= radix) { \
|
||||||
|
@ -237,7 +237,7 @@ UXTOA(long long int, ulltoa)
|
||||||
if (n == 0) { \
|
if (n == 0) { \
|
||||||
buffer[0] = '0'; \
|
buffer[0] = '0'; \
|
||||||
buffer[1] = '\0'; \
|
buffer[1] = '\0'; \
|
||||||
return buffer; \
|
return buffer + 1; \
|
||||||
} \
|
} \
|
||||||
if (n < 0) { \
|
if (n < 0) { \
|
||||||
*buffer++ = '-'; \
|
*buffer++ = '-'; \
|
||||||
|
|
Loading…
Reference in a new issue