Include gdb_assert.h in common-defs.h
[platform/upstream/binutils.git] / gdb / i386nbsd-tdep.c
1 /* Target-dependent code for NetBSD/i386.
2
3    Copyright (C) 1988-2014 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 <string.h>
32
33 #include "i386-tdep.h"
34 #include "i387-tdep.h"
35 #include "nbsd-tdep.h"
36 #include "solib-svr4.h"
37
38 /* From <machine/reg.h>.  */
39 static int i386nbsd_r_reg_offset[] =
40 {
41   0 * 4,                        /* %eax */
42   1 * 4,                        /* %ecx */
43   2 * 4,                        /* %edx */
44   3 * 4,                        /* %ebx */
45   4 * 4,                        /* %esp */
46   5 * 4,                        /* %ebp */
47   6 * 4,                        /* %esi */
48   7 * 4,                        /* %edi */
49   8 * 4,                        /* %eip */
50   9 * 4,                        /* %eflags */
51   10 * 4,                       /* %cs */
52   11 * 4,                       /* %ss */
53   12 * 4,                       /* %ds */
54   13 * 4,                       /* %es */
55   14 * 4,                       /* %fs */
56   15 * 4                        /* %gs */
57 };
58
59 /* From <machine/signal.h>.  */
60 int i386nbsd_sc_reg_offset[] =
61 {
62   10 * 4,                       /* %eax */
63   9 * 4,                        /* %ecx */
64   8 * 4,                        /* %edx */
65   7 * 4,                        /* %ebx */
66   14 * 4,                       /* %esp */
67   6 * 4,                        /* %ebp */
68   5 * 4,                        /* %esi */
69   4 * 4,                        /* %edi */
70   11 * 4,                       /* %eip */
71   13 * 4,                       /* %eflags */
72   12 * 4,                       /* %cs */
73   15 * 4,                       /* %ss */
74   3 * 4,                        /* %ds */
75   2 * 4,                        /* %es */
76   1 * 4,                        /* %fs */
77   0 * 4                         /* %gs */
78 };
79
80 /* From <machine/mcontext.h>.  */
81 int i386nbsd_mc_reg_offset[] =
82 {
83   11 * 4,                       /* %eax */
84   10 * 4,                       /* %ecx */
85   9 * 4,                        /* %edx */
86   8 * 4,                        /* %ebx */
87   7 * 4,                        /* %esp */
88   6 * 4,                        /* %ebp */
89   5 * 4,                        /* %esi */
90   4 * 4,                        /* %edi */
91   14 * 4,                       /* %eip */
92   16 * 4,                       /* %eflags */
93   15 * 4,                       /* %cs */
94   18 * 4,                       /* %ss */
95   3 * 4,                        /* %ds */
96   2 * 4,                        /* %es */
97   1 * 4,                        /* %fs */
98   0 * 4                         /* %gs */
99 };
100
101 static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
102                                           struct frame_info *,
103                                           struct trad_frame_cache *,
104                                           CORE_ADDR);
105
106 static const struct tramp_frame i386nbsd_sigtramp_sc16 =
107 {
108   SIGTRAMP_FRAME,
109   1,
110   {
111     { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 },
112                         /* leal  0x10(%esp), %eax */
113     { 0x50, -1 },       /* pushl %eax */
114     { 0x50, -1 },       /* pushl %eax */
115     { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
116                         /* movl  $0x127, %eax           # __sigreturn14 */
117     { 0xcd, -1 }, { 0x80, -1},
118                         /* int   $0x80 */
119     { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
120                         /* movl  $0x1, %eax             # exit */
121     { 0xcd, -1 }, { 0x80, -1},
122                         /* int   $0x80 */
123     { TRAMP_SENTINEL_INSN, -1 }
124   },
125   i386nbsd_sigtramp_cache_init
126 };
127
128 static const struct tramp_frame i386nbsd_sigtramp_sc2 =
129 {
130   SIGTRAMP_FRAME,
131   1,
132   {
133     { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 },
134                         /* leal  0x0c(%esp), %eax */
135     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
136                         /* movl  %eax, 0x4(%esp) */
137     { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
138                         /* movl  $0x127, %eax           # __sigreturn14 */
139     { 0xcd, -1 }, { 0x80, -1},
140                         /* int   $0x80 */
141     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
142                         /* movl  %eax, 0x4(%esp) */
143     { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
144                         /* movl  $0x1, %eax */
145     { 0xcd, -1 }, { 0x80, -1},
146                         /* int   $0x80 */
147     { TRAMP_SENTINEL_INSN, -1 }
148   },
149   i386nbsd_sigtramp_cache_init
150 };
151
152 static const struct tramp_frame i386nbsd_sigtramp_si2 =
153 {
154   SIGTRAMP_FRAME,
155   1,
156   {
157     { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 },
158                         /* movl  8(%esp),%eax */
159     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
160                         /* movl  %eax, 0x4(%esp) */
161     { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
162                         /* movl  $0x134, %eax            # setcontext */
163     { 0xcd, -1 }, { 0x80, -1 },
164                         /* int   $0x80 */
165     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
166                         /* movl  %eax, 0x4(%esp) */
167     { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
168                         /* movl  $0x1, %eax */
169     { 0xcd, -1 }, { 0x80, -1 },
170                         /* int   $0x80 */
171     { TRAMP_SENTINEL_INSN, -1 }
172   },
173   i386nbsd_sigtramp_cache_init
174 };
175
176 static const struct tramp_frame i386nbsd_sigtramp_si31 =
177 {
178   SIGTRAMP_FRAME,
179   1,
180   {
181     { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
182         { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
183                         /* leal  0x8c(%esp), %eax */
184     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
185                         /* movl  %eax, 0x4(%esp) */
186     { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
187                         /* movl  $0x134, %eax            # setcontext */
188     { 0xcd, -1 }, { 0x80, -1},
189                         /* int   $0x80 */
190     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
191                         /* movl  %eax, 0x4(%esp) */
192     { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
193                         /* movl  $0x1, %eax */
194     { 0xcd, -1 }, { 0x80, -1},
195                         /* int   $0x80 */
196     { TRAMP_SENTINEL_INSN, -1 }
197   },
198   i386nbsd_sigtramp_cache_init
199 };
200
201 static const struct tramp_frame i386nbsd_sigtramp_si4 =
202 {
203   SIGTRAMP_FRAME,
204   1,
205   {
206     { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
207         { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
208                         /* leal  0x8c(%esp), %eax */
209     { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
210                         /* movl  %eax, 0x4(%esp) */
211     { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
212                         /* movl  $0x134, %eax            # setcontext */
213     { 0xcd, -1 }, { 0x80, -1},
214                         /* int   $0x80 */
215     { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
216         { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 },
217                         /* movl   $0xffffffff,0x4(%esp) */
218     { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
219                         /* movl  $0x1, %eax */
220     { 0xcd, -1 }, { 0x80, -1},
221                         /* int   $0x80 */
222     { TRAMP_SENTINEL_INSN, -1 }
223   },
224   i386nbsd_sigtramp_cache_init
225 };
226
227 static void
228 i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
229                               struct frame_info *this_frame,
230                               struct trad_frame_cache *this_cache,
231                               CORE_ADDR func)
232 {
233   struct gdbarch *gdbarch = get_frame_arch (this_frame);
234   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
235   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
236   CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
237   CORE_ADDR base;
238   int *reg_offset;
239   int num_regs;
240   int i;
241
242   if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
243     {
244       reg_offset = i386nbsd_sc_reg_offset;
245       num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
246
247       /* Read in the sigcontext address.  */
248       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
249     }
250   else
251     {
252       reg_offset = i386nbsd_mc_reg_offset;
253       num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
254
255       /* Read in the ucontext address.  */
256       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
257       /* offsetof(ucontext_t, uc_mcontext) == 36 */
258       base += 36;
259     }
260
261   for (i = 0; i < num_regs; i++)
262     if (reg_offset[i] != -1)
263       trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
264
265   /* Construct the frame ID using the function start.  */
266   trad_frame_set_id (this_cache, frame_id_build (sp, func));
267 }
268 \f
269
270 static void 
271 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
272 {
273   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
274
275   /* Obviously NetBSD is BSD-based.  */
276   i386bsd_init_abi (info, gdbarch);
277
278   /* NetBSD has a different `struct reg'.  */
279   tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
280   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
281   tdep->sizeof_gregset = 16 * 4;
282
283   /* NetBSD uses -freg-struct-return by default.  */
284   tdep->struct_return = reg_struct_return;
285
286   /* NetBSD uses tramp_frame sniffers for signal trampolines.  */
287   tdep->sigcontext_addr= 0;
288   tdep->sigtramp_start = 0;
289   tdep->sigtramp_end = 0;
290   tdep->sigtramp_p = 0;
291   tdep->sc_reg_offset = 0;
292   tdep->sc_num_regs = 0;
293
294   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
295   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
296   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
297   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
298   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
299 }
300
301 /* NetBSD ELF.  */
302
303 static void
304 i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
305 {
306   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
307
308   /* It's still NetBSD.  */
309   i386nbsd_init_abi (info, gdbarch);
310
311   /* But ELF-based.  */
312   i386_elf_init_abi (info, gdbarch);
313
314   /* NetBSD ELF uses SVR4-style shared libraries.  */
315   set_solib_svr4_fetch_link_map_offsets
316     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
317
318   /* NetBSD ELF uses -fpcc-struct-return by default.  */
319   tdep->struct_return = pcc_struct_return;
320 }
321
322 /* Provide a prototype to silence -Wmissing-prototypes.  */
323 extern initialize_file_ftype _initialize_i386nbsd_tdep;
324
325 void
326 _initialize_i386nbsd_tdep (void)
327 {
328   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF,
329                           i386nbsdelf_init_abi);
330 }