Skip to content

Commit 82b4bb9

Browse files
better error logging
1 parent 89219b1 commit 82b4bb9

8 files changed

Lines changed: 136 additions & 42 deletions

File tree

asm/loader.S

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
.global idt_init
55
.extern idt64
66

7+
.set BT_IRQ_MARKER, 0xffffffffffffff01
8+
79
#define SELECTOR 40
810

911
.text
@@ -104,6 +106,20 @@ irq\num:
104106
pop %r15
105107
.endm
106108

109+
.macro PUSH_SENTINEL
110+
/* Build { next = old_rbp, addr = BT_IRQ_MARKER } and link it */
111+
sub $16, %rsp
112+
mov %rbp, 0(%rsp) /* next */
113+
movq $BT_IRQ_MARKER, 8(%rsp) /* addr */
114+
mov %rsp, %rbp /* link into the RBP chain */
115+
.endm
116+
117+
.macro POP_SENTINEL
118+
/* Drop the fabricated frame and restore the caller’s rbp */
119+
mov 0(%rbp), %rbp /* restore previous RBP (next) */
120+
add $16, %rsp /* drop {next,addr} */
121+
.endm
122+
107123
isrs:
108124
// CPU exceptions 0–31
109125
ISR_NOERR 0
@@ -372,12 +388,16 @@ isrs:
372388
// ----------------------
373389

374390
irq_stub:
391+
PUSH_SENTINEL
375392
call IRQ
393+
POP_SENTINEL
376394
MPOPA
377395
iretq
378396

379397
interrupt_stub:
398+
PUSH_SENTINEL
380399
call Interrupt
400+
POP_SENTINEL
381401
MPOPA
382402
iretq
383403

include/debugger.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,7 @@
55
*/
66
#pragma once
77

8-
#define SYM_ABSOLUTE 'A'
9-
#define SYM_BSS 'B'
10-
#define SYM_COMMON 'C'
11-
#define SYM_INITIALISED 'D'
12-
#define SYM_SMALLOBJECT 'G'
13-
#define SYM_INDIRECT_REF 'I'
14-
#define SYM_DEBUGGING 'N'
15-
#define SYM_READONLY 'R'
16-
#define SYM_UNINITIALISED 'S'
17-
#define SYM_TEXT 'T'
18-
#define SYM_TEXT2 't'
19-
#define SYM_UNDEFINED 'U'
20-
#define SYM_WEAK_OBJECT 'V'
21-
#define SYM_WEAK_SYMBOL 'W'
22-
#define SYM_STABS '-'
23-
#define SYM_UNKNOWN '?'
8+
#define CANONICAL_ADDRESS(x) (((((intptr_t)(x)) << 16) >> 16) == (intptr_t)(x))
249

