/[cmucl]/src/lisp/breakpoint.c
ViewVC logotype

Contents of /src/lisp/breakpoint.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.26 - (hide annotations)
Fri Sep 12 21:09:07 2008 UTC (5 years, 7 months ago) by rtoy
Branch: MAIN
CVS Tags: sparc-tramp-assem-base, post-merge-intl-branch, merged-unicode-utf16-extfmt-2009-06-11, sse2-packed-2008-11-12, intl-branch-working-2010-02-19-1000, unicode-string-buffer-impl-base, sse2-base, release-20b-pre1, release-20b-pre2, unicode-string-buffer-base, sse2-packed-base, sparc-tramp-assem-2010-07-19, amd64-dd-start, release-19f-pre1, snapshot-2008-12, snapshot-2008-11, intl-2-branch-base, GIT-CONVERSION, cross-sol-x86-merged, label-2009-03-16, release-19f-base, merge-sse2-packed, merge-with-19f, intl-branch-working-2010-02-11-1000, RELEASE_20b, RELEASE_19f, release-20a-base, cross-sol-x86-base, snapshot-2008-10, snapshot-2010-12, snapshot-2010-11, snapshot-2011-09, snapshot-2011-06, snapshot-2011-07, snapshot-2011-04, snapshot-2011-02, snapshot-2011-03, snapshot-2011-01, pre-merge-intl-branch, snapshot-2010-05, snapshot-2010-04, snapshot-2010-07, snapshot-2010-06, snapshot-2010-01, snapshot-2010-03, snapshot-2010-02, snapshot-2010-08, label-2009-03-25, cross-sol-x86-2010-12-20, sse2-checkpoint-2008-10-01, intl-branch-2010-03-18-1300, sse2-merge-with-2008-11, sse2-merge-with-2008-10, RELEASE_20a, release-20a-pre1, snapshot-2009-11, snapshot-2009-12, portable-clx-import-2009-06-16, cross-sparc-branch-base, intl-branch-base, portable-clx-base, snapshot-2009-08, snapshot-2009-02, snapshot-2009-01, snapshot-2009-07, snapshot-2009-05, snapshot-2009-04, HEAD
Branch point for: RELEASE-19F-BRANCH, portable-clx-branch, cross-sparc-branch, RELEASE-20B-BRANCH, unicode-string-buffer-branch, sparc-tramp-assem-branch, sse2-packed-branch, RELEASE-20A-BRANCH, amd64-dd-branch, unicode-string-buffer-impl-branch, intl-branch, cross-sol-x86-branch, sse2-branch, intl-2-branch
Changes since 1.25: +16 -6 lines
File MIME type: text/plain
new-genesis.lisp:
o Generate values for REAL_LRA_SLOT, KNOWN_RETURN_P_SLOT, and
  BOGUS_LRA_CONSTANTS from the actual Lisp values.

breakpoint.c:
o Use the generated values above, if available.  We leave suitable
  defaults for now, but they should probably be removed.
