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

Contents of /src/lisp/breakpoint.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.21 - (hide annotations)
Thu Sep 4 22:31:47 2008 UTC (5 years, 7 months ago) by rtoy
Branch: MAIN
Changes since 1.20: +90 -1 lines
File MIME type: text/plain
A fix for the error that causes di::handle-breakpoint to complain
about an unknown breakpoint at offset 0 when handling a function-end
breakpoint.

See the comment for compute_offset for an explanation.

Note that this seems to fix that issue, but there is still the issue
where a segfault will happen during tracing.  It seems to happen if a
GC occurs after the function end breakpoint has happened
(compute_offset has already been called before GC happens), and trace
has printed out the return value.  Then a segfault happens.

Due to some issues, this fix only works when compiled with gcc.
Compiling with Sun c produces some segfaults somewhere such that we
can't build cmucl at all.  The bizarre part is that compute_offset is
never called during a build because there are no breakpoints enabled
during a normal build.
1 ram 1.6 /*
2    
3 rtoy 1.21 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/breakpoint.c,v 1.21 2008/09/04 22:31:47 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.21 #if defined(sparc) && defined(__GNUC__)
106     /*
107     * For some unknown reason, if you compile this code with Sun C, CMUCL
108     * is unable to build itself anymore. This is bizarre because this
109     * code is not called during a build since there are no breakpoints
110     * during a build.
111     *
112     * Hence, until this is figured out, we can't use this code with Sun
113     * C. This also means we some known issues with tracing will manifest
114     * itself.
115     *
116     * During a function-end-breakpoint, the pc is sometimes less than the
117     * code address, which bypasses the function end stuff. Then the
118     * offset is zero for a function-end-breakpoint, and we can't find the
119     * breakpoint data, causing an error during tracing. But we know this
120     * is a function-end breakpoint, because function_end is set to true.
121     *
122     * (This condition of pc < code address seems to occur only if a GC
123     * happens during tracing. I guess the function-end code object
124     * sometimes gets moved to a lower address than the corresponding
125     * code.)
126     *
127     * Hence this replacement looks at the function end flag first
128     * to see if it is a function-end breakpoint and does the function-end
129     * stuff anyway. If not, we do the normal stuff.
130     */
131     static int
132     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
133     {
134     if (code == NIL)
135     return 0;
136     if (function_end) {
137     /*
138     * We're in a function end breakpoint. Compute the
139     * offset from the (known) breakpoint location and the
140     * beginning of the breakpoint guts. (See *-assem.S.)
141     *
142     * Then make the offset negative so the caller knows
143     * that the offset is not from the code object.
144     */
145     extern char function_end_breakpoint_trap;
146     extern char function_end_breakpoint_guts;
147     int offset;
148    
149     offset =
150     &function_end_breakpoint_trap -
151     &function_end_breakpoint_guts;
152     #if 0
153     fprintf(stderr, "compute_offset\n");
154     fprintf(stderr, " function end offset = %d\n", offset);
155     #endif
156     return make_fixnum(-offset);
157     } else {
158     unsigned long code_start;
159     struct code *codeptr = (struct code *) PTR(code);
160     unsigned long pc = SC_PC(scp);
161    
162     code_start = (unsigned long) codeptr
163     + HeaderValue(codeptr->header) * sizeof(lispobj);
164     #if 0
165     fprintf(stderr, "compute_offset\n");
166     fprintf(stderr, " pc = %d\n", pc);
167     fprintf(stderr, " code_start = %d\n", code_start);
168     fprintf(stderr, " function_end = %d\n", function_end);
169     #endif
170     if (pc < code_start) {
171     return 0;
172     } else {
173     int offset = pc - code_start;
174    
175     #if 0
176     fprintf(stderr, " offset = %d\n", offset);
177     fprintf(stderr, " codeptr->code_size = %d\n", codeptr->code_size);
178     fprintf(stderr, " function_end = %d\n", function_end);
179     #endif
180     if (offset >= codeptr->code_size) {
181     return 0;
182     } else {
183     return make_fixnum(offset);
184     }
185     }
186     }
187     }
188     #else
189 rtoy 1.18 static int
190     compute_offset(os_context_t * scp, lispobj code, boolean function_end)
191 wlott 1.1 {
192     if (code == NIL)
193 wlott 1.2 return 0;
194 wlott 1.1 else {
195     unsigned long code_start;
196 rtoy 1.18 struct code *codeptr = (struct code *) PTR(code);
197    
198 wlott 1.3 #ifdef parisc
199     unsigned long pc = SC_PC(scp) & ~3;
200     #else
201     unsigned long pc = SC_PC(scp);
202     #endif
203 wlott 1.1
204 rtoy 1.18 code_start = (unsigned long) codeptr
205     + HeaderValue(codeptr->header) * sizeof(lispobj);
206 wlott 1.3 if (pc < code_start)
207 wlott 1.2 return 0;
208 wlott 1.1 else {
209 wlott 1.3 int offset = pc - code_start;
210 rtoy 1.18
211 rtoy 1.15 if (offset >= codeptr->code_size) {
212 rtoy 1.18 if (function_end) {
213 cshapiro 1.20 #if defined(sparc) || (defined(DARWIN) && defined(__ppc__))
214 rtoy 1.18 /*
215     * We're in a function end breakpoint. Compute the
216     * offset from the (known) breakpoint location and the
217     * beginning of the breakpoint guts. (See *-assem.S.)
218     *
219     * Then make the offset negative so the caller knows
220     * that the offset is not from the code object.
221     */
222     extern char function_end_breakpoint_trap;
223     extern char function_end_breakpoint_guts;
224    
225     offset =
226     &function_end_breakpoint_trap -
227     &function_end_breakpoint_guts;
228     return make_fixnum(-offset);
229 rtoy 1.15 #else
230 rtoy 1.18 return 0;
231     #endif
232     } else {
233     return 0;
234     }
235 rtoy 1.15 } else {
236 rtoy 1.18 return make_fixnum(offset);
237     }
238 wlott 1.1 }
239     }
240 wlott 1.2 }
241 rtoy 1.21 #endif
242 wlott 1.1
243 dtc 1.9 #ifndef i386
244 rtoy 1.18 void
245     handle_breakpoint(int signal, int subcode, os_context_t * scp)
246 dtc 1.9 {
247     lispobj code;
248    
249     fake_foreign_function_call(scp);
250    
251     code = find_code(scp);
252    
253 rtoy 1.21 #if 0
254     fprintf(stderr, "handle_breakpoint\n");
255     fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0));
256     #endif
257 dtc 1.9 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
258 rtoy 1.18 compute_offset(scp, code, 0), code, alloc_sap(scp));
259 dtc 1.9
260     undo_fake_foreign_function_call(scp);
261     }
262     #else
263 rtoy 1.18 void
264     handle_breakpoint(int signal, int subcode, os_context_t * scp)
265 wlott 1.2 {
266 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
267 wlott 1.2
268     fake_foreign_function_call(scp);
269    
270     code = find_code(scp);
271 dtc 1.7
272 dtc 1.11 /*
273     * Don't disallow recursive breakpoint traps. Otherwise, we can't
274     * use debugger breakpoints anywhere in here.
275     */
276    
277 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
278 wlott 1.1 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
279 rtoy 1.18 compute_offset(scp, code, 0), code, scp_sap);
280 wlott 1.1
281 wlott 1.2 undo_fake_foreign_function_call(scp);
282 wlott 1.1 }
283 dtc 1.9 #endif
284 wlott 1.1
285 dtc 1.8 #ifndef i386
286 rtoy 1.18 void *
287     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
288 wlott 1.1 {
289 dtc 1.9 lispobj code, lra;
290 wlott 1.2 struct code *codeptr;
291 rtoy 1.15 int offset;
292 rtoy 1.18
293 wlott 1.2 fake_foreign_function_call(scp);
294 wlott 1.1
295 wlott 1.2 code = find_code(scp);
296 rtoy 1.18 codeptr = (struct code *) PTR(code);
297 rtoy 1.15 offset = compute_offset(scp, code, 1);
298 rtoy 1.16 #if 0
299     printf("handle_function_end:\n");
300     printf(" code = 0x%08x\n", code);
301     printf(" codeptr = %p\n", codeptr);
302     printf(" offset = %d\n", fixnum_value(offset));
303     fflush(stdout);
304     #endif
305 wlott 1.2
306 rtoy 1.18 if (offset < 0) {
307     /*
308     * We were in the function end breakpoint. Which means we are
309     * in a bogus LRA, so compute where the code-component of this
310     * bogus lra object starts. Adjust code, and codeptr
311     * appropriately so the breakpoint handler can do the right
312     * thing.
313     */
314     unsigned int pc;
315    
316     pc = SC_PC(scp);
317    
318     offset = -offset;
319     /*
320     * Some magic here. pc points to the trap instruction. The
321     * offset gives us where the function_end_breakpoint_guts
322     * begins. But we need to back up some more to get to the
323     * code-component object. The magic 2 below is
324     */
325     code = pc - fixnum_value(offset);
326     code -= sizeof(struct code) + BOGUS_LRA_CONSTANTS * sizeof(lispobj);
327    
328     code += type_OtherPointer;
329     codeptr = (struct code *) PTR(code);
330 rtoy 1.16 #if 0
331     printf(" pc = 0x%08x\n", pc);
332     printf(" code = 0x%08x\n", code);
333     printf(" codeptr = %p\n", codeptr);
334     fflush(stdout);
335     #endif
336 rtoy 1.18 }
337    
338     funcall3(SymbolFunction(HANDLE_BREAKPOINT), offset, code, alloc_sap(scp));
339 wlott 1.2
340 rtoy 1.15 /*
341     * Breakpoint handling done, so get the real LRA where we're
342     * supposed to return to so we can return there.
343     */
344 wlott 1.1 lra = codeptr->constants[REAL_LRA_SLOT];
345 wlott 1.2 #ifdef reg_CODE
346 rtoy 1.15 /*
347     * With the known-return convention, we definitely do NOT want to
348     * mangle the CODE register because it isn't pointing to the bogus
349     * LRA but to the actual routine.
350     */
351 wlott 1.1 if (codeptr->constants[KNOWN_RETURN_P_SLOT] == NIL)
352 wlott 1.2 SC_REG(scp, reg_CODE) = lra;
353 wlott 1.1 #endif
354 dtc 1.8 undo_fake_foreign_function_call(scp);
355 rtoy 1.18 return (void *) (lra - type_OtherPointer + sizeof(lispobj));
356 dtc 1.8 }
357     #else
358 rtoy 1.18 void *
359     handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
360 dtc 1.8 {
361 rtoy 1.18 lispobj code, scp_sap = alloc_sap(scp);
362 dtc 1.8 struct code *codeptr;
363    
364     fake_foreign_function_call(scp);
365    
366     code = find_code(scp);
367 dtc 1.11 codeptr = (struct code *) PTR(code);
368    
369     /*
370     * Don't disallow recursive breakpoint traps. Otherwise, we can't
371     * use debugger breakpoints anywhere in here.
372     */
373 dtc 1.8
374 rtoy 1.18 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
375 dtc 1.8 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
376 rtoy 1.18 compute_offset(scp, code, 1), code, scp_sap);
377 wlott 1.2
378     undo_fake_foreign_function_call(scp);
379    
380 dtc 1.8 return compute_pc(codeptr->constants[REAL_LRA_SLOT],
381 dtc 1.11 fixnum_value(codeptr->constants[REAL_LRA_SLOT + 1]));
382 dtc 1.8 }
383 dtc 1.7 #endif

  ViewVC Help
Powered by ViewVC 1.1.5