x86: Provide an option to enable legacy USB
[akaros.git] / kern / arch / x86 / kdebug.c
1 #include <stab.h>
2 #include <string.h>
3 #include <assert.h>
4 #include <kdebug.h>
5 #include <pmap.h>
6 #include <process.h>
7 #include <kmalloc.h>
8 #include <arch/uaccess.h>
9
10 #include <ros/memlayout.h>
11
12 /* The return address is right above ebp on the stack.  We subtract an
13  * additional 1 to make sure the eip we get is actually in the function
14  * that called us.  I had a couple cases early on where call was the last
15  * instruction in a function, and simply reading the retaddr would point
16  * into another function (the next one in the object).
17  */
18 #define GET_FRAME_START(ebp, eip)                                                       \
19         do {                                                                                                    \
20                 ebp = read_bp();                                                                        \
21                 eip = *(uintptr_t *) (ebp + sizeof(uintptr_t)) - 1; \
22                 ebp = *(uintptr_t *) ebp;                                                       \
23         } while (0)
24
25 // Beginning of stabs table
26 extern const stab_t __STAB_BEGIN__[];
27
28 // End of stabs table
29 extern const stab_t __STAB_END__[];
30
31 // Beginning of string table
32 extern const char __STABSTR_BEGIN__[];
33
34  // End of string table
35 extern const char __STABSTR_END__[];
36
37 typedef struct UserStabData {
38         const stab_t *stabs;
39         const stab_t *stab_end;
40         const char *stabstr;
41         const char *stabstr_end;
42 } user_stab_data_t;
43
44 static void printk_func(void *opaque, const char *str)
45 {
46         printk("%s", str);
47 }
48
49 void gen_backtrace_frame(uintptr_t eip, uintptr_t ebp,
50                                                  void (*pfunc)(void *, const char *), void *opaque)
51 {
52 #define MAX_BT_DEPTH 20
53         char *func_name;
54         char bt_line[128];
55         uintptr_t pcs[MAX_BT_DEPTH];
56         size_t nr_pcs = backtrace_list(eip, ebp, pcs, MAX_BT_DEPTH);
57
58         for (size_t i = 0; i < nr_pcs; i++) {
59                 func_name = get_fn_name(pcs[i]);
60                 snprintf(bt_line, sizeof(bt_line), "#%02d [<%p>] in %s\n", i + 1,
61                                  pcs[i], func_name);
62                 pfunc(opaque, bt_line);
63                 kfree(func_name);
64         }
65 }
66
67 void gen_backtrace(void (*pfunc)(void *, const char *), void *opaque)
68 {
69         uintptr_t ebp, eip;
70
71         GET_FRAME_START(ebp, eip);
72         gen_backtrace_frame(eip, ebp, pfunc, opaque);
73 }
74
75 /* We used to check for a null terminating byte for the entire strings section
76  * (due to JOS, I think), but that's not what the spec says: only that all
77  * strings are null terminated.  There might be random stuff tacked on at the
78  * end.  I had some stabs that seemed valid (lookups worked), that did not have
79  * the entire table be null terminated.  Still, something else might be jacked
80  * up.  If it turns out that's the case, put the checks in here. */
81 static bool stab_table_valid(const char *stabstr, const char *stabstr_end)
82 {
83         if (stabstr_end <= stabstr)
84                 return FALSE;
85         return TRUE;
86 }
87
88 // stab_binsearch(stabs, region_left, region_right, type, addr)
89 //
90 //      Some stab types are arranged in increasing order by instruction
91 //      address.  For example, N_FUN stabs (stab entries with n_type ==
92 //      N_FUN), which mark functions, and N_SO stabs, which mark source files.
93 //
94 //      Given an instruction address, this function finds the single stab
95 //      entry of type 'type' that contains that address.
96 //
97 //      The search takes place within the range [*region_left, *region_right].
98 //      Thus, to search an entire set of N stabs, you might do:
99 //
100 //              left = 0;
101 //              right = N - 1;     /* rightmost stab */
102 //              stab_binsearch(stabs, &left, &right, type, addr);
103 //
104 //      The search modifies *region_left and *region_right to bracket the
105 //      'addr'.  *region_left points to the matching stab that contains
106 //      'addr', and *region_right points just before the next stab.  If
107 //      *region_left > *region_right, then 'addr' is not contained in any
108 //      matching stab.
109 //
110 //      For example, given these N_SO stabs:
111 //              Index  Type   Address
112 //              0      SO     f0100000
113 //              13     SO     f0100040
114 //              117    SO     f0100176
115 //              118    SO     f0100178
116 //              555    SO     f0100652
117 //              556    SO     f0100654
118 //              657    SO     f0100849
119 //      this code:
120 //              left = 0, right = 657;
121 //              stab_binsearch(stabs, &left, &right, N_SO, 0xf0100184);
122 //      will exit setting left = 118, right = 554.
123 //
124 static void
125 stab_binsearch(const stab_t *stabs,
126            const stab_t *stab_end,
127            int *region_left, int *region_right,
128                int type, uintptr_t addr)
129 {
130         int l = *region_left, r = *region_right, any_matches = 0;
131         
132         while (l <= r) {
133                 int true_m = (l + r) / 2, m = true_m;
134                 
135                 // search for earliest stab with right type
136                 while (m >= l && stabs[m].n_type != type)
137                         m--;
138                 if (m < l) {    // no match in [l, m]
139                         l = true_m + 1;
140                         continue;
141                 }
142
143                 // actual binary search
144                 any_matches = 1;
145                 if (stabs[m].n_value < addr) {
146                         *region_left = m;
147                         l = true_m + 1;
148                 } else if (stabs[m].n_value > addr) {
149                         *region_right = m - 1;
150                         r = m - 1;
151                 } else {
152                         // exact match for 'addr', but continue loop to find
153                         // *region_right
154                         *region_left = m;
155                         l = m;
156                         addr++;
157                 }
158         }
159
160         if (!any_matches)
161                 *region_right = *region_left - 1;
162         else {
163                 // find rightmost region containing 'addr'
164                 for (l = *region_right;
165                      l > *region_left && stabs[l].n_type != type;
166                      l--)
167                         /* do nothing */;
168                 *region_left = l;
169         }
170 }
171
172
173 // debuginfo_eip(addr, info)
174 //
175 //      Fill in the 'info' structure with information about the specified
176 //      instruction address, 'addr'.  Returns 0 if information was found, and
177 //      negative if not.  But even if it returns negative it has stored some
178 //      information into '*info'.
179 //
180 int
181 debuginfo_eip(uintptr_t addr, eipdebuginfo_t *info)
182 {
183         const stab_t *stab_end;
184         const stab_t *stabs;
185         const char *stabstr_end;
186         const char *stabstr;
187         int lfile, rfile, lfun, rfun, lline, rline;
188
189         // Initialize *info
190         info->eip_file = "<unknown>";
191         info->eip_line = 0;
192         info->eip_fn_name = "<unknown>";
193         info->eip_fn_namelen = 9;
194         info->eip_fn_addr = addr;
195         info->eip_fn_narg = 0;
196
197         // Find the relevant set of stabs
198         if (addr >= ULIM) {
199                 stab_end = __STAB_END__;
200                 stabs = __STAB_BEGIN__;
201                 stabstr_end = __STABSTR_END__;
202                 stabstr = __STABSTR_BEGIN__;
203         } else {
204                 /* TODO: short circuiting this, til our user space apps pack stab data
205                  * the kernel knows about */
206                 return -1;
207                 #if 0
208                 // The user-application linker script, user/user.ld,
209                 // puts information about the application's stabs (equivalent
210                 // to __STAB_BEGIN__, __STAB_END__, __STABSTR_BEGIN__, and
211                 // __STABSTR_END__) in a structure located at virtual address
212                 // USTABDATA.
213                 const user_stab_data_t *usd = (const user_stab_data_t *)USTABDATA;
214
215                 // Make sure this memory is valid.
216                 // Return -1 if it is not.  Hint: Call user_mem_check.
217                 // LAB 3: Your code here.
218
219                 stab_end = usd->stab_end;
220                 stabs = usd->stabs;
221                 stabstr_end = usd->stabstr_end;
222                 stabstr = usd->stabstr;
223
224                 // Make sure the STABS and string table memory is valid.
225                 // LAB 3: Your code here.
226                 #endif
227         }
228
229         if (!stab_table_valid(stabstr, stabstr_end))
230                 return -1;
231
232         // Now we find the right stabs that define the function containing
233         // 'eip'.  First, we find the basic source file containing 'eip'.
234         // Then, we look in that source file for the function.  Then we look
235         // for the line number.
236         
237         // Search the entire set of stabs for the source file (type N_SO).
238         lfile = 0;
239         rfile = (stab_end - stabs) - 1;
240         stab_binsearch(stabs, stab_end, &lfile, &rfile, N_SO, addr);
241         if (lfile == 0)
242                 return -1;
243
244         // Search within that file's stabs for the function definition
245         // (N_FUN).
246         lfun = lfile;
247         rfun = rfile;
248         stab_binsearch(stabs, stab_end, &lfun, &rfun, N_FUN, addr);
249
250         if (lfun <= rfun) {
251                 // stabs[lfun] points to the function name
252                 // in the string table, but check bounds just in case.
253                 if (stabs[lfun].n_strx < stabstr_end - stabstr)
254                         info->eip_fn_name = stabstr + stabs[lfun].n_strx;
255                 info->eip_fn_addr = stabs[lfun].n_value;
256                 addr -= info->eip_fn_addr;
257                 // Search within the function definition for the line number.
258                 lline = lfun;
259                 rline = rfun;
260         } else {
261                 // Couldn't find function stab!  Maybe we're in an assembly
262                 // file.  Search the whole file for the line number.
263                 info->eip_fn_addr = addr;
264                 lline = lfile;
265                 rline = rfile;
266         }
267         // Ignore stuff after the colon.
268         info->eip_fn_namelen = strfind(info->eip_fn_name, ':') - info->eip_fn_name;
269         
270         // Search within [lline, rline] for the line number stab.
271         // If found, set info->eip_line to the right line number.
272         // If not found, return -1.
273         //
274         // Hint:
275         //      There's a particular stabs type used for line numbers.
276         //      Look at the STABS documentation and <inc/stab.h> to find
277         //      which one.
278         // Your code here.
279
280         stab_binsearch(stabs, stab_end, &lline, &rline, N_SLINE, addr);
281         if (lline <= rline) 
282                 // stabs[lline] points to the line number
283                 info->eip_line = stabs[lline].n_value;
284         else
285                 return -1;
286         
287         // Search backwards from the line number for the relevant filename
288         // stab.
289         // We can't just use the "lfile" stab because inlined functions
290         // can interpolate code from a different file!
291         // Such included source files use the N_SOL stab type.
292         while (lline >= lfile
293                && stabs[lline].n_type != N_SOL
294                && (stabs[lline].n_type != N_SO || !stabs[lline].n_value))
295                 lline--;
296         if (lline >= lfile && stabs[lline].n_strx < stabstr_end - stabstr)
297                 info->eip_file = stabstr + stabs[lline].n_strx;
298
299         // Set eip_fn_narg to the number of arguments taken by the function,
300         // or 0 if there was no containing function.
301         // Your code here.
302         info->eip_fn_narg = 0;
303         if (lfun <= rfun) {
304                 lfun++;
305                 while (stabs[lfun++].n_type == N_PSYM)
306                         info->eip_fn_narg++;
307         }
308         
309         return 0;
310 }
311
312 /* Returns a function pointer for a function name matching the given string. */
313 void *debug_get_fn_addr(char *fn_name)
314 {
315         const struct stab *stab_end = __STAB_END__;
316         const struct stab *stabs = __STAB_BEGIN__;
317         const char *stabstr_end = __STABSTR_END__;
318         const char *stabstr = __STABSTR_BEGIN__;
319
320         static int first_fn_idx = 0;
321         int i = first_fn_idx;
322         int len;
323         const char *stab_fn_name = 0;
324         void *retval = 0;
325
326         if (!stab_table_valid(stabstr, stabstr_end))
327                 return 0;
328
329         for (/* i set */; &stabs[i] < stab_end; i++) {
330                 if (stabs[i].n_type != N_FUN)
331                         continue;
332                 first_fn_idx = first_fn_idx ? first_fn_idx : i;
333                 /* broken stab, just keep going */
334                 if (!(stabs[i].n_strx < stabstr_end - stabstr))
335                         continue;
336                 stab_fn_name = stabstr + stabs[i].n_strx;
337                 len = strfind(stab_fn_name, ':') - stab_fn_name;
338                 if (!len)
339                         continue;
340                 /* we have a match. */
341                 if (!strncmp(stab_fn_name, fn_name, len)) {
342                         printd("FN name: %s, Addr: %p\n", stab_fn_name, stabs[i].n_value);
343                         retval = (void*)stabs[i].n_value;
344                         break;
345                 }
346         }
347         return retval;
348 }
349
350 size_t backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs,
351                       size_t nr_slots)
352 {
353         size_t nr_pcs = 0;
354         while ((fp > MMAP_LOWEST_VA) && (nr_pcs < nr_slots)) {
355                 /* could put some sanity checks in here...  i used to at least check for
356                  * kernel addrs, but now we also bt user stacks. (dangerous!) */
357                 pcs[nr_pcs++] = pc;
358                 printd("PC %p FP %p\n", pc, fp);
359                 /* We used to set PC = retaddr - 1, where the -1 would put our PC back
360                  * inside the function that called us.  This was for obscure cases where
361                  * a no-return function calls another function and has no other code
362                  * after the function call.  Or something. */
363                 pc = *(uintptr_t*)(fp + sizeof(uintptr_t));
364                 fp = *(uintptr_t*)fp;
365         }
366         return nr_pcs;
367 }
368
369 size_t user_backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs,
370                                                    size_t nr_slots)
371 {
372         int error;
373         size_t nr_pcs = 0;
374         uintptr_t frame[2];
375
376         for (;;) {
377                 error = copy_from_user(frame, (const void *) fp, 2 * sizeof(uintptr_t));
378                 if (unlikely(error) || unlikely(nr_pcs >= nr_slots))
379                         break;
380
381                 /* For now straight memory access, waiting for copy_from_user(). */
382                 pcs[nr_pcs++] = pc;
383                 pc = frame[1];
384                 fp = frame[0];
385         }
386
387         return nr_pcs;
388 }
389
390 void backtrace_frame(uintptr_t eip, uintptr_t ebp)
391 {
392         gen_backtrace_frame(eip, ebp, &printk_func, NULL);
393 }
394
395 void backtrace(void)
396 {
397         printk("Stack Backtrace on Core %d:\n", core_id());
398         gen_backtrace(&printk_func, NULL);
399 }
400
401 /* Assumes 32-bit header */
402 void print_fpu_state(struct ancillary_state *fpu)
403 {
404         printk("fcw:        0x%04x\n", fpu->fp_head_n64.fcw);
405         printk("fsw:        0x%04x\n", fpu->fp_head_n64.fsw);
406         printk("ftw:          0x%02x\n", fpu->fp_head_n64.ftw);
407         printk("fop:        0x%04x\n", fpu->fp_head_n64.fop);
408         printk("fpu_ip: 0x%08x\n", fpu->fp_head_n64.fpu_ip);
409         printk("cs:         0x%04x\n", fpu->fp_head_n64.cs);
410         printk("fpu_dp: 0x%08x\n", fpu->fp_head_n64.fpu_dp);
411         printk("ds:         0x%04x\n", fpu->fp_head_n64.ds);
412         printk("mxcsr:  0x%08x\n", fpu->fp_head_n64.mxcsr);
413         printk("mxcsrm: 0x%08x\n", fpu->fp_head_n64.mxcsr_mask);
414
415         for (int i = 0; i < sizeof(struct ancillary_state); i++) {
416                 if (i % 20 == 0)
417                         printk("\n");
418                 printk("%02x ", *((uint8_t*)fpu + i));
419         }
420         printk("\n");
421 }