Skip to content

Commit f863818

Browse files
add ability to stack trace into modules
1 parent 82b4bb9 commit f863818

File tree

7 files changed

+192
-61
lines changed

7 files changed

+192
-61
lines changed

asm/loader.S

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,15 @@ irq\num:
107107
.endm
108108

109109
.macro PUSH_SENTINEL
110-
/* Build { next = old_rbp, addr = BT_IRQ_MARKER } and link it */
111110
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 */
111+
mov %rbp, 0(%rsp)
112+
movq $BT_IRQ_MARKER, 8(%rsp)
113+
mov %rsp, %rbp
115114
.endm
116115

117116
.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} */
117+
mov 0(%rbp), %rbp
118+
add $16, %rsp
121119
.endm
122120

123121
isrs:

include/kernel.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@
1515
#define KSTACK_SIZE (32ULL * 1024ULL * 1024ULL) /* 32 MiB */
1616
#define KSTACK_MASK (~(KSTACK_SIZE - 1ULL))
1717

18-
#define kprintf printf
18+
#define kprintf(fmt, ...) \
19+
printf(fmt, ##__VA_ARGS__)
20+
21+
#define aprintf(fmt, ...) \
22+
do { \
23+
kprintf(fmt, ##__VA_ARGS__); \
24+
dprintf(fmt, ##__VA_ARGS__); \
25+
} while (0)
26+
1927
#include <stdint.h>
2028
#include <stdbool.h>
2129
#include <stddef.h>

include/module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#define ET_REL 1 /**< Relocatable object file */
4545
#define EM_X86_64 62 /**< AMD64 / x86-64 architecture */
4646

47+
#define ELF64_ST_TYPE(i) ((uint8_t)((i) & 0x0F))
48+
#define STT_NOTYPE 0
49+
#define STT_FUNC 2
50+
4751
/* Section types (sh_type) */
4852
#define SHT_NULL 0 /**< Inactive section header */
4953
#define SHT_PROGBITS 1 /**< Program-defined contents */
@@ -361,3 +365,5 @@ bool load_module(const char *name);
361365
* @return true on success, false if not found or unload failed
362366
*/
363367
bool unload_module(const char *name);
368+
369+
bool module_addr_to_symbol(uintptr_t addr, const char **modname_out, const char **symname_out, uint64_t *offset_out);

modules/e1000/e1000.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,11 @@ void e1000_up() {
266266
* IRQ handler (MSI)
267267
* @return
268268
*/
269-
void e1000_handler([[maybe_unused]
270-
271-
]
272-
uint8_t isr,
273-
[[maybe_unused]]
274-
uint64_t error,
275-
[[maybe_unused]]
276-
uint64_t irq,
277-
void *opaque
278-
) {
279-
uint32_t status = e1000_read_command(REG_ICR);
280-
if (status & ICR_RXT0) {
281-
e1000_handle_receive();
282-
283-
}
269+
void e1000_handler(uint8_t isr, uint64_t error, uint64_t irq, void *opaque) {
270+
uint32_t status = e1000_read_command(REG_ICR);
271+
if (status & ICR_RXT0) {
272+
e1000_handle_receive();
273+
}
284274
}
285275

286276
void e1000_enable_interrupts() {

src/debugger.c

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -432,17 +432,17 @@ uint64_t findsymbol_addr(const char *name) {
432432
static inline void get_kstack_bounds(uintptr_t *lo, uintptr_t *hi) {
433433
uintptr_t rsp;
434434
__asm__ volatile ("movq %%rsp,%0" : "=r"(rsp));
435-
uintptr_t base = rsp & KSTACK_MASK; /* aligned base for *this* CPU’s stack */
435+
uintptr_t base = rsp & KSTACK_MASK;
436436
*lo = base;
437-
*hi = base + KSTACK_SIZE; /* top (one-past) */
437+
*hi = base + KSTACK_SIZE;
438438
}
439439

440440
static size_t count_markers_ahead(const stack_frame_t *frame, uintptr_t lo, uintptr_t hi, size_t probe) {
441441
size_t cnt = 0;
442442
while (frame && CANONICAL_ADDRESS(frame) && (uintptr_t)frame >= lo && (uintptr_t)frame <= (hi - sizeof(*frame)) && probe++ < 1024) {
443443
const stack_frame_t *next = frame->next;
444444
if (next && (uintptr_t)next <= (uintptr_t)frame) {
445-
break; /* corrupted or cyclic chain */
445+
break;
446446
}
447447
if (frame->addr == BT_IRQ_MARKER) {
448448
cnt++;
@@ -455,61 +455,49 @@ static size_t count_markers_ahead(const stack_frame_t *frame, uintptr_t lo, uint
455455
void backtrace(void) {
456456
stack_frame_t *frame;
457457
__asm__ volatile("movq %%rbp,%0" : "=r"(frame));
458-
459458
uintptr_t lo, hi;
460459
size_t depth = 0;
461460
get_kstack_bounds(&lo, &hi);
462461

463462
/* We know we’re in an ISR/exception at the top */
464463
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) */
464+
aprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
469465
size_t remaining_markers = count_markers_ahead(frame, lo, hi, depth);
470-
471466
setforeground(COLOUR_LIGHTGREEN);
472467
while (frame && CANONICAL_ADDRESS(frame) && (uintptr_t)frame >= lo && (uintptr_t)frame <= (hi - sizeof(*frame)) && depth++ < 1024) {
473468

474469
stack_frame_t *next = frame->next;
475470

476471
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 */
472+
break;
473+
} else if (frame->addr == BT_IRQ_MARKER) {
482474
if (remaining_markers > 0) {
483-
remaining_markers--; /* consume this marker */
475+
remaining_markers--;
484476
}
485477
setforeground(COLOUR_LIGHTYELLOW);
486478
if (remaining_markers > 0) {
487-
kprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
488-
dprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
479+
aprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
489480
} else {
490-
kprintf("-------------------------------[ PRE-EMPTED CONTEXT ]-------------------------------\n");
491-
dprintf("-------------------------------[ PRE-EMPTED CONTEXT ]-------------------------------\n");
481+
aprintf("-------------------------------[ PRE-EMPTED CONTEXT ]-------------------------------\n");
492482
}
493483
setforeground(COLOUR_LIGHTGREEN);
494-
495484
frame = next;
496485
continue;
497486
}
498-
499487
uint64_t offset = 0;
500-
const char *name = findsymbol((uint64_t)frame->addr, &offset);
501-
if (!name || (strcmp(name, "pci_enable_msi") != 0 && strcmp(name, "vprintf") != 0 && strcmp(name, "printf") != 0)) {
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);
488+
const char *mname = NULL, *sname = NULL;
489+
if (module_addr_to_symbol(frame->addr, &mname, &sname, &offset)) {
490+
/* print "mname:sname+off" (or mname:[???]) */
491+
aprintf("\t%s:%s()+0%08lx [0x%lx]\n", mname, sname, offset, (uint64_t) frame->addr);
492+
} else {
493+
const char *name = findsymbol((uint64_t) frame->addr, &offset);
494+
aprintf("\t%s()+0%08lx [0x%lx]\n", name ? name : "[???]", offset, (uint64_t) frame->addr);
504495
}
505-
506496
frame = next;
507497
}
508-
509498
setforeground(COLOUR_WHITE);
510499
}
511500

512-
513501
uint32_t gdb_trace(const char* str) {
514502
uint32_t hash = 5381;
515503
uint8_t c;

src/module_loader.c

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,151 @@
22

33
static struct hashmap* modules;
44

5+
/* --- module symbol registry for backtraces -------------------------------- */
6+
7+
typedef struct modreg {
8+
struct modreg *next;
9+
module *m; /* stored copy in hashmap */
10+
const char *name; /* m->name (owned by module) */
11+
uintptr_t text_lo; /* lowest resolved FUNC symbol addr */
12+
uintptr_t text_hi; /* one-past-highest resolved FUNC symbol addr */
13+
} modreg;
14+
15+
static modreg *modreg_head = NULL;
16+
17+
/* Build [text_lo, text_hi] from resolved STT_FUNC symbols */
18+
static void modreg_build_text_bounds(modreg *r) {
19+
uintptr_t lo = UINTPTR_MAX, hi = 0;
20+
21+
for (size_t i = 0; i < r->m->sym_count; i++) {
22+
const elf_sym *s = &r->m->symtab[i];
23+
24+
if (s->st_name == 0) {
25+
continue;
26+
}
27+
if (s->st_shndx == SHN_UNDEF || s->st_shndx >= SHN_LORESERVE) {
28+
continue;
29+
}
30+
/* Prefer functions; accept NOTYPE as a fallback */
31+
unsigned stt = ELF64_ST_TYPE(s->st_info);
32+
if (stt != STT_FUNC && stt != STT_NOTYPE) {
33+
continue;
34+
}
35+
36+
uint8_t *b = module_section_base(r->m, s->st_shndx);
37+
if (!b) {
38+
continue;
39+
}
40+
uintptr_t a = (uintptr_t)(b + s->st_value);
41+
if (a < lo) {
42+
lo = a;
43+
}
44+
if (a > hi) {
45+
hi = a;
46+
}
47+
}
48+
49+
if (lo == UINTPTR_MAX || hi == 0 || hi <= lo) {
50+
/* Fallback: if no funcs found, cover the whole mapped module */
51+
r->text_lo = (uintptr_t)r->m->base;
52+
r->text_hi = r->text_lo + r->m->size;
53+
} else {
54+
/* hi should be one-past; nudge if equal to a symbol addr later */
55+
r->text_lo = lo;
56+
r->text_hi = hi + 1;
57+
}
58+
}
59+
60+
/* Insert/remove */
61+
static void modreg_register(module *m) {
62+
modreg *r = kmalloc(sizeof(*r));
63+
if (!r) {
64+
return;
65+
}
66+
r->m = m;
67+
r->name = m->name;
68+
r->next = modreg_head;
69+
modreg_build_text_bounds(r);
70+
modreg_head = r;
71+
}
72+
73+
static void modreg_unregister(module *m) {
74+
modreg **pp = &modreg_head;
75+
while (*pp) {
76+
if ((*pp)->m == m) {
77+
modreg *dead = *pp;
78+
*pp = dead->next;
79+
kfree(dead);
80+
return;
81+
}
82+
pp = &(*pp)->next;
83+
}
84+
}
85+
86+
/* Lookup: addr -> module:symbol + offset
87+
* Returns true on success. Outputs (optionally) modname/symname/offset.
88+
*/
89+
bool module_addr_to_symbol(uintptr_t addr, const char **modname_out, const char **symname_out, uint64_t *offset_out) {
90+
for (modreg *r = modreg_head; r; r = r->next) {
91+
if (addr < r->text_lo || addr >= r->text_hi) {
92+
continue;
93+
}
94+
95+
/* Best ≤ addr */
96+
uintptr_t best_addr = 0;
97+
const char *best_name = NULL;
98+
99+
for (size_t i = 0; i < r->m->sym_count; i++) {
100+
const elf_sym *s = &r->m->symtab[i];
101+
102+
if (s->st_name == 0) {
103+
continue;
104+
}
105+
if (s->st_shndx == SHN_UNDEF || s->st_shndx >= SHN_LORESERVE) {
106+
continue;
107+
}
108+
109+
uint8_t *b = module_section_base(r->m, s->st_shndx);
110+
if (!b) {
111+
continue;
112+
}
113+
114+
uintptr_t sa = (uintptr_t)(b + s->st_value);
115+
if (sa <= addr && sa >= best_addr) {
116+
best_addr = sa;
117+
best_name = r->m->strtab + s->st_name;
118+
}
119+
}
120+
121+
if (best_name) {
122+
if (modname_out) {
123+
*modname_out = r->name;
124+
}
125+
if (symname_out) {
126+
*symname_out = best_name;
127+
}
128+
if (offset_out) {
129+
*offset_out = (uint64_t)(addr - best_addr);
130+
}
131+
return true;
132+
}
133+
134+
/* In-range but no symbol match: still report module with [???] */
135+
if (modname_out) {
136+
*modname_out = r->name;
137+
}
138+
if (symname_out) {
139+
*symname_out = NULL;
140+
}
141+
if (offset_out) {
142+
*offset_out = 0;
143+
}
144+
return true;
145+
}
146+
147+
return false;
148+
}
149+
5150
const void *kernel_dlsym(const char *name) {
6151
if (!name) {
7152
return NULL;
@@ -424,7 +569,7 @@ void init_modules(void) {
424569
if (modules) {
425570
return;
426571
}
427-
modules = hashmap_new(sizeof(module), 0, mt_rand(), mt_rand(), module_hash, module_compare, module_hash_free, NULL);
572+
modules = hashmap_new(sizeof(module), 0, 4325874395643634, 4532498232342, module_hash, module_compare, module_hash_free, NULL);
428573
}
429574

430575
bool load_module(const char* name) {
@@ -436,6 +581,7 @@ bool load_module(const char* name) {
436581
dprintf("Out of memory\n");
437582
return false;
438583
}
584+
const char* saved_name = m.name;
439585
if (hashmap_get(modules, &m)) {
440586
dprintf("Module %s already loaded\n", name);
441587
kfree_null(&m.name);
@@ -465,7 +611,10 @@ bool load_module(const char* name) {
465611
kfree_null(&m.name);
466612
return false;
467613
}
614+
m.name = saved_name;
468615
hashmap_set(modules, &m);
616+
module* stored = hashmap_get(modules, &(module){ .name = name });
617+
modreg_register(stored);
469618
return true;
470619
}
471620

@@ -478,6 +627,7 @@ bool unload_module(const char* name) {
478627
if (!module_internal_unload(mod)) {
479628
return false;
480629
}
630+
modreg_unregister(mod);
481631
hashmap_delete(modules, mod);
482632
return true;
483633
}

src/tinyalloc.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ void ta_init(void *heap, size_t size, size_t alignment) {
4646
ta_head->next = 0;
4747
}
4848

49-
static void *align_forward(void *ptr, size_t align) {
50-
uintptr_t p = (uintptr_t) ptr;
51-
uintptr_t mod = p % align;
52-
if (mod) {
53-
p += (align - mod);
54-
}
55-
return (void *) p;
56-
}
57-
5849
void *ta_alloc(size_t size) {
5950
ta_header *current = ta_head;
6051
while (current) {

0 commit comments

Comments
 (0)