3 $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/breakpoint.c,v 1.26 2008/09/12 21:09:07 rtoy Rel $
5 This code was written as part of the CMU Common Lisp project at
6 Carnegie Mellon University, and has been placed in the public domain.
15 #include "internals.h"
16 #include "interrupt.h"
21 #include "breakpoint.h"
27 * See MAKE-BOGUS-LRA in code/debug-int.lisp for these values.
29 * Ideally, internals.h should have the correct values. We leave
30 * these defaults here for now.
33 #define REAL_LRA_SLOT 0
36 #ifndef KNOWN_RETURN_P_SLOT
38 #define KNOWN_RETURN_P_SLOT 1
40 #define KNOWN_RETURN_P_SLOT 2
44 #ifndef BOGUS_LRA_CONSTANTS
46 #define BOGUS_LRA_CONSTANTS 2
48 #define BOGUS_LRA_CONSTANTS 3
54 compute_pc(lispobj code_obj, int pc_offset)
58 code = (struct code *) PTR(code_obj);
59 return (void *) ((char *) code + HeaderValue(code->header) * sizeof(lispobj)
64 breakpoint_install(lispobj code_obj, int pc_offset)
66 return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
70 breakpoint_remove(lispobj code_obj, int pc_offset, unsigned long orig_inst)
72 arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
76 breakpoint_do_displaced_inst(os_context_t * scp, unsigned long orig_inst)
78 #if !defined(hpux) && !defined(irix) && !defined(i386)
79 undo_fake_foreign_function_call(scp);
81 arch_do_displaced_inst(scp, orig_inst);
86 find_code(os_context_t * scp)
89 lispobj code = SC_REG(scp, reg_CODE), header;
91 if (LowtagOf(code) != type_OtherPointer)
94 header = *(lispobj *) (code - type_OtherPointer);
96 if (TypeOf(header) == type_CodeHeader)
99 return code - HeaderValue(header) * sizeof(lispobj);
108 find_code(os_context_t * scp)
110 lispobj *codeptr = component_ptr_from_pc((lispobj *) SC_PC(scp));
115 return (lispobj) codeptr | type_OtherPointer;
119 #if (defined(DARWIN) && defined(__ppc__)) || (defined(sparc))
121 * During a function-end-breakpoint, the pc is sometimes less than the
122 * code address, which bypasses the function end stuff. Then the
123 * offset is zero for a function-end-breakpoint, and we can't find the
124 * breakpoint data, causing an error during tracing. But we know this
125 * is a function-end breakpoint, because function_end is set to true.
127 * (This condition of pc < code address seems to occur only if a GC
128 * happens during tracing. I guess the function-end code object
129 * sometimes gets moved to a lower address than the corresponding
132 * Hence this replacement looks at the function end flag first
133 * to see if it is a function-end breakpoint and does the function-end
134 * stuff anyway. If not, we do the normal stuff.
137 compute_offset(os_context_t * scp, lispobj code, boolean function_end)
143 * We're in a function end breakpoint. Compute the
144 * offset from the (known) breakpoint location and the
145 * beginning of the breakpoint guts. (See *-assem.S.)
147 * Then make the offset negative so the caller knows
148 * that the offset is not from the code object.
150 extern char function_end_breakpoint_trap;
151 extern char function_end_breakpoint_guts;
155 &function_end_breakpoint_trap -
156 &function_end_breakpoint_guts;
158 fprintf(stderr, "compute_offset\n");
159 fprintf(stderr, " function end offset = %d\n", offset);
161 return make_fixnum(-offset);
163 unsigned long code_start;
164 struct code *codeptr = (struct code *) PTR(code);
165 unsigned long pc = SC_PC(scp);
167 code_start = (unsigned long) codeptr
168 + HeaderValue(codeptr->header) * sizeof(lispobj);
170 fprintf(stderr, "compute_offset\n");
171 fprintf(stderr, " pc = %d\n", pc);
172 fprintf(stderr, " code_start = %d\n", code_start);
173 fprintf(stderr, " function_end = %d\n", function_end);
175 if (pc < code_start) {
178 int offset = pc - code_start;
181 fprintf(stderr, " offset = %d\n", offset);
182 fprintf(stderr, " codeptr->code_size = %d\n", codeptr->code_size);
183 fprintf(stderr, " function_end = %d\n", function_end);
185 if (offset >= codeptr->code_size) {
188 return make_fixnum(offset);
195 compute_offset(os_context_t * scp, lispobj code, boolean function_end)
200 unsigned long code_start;
201 struct code *codeptr = (struct code *) PTR(code);
204 unsigned long pc = SC_PC(scp) & ~3;
206 unsigned long pc = SC_PC(scp);
209 code_start = (unsigned long) codeptr
210 + HeaderValue(codeptr->header) * sizeof(lispobj);
214 int offset = pc - code_start;
216 if (offset >= codeptr->code_size) {
219 return make_fixnum(offset);
228 handle_breakpoint(int signal, int subcode, os_context_t * scp)
232 fake_foreign_function_call(scp);
234 code = find_code(scp);
237 fprintf(stderr, "handle_breakpoint\n");
238 fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0));
240 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
241 compute_offset(scp, code, 0), code, alloc_sap(scp));
243 undo_fake_foreign_function_call(scp);
247 handle_breakpoint(int signal, int subcode, os_context_t * scp)
249 lispobj code, scp_sap = alloc_sap(scp);
251 fake_foreign_function_call(scp);
253 code = find_code(scp);
256 * Don't disallow recursive breakpoint traps. Otherwise, we can't
257 * use debugger breakpoints anywhere in here.
260 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
261 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
262 compute_offset(scp, code, 0), code, scp_sap);
264 undo_fake_foreign_function_call(scp);
270 handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
273 struct code *codeptr;
277 fake_foreign_function_call(scp);
279 code = find_code(scp);
280 codeptr = (struct code *) PTR(code);
281 offset = compute_offset(scp, code, 1);
283 printf("handle_function_end:\n");
284 printf(" code = 0x%08x\n", code);
285 printf(" codeptr = %p\n", codeptr);
286 printf(" offset = %d\n", fixnum_value(offset));
292 * We were in the function end breakpoint. Which means we are
293 * in a bogus LRA, so compute where the code-component of this
294 * bogus lra object starts. Adjust code, and codeptr
295 * appropriately so the breakpoint handler can do the right
304 * Some magic here. pc points to the trap instruction. The
305 * offset gives us where the function_end_breakpoint_guts
306 * begins. But we need to back up some more to get to the
307 * code-component object. See MAKE-BOGUS-LRA in
310 code = pc - fixnum_value(offset);
311 code -= sizeof(struct code) + BOGUS_LRA_CONSTANTS * sizeof(lispobj);
313 code += type_OtherPointer;
314 codeptr = (struct code *) PTR(code);
316 printf(" pc = 0x%08x\n", pc);
317 printf(" code = 0x%08x\n", code);
318 printf(" codeptr = %p\n", codeptr);
323 lra = codeptr->constants[REAL_LRA_SLOT];
325 known_return_p = codeptr->constants[KNOWN_RETURN_P_SLOT] != NIL;
328 lispobj *args = current_control_stack_pointer;
331 * Because HANDLE_BREAKPOINT can GC, the LRA could move, and
332 * we need to know where it went so we can return to the
333 * correct place. We do this by saving the LRA on the Lisp
334 * stack. If GC moves the LRA, the stack entry will get
335 * updated appropriately too.
337 current_control_stack_pointer += 1;
340 funcall3(SymbolFunction(HANDLE_BREAKPOINT), offset, code, alloc_sap(scp));
343 * Breakpoint handling done. Get the (possibly changed) LRA
344 * value off the stack so we know where to return to.
347 current_control_stack_pointer -= 1;
351 * With the known-return convention, we definitely do NOT want
352 * to mangle the CODE register because it isn't pointing to
353 * the bogus LRA but to the actual routine.
355 if (!known_return_p) {
356 SC_REG(scp, reg_CODE) = lra;
361 undo_fake_foreign_function_call(scp);
362 return (void *) (lra - type_OtherPointer + sizeof(lispobj));
366 handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
368 lispobj code, scp_sap = alloc_sap(scp);
369 struct code *codeptr;
371 fake_foreign_function_call(scp);
373 code = find_code(scp);
374 codeptr = (struct code *) PTR(code);
377 * Don't disallow recursive breakpoint traps. Otherwise, we can't
378 * use debugger breakpoints anywhere in here.
381 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
382 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
383 compute_offset(scp, code, 1), code, scp_sap);
385 undo_fake_foreign_function_call(scp);
387 return compute_pc(codeptr->constants[REAL_LRA_SLOT],
388 fixnum_value(codeptr->constants[REAL_LRA_SLOT + 1]));