1 ram 1.6 /*
2    
3 rtoy 1.26 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/breakpoint.c,v 1.26 2008/09/12 21:09:07 rtoy Rel $
4 ram 1.6
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.
7    
8     */
9    
10 wlott 1.1 #include <stdio.h>
11     #include <signal.h>
12    
13     #include "lisp.h"
14     #include "os.h"
15     #include "internals.h"
16 ram 1.5 #include "interrupt.h"
17 wlott 1.1 #include "arch.h"
18     #include "lispregs.h"
19     #include "globals.h"
20     #include "alloc.h"
21     #include "breakpoint.h"
22 dtc 1.12 #if defined GENCGC
23     #include "gencgc.h"
24     #endif
25 wlott 1.1
26 rtoy 1.15 /*
27 rtoy 1.25 * See MAKE-BOGUS-LRA in code/debug-int.lisp for these values.
28     *
29 rtoy 1.26 * Ideally, internals.h should have the correct values. We leave
30     * these defaults here for now.
31 rtoy 1.15 */
32 rtoy 1.26 #ifndef REAL_LRA_SLOT
33 wlott 1.1 #define REAL_LRA_SLOT 0
34 rtoy 1.26 #endif
35    
36     #ifndef KNOWN_RETURN_P_SLOT
37 dtc 1.8 #ifndef i386
38 wlott 1.1 #define KNOWN_RETURN_P_SLOT 1
39 rtoy 1.26 #else
40     #define KNOWN_RETURN_P_SLOT 2
41     #endif
42     #endif
43    
44     #ifndef BOGUS_LRA_CONSTANTS
45     #ifndef i386
46 wlott 1.1 #define BOGUS_LRA_CONSTANTS 2
47 dtc 1.8 #else
48     #define BOGUS_LRA_CONSTANTS 3
49     #endif
50 rtoy 1.26 #endif
51    
52 wlott 1.1
53 rtoy 1.18 static void *
54     compute_pc(lispobj code_obj, int pc_offset)
55 wlott 1.1 {
56     struct code *code;
57    
58 rtoy 1.18 code = (struct code *) PTR(code_obj);
59     return (void *) ((char *) code + HeaderValue(code->header) * sizeof(lispobj)
60     + pc_offset);
61 wlott 1.1 }
62    
63 rtoy 1.18 unsigned long
64     breakpoint_install(lispobj code_obj, int pc_offset)
65 wlott 1.1 {
66     return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
67     }
68    
69 rtoy 1.18 void
70     breakpoint_remove(lispobj code_obj, int pc_offset, unsigned long orig_inst)
71 wlott 1.1 {
72     arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
73     }
74    
75 rtoy 1.18 void
76     breakpoint_do_displaced_inst(os_context_t * scp, unsigned long orig_inst)
77 wlott 1.1 {
78 dtc 1.7 #if !defined(hpux) && !defined(irix) && !defined(i386)
79 wlott 1.2 undo_fake_foreign_function_call(scp);
80 wlott 1.3 #endif
81 wlott 1.1 arch_do_displaced_inst(scp, orig_inst);
82     }
83    
84 rtoy 1.17 #if !defined(i386)
85 rtoy 1.18 static lispobj
86     find_code(os_context_t * scp)
87 wlott 1.1 {
88 wlott 1.2 #ifdef reg_CODE
89     lispobj code = SC_REG(scp, reg_CODE), header;
90 wlott 1.1
91     if (LowtagOf(code) != type_OtherPointer)
92     return NIL;
93    
94 rtoy 1.18 header = *(lispobj *) (code - type_OtherPointer);
95 wlott 1.1
96     if (TypeOf(header) == type_CodeHeader)
97     return code;
98     else
99 rtoy 1.18 return code - HeaderValue(header) * sizeof(lispobj);
100 wlott 1.1 #else
101     return NIL;
102     #endif
103     }
104 dtc 1.7 #endif
105    
106 rtoy 1.17 #if defined(i386)
107 rtoy 1.18 static lispobj
108     find_code(os_context_t * scp)
109 dtc 1.7 {
110 cshapiro 1.20 lispobj *codeptr = component_ptr_from_pc((lispobj *) SC_PC(scp));
111 dtc 1.7
112 rtoy 1.18 if (codeptr == NULL)
113     return NIL;
114     else
115     return (lispobj) codeptr | type_OtherPointer;
116 dtc 1.7 }
117     #endif
118 wlott 1.1
119 rtoy 1.23 #if (defined(DARWIN) && defined(__ppc__)) || (defined(sparc))
120 rtoy 1.21 /*
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.
126     *
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
130     * code.)
131     *
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.
135     */
136     static int
137     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
138     {
139     if (code == NIL)
140     return 0;
141     if (function_end) {
142     /*
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.)
146     *
147     * Then make the offset negative so the caller knows
148     * that the offset is not from the code object.
149     */
150     extern char function_end_breakpoint_trap;
151     extern char function_end_breakpoint_guts;
152     int offset;
153    
154     offset =
155     &function_end_breakpoint_trap -
156     &function_end_breakpoint_guts;
157     #if 0
158     fprintf(stderr, "compute_offset\n");
159     fprintf(stderr, " function end offset = %d\n", offset);
160     #endif
161     return make_fixnum(-offset);
162     } else {
163     unsigned long code_start;
164     struct code *codeptr = (struct code *) PTR(code);
165     unsigned long pc = SC_PC(scp);
166    
167     code_start = (unsigned long) codeptr
168     + HeaderValue(codeptr->header) * sizeof(lispobj);
169     #if 0
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);
174     #endif
175     if (pc < code_start) {
176     return 0;
177     } else {
178     int offset = pc - code_start;
179    
180     #if 0
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);
184     #endif
185     if (offset >= codeptr->code_size) {
186     return 0;
187     } else {
188     return make_fixnum(offset);
189     }
190     }
191     }
192     }
193     #else
194 rtoy 1.18 static int
195     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
196 wlott 1.1 {
197     if (code == NIL)
198 wlott 1.2 return 0;
199 wlott 1.1 else {
200     unsigned long code_start;
201 rtoy 1.18 struct code *codeptr = (struct code *) PTR(code);
202    
203 wlott 1.3 #ifdef parisc
204     unsigned long pc = SC_PC(scp) & ~3;
205     #else
206     unsigned long pc = SC_PC(scp);
207     #endif
208 wlott 1.1
209 rtoy 1.18 code_start = (unsigned long) codeptr
210     + HeaderValue(codeptr->header) * sizeof(lispobj);
211 wlott 1.3 if (pc < code_start)
212 wlott 1.2 return 0;
213 wlott 1.1 else {
214 wlott 1.3 int offset = pc - code_start;
215 rtoy 1.18
216 rtoy 1.15 if (offset >= codeptr->code_size) {
217 rtoy 1.25 return 0;
218 rtoy 1.15 } else {
219 rtoy 1.18 return make_fixnum(offset);
220     }
221 wlott 1.1 }
222     }
223 wlott 1.2 }
224 rtoy 1.21 #endif
225 wlott 1.1
226 dtc 1.9 #ifndef i386
227 rtoy 1.18 void
228     handle_breakpoint(int signal, int subcode, os_context_t * scp)
229 dtc 1.9 {
230     lispobj code;
231    
232     fake_foreign_function_call(scp);
233    
234     code = find_code(scp);
235    
236 rtoy 1.21 #if 0
237     fprintf(stderr, "handle_breakpoint\n");
238     fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0));
239     #endif
240 dtc 1.9 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
241 rtoy 1.18 compute_offset(scp, code, 0), code, alloc_sap(scp));
242 dtc 1.9
243     undo_fake_foreign_function_call(scp);
244     }
245     #else
246 rtoy 1.18 void
247     handle_breakpoint(int signal, int subcode, os_context_t * scp)
248 wlott 1.2 {
249 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
250 wlott 1.2
251     fake_foreign_function_call(scp);
252    
253     code = find_code(scp);
254 dtc 1.7
255 dtc 1.11 /*
256     * Don't disallow recursive breakpoint traps. Otherwise, we can't
257     * use debugger breakpoints anywhere in here.
258     */
259    
260 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
261 wlott 1.1 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
262 rtoy 1.18 compute_offset(scp, code, 0), code, scp_sap);
263 wlott 1.1
264 wlott 1.2 undo_fake_foreign_function_call(scp);
265 wlott 1.1 }
266 dtc 1.9 #endif
267 wlott 1.1
268 dtc 1.8 #ifndef i386
269 rtoy 1.18 void *
270     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
271 wlott 1.1 {
272 dtc 1.9 lispobj code, lra;
273 wlott 1.2 struct code *codeptr;
274 rtoy 1.15 int offset;
275 rtoy 1.25 int known_return_p;
276    
277 wlott 1.2 fake_foreign_function_call(scp);
278 wlott 1.1
279 wlott 1.2 code = find_code(scp);
280 rtoy 1.18 codeptr = (struct code *) PTR(code);
281 rtoy 1.15 offset = compute_offset(scp, code, 1);
282 rtoy 1.16 #if 0
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));
287     fflush(stdout);
288     #endif
289 wlott 1.2
290 rtoy 1.18 if (offset < 0) {
291     /*
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
296     * thing.
297     */
298     unsigned int pc;
299    
300     pc = SC_PC(scp);
301    
302     offset = -offset;
303     /*
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 rtoy 1.25 * code-component object. See MAKE-BOGUS-LRA in
308     * debug-int.lisp
309 rtoy 1.18 */
310     code = pc - fixnum_value(offset);
311     code -= sizeof(struct code) + BOGUS_LRA_CONSTANTS * sizeof(lispobj);
312    
313     code += type_OtherPointer;
314     codeptr = (struct code *) PTR(code);
315 rtoy 1.16 #if 0
316     printf(" pc = 0x%08x\n", pc);
317     printf(" code = 0x%08x\n", code);
318     printf(" codeptr = %p\n", codeptr);
319     fflush(stdout);
320     #endif
321 rtoy 1.18 }
322    
323 wlott 1.1 lra = codeptr->constants[REAL_LRA_SLOT];
324 rtoy 1.25
325     known_return_p = codeptr->constants[KNOWN_RETURN_P_SLOT] != NIL;
326 rtoy 1.24
327     {
328 rtoy 1.25 lispobj *args = current_control_stack_pointer;
329    
330     /*
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.
336     */
337     current_control_stack_pointer += 1;
338     args[0] = lra;
339 rtoy 1.24
340     funcall3(SymbolFunction(HANDLE_BREAKPOINT), offset, code, alloc_sap(scp));
341    
342 rtoy 1.25 /*
343     * Breakpoint handling done. Get the (possibly changed) LRA
344     * value off the stack so we know where to return to.
345     */
346     lra = args[0];
347     current_control_stack_pointer -= 1;
348    
349     #ifdef reg_CODE
350     /*
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.
354     */
355     if (!known_return_p) {
356     SC_REG(scp, reg_CODE) = lra;
357     }
358 rtoy 1.24 #endif
359     }
360    
361 dtc 1.8 undo_fake_foreign_function_call(scp);
362 rtoy 1.18 return (void *) (lra - type_OtherPointer + sizeof(lispobj));
363 dtc 1.8 }
364     #else
365 rtoy 1.18 void *
366     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
367 dtc 1.8 {
368 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
369 dtc 1.8 struct code *codeptr;
370    
371     fake_foreign_function_call(scp);
372    
373     code = find_code(scp);
374 dtc 1.11 codeptr = (struct code *) PTR(code);
375    
376     /*
377     * Don't disallow recursive breakpoint traps. Otherwise, we can't
378     * use debugger breakpoints anywhere in here.
379     */
380 dtc 1.8
381 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
382 dtc 1.8 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
383 rtoy 1.18 compute_offset(scp, code, 1), code, scp_sap);
384 wlott 1.2
385     undo_fake_foreign_function_call(scp);
386    
387 dtc 1.8 return compute_pc(codeptr->constants[REAL_LRA_SLOT],
388 dtc 1.11 fixnum_value(codeptr->constants[REAL_LRA_SLOT + 1]));
389 dtc 1.8 }
390 dtc 1.7 #endif

  ViewVC Help
Powered by ViewVC 1.1.5