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