2 * simple backtrace facility
6 * This software is part of the SBCL system. See the README file for
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.
22 #include "interrupt.h"
24 #include "genesis/static-symbols.h"
25 #include "genesis/primitive-objects.h"
29 /* KLUDGE: Sigh ... I know what the call frame looks like and it had
30 * better not change. */
34 struct call_frame *old_cont;
40 lispobj other_state[5];
45 struct call_frame *frame;
56 int pc; /* Note: this is the trace file offset, not the actual pc. */
59 #define HEADER_LENGTH(header) ((header)>>8)
61 static int previous_info(struct call_info *info);
64 code_pointer(lispobj object)
66 lispobj *headerp, header;
69 headerp = (lispobj *) native_pointer(object);
71 type = widetag_of(header);
74 case CODE_HEADER_WIDETAG:
76 case RETURN_PC_HEADER_WIDETAG:
77 case SIMPLE_FUN_HEADER_WIDETAG:
78 case CLOSURE_FUN_HEADER_WIDETAG:
79 len = HEADER_LENGTH(header);
89 return (struct code *) headerp;
93 cs_valid_pointer_p(struct call_frame *pointer)
95 return (((char *) CONTROL_STACK_START <= (char *) pointer) &&
96 ((char *) pointer < (char *) current_control_stack_pointer));
100 call_info_from_lisp_state(struct call_info *info)
102 info->frame = (struct call_frame *)current_control_frame_pointer;
103 info->interrupted = 0;
112 call_info_from_context(struct call_info *info, os_context_t *context)
116 info->interrupted = 1;
117 if (lowtag_of(*os_context_register_addr(context, reg_CODE))
118 == FUN_POINTER_LOWTAG) {
119 /* We tried to call a function, but crapped out before $CODE could
120 * be fixed up. Probably an undefined function. */
122 (struct call_frame *)(*os_context_register_addr(context,
124 info->lra = (lispobj)(*os_context_register_addr(context, reg_LRA));
125 info->code = code_pointer(info->lra);
126 pc = (unsigned long)native_pointer(info->lra);
130 (struct call_frame *)(*os_context_register_addr(context, reg_CFP));
132 code_pointer(*os_context_register_addr(context, reg_CODE));
134 pc = *os_context_pc_addr(context);
136 if (info->code != NULL)
137 info->pc = pc - (unsigned long) info->code -
139 (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
141 (HEADER_LENGTH(((struct code *)info->code)->header) * sizeof(lispobj));
148 previous_info(struct call_info *info)
150 struct call_frame *this_frame;
153 if (!cs_valid_pointer_p(info->frame)) {
154 printf("Bogus callee value (0x%08x).\n", (unsigned long)info->frame);
158 this_frame = info->frame;
159 info->lra = this_frame->saved_lra;
160 info->frame = this_frame->old_cont;
161 info->interrupted = 0;
163 if (info->frame == NULL || info->frame == this_frame)
166 if (info->lra == NIL) {
167 /* We were interrupted. Find the correct signal context. */
168 free = SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)>>2;
170 os_context_t *context =
171 lisp_interrupt_contexts[free];
172 if ((struct call_frame *)(*os_context_register_addr(context,
175 call_info_from_context(info, context);
181 info->code = code_pointer(info->lra);
182 if (info->code != NULL)
183 info->pc = (unsigned long)native_pointer(info->lra) -
184 (unsigned long)info->code -
186 (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
188 (HEADER_LENGTH(((struct code *)info->code)->header) * sizeof(lispobj));
198 backtrace(int nframes)
200 struct call_info info;
202 call_info_from_lisp_state(&info);
205 printf("<Frame 0x%08x%s, ", (unsigned long) info.frame,
206 info.interrupted ? " [interrupted]" : "");
208 if (info.code != (struct code *) 0) {
211 printf("CODE: 0x%08X, ", (unsigned long) info.code | OTHER_POINTER_LOWTAG);
214 function = info.code->entry_points;
216 function = ((struct code *)info.code)->entry_points;
218 while (function != NIL) {
219 struct simple_fun *header;
222 header = (struct simple_fun *) native_pointer(function);
225 if (lowtag_of(name) == OTHER_POINTER_LOWTAG) {
228 object = (lispobj *) native_pointer(name);
230 if (widetag_of(*object) == SYMBOL_HEADER_WIDETAG) {
231 struct symbol *symbol;
233 symbol = (struct symbol *) object;
234 object = (lispobj *) native_pointer(symbol->name);
236 if (widetag_of(*object) == SIMPLE_STRING_WIDETAG) {
237 struct vector *string;
239 string = (struct vector *) object;
240 printf("%s, ", (char *) string->data);
242 printf("(Not simple string??\?), ");
244 printf("(Not other pointer??\?), ");
247 function = header->next;
251 printf("CODE: ???, ");
254 printf("LRA: 0x%08x, ", (unsigned long)info.lra);
256 printf("<no LRA>, ");
259 printf("PC: 0x%x>\n", info.pc);
261 printf("PC: ??\?>\n");
263 } while (--nframes > 0 && previous_info(&info));
269 backtrace(int nframes)
271 printf("Can't backtrace on this hardware platform.\n");