e4784a2d31455b1d261426bb759ae784942f787d
[sbcl.git] / src / runtime / backtrace.c
1 /*
2  * simple backtrace facility
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 #include <stdio.h>
17 #include <signal.h>
18 #include "sbcl.h"
19 #include "runtime.h"
20 #include "globals.h"
21 #include "os.h"
22 #include "interrupt.h"
23 #include "lispregs.h"
24 #ifdef LISP_FEATURE_GENCGC
25 #include "arch.h"
26 #include "gencgc-alloc-region.h"
27 #include "genesis/compiled-debug-fun.h"
28 #include "genesis/compiled-debug-info.h"
29 #include "genesis/package.h"
30 #endif
31 #include "genesis/static-symbols.h"
32 #include "genesis/primitive-objects.h"
33 #include "thread.h"
34
35 #if !(defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
36
37 /* KLUDGE: Sigh ... I know what the call frame looks like and it had
38  * better not change. */
39
40 struct call_frame {
41 #ifndef LISP_FEATURE_ALPHA
42         struct call_frame *old_cont;
43 #else
44         u32 old_cont;
45 #endif
46         lispobj saved_lra;
47         lispobj code;
48         lispobj other_state[5];
49 };
50
51 struct call_info {
52 #ifndef LISP_FEATURE_ALPHA
53     struct call_frame *frame;
54 #else
55     u32 frame;
56 #endif
57     int interrupted;
58 #ifndef LISP_FEATURE_ALPHA
59     struct code *code;
60 #else
61     u32 code;
62 #endif
63     lispobj lra;
64     int pc; /* Note: this is the trace file offset, not the actual pc. */
65 };
66
67 #define HEADER_LENGTH(header) ((header)>>8)
68
69 static int previous_info(struct call_info *info);
70
71 static struct code *
72 code_pointer(lispobj object)
73 {
74     lispobj *headerp, header;
75     int type, len;
76
77     headerp = (lispobj *) native_pointer(object);
78     header = *headerp;
79     type = widetag_of(header);
80
81     switch (type) {
82         case CODE_HEADER_WIDETAG:
83             break;
84         case RETURN_PC_HEADER_WIDETAG:
85         case SIMPLE_FUN_HEADER_WIDETAG:
86             len = HEADER_LENGTH(header);
87             if (len == 0)
88                 headerp = NULL;
89             else
90                 headerp -= len;
91             break;
92         default:
93             headerp = NULL;
94     }
95
96     return (struct code *) headerp;
97 }
98
99 static boolean
100 cs_valid_pointer_p(struct call_frame *pointer)
101 {
102     struct thread *thread=arch_os_get_current_thread();
103     return (((char *) thread->control_stack_start <= (char *) pointer) &&
104             ((char *) pointer < (char *) current_control_stack_pointer));
105 }
106
107 static void
108 call_info_from_lisp_state(struct call_info *info)
109 {
110     info->frame = (struct call_frame *)current_control_frame_pointer;
111     info->interrupted = 0;
112     info->code = NULL;
113     info->lra = 0;
114     info->pc = 0;
115
116     previous_info(info);
117 }
118
119 static void
120 call_info_from_context(struct call_info *info, os_context_t *context)
121 {
122     unsigned long pc;
123
124     info->interrupted = 1;
125     if (lowtag_of(*os_context_register_addr(context, reg_CODE))
126         == FUN_POINTER_LOWTAG) {
127         /* We tried to call a function, but crapped out before $CODE could
128          * be fixed up. Probably an undefined function. */
129         info->frame =
130             (struct call_frame *)(*os_context_register_addr(context,
131                                                             reg_OCFP));
132         info->lra = (lispobj)(*os_context_register_addr(context, reg_LRA));
133         info->code = code_pointer(info->lra);
134         pc = (unsigned long)native_pointer(info->lra);
135     }
136     else {
137         info->frame =
138             (struct call_frame *)(*os_context_register_addr(context, reg_CFP));
139         info->code =
140             code_pointer(*os_context_register_addr(context, reg_CODE));
141         info->lra = NIL;
142         pc = *os_context_pc_addr(context);
143     }
144     if (info->code != NULL)
145         info->pc = pc - (unsigned long) info->code -
146 #ifndef LISP_FEATURE_ALPHA
147             (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
148 #else
149             (HEADER_LENGTH(((struct code *)info->code)->header) * sizeof(lispobj));
150 #endif
151     else
152         info->pc = 0;
153 }
154
155 static int
156 previous_info(struct call_info *info)
157 {
158     struct call_frame *this_frame;
159     struct thread *thread=arch_os_get_current_thread();
160     int free;
161
162     if (!cs_valid_pointer_p(info->frame)) {
163         printf("Bogus callee value (0x%08lx).\n", (unsigned long)info->frame);
164         return 0;
165     }
166
167     this_frame = info->frame;
168     info->lra = this_frame->saved_lra;
169     info->frame = this_frame->old_cont;
170     info->interrupted = 0;
171
172     if (info->frame == NULL || info->frame == this_frame)
173         return 0;
174
175     if (info->lra == NIL) {
176         /* We were interrupted. Find the correct signal context. */
177         free = SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread)>>2;
178         while (free-- > 0) {
179             os_context_t *context =
180                 thread->interrupt_contexts[free];
181             if ((struct call_frame *)(*os_context_register_addr(context,
182                                                                 reg_CFP))
183                 == info->frame) {
184                 call_info_from_context(info, context);
185                 break;
186             }
187         }
188     }
189     else {
190         info->code = code_pointer(info->lra);
191         if (info->code != NULL)
192             info->pc = (unsigned long)native_pointer(info->lra) -
193                 (unsigned long)info->code -
194 #ifndef LISP_FEATURE_ALPHA
195                 (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
196 #else
197                 (HEADER_LENGTH(((struct code *)info->code)->header) * sizeof(lispobj));
198 #endif
199         else
200             info->pc = 0;
201     }
202
203     return 1;
204 }
205
206 void
207 backtrace(int nframes)
208 {
209     struct call_info info;
210
211     call_info_from_lisp_state(&info);
212
213     do {
214         printf("<Frame 0x%08lx%s, ", (unsigned long) info.frame,
215                 info.interrupted ? " [interrupted]" : "");
216
217         if (info.code != (struct code *) 0) {
218             lispobj function;
219
220             printf("CODE: 0x%08lX, ", (unsigned long) info.code | OTHER_POINTER_LOWTAG);
221
222 #ifndef LISP_FEATURE_ALPHA
223             function = info.code->entry_points;
224 #else
225             function = ((struct code *)info.code)->entry_points;
226 #endif
227             while (function != NIL) {
228                 struct simple_fun *header;
229                 lispobj name;
230
231                 header = (struct simple_fun *) native_pointer(function);
232                 name = header->name;
233
234                 if (lowtag_of(name) == OTHER_POINTER_LOWTAG) {
235                     lispobj *object;
236
237                     object = (lispobj *) native_pointer(name);
238
239                     if (widetag_of(*object) == SYMBOL_HEADER_WIDETAG) {
240                         struct symbol *symbol;
241
242                         symbol = (struct symbol *) object;
243                         object = (lispobj *) native_pointer(symbol->name);
244                     }
245                     if (widetag_of(*object) == SIMPLE_BASE_STRING_WIDETAG) {
246                         struct vector *string;
247
248                         string = (struct vector *) object;
249                         printf("%s, ", (char *) string->data);
250                     } else
251                         /* FIXME: broken from (VECTOR NIL) */
252                         printf("(Not simple string??\?), ");
253                 } else
254                     printf("(Not other pointer??\?), ");
255
256
257                 function = header->next;
258             }
259         }
260         else
261             printf("CODE: ???, ");
262
263         if (info.lra != NIL)
264             printf("LRA: 0x%08lx, ", (unsigned long)info.lra);
265         else
266             printf("<no LRA>, ");
267
268         if (info.pc)
269             printf("PC: 0x%x>\n", info.pc);
270         else
271             printf("PC: ??\?>\n");
272
273     } while (--nframes > 0 && previous_info(&info));
274 }
275
276 #else
277
278 static int
279 stack_pointer_p (void *p)
280 {
281   return (p < (void *) arch_os_get_current_thread()->control_stack_end
282           && p > (void *) &p
283           && (((unsigned long) p) & 3) == 0);
284 }
285
286 static int
287 ra_pointer_p (void *ra)
288 {
289   return ((unsigned long) ra) > 4096 && !stack_pointer_p (ra);
290 }
291
292 static int
293 x86_call_context (void *fp, void **ra, void **ocfp)
294 {
295   void *lisp_ocfp;
296   void *lisp_ra;
297   void *c_ocfp;
298   void *c_ra;
299   int lisp_valid_p, c_valid_p;
300
301   if (!stack_pointer_p(fp))
302     return 0;
303
304   c_ocfp    = *((void **) fp);
305   c_ra      = *((void **) fp + 1);
306   lisp_ocfp = *((void **) fp - 1);
307   lisp_ra   = *((void **) fp - 2);
308
309   lisp_valid_p = (lisp_ocfp > fp
310                   && stack_pointer_p(lisp_ocfp)
311                   && ra_pointer_p(lisp_ra));
312   c_valid_p = (c_ocfp > fp
313                && stack_pointer_p(c_ocfp)
314                && ra_pointer_p(c_ra));
315
316   if (lisp_valid_p && c_valid_p) {
317     void *lisp_path_fp;
318     void *c_path_fp;
319     void *dummy;
320
321     int lisp_path_p = x86_call_context(lisp_ocfp, &lisp_path_fp, &dummy);
322     int c_path_p = x86_call_context(c_ocfp, &c_path_fp, &dummy);
323
324     if (lisp_path_p && c_path_p) {
325 #if defined __FreeBSD__ && __FreeBSD_version > 400000
326       if (lisp_ocfp > c_ocfp)
327         *ra = lisp_ra, *ocfp = lisp_ocfp;
328       else
329         *ra = c_ra, *ocfp = c_ocfp;
330 #else
331       *ra = lisp_ra, *ocfp = lisp_ocfp;
332 #endif
333     }
334     else if (lisp_path_p)
335       *ra = lisp_ra, *ocfp = lisp_ocfp;
336     else if (c_path_p)
337       *ra = c_ra, *ocfp = c_ocfp;
338     else
339       return 0;
340   }
341   else if (lisp_valid_p)
342     *ra = lisp_ra, *ocfp = lisp_ocfp;
343   else if (c_valid_p)
344     *ra = c_ra, *ocfp = c_ocfp;
345   else
346     return 0;
347
348   return 1;
349 }
350
351 struct compiled_debug_fun *
352 debug_function_from_pc (struct code* code, void *pc)
353 {
354   unsigned long code_header_len = sizeof(lispobj) * HeaderValue(code->header);
355   unsigned long offset
356     = (unsigned long) pc - (unsigned long) code - code_header_len;
357   struct compiled_debug_fun *df;
358   struct compiled_debug_info *di;
359   struct vector *v;
360   int i, len;
361
362   if (lowtag_of(code->debug_info) != INSTANCE_POINTER_LOWTAG)
363     return 0;
364
365   di = (struct compiled_debug_info *) native_pointer(code->debug_info);
366   v = (struct vector *) native_pointer(di->fun_map);
367   len = fixnum_value(v->length);
368   df = (struct compiled_debug_fun *) native_pointer(v->data[0]);
369
370   if (len == 1)
371     return df;
372
373   for (i = 1;; i += 2) {
374     unsigned next_pc;
375                   
376     if (i == len)
377       return ((struct compiled_debug_fun *) native_pointer(v->data[i - 1]));
378
379     if (offset >= fixnum_value(df->elsewhere_pc)) {
380       struct compiled_debug_fun *p
381         = ((struct compiled_debug_fun *) native_pointer(v->data[i + 1]));
382       next_pc = fixnum_value(p->elsewhere_pc);
383     } else
384       next_pc = fixnum_value(v->data[i]);
385
386     if (offset < next_pc)
387       return ((struct compiled_debug_fun *) native_pointer(v->data[i - 1]));
388   }
389
390   return NULL;
391 }
392
393 static void
394 print_entry_name (lispobj name)
395 {
396   if (lowtag_of (name) == LIST_POINTER_LOWTAG) {
397     putchar('(');
398     while (name != NIL) {
399       struct cons *cons = (struct cons *) native_pointer(name);
400       print_entry_name(cons->car);
401       name = cons->cdr;
402       if (name != NIL)
403         putchar(' ');
404     }
405     putchar(')');
406   } else if (lowtag_of(name) == OTHER_POINTER_LOWTAG) {
407     lispobj *object = (lispobj *) native_pointer(name);
408
409     if (widetag_of(*object) == SYMBOL_HEADER_WIDETAG) {
410       struct symbol *symbol = (struct symbol *) object;
411       struct vector *string;
412
413       if (symbol->package != NIL) {
414         struct package *pkg
415           = (struct package *) native_pointer(symbol->package);
416         lispobj pkg_name = pkg->_name;
417         string = (struct vector *) native_pointer(pkg_name);
418         printf("%s::", (char *) string->data);
419       }
420
421       object = (lispobj *) native_pointer(symbol->name);
422       string = (struct vector *) object;
423       printf("%s", (char *) string->data);
424     } else if (widetag_of(*object) == SIMPLE_BASE_STRING_WIDETAG) {
425       struct vector *string = (struct vector *) object;
426       printf("\"%s\"", (char *) string->data);
427 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
428     } else if (widetag_of(*object) == SIMPLE_CHARACTER_STRING_WIDETAG) {
429       struct vector *string = (struct vector *) object;
430       printf("<oops, a unicode string>");                           /* FIXME */
431 #endif
432     } else
433       printf("<??? type %d>", (int) widetag_of(*object));
434   } else
435     printf("<??? lowtag %d>", (int) lowtag_of(name));
436 }
437
438 static void
439 print_entry_points (struct code *code)
440 {
441   lispobj function = code->entry_points;
442
443   while (function != NIL) {
444     struct simple_fun *header = (struct simple_fun *) native_pointer(function);
445     print_entry_name(header->name);
446       
447     function = header->next;
448     if (function != NIL)
449       printf (", ");
450   }
451 }
452
453 void
454 backtrace(int nframes)
455 {
456   void *fp;
457   int i;
458
459 #if defined(LISP_FEATURE_X86)
460   asm("movl %%ebp,%0" : "=g" (fp));
461 #elif defined (LISP_FEATURE_X86_64)
462   asm("movq %%rbp,%0" : "=g" (fp));
463 #else
464 #error "How did we get here?"
465 #endif
466
467   for (i = 0; i < nframes; ++i) {
468     lispobj *p;
469     void *ra;
470     void *next_fp;
471       
472     if (!x86_call_context(fp, &ra, &next_fp))
473       break;
474
475     printf("%4d: ", i);
476
477     p = (lispobj *) component_ptr_from_pc((lispobj *) ra);
478     if (p) {
479       struct code *cp = (struct code *) p;
480       struct compiled_debug_fun *df = debug_function_from_pc(cp, ra);
481       if (df)
482         print_entry_name(df->name);
483       else
484         print_entry_points(cp);
485     } else
486       printf("Foreign fp = 0x%lx, ra = 0x%lx",
487              (unsigned long) next_fp,
488              (unsigned long) ra);
489
490     putchar('\n');
491     fp = next_fp;
492   }
493 }
494
495 #endif