Automatic date update in version.in
[external/binutils.git] / gdb / i386-nbsd-tdep.c
1 /* Target-dependent code for NetBSD/i386.
2
3    Copyright (C) 1988-2019 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "arch-utils.h"
22 #include "frame.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "regset.h"
26 #include "osabi.h"
27 #include "symtab.h"
28 #include "trad-frame.h"
29 #include "tramp-frame.h"
30
31 #include "i386-tdep.h"
32 #include "i387-tdep.h"
33 #include "nbsd-tdep.h"
34 #include "solib-svr4.h"
35
36 /* From <machine/reg.h>.  */
37 static int i386nbsd_r_reg_offset[] =
38 {
39   0 * 4,                        /* %eax */
40   1 * 4,                        /* %ecx */
41   2 * 4,                        /* %edx */
42   3 * 4,                        /* %ebx */
43   4 * 4,                        /* %esp */
44   5 * 4,                        /* %ebp */
45   6 * 4,                        /* %esi */
46   7 * 4,                        /* %edi */
47   8 * 4,                        /* %eip */
48   9 * 4,                        /* %eflags */
49   10 * 4,                       /* %cs */
50   11 * 4,                       /* %ss */
51   12 * 4,                       /* %ds */
52   13 * 4,                       /* %es */
53   14 * 4,                       /* %fs */
54   15 * 4                        /* %gs */
55 };
56
57 /* From <machine/signal.h>.  */
58 int i386nbsd_sc_reg_offset[] =
59 {
60   10 * 4,                       /* %eax */
61   9 * 4,                        /* %ecx */
62   8 * 4,                        /* %edx */
63   7 * 4,                        /* %ebx */
64   14 * 4,                       /* %esp */
65   6 * 4,                        /* %ebp */
66   5 * 4,                        /* %esi */
67   4 * 4,                        /* %edi */
68   11 * 4,                       /* %eip */
69   13 * 4,                       /* %eflags */
70   12 * 4,                       /* %cs */
71   15 * 4,                       /* %ss */
72   3 * 4,                        /* %ds */
73   2 * 4,                        /* %es */
74   1 * 4,                        /* %fs */
75   0 * 4                         /* %gs */
76 };
77
78 /* From <machine/mcontext.h>.  */
79 int i386nbsd_mc_reg_offset[] =
80 {
81   11 * 4,                       /* %eax */
82   10 * 4,                       /* %ecx */
83   9 * 4,                        /* %edx */
84   8 * 4,                        /* %ebx */
85   7 * 4,                        /* %esp */
86   6 * 4,                        /* %ebp */
87   5 * 4,                        /* %esi */
88   4 * 4,                        /* %edi */
89   14 * 4,                       /* %eip */
90   16 * 4,                       /* %eflags */
91   15 * 4,                       /* %cs */
92   18 * 4,                       /* %ss */
93   3 * 4,                        /* %ds */
94   2 * 4,                        /* %es */
95   1 * 4,                        /* %fs */
96   0 * 4                         /* %gs */
97 };
98
99 static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
100                                           struct frame_info *,
101                                           struct trad_frame_cache *,
102                                           CORE_ADDR);
103
104 static const struct tramp_frame i386nbsd_sigtramp_sc16 =
105 {
106   SIGTRAMP_FRAME,
107   1,
108   {
109    /* leal  0x10(%esp), %eax */
110    { 0x8d, ULONGEST_MAX },
111    { 0x44, ULONGEST_MAX },
112    { 0x24, ULONGEST_MAX },
113    { 0x10, ULONGEST_MAX },
114
115    /* pushl %eax */
116    { 0x50, ULONGEST_MAX },
117
118    /* pushl %eax */
119    { 0x50, ULONGEST_MAX },
120
121    /* movl  $0x127, %eax                # __sigreturn14 */
122    { 0xb8, ULONGEST_MAX },
123    { 0x27, ULONGEST_MAX },
124    {0x01, ULONGEST_MAX },
125    {0x00, ULONGEST_MAX },
126    {0x00, ULONGEST_MAX },
127
128    /* int   $0x80 */
129    { 0xcd, ULONGEST_MAX },
130    { 0x80, ULONGEST_MAX},
131
132    /* movl  $0x1, %eax          # exit */
133    { 0xb8, ULONGEST_MAX },
134    { 0x01, ULONGEST_MAX },
135    {0x00, ULONGEST_MAX },
136    {0x00, ULONGEST_MAX },
137    {0x00, ULONGEST_MAX },
138
139    /* int   $0x80 */
140    { 0xcd, ULONGEST_MAX },
141    { 0x80, ULONGEST_MAX},
142
143    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
144   },
145   i386nbsd_sigtramp_cache_init
146 };
147
148 static const struct tramp_frame i386nbsd_sigtramp_sc2 =
149 {
150   SIGTRAMP_FRAME,
151   1,
152   {
153    /* leal  0x0c(%esp), %eax */
154    { 0x8d, ULONGEST_MAX },
155    { 0x44, ULONGEST_MAX },
156    { 0x24, ULONGEST_MAX },
157    { 0x0c, ULONGEST_MAX },
158    /* movl  %eax, 0x4(%esp) */
159    { 0x89, ULONGEST_MAX },
160    { 0x44, ULONGEST_MAX },
161    { 0x24, ULONGEST_MAX },
162    { 0x04, ULONGEST_MAX },
163    /* movl  $0x127, %eax                # __sigreturn14 */
164    { 0xb8, ULONGEST_MAX },
165    { 0x27, ULONGEST_MAX },
166    {0x01, ULONGEST_MAX },
167    {0x00, ULONGEST_MAX },
168    {0x00, ULONGEST_MAX },
169    /* int   $0x80 */
170    { 0xcd, ULONGEST_MAX },
171    { 0x80, ULONGEST_MAX},
172    /* movl  %eax, 0x4(%esp) */
173    { 0x89, ULONGEST_MAX },
174    { 0x44, ULONGEST_MAX },
175    { 0x24, ULONGEST_MAX },
176    { 0x04, ULONGEST_MAX },
177    /* movl  $0x1, %eax */
178    { 0xb8, ULONGEST_MAX },
179    { 0x01, ULONGEST_MAX },
180    {0x00, ULONGEST_MAX },
181    {0x00, ULONGEST_MAX },
182    {0x00, ULONGEST_MAX },
183    /* int   $0x80 */
184    { 0xcd, ULONGEST_MAX },
185    { 0x80, ULONGEST_MAX},
186    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
187   },
188   i386nbsd_sigtramp_cache_init
189 };
190
191 static const struct tramp_frame i386nbsd_sigtramp_si2 =
192 {
193   SIGTRAMP_FRAME,
194   1,
195   {
196    /* movl  8(%esp),%eax */
197    { 0x8b, ULONGEST_MAX },
198    { 0x44, ULONGEST_MAX },
199    { 0x24, ULONGEST_MAX },
200    { 0x08, ULONGEST_MAX },
201    /* movl  %eax, 0x4(%esp) */
202    { 0x89, ULONGEST_MAX },
203    { 0x44, ULONGEST_MAX },
204    { 0x24, ULONGEST_MAX },
205    { 0x04, ULONGEST_MAX },
206    /* movl  $0x134, %eax            # setcontext */
207    { 0xb8, ULONGEST_MAX },
208    { 0x34, ULONGEST_MAX },
209    { 0x01, ULONGEST_MAX },
210    { 0x00, ULONGEST_MAX },
211    { 0x00, ULONGEST_MAX },
212    /* int   $0x80 */
213    { 0xcd, ULONGEST_MAX },
214    { 0x80, ULONGEST_MAX },
215    /* movl  %eax, 0x4(%esp) */
216    { 0x89, ULONGEST_MAX },
217    { 0x44, ULONGEST_MAX },
218    { 0x24, ULONGEST_MAX },
219    { 0x04, ULONGEST_MAX },
220    /* movl  $0x1, %eax */
221    { 0xb8, ULONGEST_MAX },
222    { 0x01, ULONGEST_MAX },
223    { 0x00, ULONGEST_MAX },
224    { 0x00, ULONGEST_MAX },
225    { 0x00, ULONGEST_MAX },
226    /* int   $0x80 */
227    { 0xcd, ULONGEST_MAX },
228    { 0x80, ULONGEST_MAX },
229    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
230   },
231   i386nbsd_sigtramp_cache_init
232 };
233
234 static const struct tramp_frame i386nbsd_sigtramp_si31 =
235 {
236   SIGTRAMP_FRAME,
237   1,
238   {
239    /* leal  0x8c(%esp), %eax */
240    { 0x8d, ULONGEST_MAX },
241    { 0x84, ULONGEST_MAX },
242    { 0x24, ULONGEST_MAX },
243    { 0x8c, ULONGEST_MAX },
244    { 0x00, ULONGEST_MAX },
245    { 0x00, ULONGEST_MAX },
246    { 0x00, ULONGEST_MAX },
247    /* movl  %eax, 0x4(%esp) */
248    { 0x89, ULONGEST_MAX },
249    { 0x44, ULONGEST_MAX },
250    { 0x24, ULONGEST_MAX },
251    { 0x04, ULONGEST_MAX },
252    /* movl  $0x134, %eax            # setcontext */
253    { 0xb8, ULONGEST_MAX },
254    { 0x34, ULONGEST_MAX },
255    { 0x01, ULONGEST_MAX },
256    { 0x00, ULONGEST_MAX },
257    { 0x00, ULONGEST_MAX },
258    /* int   $0x80 */
259    { 0xcd, ULONGEST_MAX },
260    { 0x80, ULONGEST_MAX},
261    /* movl  %eax, 0x4(%esp) */
262    { 0x89, ULONGEST_MAX },
263    { 0x44, ULONGEST_MAX },
264    { 0x24, ULONGEST_MAX },
265    { 0x04, ULONGEST_MAX },
266    /* movl  $0x1, %eax */
267    { 0xb8, ULONGEST_MAX },
268    { 0x01, ULONGEST_MAX },
269    {0x00, ULONGEST_MAX },
270    {0x00, ULONGEST_MAX },
271    {0x00, ULONGEST_MAX },
272    /* int   $0x80 */
273    { 0xcd, ULONGEST_MAX },
274    { 0x80, ULONGEST_MAX},
275    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
276   },
277   i386nbsd_sigtramp_cache_init
278 };
279
280 static const struct tramp_frame i386nbsd_sigtramp_si4 =
281 {
282   SIGTRAMP_FRAME,
283   1,
284   {
285    /* leal  0x8c(%esp), %eax */
286    { 0x8d, ULONGEST_MAX },
287    { 0x84, ULONGEST_MAX },
288    { 0x24, ULONGEST_MAX },
289    { 0x8c, ULONGEST_MAX },
290    { 0x00, ULONGEST_MAX },
291    { 0x00, ULONGEST_MAX },
292    { 0x00, ULONGEST_MAX },
293    /* movl  %eax, 0x4(%esp) */
294    { 0x89, ULONGEST_MAX },
295    { 0x44, ULONGEST_MAX },
296    { 0x24, ULONGEST_MAX },
297    { 0x04, ULONGEST_MAX },
298    /* movl  $0x134, %eax            # setcontext */
299    { 0xb8, ULONGEST_MAX },
300    { 0x34, ULONGEST_MAX },
301    { 0x01, ULONGEST_MAX },
302    { 0x00, ULONGEST_MAX },
303    { 0x00, ULONGEST_MAX },
304    /* int   $0x80 */
305    { 0xcd, ULONGEST_MAX },
306    { 0x80, ULONGEST_MAX},
307    /* movl   $0xffffffff,0x4(%esp) */
308    { 0xc7, ULONGEST_MAX },
309    { 0x44, ULONGEST_MAX },
310    { 0x24, ULONGEST_MAX },
311    { 0x04, ULONGEST_MAX },
312    { 0xff, ULONGEST_MAX },
313    { 0xff, ULONGEST_MAX },
314    { 0xff, ULONGEST_MAX },
315    { 0xff, ULONGEST_MAX },
316    /* movl  $0x1, %eax */
317    { 0xb8, ULONGEST_MAX },
318    { 0x01, ULONGEST_MAX },
319    {0x00, ULONGEST_MAX },
320    {0x00, ULONGEST_MAX },
321    {0x00, ULONGEST_MAX },
322    /* int   $0x80 */
323    { 0xcd, ULONGEST_MAX },
324    { 0x80, ULONGEST_MAX},
325    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
326   },
327   i386nbsd_sigtramp_cache_init
328 };
329
330 static void
331 i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
332                               struct frame_info *this_frame,
333                               struct trad_frame_cache *this_cache,
334                               CORE_ADDR func)
335 {
336   struct gdbarch *gdbarch = get_frame_arch (this_frame);
337   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
338   CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
339   CORE_ADDR base;
340   int *reg_offset;
341   int num_regs;
342   int i;
343
344   if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
345     {
346       reg_offset = i386nbsd_sc_reg_offset;
347       num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
348
349       /* Read in the sigcontext address.  */
350       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
351     }
352   else
353     {
354       reg_offset = i386nbsd_mc_reg_offset;
355       num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
356
357       /* Read in the ucontext address.  */
358       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
359       /* offsetof(ucontext_t, uc_mcontext) == 36 */
360       base += 36;
361     }
362
363   for (i = 0; i < num_regs; i++)
364     if (reg_offset[i] != -1)
365       trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
366
367   /* Construct the frame ID using the function start.  */
368   trad_frame_set_id (this_cache, frame_id_build (sp, func));
369 }
370 \f
371
372 static void 
373 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
374 {
375   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
376
377   /* Obviously NetBSD is BSD-based.  */
378   i386bsd_init_abi (info, gdbarch);
379
380   /* NetBSD has a different `struct reg'.  */
381   tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
382   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
383   tdep->sizeof_gregset = 16 * 4;
384
385   /* NetBSD uses -freg-struct-return by default.  */
386   tdep->struct_return = reg_struct_return;
387
388   /* NetBSD uses tramp_frame sniffers for signal trampolines.  */
389   tdep->sigcontext_addr= 0;
390   tdep->sigtramp_start = 0;
391   tdep->sigtramp_end = 0;
392   tdep->sigtramp_p = 0;
393   tdep->sc_reg_offset = 0;
394   tdep->sc_num_regs = 0;
395
396   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
397   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
398   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
399   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
400   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
401 }
402
403 /* NetBSD ELF.  */
404
405 static void
406 i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
407 {
408   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
409
410   /* It's still NetBSD.  */
411   i386nbsd_init_abi (info, gdbarch);
412
413   /* But ELF-based.  */
414   i386_elf_init_abi (info, gdbarch);
415
416   /* NetBSD ELF uses SVR4-style shared libraries.  */
417   set_solib_svr4_fetch_link_map_offsets
418     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
419
420   /* NetBSD ELF uses -fpcc-struct-return by default.  */
421   tdep->struct_return = pcc_struct_return;
422 }
423
424 void
425 _initialize_i386nbsd_tdep (void)
426 {
427   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
428                           i386nbsdelf_init_abi);
429 }