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