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