diff --git a/lisp/breakpoint.c b/lisp/breakpoint.c index 79a68dd560637770d51ea8d4b929abc9489bc789..369e784016f7e3cf3488dc4edb15562659f91c76 100644 --- a/lisp/breakpoint.c +++ b/lisp/breakpoint.c @@ -1,6 +1,6 @@ /* - $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/breakpoint.c,v 1.20 2007/07/06 08:04:39 cshapiro Exp $ + $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/breakpoint.c,v 1.21 2008/09/04 22:31:47 rtoy Exp $ This code was written as part of the CMU Common Lisp project at Carnegie Mellon University, and has been placed in the public domain. @@ -102,6 +102,90 @@ find_code(os_context_t * scp) } #endif +#if defined(sparc) && defined(__GNUC__) +/* + * For some unknown reason, if you compile this code with Sun C, CMUCL + * is unable to build itself anymore. This is bizarre because this + * code is not called during a build since there are no breakpoints + * during a build. + * + * Hence, until this is figured out, we can't use this code with Sun + * C. This also means we some known issues with tracing will manifest + * itself. + * + * During a function-end-breakpoint, the pc is sometimes less than the + * code address, which bypasses the function end stuff. Then the + * offset is zero for a function-end-breakpoint, and we can't find the + * breakpoint data, causing an error during tracing. But we know this + * is a function-end breakpoint, because function_end is set to true. + * + * (This condition of pc < code address seems to occur only if a GC + * happens during tracing. I guess the function-end code object + * sometimes gets moved to a lower address than the corresponding + * code.) + * + * Hence this replacement looks at the function end flag first + * to see if it is a function-end breakpoint and does the function-end + * stuff anyway. If not, we do the normal stuff. + */ +static int +compute_offset(os_context_t * scp, lispobj code, boolean function_end) +{ + if (code == NIL) + return 0; + if (function_end) { + /* + * We're in a function end breakpoint. Compute the + * offset from the (known) breakpoint location and the + * beginning of the breakpoint guts. (See *-assem.S.) + * + * Then make the offset negative so the caller knows + * that the offset is not from the code object. + */ + extern char function_end_breakpoint_trap; + extern char function_end_breakpoint_guts; + int offset; + + offset = + &function_end_breakpoint_trap - + &function_end_breakpoint_guts; +#if 0 + fprintf(stderr, "compute_offset\n"); + fprintf(stderr, " function end offset = %d\n", offset); +#endif + return make_fixnum(-offset); + } else { + unsigned long code_start; + struct code *codeptr = (struct code *) PTR(code); + unsigned long pc = SC_PC(scp); + + code_start = (unsigned long) codeptr + + HeaderValue(codeptr->header) * sizeof(lispobj); +#if 0 + fprintf(stderr, "compute_offset\n"); + fprintf(stderr, " pc = %d\n", pc); + fprintf(stderr, " code_start = %d\n", code_start); + fprintf(stderr, " function_end = %d\n", function_end); +#endif + if (pc < code_start) { + return 0; + } else { + int offset = pc - code_start; + +#if 0 + fprintf(stderr, " offset = %d\n", offset); + fprintf(stderr, " codeptr->code_size = %d\n", codeptr->code_size); + fprintf(stderr, " function_end = %d\n", function_end); +#endif + if (offset >= codeptr->code_size) { + return 0; + } else { + return make_fixnum(offset); + } + } + } +} +#else static int compute_offset(os_context_t * scp, lispobj code, boolean function_end) { @@ -154,6 +238,7 @@ compute_offset(os_context_t * scp, lispobj code, boolean function_end) } } } +#endif #ifndef i386 void @@ -165,6 +250,10 @@ handle_breakpoint(int signal, int subcode, os_context_t * scp) code = find_code(scp); +#if 0 + fprintf(stderr, "handle_breakpoint\n"); + fprintf(stderr, " offset = %d\n", compute_offset(scp, code, 0)); +#endif funcall3(SymbolFunction(HANDLE_BREAKPOINT), compute_offset(scp, code, 0), code, alloc_sap(scp));