33#include "limine.h"
44#include "mem/heap.h"
55#include "ptrace.h"
6+ #include "task/task.h"
67#include "term/klog.h"
78
89typedef struct {
@@ -14,15 +15,90 @@ LIMINE_REQUEST struct limine_kernel_file_request kfile_request = {
1415 .id = LIMINE_KERNEL_FILE_REQUEST ,
1516};
1617extern char _kernel_start [];
17- static ksym_t static_ksyms [8192 ];
1818ksym_t * kallsyms = NULL ;
1919size_t kallsyms_num = 0 ;
2020void * eh_frame_start = NULL ;
2121size_t eh_frame_size = 0 ;
22+ static uint64_t kernel_text_start = 0 ;
23+ static uint64_t kernel_text_end = 0 ;
24+
25+ const char * kallsyms_lookup (uint64_t addr , uint64_t * sym_addr );
26+
27+ static bool addr_in_kernel_text (uint64_t addr ) {
28+ if (kernel_text_start && kernel_text_end ) {
29+ return addr >= kernel_text_start && addr < kernel_text_end ;
30+ }
31+ return addr >= 0xffffffff80000000UL && addr < 0xfffffffffffff000UL ;
32+ }
33+
34+ static void get_stack_bounds (uint64_t rsp , uint64_t * stack_low , uint64_t * stack_high ) {
35+ tcb_t task = get_current_task ();
36+ if (task != NULL ) {
37+ uint64_t k_low = (uint64_t )task ;
38+ uint64_t k_high = task -> context .kernel_stack ;
39+ if (k_high == 0 ) { k_high = k_low + STACK_SIZE ; }
40+ if (rsp >= k_low && rsp < k_high ) {
41+ * stack_low = k_low ;
42+ * stack_high = k_high ;
43+ return ;
44+ }
45+
46+ if (task -> syscall_stack != 0 ) {
47+ uint64_t s_high = task -> syscall_stack ;
48+ uint64_t s_low = s_high - MAX_STACK_SIZE ;
49+ if (rsp >= s_low && rsp < s_high ) {
50+ * stack_low = s_low ;
51+ * stack_high = s_high ;
52+ return ;
53+ }
54+ }
55+
56+ if (task -> signal_stack != 0 ) {
57+ uint64_t s_high = task -> signal_stack ;
58+ uint64_t s_low = s_high - STACK_SIZE ;
59+ if (rsp >= s_low && rsp < s_high ) {
60+ * stack_low = s_low ;
61+ * stack_high = s_high ;
62+ return ;
63+ }
64+ }
65+ }
66+
67+ * stack_low = rsp ;
68+ * stack_high = rsp + MAX_STACK_SIZE ;
69+ }
70+
71+ static int backtrace_from_rbp (uint64_t rbp , uint64_t stack_low , uint64_t stack_high ,
72+ int max_frames ) {
73+ int count = 0 ;
74+ uint64_t sym_addr = 0 ;
75+
76+ while (count < max_frames ) {
77+ if (rbp < stack_low || rbp + 16 > stack_high ) { break ; }
78+
79+ uint64_t next_rbp = * (uint64_t * )rbp ;
80+ uint64_t ret_addr = * ((uint64_t * )rbp + 1 );
81+
82+ if (!addr_in_kernel_text (ret_addr )) { break ; }
83+
84+ const char * name = kallsyms_lookup (ret_addr , & sym_addr );
85+ if (name ) {
86+ printk (" [<0x%lx>] %s+0x%lx\n" , ret_addr , name , ret_addr - sym_addr );
87+ } else {
88+ printk (" [<0x%lx>] ???\n" , ret_addr );
89+ }
90+ count ++ ;
91+
92+ if (next_rbp <= rbp ) { break ; }
93+ rbp = next_rbp ;
94+ }
95+
96+ return count ;
97+ }
2298
2399static int ksym_cmp (const void * a , const void * b ) {
24- const ksym_t * sym_a = ( const ksym_t * ) a ;
25- const ksym_t * sym_b = ( const ksym_t * ) b ;
100+ const ksym_t * sym_a = a ;
101+ const ksym_t * sym_b = b ;
26102
27103 if (sym_a -> addr < sym_b -> addr ) return -1 ;
28104 if (sym_a -> addr > sym_b -> addr ) return 1 ;
@@ -64,17 +140,22 @@ void kallsyms_init_from_elf() {
64140 eh_frame_size = shdrs [i ].sh_size ;
65141 break ;
66142 }
143+ if (strcmp (sec_name , ".text" ) == 0 ) {
144+ kernel_text_start = shdrs [i ].sh_addr ;
145+ kernel_text_end = shdrs [i ].sh_addr + shdrs [i ].sh_size ;
146+ break ;
147+ }
148+ default :break ;
67149 }
68150 }
69151
70- size_t num_symbols = symtabsz / sizeof (Elf64_Sym );
152+ const size_t num_symbols = symtabsz / sizeof (Elf64_Sym );
71153
72154 kallsyms = calloc (num_symbols , sizeof (ksym_t ));
73155
74156 for (size_t i = 0 ; i < num_symbols ; i ++ ) {
75157 Elf64_Sym * sym = & symtab [i ];
76158 char * sym_name = & strtab [sym -> st_name ];
77- uint64_t bind = ELF64_ST_BIND (sym -> st_info );
78159 uint64_t type = ELF64_ST_TYPE (sym -> st_info );
79160 if (sym -> st_shndx == SHN_UNDEF ) continue ;
80161 if (type == STT_FUNC ) {
@@ -107,7 +188,7 @@ const char *kallsyms_lookup(uint64_t addr, uint64_t *sym_addr) {
107188}
108189
109190void print_kernel_backtrace (struct interrupt_frame * frame , uint64_t saved_rbp ) {
110- printk ("Call Trace (stack scanning) :\n" );
191+ printk ("Call Trace:\n" );
111192
112193 uint64_t sym_addr = 0 ;
113194 const char * name = kallsyms_lookup (frame -> rip , & sym_addr );
@@ -117,29 +198,45 @@ void print_kernel_backtrace(struct interrupt_frame *frame, uint64_t saved_rbp) {
117198 printk (" [<0x%lx>] ??? (RIP)\n" , frame -> rip );
118199 }
119200
120- // 从 RSP 开始向上扫描栈(限制范围防止越界)
121- uint64_t * stack = (uint64_t * )frame -> rsp ;
122- const uint64_t stack_top = frame -> rsp + 0x2000 ; // 扫描最多 8KB
123- int count = 0 ;
124- const int max_frames = 20 ;
125-
126- for (uint64_t * p = stack ; p < (uint64_t * )stack_top && count < max_frames ; p ++ ) {
127- uint64_t candidate = * p ;
128-
129- // 合法内核地址范围(根据你的链接脚本)
130- if (candidate >= 0xffffffff80000000UL && candidate < 0xfffffffffffff000UL ) {
131- // 检查是否对齐(指令地址通常是 16 字节对齐)
132- if ((candidate & 0xF ) == 0 ) {
133- const char * name = kallsyms_lookup (candidate , & sym_addr );
134- if (name ) {
135- printk (" [<0x%lx>] %s+0x%lx\n" , candidate , name , candidate - sym_addr );
136- } else {
137- printk (" [<0x%lx>] ???\n" , candidate );
138- }
139- count ++ ;
201+ const int max_frames = 20 ;
202+ int count = 0 ;
203+
204+ uint64_t stack_low = 0 ;
205+ uint64_t stack_high = 0 ;
206+ get_stack_bounds (frame -> rsp , & stack_low , & stack_high );
207+
208+ if (saved_rbp >= stack_low && saved_rbp + 16 <= stack_high ) {
209+ uint64_t rbp = 0 ;
210+ uint64_t ret = * ((uint64_t * )saved_rbp + 1 );
211+ if (ret == frame -> rip ) {
212+ rbp = * (uint64_t * )saved_rbp ; // handler 栈帧,取中断前的 RBP
213+ } else {
214+ rbp = saved_rbp ; // saved_rbp 本身就是中断前的 RBP
215+ }
216+ if (rbp >= stack_low && rbp + 16 <= stack_high ) {
217+ count = backtrace_from_rbp (rbp , stack_low , stack_high , max_frames );
218+ }
219+ }
220+
221+ if (count == 0 ) {
222+ uint64_t start_rsp = frame -> rsp ;
223+ if (start_rsp < stack_low || start_rsp >= stack_high ) { start_rsp = stack_low ; }
224+
225+ for (uint64_t * p = (uint64_t * )start_rsp ;
226+ (uint64_t )p + sizeof (uint64_t ) <= stack_high && count < max_frames ; p ++ ) {
227+ const uint64_t candidate = * p ;
228+
229+ if (!addr_in_kernel_text (candidate )) { continue ; }
230+
231+ const char * name = kallsyms_lookup (candidate , & sym_addr );
232+ if (name ) {
233+ printk (" [<0x%lx>] %s+0x%lx\n" , candidate , name , candidate - sym_addr );
234+ } else {
235+ printk (" [<0x%lx>] ???\n" , candidate );
140236 }
237+ count ++ ;
141238 }
142239 }
143240
144- if (count == 0 ) { printk (" (no valid return addresses found on stack )\n" ); }
241+ if (count == 0 ) { printk (" (no valid return addresses found)\n" ); }
145242}
0 commit comments