Include gdb_assert.h in common-defs.h
[deliverable/binutils-gdb.git] / gdb / i386-nto-tdep.c
CommitLineData
911bc6ee 1/* Target-dependent code for QNX Neutrino x86.
1b883d35 2
ecd75fc8 3 Copyright (C) 2003-2014 Free Software Foundation, Inc.
1b883d35
KW
4
5 Contributed by QNX Software Systems Ltd.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
1b883d35
KW
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1b883d35 21
1b883d35
KW
22#include "defs.h"
23#include "frame.h"
17ca283a 24#include "osabi.h"
1b883d35 25#include "regcache.h"
17ca283a
MK
26#include "target.h"
27
0e9f083f 28#include <string.h>
17ca283a 29
1b883d35 30#include "i386-tdep.h"
1b883d35 31#include "i387-tdep.h"
17ca283a 32#include "nto-tdep.h"
59215afb 33#include "solib.h"
17ca283a 34#include "solib-svr4.h"
1b883d35
KW
35
36#ifndef X86_CPU_FXSR
37#define X86_CPU_FXSR (1L << 12)
38#endif
39
40/* Why 13? Look in our /usr/include/x86/context.h header at the
41 x86_cpu_registers structure and you'll see an 'exx' junk register
42 that is just filler. Don't ask me, ask the kernel guys. */
43#define NUM_GPREGS 13
44
3d171c85
MK
45/* Mapping between the general-purpose registers in `struct xxx'
46 format and GDB's register cache layout. */
47
48/* From <x86/context.h>. */
49static int i386nto_gregset_reg_offset[] =
50{
51 7 * 4, /* %eax */
52 6 * 4, /* %ecx */
53 5 * 4, /* %edx */
54 4 * 4, /* %ebx */
55 11 * 4, /* %esp */
56 2 * 4, /* %epb */
57 1 * 4, /* %esi */
58 0 * 4, /* %edi */
59 8 * 4, /* %eip */
60 10 * 4, /* %eflags */
61 9 * 4, /* %cs */
62 12 * 4, /* %ss */
63 -1 /* filler */
1b883d35
KW
64};
65
3d171c85
MK
66/* Given a GDB register number REGNUM, return the offset into
67 Neutrino's register structure or -1 if the register is unknown. */
d737fd7f 68
1b883d35 69static int
3d171c85 70nto_reg_offset (int regnum)
1b883d35 71{
3d171c85
MK
72 if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
73 return i386nto_gregset_reg_offset[regnum];
74
75 return -1;
1b883d35
KW
76}
77
78static void
468e3d51 79i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
1b883d35 80{
875f8d0e
UW
81 struct gdbarch *gdbarch = get_regcache_arch (regcache);
82 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35 83
3d171c85 84 gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset);
ecc37a5a
AA
85 i386_gregset.supply_regset (&i386_gregset, regcache, -1,
86 gpregs, NUM_GPREGS * 4);
1b883d35
KW
87}
88
89static void
468e3d51 90i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
1b883d35
KW
91{
92 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 93 i387_supply_fxsave (regcache, -1, fpregs);
1b883d35 94 else
468e3d51 95 i387_supply_fsave (regcache, -1, fpregs);
1b883d35
KW
96}
97
98static void
468e3d51 99i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
1b883d35
KW
100{
101 switch (regset)
102 {
3d171c85 103 case NTO_REG_GENERAL:
468e3d51 104 i386nto_supply_gregset (regcache, data);
1b883d35
KW
105 break;
106 case NTO_REG_FLOAT:
468e3d51 107 i386nto_supply_fpregset (regcache, data);
1b883d35
KW
108 break;
109 }
110}
111
112static int
113i386nto_regset_id (int regno)
114{
115 if (regno == -1)
116 return NTO_REG_END;
f6792ef4 117 else if (regno < I386_NUM_GREGS)
1b883d35 118 return NTO_REG_GENERAL;
90884b2b 119 else if (regno < I386_NUM_GREGS + I387_NUM_REGS)
1b883d35 120 return NTO_REG_FLOAT;
dbfb31a4
AR
121 else if (regno < I386_SSE_NUM_REGS)
122 return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
1b883d35
KW
123
124 return -1; /* Error. */
125}
126
127static int
60441ab9
UW
128i386nto_register_area (struct gdbarch *gdbarch,
129 int regno, int regset, unsigned *off)
1b883d35 130{
dbfb31a4 131 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35
KW
132
133 *off = 0;
134 if (regset == NTO_REG_GENERAL)
135 {
136 if (regno == -1)
137 return NUM_GPREGS * 4;
138
139 *off = nto_reg_offset (regno);
140 if (*off == -1)
141 return 0;
142 return 4;
143 }
144 else if (regset == NTO_REG_FLOAT)
145 {
dbfb31a4
AR
146 unsigned off_adjust, regsize, regset_size, regno_base;
147 /* The following are flags indicating number in our fxsave_area. */
148 int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
149 && regno <= I387_FISEG_REGNUM (tdep));
150 int second_four = (regno > I387_FISEG_REGNUM (tdep)
151 && regno <= I387_FOP_REGNUM (tdep));
152 int st_reg = (regno >= I387_ST0_REGNUM (tdep)
153 && regno < I387_ST0_REGNUM (tdep) + 8);
154 int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
155 && regno < I387_MXCSR_REGNUM (tdep));
1b883d35
KW
156
157 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
158 {
159 off_adjust = 32;
160 regsize = 16;
161 regset_size = 512;
dbfb31a4
AR
162 /* fxsave_area structure. */
163 if (first_four)
164 {
165 /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
166 registers. */
167 regsize = 2; /* Two bytes each. */
168 off_adjust = 0;
169 regno_base = I387_FCTRL_REGNUM (tdep);
170 }
171 else if (second_four)
172 {
173 /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
174 regsize = 4;
175 off_adjust = 8;
176 regno_base = I387_FISEG_REGNUM (tdep) + 1;
177 }
178 else if (st_reg)
179 {
180 /* ST registers. */
181 regsize = 16;
182 off_adjust = 32;
183 regno_base = I387_ST0_REGNUM (tdep);
184 }
185 else if (xmm_reg)
186 {
187 /* XMM registers. */
188 regsize = 16;
189 off_adjust = 160;
190 regno_base = I387_XMM0_REGNUM (tdep);
191 }
192 else if (regno == I387_MXCSR_REGNUM (tdep))
193 {
194 regsize = 4;
195 off_adjust = 24;
196 regno_base = I387_MXCSR_REGNUM (tdep);
197 }
198 else
199 {
200 /* Whole regset. */
201 gdb_assert (regno == -1);
202 off_adjust = 0;
203 regno_base = 0;
204 regsize = regset_size;
205 }
1b883d35
KW
206 }
207 else
208 {
dbfb31a4
AR
209 regset_size = 108;
210 /* fsave_area structure. */
211 if (first_four || second_four)
212 {
213 /* fpu_control_word, ... , fpu_ds registers. */
214 regsize = 4;
215 off_adjust = 0;
216 regno_base = I387_FCTRL_REGNUM (tdep);
217 }
218 else if (st_reg)
219 {
220 /* One of ST registers. */
221 regsize = 10;
222 off_adjust = 7 * 4;
223 regno_base = I387_ST0_REGNUM (tdep);
224 }
225 else
226 {
227 /* Whole regset. */
228 gdb_assert (regno == -1);
229 off_adjust = 0;
230 regno_base = 0;
231 regsize = regset_size;
232 }
1b883d35
KW
233 }
234
dbfb31a4
AR
235 if (regno != -1)
236 *off = off_adjust + (regno - regno_base) * regsize;
237 else
238 *off = 0;
239 return regsize;
1b883d35
KW
240 }
241 return -1;
242}
243
244static int
468e3d51 245i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
246{
247 if (regset == NTO_REG_GENERAL)
248 {
249 int regno;
250
251 for (regno = 0; regno < NUM_GPREGS; regno++)
252 {
253 int offset = nto_reg_offset (regno);
254 if (offset != -1)
468e3d51 255 regcache_raw_collect (regcache, regno, data + offset);
1b883d35
KW
256 }
257 }
258 else if (regset == NTO_REG_FLOAT)
259 {
260 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 261 i387_collect_fxsave (regcache, -1, data);
1b883d35 262 else
468e3d51 263 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
264 }
265 else
266 return -1;
267
268 return 0;
269}
270
10458914
DJ
271/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
272 routine. */
911bc6ee 273
1b883d35 274static int
10458914 275i386nto_sigtramp_p (struct frame_info *this_frame)
1b883d35 276{
10458914 277 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 278 const char *name;
911bc6ee
MK
279
280 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
281 return name && strcmp ("__signalstub", name) == 0;
282}
283
10458914
DJ
284/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
285 address of the associated sigcontext structure. */
acd5c798 286
1b883d35 287static CORE_ADDR
10458914 288i386nto_sigcontext_addr (struct frame_info *this_frame)
1b883d35 289{
e17a4113
UW
290 struct gdbarch *gdbarch = get_frame_arch (this_frame);
291 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
e362b510 292 gdb_byte buf[4];
19a934d8 293 CORE_ADDR ptrctx;
acd5c798 294
19a934d8
AR
295 /* We store __ucontext_t addr in EDI register. */
296 get_frame_register (this_frame, I386_EDI_REGNUM, buf);
e17a4113 297 ptrctx = extract_unsigned_integer (buf, 4, byte_order);
19a934d8 298 ptrctx += 24 /* Context pointer is at this offset. */;
1b883d35 299
19a934d8 300 return ptrctx;
1b883d35
KW
301}
302
303static void
47979a4b 304init_i386nto_ops (void)
1b883d35 305{
80b1849c
AR
306 nto_regset_id = i386nto_regset_id;
307 nto_supply_gregset = i386nto_supply_gregset;
308 nto_supply_fpregset = i386nto_supply_fpregset;
309 nto_supply_altregset = nto_dummy_supply_regset;
310 nto_supply_regset = i386nto_supply_regset;
311 nto_register_area = i386nto_register_area;
312 nto_regset_fill = i386nto_regset_fill;
313 nto_fetch_link_map_offsets =
17ca283a 314 svr4_ilp32_fetch_link_map_offsets;
1b883d35
KW
315}
316
317static void
318i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
319{
320 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
59215afb 321 static struct target_so_ops nto_svr4_so_ops;
1b883d35 322
d737fd7f
KW
323 /* Deal with our strange signals. */
324 nto_initialize_signals ();
325
1b883d35
KW
326 /* NTO uses ELF. */
327 i386_elf_init_abi (info, gdbarch);
328
71bd6bd4 329 /* Neutrino rewinds to look more normal. Need to override the i386
d3efc286 330 default which is [unfortunately] to decrement the PC. */
1b883d35
KW
331 set_gdbarch_decr_pc_after_break (gdbarch, 0);
332
3d171c85
MK
333 tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
334 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
335 tdep->sizeof_gregset = NUM_GPREGS * 4;
336
911bc6ee 337 tdep->sigtramp_p = i386nto_sigtramp_p;
1b883d35 338 tdep->sigcontext_addr = i386nto_sigcontext_addr;
19a934d8
AR
339 tdep->sc_reg_offset = i386nto_gregset_reg_offset;
340 tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
1b883d35
KW
341
342 /* Setjmp()'s return PC saved in EDX (5). */
343 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
344
17ca283a
MK
345 set_solib_svr4_fetch_link_map_offsets
346 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
1b883d35 347
59215afb
UW
348 /* Initialize this lazily, to avoid an initialization order
349 dependency on solib-svr4.c's _initialize routine. */
350 if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
351 {
352 nto_svr4_so_ops = svr4_so_ops;
353
354 /* Our loader handles solib relocations differently than svr4. */
355 nto_svr4_so_ops.relocate_section_addresses
356 = nto_relocate_section_addresses;
1b883d35 357
59215afb
UW
358 /* Supply a nice function to find our solibs. */
359 nto_svr4_so_ops.find_and_open_solib
360 = nto_find_and_open_solib;
1b883d35 361
59215afb
UW
362 /* Our linker code is in libc. */
363 nto_svr4_so_ops.in_dynsym_resolve_code
364 = nto_in_dynsym_resolve_code;
365 }
366 set_solib_ops (gdbarch, &nto_svr4_so_ops);
1b883d35
KW
367}
368
63807e1d
PA
369/* Provide a prototype to silence -Wmissing-prototypes. */
370extern initialize_file_ftype _initialize_i386nto_tdep;
371
1b883d35
KW
372void
373_initialize_i386nto_tdep (void)
374{
d737fd7f 375 init_i386nto_ops ();
1b883d35
KW
376 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
377 i386nto_init_abi);
d737fd7f
KW
378 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
379 nto_elf_osabi_sniffer);
1b883d35 380}
This page took 1.208649 seconds and 4 git commands to generate.