Apply "search for cp" patch by Hraban Luyat
[sbcl.git] / src / runtime / breakpoint.c
blob1919ffcf0132d20cced42563be7d6388fdaa77c2
1 /*
2 * This software is part of the SBCL system. See the README file for
3 * more information.
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <signal.h>
16 #include "genesis/sbcl.h"
17 #include "genesis/sap.h"
18 #include "runtime.h"
19 #include "os.h"
20 #include "interrupt.h"
21 #include "arch.h"
22 #include "gc.h"
23 #include "lispregs.h"
24 #include "globals.h"
25 #include "breakpoint.h"
26 #include "thread.h"
27 #include "code.h"
28 #include "genesis/symbol.h"
30 #define REAL_LRA_SLOT 0
32 static void *compute_pc(lispobj code_obj, int pc_offset)
34 return code_text_start((struct code*)native_pointer(code_obj)) + pc_offset;
37 unsigned int breakpoint_install(lispobj code_obj, int pc_offset)
39 return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
42 void breakpoint_remove(lispobj code_obj, int pc_offset,
43 unsigned int orig_inst)
45 arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
48 void breakpoint_do_displaced_inst(os_context_t* context,
49 unsigned int orig_inst)
51 /* on platforms with sigreturn(), we go directly back from
52 * arch_do_displaced_inst() to lisp code, so we need to clean up
53 * our bindings now. (side note: I'd love to know in exactly what
54 * scenario the speed of breakpoint handling is critical enough to
55 * justify this maintenance mess)
57 * -dan 2001.08.09 */
59 #if (defined(LISP_FEATURE_SPARC) && defined (solaris))
60 undo_fake_foreign_function_call(context);
61 #endif
62 arch_do_displaced_inst(context, orig_inst);
65 lispobj find_code(os_context_t *context)
67 #ifdef reg_CODE
68 lispobj code = *os_context_register_addr(context, reg_CODE);
69 lispobj header;
71 #ifdef LISP_FEATURE_PPC64
72 if (lowtag_of(code) == 0)
73 code |= OTHER_POINTER_LOWTAG;
74 #endif
76 if (lowtag_of(code) != OTHER_POINTER_LOWTAG)
77 return NIL;
79 header = *(lispobj *)(code-OTHER_POINTER_LOWTAG);
81 if (header_widetag(header) == CODE_HEADER_WIDETAG)
82 return code;
83 else
84 return code - HeaderValue(header)*sizeof(lispobj);
85 #else
86 lispobj codeptr =
87 (lispobj)component_ptr_from_pc((char *)os_context_pc(context));
89 if (codeptr == 0)
90 return NIL;
91 else
92 return codeptr + OTHER_POINTER_LOWTAG;
93 #endif
96 static long compute_offset(os_context_t *context, lispobj code)
98 if (code != NIL) {
99 uword_t pc = os_context_pc(context);
100 struct code *codeptr = (struct code *)native_pointer(code);
101 uword_t code_start = (uword_t)code_text_start(codeptr);
102 int offset;
103 if (pc >= code_start &&
104 ((offset = pc - code_start) < code_text_size(codeptr)))
105 return make_fixnum(offset);
107 return 0;
110 void handle_breakpoint(os_context_t *context)
112 lispobj code;
113 DX_ALLOC_SAP(context_sap, context);
115 fake_foreign_function_call(context);
117 #ifndef LISP_FEATURE_SB_SAFEPOINT
118 unblock_gc_stop_signal();
119 #endif
120 code = find_code(context);
122 #ifndef LISP_FEATURE_WIN32
123 /* Don't disallow recursive breakpoint traps. Otherwise, we can't
124 * use debugger breakpoints anywhere in here. */
125 thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
126 #endif
128 funcall3(StaticSymbolFunction(HANDLE_BREAKPOINT),
129 compute_offset(context, code),
130 code,
131 context_sap);
133 undo_fake_foreign_function_call(context);
136 void *handle_fun_end_breakpoint(os_context_t *context)
138 lispobj code, lra;
139 struct code *codeptr;
140 DX_ALLOC_SAP(context_sap, context);
142 fake_foreign_function_call(context);
144 #ifndef LISP_FEATURE_SB_SAFEPOINT
145 unblock_gc_stop_signal();
146 #endif
148 code = find_code(context);
149 codeptr = (struct code *)native_pointer(code);
151 #ifndef LISP_FEATURE_WIN32
152 /* Don't disallow recursive breakpoint traps. Otherwise, we can't
153 * use debugger breakpoints anywhere in here. */
154 thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
155 #endif
157 funcall3(StaticSymbolFunction(HANDLE_BREAKPOINT),
158 compute_offset(context, code),
159 code,
160 context_sap);
162 lra = codeptr->constants[REAL_LRA_SLOT];
164 #if defined LISP_FEATURE_PPC || defined LISP_FEATURE_PPC64
165 /* PPC now passes LRA objects in reg_LRA during return. Other
166 * platforms should as well, but haven't been fixed yet. */
167 *os_context_register_addr(context, reg_LRA) = lra;
168 #else
169 #ifdef reg_CODE
170 *os_context_register_addr(context, reg_CODE) = lra;
171 #endif
172 #endif
174 undo_fake_foreign_function_call(context);
176 #ifdef reg_LRA
177 return (void *)(lra-OTHER_POINTER_LOWTAG+sizeof(lispobj));
178 #else
179 return compute_pc(lra, fixnum_value(codeptr->constants[REAL_LRA_SLOT+1]));
180 #endif
183 void
184 handle_single_step_trap (os_context_t *context, int kind, int register_offset)
186 fake_foreign_function_call(context);
188 #ifndef LISP_FEATURE_WIN32
189 thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
190 #endif
192 funcall2(StaticSymbolFunction(HANDLE_SINGLE_STEP_TRAP),
193 make_fixnum(kind),
194 make_fixnum(register_offset));
196 undo_fake_foreign_function_call(context); /* blocks signals again */