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

Contents of /src/lisp/breakpoint.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations)
Fri Sep 5 13:12:03 2008 UTC (5 years, 7 months ago) by rtoy
Branch: MAIN
Changes since 1.22: +2 -11 lines
File MIME type: text/plain
New compute_offset is working on Solaris with Sun C now.  Enable it.
1 /*
2
3 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/breakpoint.c,v 1.23 2008/09/05 13:12:03 rtoy Exp $
4
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 #include <stdio.h>
11 #include <signal.h>
12
13 #include "lisp.h"
14 #include "os.h"
15 #include "internals.h"
16 #include "interrupt.h"
17 #include "arch.h"
18 #include "lispregs.h"
19 #include "globals.h"
20 #include "alloc.h"
21 #include "breakpoint.h"
22 #if defined GENCGC
23 #include "gencgc.h"
24 #endif
25
26 /*
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 #define REAL_LRA_SLOT 0
31 #ifndef i386
32 #define KNOWN_RETURN_P_SLOT 1
33 #define BOGUS_LRA_CONSTANTS 2
34 #else
35 #define KNOWN_RETURN_P_SLOT 2
36 #define BOGUS_LRA_CONSTANTS 3
37 #endif
38
39 static void *
40 compute_pc(lispobj code_obj, int pc_offset)
41 {
42 struct code *code;
43
44 code = (struct code *) PTR(code_obj);
45 return (void *) ((char *) code + HeaderValue(code->header) * sizeof(lispobj)
46 + pc_offset);
47 }
48
49 unsigned long
50 breakpoint_install(lispobj code_obj, int pc_offset)
51 {
52 return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
53 }
54
55 void
56 breakpoint_remove(lispobj code_obj, int pc_offset, unsigned long orig_inst)
57 {
58 arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
59 }
60
61 void
62 breakpoint_do_displaced_inst(os_context_t * scp, unsigned long orig_inst)
63 {
64 #if !defined(hpux) && !defined(irix) && !defined(i386)
65 undo_fake_foreign_function_call(scp);
66 #endif
67 arch_do_displaced_inst(scp, orig_inst);
68 }
69
70 #if !defined(i386)
71 static lispobj
72 find_code(os_context_t * scp)
73 {
74 #ifdef reg_CODE
75 lispobj code = SC_REG(scp, reg_CODE), header;
76
77 if (LowtagOf(code) != type_OtherPointer)
78 return NIL;
79
80 header = *(lispobj *) (code - type_OtherPointer);
81
82 if (TypeOf(header) == type_CodeHeader)
83 return code;
84 else
85 return code - HeaderValue(header) * sizeof(lispobj);
86 #else
87 return NIL;
88 #endif
89 }
90 #endif
91
92 #if defined(i386)
93 static lispobj
94 find_code(os_context_t * scp)
95 {
96 lispobj *codeptr = component_ptr_from_pc((lispobj *) SC_PC(scp));
97
98 if (codeptr == NULL)
99 return NIL;
100 else
101 return (lispobj) codeptr | type_OtherPointer;
102 }
103 #endif
104
105 #if (defined(DARWIN) && defined(__ppc__)) || (defined(sparc))
106 /*
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 static int
181 compute_offset(os_context_t * scp, lispobj code, boolean function_end)
182 {
183 if (code == NIL)
184 return 0;
185 else {
186 unsigned long code_start;
187 struct code *codeptr = (struct code *) PTR(code);
188
189 #ifdef parisc
190 unsigned long pc = SC_PC(scp) & ~3;
191 #else
192 unsigned long pc = SC_PC(scp);
193 #endif
194
195 code_start = (unsigned long) codeptr
196 + HeaderValue(codeptr->header) * sizeof(lispobj);
197 if (pc < code_start)
198 return 0;
199 else {
200 int offset = pc - code_start;
201
202 if (offset >= codeptr->code_size) {
203 if (function_end) {
204 #if defined(sparc) || (defined(DARWIN) && defined(__ppc__))
205 /*
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 #else
221 return 0;
222 #endif
223 } else {
224 return 0;
225 }
226 } else {
227 return make_fixnum(offset);
228 }
229 }
230 }
231 }
232 #endif
233
234 #ifndef i386
235 void
236 handle_breakpoint(int signal, int subcode, os_context_t * scp)
237 {
238 lispobj code;
239
240 fake_foreign_function_call(scp);
241
242 code = find_code(scp);
243
244 #if 0
245 fprintf(stderr, "handle_breakpoint\n");
246 fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0));
247 #endif
248 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
249 compute_offset(scp, code, 0), code, alloc_sap(scp));
250
251 undo_fake_foreign_function_call(scp);
252 }
253 #else
254 void
255 handle_breakpoint(int signal, int subcode, os_context_t * scp)
256 {
257 lispobj code, scp_sap = alloc_sap(scp);
258
259 fake_foreign_function_call(scp);
260
261 code = find_code(scp);
262
263 /*
264 * Don't disallow recursive breakpoint traps. Otherwise, we can't
265 * use debugger breakpoints anywhere in here.
266 */
267
268 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
269 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
270 compute_offset(scp, code, 0), code, scp_sap);
271
272 undo_fake_foreign_function_call(scp);
273 }
274 #endif
275
276 #ifndef i386
277 void *
278 handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
279 {
280 lispobj code, lra;
281 struct code *codeptr;
282 int offset;
283
284 fake_foreign_function_call(scp);
285
286 code = find_code(scp);
287 codeptr = (struct code *) PTR(code);
288 offset = compute_offset(scp, code, 1);
289 #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
297 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 #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 }
328
329 funcall3(SymbolFunction(HANDLE_BREAKPOINT), offset, code, alloc_sap(scp));
330
331 /*
332 * Breakpoint handling done, so get the real LRA where we're
333 * supposed to return to so we can return there.
334 */
335 lra = codeptr->constants[REAL_LRA_SLOT];
336 #ifdef reg_CODE
337 /*
338 * With the known-return convention, we definitely do NOT want to
339 * mangle the CODE register because it isn't pointing to the bogus
340 * LRA but to the actual routine.
341 */
342 if (codeptr->constants[KNOWN_RETURN_P_SLOT] == NIL)
343 SC_REG(scp, reg_CODE) = lra;
344 #endif
345 undo_fake_foreign_function_call(scp);
346 return (void *) (lra - type_OtherPointer + sizeof(lispobj));
347 }
348 #else
349 void *
350 handle_function_end_breakpoint(int signal, int subcode, os_context_t * scp)
351 {
352 lispobj code, scp_sap = alloc_sap(scp);
353 struct code *codeptr;
354
355 fake_foreign_function_call(scp);
356
357 code = find_code(scp);
358 codeptr = (struct code *) PTR(code);
359
360 /*
361 * Don't disallow recursive breakpoint traps. Otherwise, we can't
362 * use debugger breakpoints anywhere in here.
363 */
364
365 sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
366 funcall3(SymbolFunction(HANDLE_BREAKPOINT),
367 compute_offset(scp, code, 1), code, scp_sap);
368
369 undo_fake_foreign_function_call(scp);
370
371 return compute_pc(codeptr->constants[REAL_LRA_SLOT],
372 fixnum_value(codeptr->constants[REAL_LRA_SLOT + 1]));
373 }
374 #endif

  ViewVC Help
Powered by ViewVC 1.1.5