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

Contents of /src/lisp/breakpoint.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (hide annotations)
Fri Sep 5 22:03:12 2008 UTC (5 years, 7 months ago) by rtoy
Branch: MAIN
Changes since 1.23: +16 -3 lines
File MIME type: text/plain
compiler/ppc/parms.lisp:
compiler/sparc/parms.lisp:
o Add lisp::*gc-inhibit* to list of static symbols.  (No cross-compile
  needed because we used one of the spare static symbols.  Full cycle
  of builds needed to progate the changes.)

lisp/breakpoint.c:
o Disable GC when calling HANDLE-BREAKPOINT.  This is a temporary
  workaround to the issue where a GC occurring during
  HANDLE-BREAKPOINT can cause a segfault during tracing.  GC moves the
  code object and/or bogus lra such that we don't know where we should
  return to.
1 ram 1.6 /*
2    
3 rtoy 1.24 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/breakpoint.c,v 1.24 2008/09/05 22:03:12 rtoy Exp $
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     * See MAKE-BOGUS-LRA in code/debug-int.lisp for these values. (We
28     * really should generate these from the Lisp code.)
29     */
30 wlott 1.1 #define REAL_LRA_SLOT 0
31 dtc 1.8 #ifndef i386
32 wlott 1.1 #define KNOWN_RETURN_P_SLOT 1
33     #define BOGUS_LRA_CONSTANTS 2
34 dtc 1.8 #else
35     #define KNOWN_RETURN_P_SLOT 2
36     #define BOGUS_LRA_CONSTANTS 3
37     #endif
38 wlott 1.1
39 rtoy 1.18 static void *
40     compute_pc(lispobj code_obj, int pc_offset)
41 wlott 1.1 {
42     struct code *code;
43    
44 rtoy 1.18 code = (struct code *) PTR(code_obj);
45     return (void *) ((char *) code + HeaderValue(code->header) * sizeof(lispobj)
46     + pc_offset);
47 wlott 1.1 }
48    
49 rtoy 1.18 unsigned long
50     breakpoint_install(lispobj code_obj, int pc_offset)
51 wlott 1.1 {
52     return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
53     }
54    
55 rtoy 1.18 void
56     breakpoint_remove(lispobj code_obj, int pc_offset, unsigned long orig_inst)
57 wlott 1.1 {
58     arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
59     }
60    
61 rtoy 1.18 void
62     breakpoint_do_displaced_inst(os_context_t * scp, unsigned long orig_inst)
63 wlott 1.1 {
64 dtc 1.7 #if !defined(hpux) && !defined(irix) && !defined(i386)
65 wlott 1.2 undo_fake_foreign_function_call(scp);
66 wlott 1.3 #endif
67 wlott 1.1 arch_do_displaced_inst(scp, orig_inst);
68     }
69    
70 rtoy 1.17 #if !defined(i386)
71 rtoy 1.18 static lispobj
72     find_code(os_context_t * scp)
73 wlott 1.1 {
74 wlott 1.2 #ifdef reg_CODE
75     lispobj code = SC_REG(scp, reg_CODE), header;
76 wlott 1.1
77     if (LowtagOf(code) != type_OtherPointer)
78     return NIL;
79    
80 rtoy 1.18 header = *(lispobj *) (code - type_OtherPointer);
81 wlott 1.1
82     if (TypeOf(header) == type_CodeHeader)
83     return code;
84     else
85 rtoy 1.18 return code - HeaderValue(header) * sizeof(lispobj);
86 wlott 1.1 #else
87     return NIL;
88     #endif
89     }
90 dtc 1.7 #endif
91    
92 rtoy 1.17 #if defined(i386)
93 rtoy 1.18 static lispobj
94     find_code(os_context_t * scp)
95 dtc 1.7 {
96 cshapiro 1.20 lispobj *codeptr = component_ptr_from_pc((lispobj *) SC_PC(scp));
97 dtc 1.7
98 rtoy 1.18 if (codeptr == NULL)
99     return NIL;
100     else
101     return (lispobj) codeptr | type_OtherPointer;
102 dtc 1.7 }
103     #endif
104 wlott 1.1
105 rtoy 1.23 #if (defined(DARWIN) && defined(__ppc__)) || (defined(sparc))
106 rtoy 1.21 /*
107     * During a function-end-breakpoint, the pc is sometimes less than the
108     * code address, which bypasses the function end stuff. Then the
109     * offset is zero for a function-end-breakpoint, and we can't find the
110     * breakpoint data, causing an error during tracing. But we know this
111     * is a function-end breakpoint, because function_end is set to true.
112     *
113     * (This condition of pc < code address seems to occur only if a GC
114     * happens during tracing. I guess the function-end code object
115     * sometimes gets moved to a lower address than the corresponding
116     * code.)
117     *
118     * Hence this replacement looks at the function end flag first
119     * to see if it is a function-end breakpoint and does the function-end
120     * stuff anyway. If not, we do the normal stuff.
121     */
122     static int
123     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
124     {
125     if (code == NIL)
126     return 0;
127     if (function_end) {
128     /*
129     * We're in a function end breakpoint. Compute the
130     * offset from the (known) breakpoint location and the
131     * beginning of the breakpoint guts. (See *-assem.S.)
132     *
133     * Then make the offset negative so the caller knows
134     * that the offset is not from the code object.
135     */
136     extern char function_end_breakpoint_trap;
137     extern char function_end_breakpoint_guts;
138     int offset;
139    
140     offset =
141     &function_end_breakpoint_trap -
142     &function_end_breakpoint_guts;
143     #if 0
144     fprintf(stderr, "compute_offset\n");
145     fprintf(stderr, " function end offset = %d\n", offset);
146     #endif
147     return make_fixnum(-offset);
148     } else {
149     unsigned long code_start;
150     struct code *codeptr = (struct code *) PTR(code);
151     unsigned long pc = SC_PC(scp);
152    
153     code_start = (unsigned long) codeptr
154     + HeaderValue(codeptr->header) * sizeof(lispobj);
155     #if 0
156     fprintf(stderr, "compute_offset\n");
157     fprintf(stderr, " pc = %d\n", pc);
158     fprintf(stderr, " code_start = %d\n", code_start);
159     fprintf(stderr, " function_end = %d\n", function_end);
160     #endif
161     if (pc < code_start) {
162     return 0;
163     } else {
164     int offset = pc - code_start;
165    
166     #if 0
167     fprintf(stderr, " offset = %d\n", offset);
168     fprintf(stderr, " codeptr->code_size = %d\n", codeptr->code_size);
169     fprintf(stderr, " function_end = %d\n", function_end);
170     #endif
171     if (offset >= codeptr->code_size) {
172     return 0;
173     } else {
174     return make_fixnum(offset);
175     }
176     }
177     }
178     }
179     #else
180 rtoy 1.18 static int
181     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
182 wlott 1.1 {
183     if (code == NIL)
184 wlott 1.2 return 0;
185 wlott 1.1 else {
186     unsigned long code_start;
187 rtoy 1.18 struct code *codeptr = (struct code *) PTR(code);
188    
189 wlott 1.3 #ifdef parisc
190     unsigned long pc = SC_PC(scp) & ~3;
191     #else
192     unsigned long pc = SC_PC(scp);
193     #endif
194 wlott 1.1
195 rtoy 1.18 code_start = (unsigned long) codeptr
196     + HeaderValue(codeptr->header) * sizeof(lispobj);
197 wlott 1.3 if (pc < code_start)
198 wlott 1.2 return 0;
199 wlott 1.1 else {
200 wlott 1.3 int offset = pc - code_start;
201 rtoy 1.18
202 rtoy 1.15 if (offset >= codeptr->code_size) {
203 rtoy 1.18 if (function_end) {
204 cshapiro 1.20 #if defined(sparc) || (defined(DARWIN) && defined(__ppc__))
205 rtoy 1.18 /*
206     * We're in a function end breakpoint. Compute the
207     * offset from the (known) breakpoint location and the
208     * beginning of the breakpoint guts. (See *-assem.S.)
209     *
210     * Then make the offset negative so the caller knows
211     * that the offset is not from the code object.
212     */
213     extern char function_end_breakpoint_trap;
214     extern char function_end_breakpoint_guts;
215    
216     offset =
217     &function_end_breakpoint_trap -
218     &function_end_breakpoint_guts;
219     return make_fixnum(-offset);
220 rtoy 1.15 #else
221 rtoy 1.18 return 0;
222     #endif
223     } else {
224     return 0;
225     }
226 rtoy 1.15 } else {
227 rtoy 1.18 return make_fixnum(offset);
228     }
229 wlott 1.1 }
230     }
231 wlott 1.2 }
232 rtoy 1.21 #endif
233 wlott 1.1
234 dtc 1.9 #ifndef i386
235 rtoy 1.18 void
236     handle_breakpoint(int signal, int subcode, os_context_t * scp)
237 dtc 1.9 {
238     lispobj code;
239    
240     fake_foreign_function_call(scp);
241    
242     code = find_code(scp);
243    
244 rtoy 1.21 #if 0
245     fprintf(stderr, "handle_breakpoint\n");
246     fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0));
247     #endif
248 dtc 1.9 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
249 rtoy 1.18 compute_offset(scp, code, 0), code, alloc_sap(scp));
250 dtc 1.9
251     undo_fake_foreign_function_call(scp);
252     }
253     #else
254 rtoy 1.18 void
255     handle_breakpoint(int signal, int subcode, os_context_t * scp)
256 wlott 1.2 {
257 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
258 wlott 1.2
259     fake_foreign_function_call(scp);
260    
261     code = find_code(scp);
262 dtc 1.7
263 dtc 1.11 /*
264     * Don't disallow recursive breakpoint traps. Otherwise, we can't
265     * use debugger breakpoints anywhere in here.
266     */
267    
268 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
269 wlott 1.1 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
270 rtoy 1.18 compute_offset(scp, code, 0), code, scp_sap);
271 wlott 1.1
272 wlott 1.2 undo_fake_foreign_function_call(scp);
273 wlott 1.1 }
274 dtc 1.9 #endif
275 wlott 1.1
276 dtc 1.8 #ifndef i386
277 rtoy 1.18 void *
278     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
279 wlott 1.1 {
280 dtc 1.9 lispobj code, lra;
281 wlott 1.2 struct code *codeptr;
282 rtoy 1.15 int offset;
283 rtoy 1.18
284 wlott 1.2 fake_foreign_function_call(scp);
285 wlott 1.1
286 wlott 1.2 code = find_code(scp);
287 rtoy 1.18 codeptr = (struct code *) PTR(code);
288 rtoy 1.15 offset = compute_offset(scp, code, 1);
289 rtoy 1.16 #if 0
290     printf("handle_function_end:\n");
291     printf(" code = 0x%08x\n", code);
292     printf(" codeptr = %p\n", codeptr);
293     printf(" offset = %d\n", fixnum_value(offset));
294     fflush(stdout);
295     #endif
296 wlott 1.2
297 rtoy 1.18 if (offset < 0) {
298     /*
299     * We were in the function end breakpoint. Which means we are
300     * in a bogus LRA, so compute where the code-component of this
301     * bogus lra object starts. Adjust code, and codeptr
302     * appropriately so the breakpoint handler can do the right
303     * thing.
304     */
305     unsigned int pc;
306    
307     pc = SC_PC(scp);
308    
309     offset = -offset;
310     /*
311     * Some magic here. pc points to the trap instruction. The
312     * offset gives us where the function_end_breakpoint_guts
313     * begins. But we need to back up some more to get to the
314     * code-component object. The magic 2 below is
315     */
316     code = pc - fixnum_value(offset);
317     code -= sizeof(struct code) + BOGUS_LRA_CONSTANTS * sizeof(lispobj);
318    
319     code += type_OtherPointer;
320     codeptr = (struct code *) PTR(code);
321 rtoy 1.16 #if 0
322     printf(" pc = 0x%08x\n", pc);
323     printf(" code = 0x%08x\n", code);
324     printf(" codeptr = %p\n", codeptr);
325     fflush(stdout);
326     #endif
327 rtoy 1.18 }
328    
329 rtoy 1.15 /*
330     * Breakpoint handling done, so get the real LRA where we're
331     * supposed to return to so we can return there.
332     */
333 wlott 1.1 lra = codeptr->constants[REAL_LRA_SLOT];
334 wlott 1.2 #ifdef reg_CODE
335 rtoy 1.15 /*
336     * With the known-return convention, we definitely do NOT want to
337     * mangle the CODE register because it isn't pointing to the bogus
338     * LRA but to the actual routine.
339     */
340 wlott 1.1 if (codeptr->constants[KNOWN_RETURN_P_SLOT] == NIL)
341 wlott 1.2 SC_REG(scp, reg_CODE) = lra;
342 wlott 1.1 #endif
343 rtoy 1.24
344     {
345     lispobj saved_gc_inhibit;
346    
347     #ifdef GC_INHIBIT
348     saved_gc_inhibit = SymbolValue(GC_INHIBIT);
349     SetSymbolValue(GC_INHIBIT, T);
350     #endif
351     funcall3(SymbolFunction(HANDLE_BREAKPOINT), offset, code, alloc_sap(scp));
352    
353     #ifdef GC_INHIBIT
354     SetSymbolValue(GC_INHIBIT, saved_gc_inhibit);
355     #endif
356     }
357    
358 dtc 1.8 undo_fake_foreign_function_call(scp);
359 rtoy 1.18 return (void *) (lra - type_OtherPointer + sizeof(lispobj));
360 dtc 1.8 }
361     #else
362 rtoy 1.18 void *
363     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
364 dtc 1.8 {
365 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
366 dtc 1.8 struct code *codeptr;
367    
368     fake_foreign_function_call(scp);
369    
370     code = find_code(scp);
371 dtc 1.11 codeptr = (struct code *) PTR(code);
372    
373     /*
374     * Don't disallow recursive breakpoint traps. Otherwise, we can't
375     * use debugger breakpoints anywhere in here.
376     */
377 dtc 1.8
378 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
379 dtc 1.8 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
380 rtoy 1.18 compute_offset(scp, code, 1), code, scp_sap);
381 wlott 1.2
382     undo_fake_foreign_function_call(scp);
383    
384 dtc 1.8 return compute_pc(codeptr->constants[REAL_LRA_SLOT],
385 dtc 1.11 fixnum_value(codeptr->constants[REAL_LRA_SLOT + 1]));
386 dtc 1.8 }
387 dtc 1.7 #endif

  ViewVC Help
Powered by ViewVC 1.1.5