0.6.7.22: removed CVS dollar-Header-dollar tags from sources
[sbcl.git] / src / runtime / breakpoint.c
1 /*
2  * This software is part of the SBCL system. See the README file for
3  * more information.
4  *
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.
10  */
11
12 #include <stdio.h>
13 #include <signal.h>
14
15 #include "runtime.h"
16 #include "os.h"
17 #include "sbcl.h"
18 #include "interrupt.h"
19 #include "arch.h"
20 #include "lispregs.h"
21 #include "globals.h"
22 #include "alloc.h"
23 #include "breakpoint.h"
24
25 #define REAL_LRA_SLOT 0
26 #ifndef __i386__
27 #define KNOWN_RETURN_P_SLOT 1
28 #define BOGUS_LRA_CONSTANTS 2
29 #else
30 #define KNOWN_RETURN_P_SLOT 2
31 #define BOGUS_LRA_CONSTANTS 3
32 #endif
33
34 static void *compute_pc(lispobj code_obj, int pc_offset)
35 {
36     struct code *code;
37
38     code = (struct code *)PTR(code_obj);
39     return (void *)((char *)code + HeaderValue(code->header)*sizeof(lispobj)
40                     + pc_offset);
41 }
42
43 unsigned long breakpoint_install(lispobj code_obj, int pc_offset)
44 {
45     return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
46 }
47
48 void breakpoint_remove(lispobj code_obj, int pc_offset,
49                        unsigned long orig_inst)
50 {
51     arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
52 }
53
54 void breakpoint_do_displaced_inst(os_context_t* context,
55                                   unsigned long orig_inst)
56 {
57 #if !defined(hpux) && !defined(irix) && !defined(__i386__)
58     undo_fake_foreign_function_call(context);
59 #endif
60     arch_do_displaced_inst(context, orig_inst);
61 }
62
63 #ifndef __i386__
64 static lispobj find_code(os_context_t *context)
65 {
66 #ifdef reg_CODE
67     lispobj code = *os_context_register_addr(context, reg_CODE);
68     lispobj header;
69
70     if (LowtagOf(code) != type_OtherPointer)
71         return NIL;
72
73     header = *(lispobj *)(code-type_OtherPointer);
74
75     if (TypeOf(header) == type_CodeHeader)
76         return code;
77     else
78         return code - HeaderValue(header)*sizeof(lispobj);
79 #else
80     return NIL;
81 #endif
82 }
83 #endif
84
85 #ifdef __i386__
86 static lispobj find_code(os_context_t *context)
87 {
88   lispobj codeptr = component_ptr_from_pc(*os_context_pc_addr(context));
89
90   if (codeptr == 0) {
91       return NIL;
92   } else {
93       return codeptr + type_OtherPointer;
94   }
95 }
96 #endif
97
98 static int compute_offset(os_context_t *context, lispobj code)
99 {
100     if (code == NIL)
101         return 0;
102     else {
103         unsigned long code_start;
104         struct code *codeptr = (struct code *)PTR(code);
105 #ifdef parisc
106         unsigned long pc = *os_context_pc_addr(context) & ~3;
107 #else
108         unsigned long pc = *os_context_pc_addr(context);
109 #endif
110
111         code_start = (unsigned long)codeptr
112             + HeaderValue(codeptr->header)*sizeof(lispobj);
113         if (pc < code_start)
114             return 0;
115         else {
116             int offset = pc - code_start;
117             if (offset >= codeptr->code_size)
118                 return 0;
119             else
120                 return make_fixnum(offset);
121         }
122     }
123 }
124
125 #ifndef __i386__
126 void handle_breakpoint(int signal, siginfo_t *info, os_context_t *context)
127 {
128     lispobj code;
129
130     fake_foreign_function_call(context);
131
132     code = find_code(context);
133
134     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
135              compute_offset(context, code),
136              code,
137              alloc_sap(context));
138
139     undo_fake_foreign_function_call(context);
140 }
141 #else
142 void handle_breakpoint(int signal, siginfo_t* info, os_context_t *context)
143 {
144     lispobj code, context_sap = alloc_sap(context);
145
146     fake_foreign_function_call(context);
147
148     code = find_code(context);
149
150     /* Don't disallow recursive breakpoint traps. Otherwise, we can't
151      * use debugger breakpoints anywhere in here. */
152     sigprocmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
153
154     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
155              compute_offset(context, code),
156              code,
157              context_sap);
158
159     undo_fake_foreign_function_call(context);
160 }
161 #endif
162
163 #ifndef __i386__
164 void *handle_function_end_breakpoint(int signal, siginfo_t *info,
165                                      os_context_t *context)
166 {
167     lispobj code, lra;
168     struct code *codeptr;
169
170     fake_foreign_function_call(context);
171
172     code = find_code(context);
173     codeptr = (struct code *)PTR(code);
174
175     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
176              compute_offset(context, code),
177              code,
178              alloc_sap(context));
179
180     lra = codeptr->constants[REAL_LRA_SLOT];
181 #ifdef reg_CODE
182     if (codeptr->constants[KNOWN_RETURN_P_SLOT] == NIL) {
183         *os_context_register_addr(context, reg_CODE) = lra;
184     }
185 #endif
186     undo_fake_foreign_function_call(context);
187     return (void *)(lra-type_OtherPointer+sizeof(lispobj));
188 }
189 #else
190 void *handle_function_end_breakpoint(int signal, siginfo_t *info,
191                                      os_context_t *context)
192 {
193     lispobj code, context_sap = alloc_sap(context);
194     struct code *codeptr;
195
196     fake_foreign_function_call(context);
197
198     code = find_code(context);
199     codeptr = (struct code *)PTR(code);
200
201     /* Don't disallow recursive breakpoint traps. Otherwise, we can't
202      * use debugger breakpoints anywhere in here. */
203     sigprocmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
204
205     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
206              compute_offset(context, code),
207              code,
208              context_sap);
209
210     undo_fake_foreign_function_call(context);
211
212     return compute_pc(codeptr->constants[REAL_LRA_SLOT],
213                       fixnum_value(codeptr->constants[REAL_LRA_SLOT+1]));
214 }
215 #endif