* i386-nto-tdep.c (i386_nto_target): Remove definition.
[deliverable/binutils-gdb.git] / gdb / i386-nto-tdep.c
CommitLineData
911bc6ee 1/* Target-dependent code for QNX Neutrino x86.
1b883d35 2
0fb0cc75 3 Copyright (C) 2003, 2004, 2007, 2008, 2009 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;
f6792ef4 124 else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
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 int len;
138
139 *off = 0;
140 if (regset == NTO_REG_GENERAL)
141 {
142 if (regno == -1)
143 return NUM_GPREGS * 4;
144
145 *off = nto_reg_offset (regno);
146 if (*off == -1)
147 return 0;
148 return 4;
149 }
150 else if (regset == NTO_REG_FLOAT)
151 {
dbfb31a4
AR
152 unsigned off_adjust, regsize, regset_size, regno_base;
153 /* The following are flags indicating number in our fxsave_area. */
154 int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
155 && regno <= I387_FISEG_REGNUM (tdep));
156 int second_four = (regno > I387_FISEG_REGNUM (tdep)
157 && regno <= I387_FOP_REGNUM (tdep));
158 int st_reg = (regno >= I387_ST0_REGNUM (tdep)
159 && regno < I387_ST0_REGNUM (tdep) + 8);
160 int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
161 && regno < I387_MXCSR_REGNUM (tdep));
1b883d35
KW
162
163 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
164 {
165 off_adjust = 32;
166 regsize = 16;
167 regset_size = 512;
dbfb31a4
AR
168 /* fxsave_area structure. */
169 if (first_four)
170 {
171 /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
172 registers. */
173 regsize = 2; /* Two bytes each. */
174 off_adjust = 0;
175 regno_base = I387_FCTRL_REGNUM (tdep);
176 }
177 else if (second_four)
178 {
179 /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
180 regsize = 4;
181 off_adjust = 8;
182 regno_base = I387_FISEG_REGNUM (tdep) + 1;
183 }
184 else if (st_reg)
185 {
186 /* ST registers. */
187 regsize = 16;
188 off_adjust = 32;
189 regno_base = I387_ST0_REGNUM (tdep);
190 }
191 else if (xmm_reg)
192 {
193 /* XMM registers. */
194 regsize = 16;
195 off_adjust = 160;
196 regno_base = I387_XMM0_REGNUM (tdep);
197 }
198 else if (regno == I387_MXCSR_REGNUM (tdep))
199 {
200 regsize = 4;
201 off_adjust = 24;
202 regno_base = I387_MXCSR_REGNUM (tdep);
203 }
204 else
205 {
206 /* Whole regset. */
207 gdb_assert (regno == -1);
208 off_adjust = 0;
209 regno_base = 0;
210 regsize = regset_size;
211 }
1b883d35
KW
212 }
213 else
214 {
dbfb31a4
AR
215 regset_size = 108;
216 /* fsave_area structure. */
217 if (first_four || second_four)
218 {
219 /* fpu_control_word, ... , fpu_ds registers. */
220 regsize = 4;
221 off_adjust = 0;
222 regno_base = I387_FCTRL_REGNUM (tdep);
223 }
224 else if (st_reg)
225 {
226 /* One of ST registers. */
227 regsize = 10;
228 off_adjust = 7 * 4;
229 regno_base = I387_ST0_REGNUM (tdep);
230 }
231 else
232 {
233 /* Whole regset. */
234 gdb_assert (regno == -1);
235 off_adjust = 0;
236 regno_base = 0;
237 regsize = regset_size;
238 }
1b883d35
KW
239 }
240
dbfb31a4
AR
241 if (regno != -1)
242 *off = off_adjust + (regno - regno_base) * regsize;
243 else
244 *off = 0;
245 return regsize;
1b883d35
KW
246 }
247 return -1;
248}
249
250static int
468e3d51 251i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
252{
253 if (regset == NTO_REG_GENERAL)
254 {
255 int regno;
256
257 for (regno = 0; regno < NUM_GPREGS; regno++)
258 {
259 int offset = nto_reg_offset (regno);
260 if (offset != -1)
468e3d51 261 regcache_raw_collect (regcache, regno, data + offset);
1b883d35
KW
262 }
263 }
264 else if (regset == NTO_REG_FLOAT)
265 {
266 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 267 i387_collect_fxsave (regcache, -1, data);
1b883d35 268 else
468e3d51 269 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
270 }
271 else
272 return -1;
273
274 return 0;
275}
276
10458914
DJ
277/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
278 routine. */
911bc6ee 279
1b883d35 280static int
10458914 281i386nto_sigtramp_p (struct frame_info *this_frame)
1b883d35 282{
10458914 283 CORE_ADDR pc = get_frame_pc (this_frame);
911bc6ee
MK
284 char *name;
285
286 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
287 return name && strcmp ("__signalstub", name) == 0;
288}
289
acd5c798
MK
290#define I386_NTO_SIGCONTEXT_OFFSET 136
291
10458914
DJ
292/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
293 address of the associated sigcontext structure. */
acd5c798 294
1b883d35 295static CORE_ADDR
10458914 296i386nto_sigcontext_addr (struct frame_info *this_frame)
1b883d35 297{
acd5c798 298 char buf[4];
89929b45 299 CORE_ADDR sp;
acd5c798 300
10458914 301 get_frame_register (this_frame, I386_ESP_REGNUM, buf);
acd5c798 302 sp = extract_unsigned_integer (buf, 4);
1b883d35 303
acd5c798 304 return sp + I386_NTO_SIGCONTEXT_OFFSET;
1b883d35
KW
305}
306
307static void
47979a4b 308init_i386nto_ops (void)
1b883d35 309{
80b1849c
AR
310 nto_regset_id = i386nto_regset_id;
311 nto_supply_gregset = i386nto_supply_gregset;
312 nto_supply_fpregset = i386nto_supply_fpregset;
313 nto_supply_altregset = nto_dummy_supply_regset;
314 nto_supply_regset = i386nto_supply_regset;
315 nto_register_area = i386nto_register_area;
316 nto_regset_fill = i386nto_regset_fill;
317 nto_fetch_link_map_offsets =
17ca283a 318 svr4_ilp32_fetch_link_map_offsets;
1b883d35
KW
319}
320
321static void
322i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
323{
324 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
59215afb 325 static struct target_so_ops nto_svr4_so_ops;
1b883d35 326
d737fd7f
KW
327 /* Deal with our strange signals. */
328 nto_initialize_signals ();
329
1b883d35
KW
330 /* NTO uses ELF. */
331 i386_elf_init_abi (info, gdbarch);
332
71bd6bd4 333 /* Neutrino rewinds to look more normal. Need to override the i386
d3efc286 334 default which is [unfortunately] to decrement the PC. */
1b883d35
KW
335 set_gdbarch_decr_pc_after_break (gdbarch, 0);
336
3d171c85
MK
337 tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
338 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
339 tdep->sizeof_gregset = NUM_GPREGS * 4;
340
911bc6ee 341 tdep->sigtramp_p = i386nto_sigtramp_p;
1b883d35
KW
342 tdep->sigcontext_addr = i386nto_sigcontext_addr;
343 tdep->sc_pc_offset = 56;
344 tdep->sc_sp_offset = 68;
345
346 /* Setjmp()'s return PC saved in EDX (5). */
347 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
348
17ca283a
MK
349 set_solib_svr4_fetch_link_map_offsets
350 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
1b883d35 351
59215afb
UW
352 /* Initialize this lazily, to avoid an initialization order
353 dependency on solib-svr4.c's _initialize routine. */
354 if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
355 {
356 nto_svr4_so_ops = svr4_so_ops;
357
358 /* Our loader handles solib relocations differently than svr4. */
359 nto_svr4_so_ops.relocate_section_addresses
360 = nto_relocate_section_addresses;
1b883d35 361
59215afb
UW
362 /* Supply a nice function to find our solibs. */
363 nto_svr4_so_ops.find_and_open_solib
364 = nto_find_and_open_solib;
1b883d35 365
59215afb
UW
366 /* Our linker code is in libc. */
367 nto_svr4_so_ops.in_dynsym_resolve_code
368 = nto_in_dynsym_resolve_code;
369 }
370 set_solib_ops (gdbarch, &nto_svr4_so_ops);
1b883d35
KW
371}
372
63807e1d
PA
373/* Provide a prototype to silence -Wmissing-prototypes. */
374extern initialize_file_ftype _initialize_i386nto_tdep;
375
1b883d35
KW
376void
377_initialize_i386nto_tdep (void)
378{
d737fd7f 379 init_i386nto_ops ();
1b883d35
KW
380 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
381 i386nto_init_abi);
d737fd7f
KW
382 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
383 nto_elf_osabi_sniffer);
1b883d35 384}
This page took 0.624077 seconds and 4 git commands to generate.