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