[93108e]: src / runtime / breakpoint.c Maximize Restore History

Download this file

breakpoint.c    234 lines (197 with data), 6.2 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
* This software is part of the SBCL system. See the README file for
* more information.
*
* This software is derived from the CMU CL system, which was
* written at Carnegie Mellon University and released into the
* public domain. The software is in the public domain and is
* provided with absolutely no warranty. See the COPYING and CREDITS
* files for more information.
*/
#include <stdio.h>
#include <signal.h>
#include "runtime.h"
#include "os.h"
#include "sbcl.h"
#include "interrupt.h"
#include "arch.h"
#include "lispregs.h"
#include "globals.h"
#include "alloc.h"
#include "breakpoint.h"
#include "thread.h"
#include "genesis/code.h"
#include "genesis/fdefn.h"
#define REAL_LRA_SLOT 0
#ifndef LISP_FEATURE_X86
#define KNOWN_RETURN_P_SLOT 1
#define BOGUS_LRA_CONSTANTS 2
#else
#define KNOWN_RETURN_P_SLOT 2
#define BOGUS_LRA_CONSTANTS 3
#endif
static void *compute_pc(lispobj code_obj, int pc_offset)
{
struct code *code;
code = (struct code *)native_pointer(code_obj);
return (void *)((char *)code + HeaderValue(code->header)*sizeof(lispobj)
+ pc_offset);
}
unsigned long breakpoint_install(lispobj code_obj, int pc_offset)
{
return arch_install_breakpoint(compute_pc(code_obj, pc_offset));
}
void breakpoint_remove(lispobj code_obj, int pc_offset,
unsigned long orig_inst)
{
arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst);
}
void breakpoint_do_displaced_inst(os_context_t* context,
unsigned long orig_inst)
{
/* on platforms with sigreturn(), we go directly back from
* arch_do_displaced_inst() to lisp code, so we need to clean up
* our bindings now. (side note: I'd love to know in exactly what
* scenario the speed of breakpoint handling is critical enough to
* justify this maintenance mess)
*
* -dan 2001.08.09 */
#if (defined(sparc) && defined (solaris))
undo_fake_foreign_function_call(context);
#endif
arch_do_displaced_inst(context, orig_inst);
}
#ifndef LISP_FEATURE_X86
static lispobj find_code(os_context_t *context)
{
#ifdef reg_CODE
lispobj code = *os_context_register_addr(context, reg_CODE);
lispobj header;
if (lowtag_of(code) != OTHER_POINTER_LOWTAG)
return NIL;
header = *(lispobj *)(code-OTHER_POINTER_LOWTAG);
if (widetag_of(header) == CODE_HEADER_WIDETAG)
return code;
else
return code - HeaderValue(header)*sizeof(lispobj);
#else
return NIL;
#endif
}
#endif
#ifdef LISP_FEATURE_X86
static lispobj find_code(os_context_t *context)
{
lispobj codeptr =
(lispobj)component_ptr_from_pc((lispobj *)(*os_context_pc_addr(context)));
if (codeptr == 0) {
return NIL;
} else {
return codeptr + OTHER_POINTER_LOWTAG;
}
}
#endif
static int compute_offset(os_context_t *context, lispobj code)
{
if (code == NIL)
return 0;
else {
unsigned long code_start;
struct code *codeptr = (struct code *)native_pointer(code);
#ifdef parisc
unsigned long pc = *os_context_pc_addr(context) & ~3;
#else
unsigned long pc = *os_context_pc_addr(context);
#endif
code_start = (unsigned long)codeptr
+ HeaderValue(codeptr->header)*sizeof(lispobj);
if (pc < code_start)
return 0;
else {
int offset = pc - code_start;
if (offset >= codeptr->code_size)
return 0;
else
return make_fixnum(offset);
}
}
}
/* FIXME: I can see no really good reason these couldn't be merged, but haven't
* tried. The sigprocmask() call would work just as well on alpha as it
* presumably does on x86 -dan 2001.08.10
*/
#ifndef LISP_FEATURE_X86
void handle_breakpoint(int signal, siginfo_t *info, os_context_t *context)
{
lispobj code;
fake_foreign_function_call(context);
code = find_code(context);
/* FIXME we're calling into Lisp with signals masked here. Is this
* the right thing to do? */
funcall3(SymbolFunction(HANDLE_BREAKPOINT),
compute_offset(context, code),
code,
alloc_sap(context));
undo_fake_foreign_function_call(context);
}
#else
void handle_breakpoint(int signal, siginfo_t* info, os_context_t *context)
{
lispobj code, context_sap = alloc_sap(context);
fake_foreign_function_call(context);
code = find_code(context);
/* Don't disallow recursive breakpoint traps. Otherwise, we can't
* use debugger breakpoints anywhere in here. */
sigprocmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
funcall3(SymbolFunction(HANDLE_BREAKPOINT),
compute_offset(context, code),
code,
context_sap);
undo_fake_foreign_function_call(context);
}
#endif
#ifndef LISP_FEATURE_X86
void *handle_fun_end_breakpoint(int signal, siginfo_t *info,
os_context_t *context)
{
lispobj code, lra;
struct code *codeptr;
fake_foreign_function_call(context);
code = find_code(context);
codeptr = (struct code *)native_pointer(code);
/* FIXME again, calling into Lisp with signals masked. Is this
* sensible? */
funcall3(SymbolFunction(HANDLE_BREAKPOINT),
compute_offset(context, code),
code,
alloc_sap(context));
lra = codeptr->constants[REAL_LRA_SLOT];
#ifdef reg_CODE
if (codeptr->constants[KNOWN_RETURN_P_SLOT] == NIL) {
*os_context_register_addr(context, reg_CODE) = lra;
}
#endif
undo_fake_foreign_function_call(context);
return (void *)(lra-OTHER_POINTER_LOWTAG+sizeof(lispobj));
}
#else
void *handle_fun_end_breakpoint(int signal, siginfo_t *info,
os_context_t *context)
{
lispobj code, context_sap = alloc_sap(context);
struct code *codeptr;
fake_foreign_function_call(context);
code = find_code(context);
codeptr = (struct code *)native_pointer(code);
/* Don't disallow recursive breakpoint traps. Otherwise, we can't
* use debugger breakpoints anywhere in here. */
sigprocmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
funcall3(SymbolFunction(HANDLE_BREAKPOINT),
compute_offset(context, code),
code,
context_sap);
undo_fake_foreign_function_call(context);
return compute_pc(codeptr->constants[REAL_LRA_SLOT],
fixnum_value(codeptr->constants[REAL_LRA_SLOT+1]));
}
#endif