2510
typedef struct symbol
2611
{

include/kernel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#error "Bit-field layout assumed: x86_64 little-endian."
1313
#endif
1414

15+
#define KSTACK_SIZE (32ULL * 1024ULL * 1024ULL) /* 32 MiB */
16+
#define KSTACK_MASK (~(KSTACK_SIZE - 1ULL))
17+
1518
#define kprintf printf
1619
#include <stdint.h>
1720
#include <stdbool.h>

src/debugger.c

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ static symbol_t* symbol_table = NULL;
44
uint32_t trace_thread_id = 0;
55
static bool debug_signal = false;
66

7+
#define BT_IRQ_MARKER ((void*)0xFFFFffffFFFFff01ull)
8+
79
volatile struct limine_module_request module_request = {
810
.id = LIMINE_MODULE_REQUEST,
911
.revision = 0,
@@ -427,27 +429,87 @@ uint64_t findsymbol_addr(const char *name) {
427429
return 0;
428430
}
429431

432+
static inline void get_kstack_bounds(uintptr_t *lo, uintptr_t *hi) {
433+
uintptr_t rsp;
434+
__asm__ volatile ("movq %%rsp,%0" : "=r"(rsp));
435+
uintptr_t base = rsp & KSTACK_MASK; /* aligned base for *this* CPU’s stack */
436+
*lo = base;
437+
*hi = base + KSTACK_SIZE; /* top (one-past) */
438+
}
430439

431-
void backtrace()
432-
{
440+
static size_t count_markers_ahead(const stack_frame_t *frame, uintptr_t lo, uintptr_t hi, size_t probe) {
441+
size_t cnt = 0;
442+
while (frame && CANONICAL_ADDRESS(frame) && (uintptr_t)frame >= lo && (uintptr_t)frame <= (hi - sizeof(*frame)) && probe++ < 1024) {
443+
const stack_frame_t *next = frame->next;
444+
if (next && (uintptr_t)next <= (uintptr_t)frame) {
445+
break; /* corrupted or cyclic chain */
446+
}
447+
if (frame->addr == BT_IRQ_MARKER) {
448+
cnt++;
449+
}
450+
frame = next;
451+
}
452+
return cnt;
453+
}
454+
455+
void backtrace(void) {
433456
stack_frame_t *frame;
434457
__asm__ volatile("movq %%rbp,%0" : "=r"(frame));
435-
uint64_t page = (uint64_t) frame & 0xFFFFFFFFFFFFF000ull;
436-
uint64_t offset = 0;
437-
const char* name = NULL;
438458

439-
/* Stack frame loop inspired by AlexExtreme's stack trace in Exclaim */
459+
uintptr_t lo, hi;
460+
size_t depth = 0;
461+
get_kstack_bounds(&lo, &hi);
462+
463+
/* We know we’re in an ISR/exception at the top */
464+
setforeground(COLOUR_LIGHTYELLOW);
465+
kprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
466+
dprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
467+
468+
/* How many sentinels remain in this chain? (there is at least one) */
469+
size_t remaining_markers = count_markers_ahead(frame, lo, hi, depth);
470+
440471
setforeground(COLOUR_LIGHTGREEN);
441-
while (frame && ((uint64_t)frame & 0xFFFFFFFFFFFFF000ull) == page) {
442-
name = findsymbol((uint64_t)frame->addr, &offset);
472+
while (frame && CANONICAL_ADDRESS(frame) && (uintptr_t)frame >= lo && (uintptr_t)frame <= (hi - sizeof(*frame)) && depth++ < 1024) {
473+
474+
stack_frame_t *next = frame->next;
475+
476+
if (next && (uintptr_t)next <= (uintptr_t)frame) {
477+
break; /* corrupted or cyclic chain */
478+
}
479+
480+
if (frame->addr == BT_IRQ_MARKER) {
481+
/* Crossing this boundary */
482+
if (remaining_markers > 0) {
483+
remaining_markers--; /* consume this marker */
484+
}
485+
setforeground(COLOUR_LIGHTYELLOW);
486+
if (remaining_markers > 0) {
487+
kprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
488+
dprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
489+
} else {
490+
kprintf("-------------------------------[ PRE-EMPTED CONTEXT ]-------------------------------\n");
491+
dprintf("-------------------------------[ PRE-EMPTED CONTEXT ]-------------------------------\n");
492+
}
493+
setforeground(COLOUR_LIGHTGREEN);
494+
495+
frame = next;
496+
continue;
497+
}
498+
499+
uint64_t offset = 0;
500+
const char *name = findsymbol((uint64_t)frame->addr, &offset);
443501
if (!name || (strcmp(name, "pci_enable_msi") != 0 && strcmp(name, "vprintf") != 0 && strcmp(name, "printf") != 0)) {
444-
kprintf("\tat %s()+0%08lx [0x%lx]\n", name ? name : "[???]", offset, (uint64_t)frame->addr);
502+
kprintf("\tat %s()+0%08lx [0x%lx]\n", name ? name : "[???]", offset, (uint64_t)frame->addr);
503+
dprintf("\tat %s()+0%08lx [0x%lx]\n", name ? name : "[???]", offset, (uint64_t)frame->addr);
445504
}
446-
frame = frame->next;
505+
506+
frame = next;
447507
}
508+
448509
setforeground(COLOUR_WHITE);
449510
}
450511

512+
451513
uint32_t gdb_trace(const char* str) {
452514
uint32_t hash = 5381;
453515
uint8_t c;

src/errorhandler.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,54 @@ const char* const error_table[] = {
3838

3939
void error_handler(uint8_t int_no, uint64_t errorcode, uint64_t irq_no, void* opaque);
4040

41-
void init_error_handler()
42-
{
41+
void init_error_handler() {
4342
for (int interrupt = 0; interrupt < 32; ++interrupt) {
4443
register_interrupt_handler(interrupt, error_handler, dev_zero, NULL);
4544
}
4645
dprintf("Init error handlers\n");
4746
}
4847

49-
void error_handler(uint8_t int_no, uint64_t errorcode, [[maybe_unused]] uint64_t irq_no, void* opaque)
50-
{
48+
#include <stddef.h>
49+
#include <string.h>
50+
51+
const char* tail_last_lines(const char *s, size_t n) {
52+
if (s == NULL) {
53+
return NULL;
54+
}
55+
if (n == 0) {
56+
return s + strlen(s);
57+
}
58+
const char *end = s + strlen(s);
59+
const char *p = end;
60+
if (p > s && *(p - 1) == '\n') {
61+
p--;
62+
}
63+
size_t need = n;
64+
while (p > s) {
65+
p--;
66+
if (*p == '\n') {
67+
if (--need == 0) {
68+
return p + 1;
69+
}
70+
}
71+
}
72+
return s;
73+
}
74+
75+
76+
void error_handler(uint8_t int_no, uint64_t errorcode, uint64_t irq_no, void* opaque) {
5177
interrupts_off();
52-
setforeground(COLOUR_LIGHTWHITE);
78+
setforeground(COLOUR_LIGHTRED);
5379
setbackground(COLOUR_BLACK);
54-
const char* log = dprintf_buffer_snapshot();
80+
const char* log = tail_last_lines(dprintf_buffer_snapshot(), 15);
81+
kprintf("\nFatal exception %02X (Error code %016lx): %s\n", int_no, errorcode, error_table[int_no]);
82+
dprintf("\nFatal exception %02X (Error code %016lx): %s\n", int_no, errorcode, error_table[int_no]);
83+
setforeground(COLOUR_WHITE);
84+
kprintf("------------------------------------[ DEBUG LOG ]-----------------------------------\n");
85+
setforeground(COLOUR_GREY);
5586
if (log) {
56-
kprintf("\n%s\n", log);
87+
kprintf("%s\n", log);
5788
}
58-
setforeground(COLOUR_LIGHTRED);
59-
kprintf("Fatal exception %02X (Error code %016lx): %s\n", int_no, errorcode, error_table[int_no]);
6089
setforeground(COLOUR_WHITE);
6190
backtrace();
6291
rr_flip();

src/gdt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
volatile struct limine_stack_size_request stack_size_request = {
99
.id = LIMINE_STACK_SIZE_REQUEST,
1010
.revision = 0,
11-
.stack_size = (1024 * 1024 * 32),
11+
.stack_size = KSTACK_SIZE,
1212
};
1313

1414
volatile struct limine_hhdm_request hhdm_request = {

src/interrupt.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ void Interrupt(uint64_t isrnumber, uint64_t errorcode) {
9898

9999
if (isrnumber < 32) {
100100
/* This simple error handler is replaced by a more complex debugger once the system is up */
101-
kprintf("CPU %d halted with exception %016lx, error code %016lx: %s.\n", logical_cpu_id(), isrnumber,
102-
errorcode, error_table[isrnumber]);
101+
kprintf("CPU %d halted with exception %016lx, error code %016lx: %s.\n", logical_cpu_id(), isrnumber, errorcode, error_table[isrnumber]);
103102
wait_forever();
104103
}
105104

src/net/arp.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ void arp_handle_packet(arp_packet_t* arp_packet, [[maybe_unused]] int len) {
3030
memcpy(dst_hardware_addr, arp_packet->src_hardware_addr, 6);
3131
memcpy(dst_protocol_addr, arp_packet->src_protocol_addr, 4);
3232
if (ntohs(arp_packet->opcode) == ARP_REQUEST) {
33-
dprintf("arp request\n");
3433
unsigned char addr[4];
3534
uint32_t my_ip = 0;
3635
if (gethostaddr(addr)) {
@@ -62,16 +61,13 @@ void arp_handle_packet(arp_packet_t* arp_packet, [[maybe_unused]] int len) {
6261
arp_packet->protocol = htons(ETHERNET_TYPE_IP);
6362

6463
ethernet_send_packet(dst_hardware_addr, (uint8_t*)arp_packet, sizeof(arp_packet_t), ETHERNET_TYPE_ARP);
65-
} else {
66-
dprintf("Invalid addr %08x\n", my_ip);
6764
}
6865
} else if(ntohs(arp_packet->opcode) == ARP_REPLY) {
6966
dprintf("ARP_REPLY from: %08x hw %02x:%02x:%02x:%02x:%02x:%02x\n", *(uint32_t*)&dst_protocol_addr, dst_hardware_addr[0], dst_hardware_addr[1], dst_hardware_addr[2], dst_hardware_addr[3], dst_hardware_addr[4], dst_hardware_addr[5]);
7067
}
7168

7269
uint8_t dummy[6];
7370
if (!arp_lookup(dummy, dst_protocol_addr)) {
74-
dprintf("not in arp table, storing at %d\n", arp_table_size);
7571
memcpy(&arp_table[arp_table_curr].ip_addr, dst_protocol_addr, 4);
7672
memcpy(&arp_table[arp_table_curr++].mac_addr, dst_hardware_addr, 6);
7773
if(arp_table_size < 512) {

0 commit comments

Comments
 (0)