i386-netbsd-tdep.c revision 1.1.1.2 1 1.1 christos /* Target-dependent code for NetBSD/i386.
2 1.1 christos
3 1.1.1.2 christos Copyright (C) 1988-2024 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include "arch-utils.h"
21 1.1 christos #include "frame.h"
22 1.1 christos #include "gdbcore.h"
23 1.1 christos #include "regcache.h"
24 1.1 christos #include "regset.h"
25 1.1 christos #include "osabi.h"
26 1.1 christos #include "symtab.h"
27 1.1 christos #include "trad-frame.h"
28 1.1 christos #include "tramp-frame.h"
29 1.1 christos #include "frame-unwind.h"
30 1.1 christos
31 1.1 christos #include "i386-tdep.h"
32 1.1 christos #include "i387-tdep.h"
33 1.1 christos #include "netbsd-tdep.h"
34 1.1 christos #include "solib-svr4.h"
35 1.1 christos
36 1.1 christos /* From <machine/reg.h>. */
37 1.1 christos static int i386nbsd_r_reg_offset[] =
38 1.1 christos {
39 1.1 christos 0 * 4, /* %eax */
40 1.1 christos 1 * 4, /* %ecx */
41 1.1 christos 2 * 4, /* %edx */
42 1.1 christos 3 * 4, /* %ebx */
43 1.1 christos 4 * 4, /* %esp */
44 1.1 christos 5 * 4, /* %ebp */
45 1.1 christos 6 * 4, /* %esi */
46 1.1 christos 7 * 4, /* %edi */
47 1.1 christos 8 * 4, /* %eip */
48 1.1 christos 9 * 4, /* %eflags */
49 1.1 christos 10 * 4, /* %cs */
50 1.1 christos 11 * 4, /* %ss */
51 1.1 christos 12 * 4, /* %ds */
52 1.1 christos 13 * 4, /* %es */
53 1.1 christos 14 * 4, /* %fs */
54 1.1 christos 15 * 4 /* %gs */
55 1.1 christos };
56 1.1 christos
57 1.1 christos /* From <machine/signal.h>. */
58 1.1 christos static int i386nbsd_sc_reg_offset[] =
59 1.1 christos {
60 1.1 christos 10 * 4, /* %eax */
61 1.1 christos 9 * 4, /* %ecx */
62 1.1 christos 8 * 4, /* %edx */
63 1.1 christos 7 * 4, /* %ebx */
64 1.1 christos 14 * 4, /* %esp */
65 1.1 christos 6 * 4, /* %ebp */
66 1.1 christos 5 * 4, /* %esi */
67 1.1 christos 4 * 4, /* %edi */
68 1.1 christos 11 * 4, /* %eip */
69 1.1 christos 13 * 4, /* %eflags */
70 1.1 christos 12 * 4, /* %cs */
71 1.1 christos 15 * 4, /* %ss */
72 1.1 christos 3 * 4, /* %ds */
73 1.1 christos 2 * 4, /* %es */
74 1.1 christos 1 * 4, /* %fs */
75 1.1 christos 0 * 4 /* %gs */
76 1.1 christos };
77 1.1 christos
78 1.1 christos /* From <machine/mcontext.h>. */
79 1.1 christos static int i386nbsd_mc_reg_offset[] =
80 1.1 christos {
81 1.1 christos 11 * 4, /* %eax */
82 1.1 christos 10 * 4, /* %ecx */
83 1.1 christos 9 * 4, /* %edx */
84 1.1 christos 8 * 4, /* %ebx */
85 1.1 christos 7 * 4, /* %esp */
86 1.1 christos 6 * 4, /* %ebp */
87 1.1 christos 5 * 4, /* %esi */
88 1.1 christos 4 * 4, /* %edi */
89 1.1 christos 14 * 4, /* %eip */
90 1.1 christos 16 * 4, /* %eflags */
91 1.1 christos 15 * 4, /* %cs */
92 1.1 christos 18 * 4, /* %ss */
93 1.1 christos 3 * 4, /* %ds */
94 1.1 christos 2 * 4, /* %es */
95 1.1 christos 1 * 4, /* %fs */
96 1.1 christos 0 * 4 /* %gs */
97 1.1 christos };
98 1.1 christos
99 1.1 christos static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
100 1.1.1.2 christos const frame_info_ptr &,
101 1.1 christos struct trad_frame_cache *,
102 1.1 christos CORE_ADDR);
103 1.1 christos
104 1.1 christos static const struct tramp_frame i386nbsd_sigtramp_sc16 =
105 1.1 christos {
106 1.1 christos SIGTRAMP_FRAME,
107 1.1 christos 1,
108 1.1 christos {
109 1.1 christos /* leal 0x10(%esp), %eax */
110 1.1 christos { 0x8d, ULONGEST_MAX },
111 1.1 christos { 0x44, ULONGEST_MAX },
112 1.1 christos { 0x24, ULONGEST_MAX },
113 1.1 christos { 0x10, ULONGEST_MAX },
114 1.1 christos
115 1.1 christos /* pushl %eax */
116 1.1 christos { 0x50, ULONGEST_MAX },
117 1.1 christos
118 1.1 christos /* pushl %eax */
119 1.1 christos { 0x50, ULONGEST_MAX },
120 1.1 christos
121 1.1 christos /* movl $0x127, %eax # __sigreturn14 */
122 1.1 christos { 0xb8, ULONGEST_MAX },
123 1.1 christos { 0x27, ULONGEST_MAX },
124 1.1 christos {0x01, ULONGEST_MAX },
125 1.1 christos {0x00, ULONGEST_MAX },
126 1.1 christos {0x00, ULONGEST_MAX },
127 1.1 christos
128 1.1 christos /* int $0x80 */
129 1.1 christos { 0xcd, ULONGEST_MAX },
130 1.1 christos { 0x80, ULONGEST_MAX},
131 1.1 christos
132 1.1 christos /* movl $0x1, %eax # exit */
133 1.1 christos { 0xb8, ULONGEST_MAX },
134 1.1 christos { 0x01, ULONGEST_MAX },
135 1.1 christos {0x00, ULONGEST_MAX },
136 1.1 christos {0x00, ULONGEST_MAX },
137 1.1 christos {0x00, ULONGEST_MAX },
138 1.1 christos
139 1.1 christos /* int $0x80 */
140 1.1 christos { 0xcd, ULONGEST_MAX },
141 1.1 christos { 0x80, ULONGEST_MAX},
142 1.1 christos
143 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
144 1.1 christos },
145 1.1 christos i386nbsd_sigtramp_cache_init
146 1.1 christos };
147 1.1 christos
148 1.1 christos static const struct tramp_frame i386nbsd_sigtramp_sc2 =
149 1.1 christos {
150 1.1 christos SIGTRAMP_FRAME,
151 1.1 christos 1,
152 1.1 christos {
153 1.1 christos /* leal 0x0c(%esp), %eax */
154 1.1 christos { 0x8d, ULONGEST_MAX },
155 1.1 christos { 0x44, ULONGEST_MAX },
156 1.1 christos { 0x24, ULONGEST_MAX },
157 1.1 christos { 0x0c, ULONGEST_MAX },
158 1.1 christos /* movl %eax, 0x4(%esp) */
159 1.1 christos { 0x89, ULONGEST_MAX },
160 1.1 christos { 0x44, ULONGEST_MAX },
161 1.1 christos { 0x24, ULONGEST_MAX },
162 1.1 christos { 0x04, ULONGEST_MAX },
163 1.1 christos /* movl $0x127, %eax # __sigreturn14 */
164 1.1 christos { 0xb8, ULONGEST_MAX },
165 1.1 christos { 0x27, ULONGEST_MAX },
166 1.1 christos {0x01, ULONGEST_MAX },
167 1.1 christos {0x00, ULONGEST_MAX },
168 1.1 christos {0x00, ULONGEST_MAX },
169 1.1 christos /* int $0x80 */
170 1.1 christos { 0xcd, ULONGEST_MAX },
171 1.1 christos { 0x80, ULONGEST_MAX},
172 1.1 christos /* movl %eax, 0x4(%esp) */
173 1.1 christos { 0x89, ULONGEST_MAX },
174 1.1 christos { 0x44, ULONGEST_MAX },
175 1.1 christos { 0x24, ULONGEST_MAX },
176 1.1 christos { 0x04, ULONGEST_MAX },
177 1.1 christos /* movl $0x1, %eax */
178 1.1 christos { 0xb8, ULONGEST_MAX },
179 1.1 christos { 0x01, ULONGEST_MAX },
180 1.1 christos {0x00, ULONGEST_MAX },
181 1.1 christos {0x00, ULONGEST_MAX },
182 1.1 christos {0x00, ULONGEST_MAX },
183 1.1 christos /* int $0x80 */
184 1.1 christos { 0xcd, ULONGEST_MAX },
185 1.1 christos { 0x80, ULONGEST_MAX},
186 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
187 1.1 christos },
188 1.1 christos i386nbsd_sigtramp_cache_init
189 1.1 christos };
190 1.1 christos
191 1.1 christos static const struct tramp_frame i386nbsd_sigtramp_si2 =
192 1.1 christos {
193 1.1 christos SIGTRAMP_FRAME,
194 1.1 christos 1,
195 1.1 christos {
196 1.1 christos /* movl 8(%esp),%eax */
197 1.1 christos { 0x8b, ULONGEST_MAX },
198 1.1 christos { 0x44, ULONGEST_MAX },
199 1.1 christos { 0x24, ULONGEST_MAX },
200 1.1 christos { 0x08, ULONGEST_MAX },
201 1.1 christos /* movl %eax, 0x4(%esp) */
202 1.1 christos { 0x89, ULONGEST_MAX },
203 1.1 christos { 0x44, ULONGEST_MAX },
204 1.1 christos { 0x24, ULONGEST_MAX },
205 1.1 christos { 0x04, ULONGEST_MAX },
206 1.1 christos /* movl $0x134, %eax # setcontext */
207 1.1 christos { 0xb8, ULONGEST_MAX },
208 1.1 christos { 0x34, ULONGEST_MAX },
209 1.1 christos { 0x01, ULONGEST_MAX },
210 1.1 christos { 0x00, ULONGEST_MAX },
211 1.1 christos { 0x00, ULONGEST_MAX },
212 1.1 christos /* int $0x80 */
213 1.1 christos { 0xcd, ULONGEST_MAX },
214 1.1 christos { 0x80, ULONGEST_MAX },
215 1.1 christos /* movl %eax, 0x4(%esp) */
216 1.1 christos { 0x89, ULONGEST_MAX },
217 1.1 christos { 0x44, ULONGEST_MAX },
218 1.1 christos { 0x24, ULONGEST_MAX },
219 1.1 christos { 0x04, ULONGEST_MAX },
220 1.1 christos /* movl $0x1, %eax */
221 1.1 christos { 0xb8, ULONGEST_MAX },
222 1.1 christos { 0x01, ULONGEST_MAX },
223 1.1 christos { 0x00, ULONGEST_MAX },
224 1.1 christos { 0x00, ULONGEST_MAX },
225 1.1 christos { 0x00, ULONGEST_MAX },
226 1.1 christos /* int $0x80 */
227 1.1 christos { 0xcd, ULONGEST_MAX },
228 1.1 christos { 0x80, ULONGEST_MAX },
229 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
230 1.1 christos },
231 1.1 christos i386nbsd_sigtramp_cache_init
232 1.1 christos };
233 1.1 christos
234 1.1 christos static const struct tramp_frame i386nbsd_sigtramp_si31 =
235 1.1 christos {
236 1.1 christos SIGTRAMP_FRAME,
237 1.1 christos 1,
238 1.1 christos {
239 1.1 christos /* leal 0x8c(%esp), %eax */
240 1.1 christos { 0x8d, ULONGEST_MAX },
241 1.1 christos { 0x84, ULONGEST_MAX },
242 1.1 christos { 0x24, ULONGEST_MAX },
243 1.1 christos { 0x8c, ULONGEST_MAX },
244 1.1 christos { 0x00, ULONGEST_MAX },
245 1.1 christos { 0x00, ULONGEST_MAX },
246 1.1 christos { 0x00, ULONGEST_MAX },
247 1.1 christos /* movl %eax, 0x4(%esp) */
248 1.1 christos { 0x89, ULONGEST_MAX },
249 1.1 christos { 0x44, ULONGEST_MAX },
250 1.1 christos { 0x24, ULONGEST_MAX },
251 1.1 christos { 0x04, ULONGEST_MAX },
252 1.1 christos /* movl $0x134, %eax # setcontext */
253 1.1 christos { 0xb8, ULONGEST_MAX },
254 1.1 christos { 0x34, ULONGEST_MAX },
255 1.1 christos { 0x01, ULONGEST_MAX },
256 1.1 christos { 0x00, ULONGEST_MAX },
257 1.1 christos { 0x00, ULONGEST_MAX },
258 1.1 christos /* int $0x80 */
259 1.1 christos { 0xcd, ULONGEST_MAX },
260 1.1 christos { 0x80, ULONGEST_MAX},
261 1.1 christos /* movl %eax, 0x4(%esp) */
262 1.1 christos { 0x89, ULONGEST_MAX },
263 1.1 christos { 0x44, ULONGEST_MAX },
264 1.1 christos { 0x24, ULONGEST_MAX },
265 1.1 christos { 0x04, ULONGEST_MAX },
266 1.1 christos /* movl $0x1, %eax */
267 1.1 christos { 0xb8, ULONGEST_MAX },
268 1.1 christos { 0x01, ULONGEST_MAX },
269 1.1 christos {0x00, ULONGEST_MAX },
270 1.1 christos {0x00, ULONGEST_MAX },
271 1.1 christos {0x00, ULONGEST_MAX },
272 1.1 christos /* int $0x80 */
273 1.1 christos { 0xcd, ULONGEST_MAX },
274 1.1 christos { 0x80, ULONGEST_MAX},
275 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
276 1.1 christos },
277 1.1 christos i386nbsd_sigtramp_cache_init
278 1.1 christos };
279 1.1 christos
280 1.1 christos static const struct tramp_frame i386nbsd_sigtramp_si4 =
281 1.1 christos {
282 1.1 christos SIGTRAMP_FRAME,
283 1.1 christos 1,
284 1.1 christos {
285 1.1 christos /* leal 0x8c(%esp), %eax */
286 1.1 christos { 0x8d, ULONGEST_MAX },
287 1.1 christos { 0x84, ULONGEST_MAX },
288 1.1 christos { 0x24, ULONGEST_MAX },
289 1.1 christos { 0x8c, ULONGEST_MAX },
290 1.1 christos { 0x00, ULONGEST_MAX },
291 1.1 christos { 0x00, ULONGEST_MAX },
292 1.1 christos { 0x00, ULONGEST_MAX },
293 1.1 christos /* movl %eax, 0x4(%esp) */
294 1.1 christos { 0x89, ULONGEST_MAX },
295 1.1 christos { 0x44, ULONGEST_MAX },
296 1.1 christos { 0x24, ULONGEST_MAX },
297 1.1 christos { 0x04, ULONGEST_MAX },
298 1.1 christos /* movl $0x134, %eax # setcontext */
299 1.1 christos { 0xb8, ULONGEST_MAX },
300 1.1 christos { 0x34, ULONGEST_MAX },
301 1.1 christos { 0x01, ULONGEST_MAX },
302 1.1 christos { 0x00, ULONGEST_MAX },
303 1.1 christos { 0x00, ULONGEST_MAX },
304 1.1 christos /* int $0x80 */
305 1.1 christos { 0xcd, ULONGEST_MAX },
306 1.1 christos { 0x80, ULONGEST_MAX},
307 1.1 christos /* movl $0xffffffff,0x4(%esp) */
308 1.1 christos { 0xc7, ULONGEST_MAX },
309 1.1 christos { 0x44, ULONGEST_MAX },
310 1.1 christos { 0x24, ULONGEST_MAX },
311 1.1 christos { 0x04, ULONGEST_MAX },
312 1.1 christos { 0xff, ULONGEST_MAX },
313 1.1 christos { 0xff, ULONGEST_MAX },
314 1.1 christos { 0xff, ULONGEST_MAX },
315 1.1 christos { 0xff, ULONGEST_MAX },
316 1.1 christos /* movl $0x1, %eax */
317 1.1 christos { 0xb8, ULONGEST_MAX },
318 1.1 christos { 0x01, ULONGEST_MAX },
319 1.1 christos {0x00, ULONGEST_MAX },
320 1.1 christos {0x00, ULONGEST_MAX },
321 1.1 christos {0x00, ULONGEST_MAX },
322 1.1 christos /* int $0x80 */
323 1.1 christos { 0xcd, ULONGEST_MAX },
324 1.1 christos { 0x80, ULONGEST_MAX},
325 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
326 1.1 christos },
327 1.1 christos i386nbsd_sigtramp_cache_init
328 1.1 christos };
329 1.1 christos
330 1.1 christos static void
331 1.1 christos i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
332 1.1.1.2 christos const frame_info_ptr &this_frame,
333 1.1 christos struct trad_frame_cache *this_cache,
334 1.1 christos CORE_ADDR func)
335 1.1 christos {
336 1.1 christos struct gdbarch *gdbarch = get_frame_arch (this_frame);
337 1.1 christos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
338 1.1 christos CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
339 1.1 christos CORE_ADDR base;
340 1.1 christos int *reg_offset;
341 1.1 christos int num_regs;
342 1.1 christos int i;
343 1.1 christos
344 1.1 christos if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
345 1.1 christos {
346 1.1 christos reg_offset = i386nbsd_sc_reg_offset;
347 1.1 christos num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
348 1.1 christos
349 1.1 christos /* Read in the sigcontext address. */
350 1.1 christos base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
351 1.1 christos }
352 1.1 christos else
353 1.1 christos {
354 1.1 christos reg_offset = i386nbsd_mc_reg_offset;
355 1.1 christos num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
356 1.1 christos
357 1.1 christos /* Read in the ucontext address. */
358 1.1 christos base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
359 1.1 christos /* offsetof(ucontext_t, uc_mcontext) == 36 */
360 1.1 christos base += 36;
361 1.1 christos }
362 1.1 christos
363 1.1 christos for (i = 0; i < num_regs; i++)
364 1.1 christos if (reg_offset[i] != -1)
365 1.1 christos trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
366 1.1 christos
367 1.1 christos /* Construct the frame ID using the function start. */
368 1.1 christos trad_frame_set_id (this_cache, frame_id_build (sp, func));
369 1.1 christos }
370 1.1 christos
371 1.1 christos
373 1.1 christos /* From <machine/frame.h>. Note that %esp and %ess are only saved in
374 1.1 christos a trap frame when entering the kernel from user space. */
375 1.1 christos static int i386nbsd_tf_reg_offset[] =
376 1.1 christos {
377 1.1 christos 10 * 4, /* %eax */
378 1.1 christos 9 * 4, /* %ecx */
379 1.1 christos 8 * 4, /* %edx */
380 1.1 christos 7 * 4, /* %ebx */
381 1.1 christos -1, /* %esp */
382 1.1 christos 6 * 4, /* %ebp */
383 1.1 christos 5 * 4, /* %esi */
384 1.1 christos 4 * 4, /* %edi */
385 1.1 christos 13 * 4, /* %eip */
386 1.1 christos 15 * 4, /* %eflags */
387 1.1 christos 14 * 4, /* %cs */
388 1.1 christos -1, /* %ss */
389 1.1 christos 3 * 4, /* %ds */
390 1.1 christos 2 * 4, /* %es */
391 1.1 christos 1 * 4, /* %fs */
392 1.1 christos 0 * 4 /* %gs */
393 1.1 christos };
394 1.1 christos
395 1.1 christos static struct trad_frame_cache *
396 1.1 christos i386nbsd_trapframe_cache(frame_info_ptr this_frame, void **this_cache)
397 1.1 christos {
398 1.1 christos struct trad_frame_cache *cache;
399 1.1 christos CORE_ADDR func, sp, addr, tmp;
400 1.1 christos ULONGEST cs;
401 1.1 christos const char *name;
402 1.1 christos int i;
403 1.1 christos struct gdbarch *gdbarch = get_frame_arch (this_frame);
404 1.1 christos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
405 1.1 christos
406 1.1 christos if (*this_cache)
407 1.1 christos return (struct trad_frame_cache *)*this_cache;
408 1.1 christos
409 1.1 christos cache = trad_frame_cache_zalloc (this_frame);
410 1.1 christos *this_cache = cache;
411 1.1 christos
412 1.1 christos func = get_frame_func (this_frame);
413 1.1 christos sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
414 1.1 christos
415 1.1 christos find_pc_partial_function (func, &name, NULL, NULL);
416 1.1 christos if (name && (strncmp (name, "Xintr", 5) == 0 ||
417 1.1 christos strncmp (name, "Xhandle", 7) == 0))
418 1.1 christos {
419 1.1 christos /* It's an interrupt frame. */
420 1.1 christos tmp = read_memory_unsigned_integer (sp + 4, 4, byte_order);
421 1.1 christos if (tmp < 15)
422 1.1 christos {
423 1.1 christos /* Reasonable value for 'ppl': already on interrupt stack. */
424 1.1 christos addr = sp + 8;
425 1.1 christos }
426 1.1 christos else
427 1.1 christos {
428 1.1 christos /* Switch to previous stack. */
429 1.1 christos addr = tmp + 4;
430 1.1 christos }
431 1.1 christos }
432 1.1 christos else
433 1.1 christos {
434 1.1 christos /* It's a trap frame. */
435 1.1 christos addr = sp + 4;
436 1.1 christos }
437 1.1 christos
438 1.1 christos for (i = 0; i < ARRAY_SIZE (i386nbsd_tf_reg_offset); i++)
439 1.1 christos if (i386nbsd_tf_reg_offset[i] != -1)
440 1.1 christos trad_frame_set_reg_addr (cache, i, addr + i386nbsd_tf_reg_offset[i]);
441 1.1 christos
442 1.1 christos /* Read %cs from trap frame. */
443 1.1 christos addr += i386nbsd_tf_reg_offset[I386_CS_REGNUM];
444 1.1 christos cs = read_memory_unsigned_integer (addr, 4, byte_order);
445 1.1 christos if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
446 1.1 christos {
447 1.1 christos /* Trap from user space; terminate backtrace. */
448 1.1 christos trad_frame_set_id (cache, outer_frame_id);
449 1.1 christos }
450 1.1 christos else
451 1.1 christos {
452 1.1 christos /* Construct the frame ID using the function start. */
453 1.1 christos trad_frame_set_id (cache, frame_id_build (sp + 8, func));
454 1.1 christos }
455 1.1 christos
456 1.1 christos return cache;
457 1.1 christos }
458 1.1 christos
459 1.1.1.2 christos static void
460 1.1 christos i386nbsd_trapframe_this_id (const frame_info_ptr& this_frame,
461 1.1 christos void **this_cache, struct frame_id *this_id)
462 1.1 christos {
463 1.1 christos struct trad_frame_cache *cache =
464 1.1 christos i386nbsd_trapframe_cache (this_frame, this_cache);
465 1.1 christos
466 1.1 christos trad_frame_get_id (cache, this_id);
467 1.1 christos }
468 1.1 christos
469 1.1.1.2 christos static struct value *
470 1.1 christos i386nbsd_trapframe_prev_register (const frame_info_ptr& this_frame,
471 1.1 christos void **this_cache, int regnum)
472 1.1 christos {
473 1.1 christos struct trad_frame_cache *cache =
474 1.1 christos i386nbsd_trapframe_cache (this_frame, this_cache);
475 1.1 christos
476 1.1 christos return trad_frame_get_register (cache, this_frame, regnum);
477 1.1 christos }
478 1.1 christos
479 1.1 christos static int
480 1.1.1.2 christos i386nbsd_trapframe_sniffer (const struct frame_unwind *self,
481 1.1 christos const frame_info_ptr& this_frame,
482 1.1 christos void **this_prologue_cache)
483 1.1 christos {
484 1.1 christos ULONGEST cs;
485 1.1 christos const char *name;
486 1.1 christos
487 1.1 christos /* Check Current Privilege Level and bail out if we're not executing
488 1.1 christos in kernel space. */
489 1.1 christos cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM);
490 1.1 christos if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
491 1.1 christos return 0;
492 1.1 christos
493 1.1 christos
494 1.1 christos find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
495 1.1 christos return (name && ((strcmp (name, "alltraps") == 0)
496 1.1 christos || (strcmp (name, "calltrap") == 0)
497 1.1 christos || (strcmp (name, "syscall1") == 0)
498 1.1 christos || (strcmp (name, "Xdoreti") == 0)
499 1.1 christos || (strncmp (name, "Xintr", 5) == 0)
500 1.1 christos || (strncmp (name, "Xhandle", 7) == 0)
501 1.1 christos || (strncmp (name, "Xpreempt", 8) == 0)
502 1.1 christos || (strncmp (name, "Xrecurse", 8) == 0)
503 1.1 christos || (strncmp (name, "Xresume", 7) == 0)
504 1.1 christos || (strncmp (name, "Xsoft", 5) == 0)
505 1.1 christos || (strncmp (name, "Xstray", 6) == 0)
506 1.1 christos || (strncmp (name, "Xsyscall", 8) == 0)
507 1.1 christos || (strncmp (name, "Xtrap", 5) == 0)
508 1.1 christos ));
509 1.1 christos }
510 1.1 christos
511 1.1 christos const struct frame_unwind i386nbsd_trapframe_unwind = {
512 1.1 christos /* FIXME: kettenis/20051219: This really is more like an interrupt
513 1.1 christos frame, but SIGTRAMP_FRAME would print <signal handler called>,
514 1.1 christos which really is not what we want here. */
515 1.1 christos "i386 trapframe",
516 1.1 christos NORMAL_FRAME,
517 1.1 christos default_frame_unwind_stop_reason,
518 1.1 christos i386nbsd_trapframe_this_id,
519 1.1 christos i386nbsd_trapframe_prev_register,
520 1.1 christos NULL,
521 1.1 christos i386nbsd_trapframe_sniffer
522 1.1 christos };
523 1.1 christos
524 1.1 christos static void
525 1.1 christos i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
526 1.1 christos {
527 1.1 christos i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
528 1.1 christos
529 1.1 christos /* Obviously NetBSD is BSD-based. */
530 1.1 christos i386bsd_init_abi (info, gdbarch);
531 1.1 christos
532 1.1 christos nbsd_init_abi (info, gdbarch);
533 1.1 christos
534 1.1 christos /* NetBSD has a different `struct reg'. */
535 1.1 christos tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
536 1.1 christos tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
537 1.1 christos tdep->sizeof_gregset = 16 * 4;
538 1.1 christos
539 1.1 christos /* NetBSD uses -freg-struct-return by default. */
540 1.1 christos tdep->struct_return = reg_struct_return;
541 1.1 christos
542 1.1 christos /* NetBSD uses tramp_frame sniffers for signal trampolines. */
543 1.1 christos tdep->sigcontext_addr= 0;
544 1.1 christos tdep->sigtramp_start = 0;
545 1.1 christos tdep->sigtramp_end = 0;
546 1.1 christos tdep->sigtramp_p = 0;
547 1.1 christos tdep->sc_reg_offset = 0;
548 1.1 christos tdep->sc_num_regs = 0;
549 1.1 christos
550 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
551 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
552 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
553 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
554 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
555 1.1 christos
556 1.1 christos /* Unwind kernel trap frames correctly. */
557 1.1 christos frame_unwind_prepend_unwinder (gdbarch, &i386nbsd_trapframe_unwind);
558 1.1 christos }
559 1.1 christos
560 1.1 christos /* NetBSD ELF. */
561 1.1 christos
562 1.1 christos static void
563 1.1 christos i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
564 1.1 christos {
565 1.1 christos i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
566 1.1 christos
567 1.1 christos /* It's still NetBSD. */
568 1.1 christos i386nbsd_init_abi (info, gdbarch);
569 1.1 christos
570 1.1 christos /* But ELF-based. */
571 1.1 christos i386_elf_init_abi (info, gdbarch);
572 1.1 christos
573 1.1 christos /* NetBSD ELF uses SVR4-style shared libraries. */
574 1.1 christos set_solib_svr4_fetch_link_map_offsets
575 1.1 christos (gdbarch, svr4_ilp32_fetch_link_map_offsets);
576 1.1 christos
577 1.1 christos /* NetBSD ELF uses -fpcc-struct-return by default. */
578 1.1 christos tdep->struct_return = pcc_struct_return;
579 1.1 christos }
580 1.1 christos
581 1.1 christos void _initialize_i386nbsd_tdep ();
582 1.1 christos void
583 1.1 christos _initialize_i386nbsd_tdep ()
584 1.1 christos {
585 1.1 christos gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
586 1.1 christos i386nbsdelf_init_abi);
587 }
588