22
33static 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+
5150const 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
430575bool 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}
0 commit comments