* trad-frame.c (struct trad_frame_cache): Rename next_frame to this_frame.
[deliverable/binutils-gdb.git] / gdb / i386-nto-tdep.c
CommitLineData
911bc6ee 1/* Target-dependent code for QNX Neutrino x86.
1b883d35 2
9b254dd1 3 Copyright (C) 2003, 2004, 2007, 2008 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 36
3d171c85
MK
37/* Target vector for QNX NTO x86. */
38static struct nto_target_ops i386_nto_target;
39
1b883d35
KW
40#ifndef X86_CPU_FXSR
41#define X86_CPU_FXSR (1L << 12)
42#endif
43
44/* Why 13? Look in our /usr/include/x86/context.h header at the
45 x86_cpu_registers structure and you'll see an 'exx' junk register
46 that is just filler. Don't ask me, ask the kernel guys. */
47#define NUM_GPREGS 13
48
3d171c85
MK
49/* Mapping between the general-purpose registers in `struct xxx'
50 format and GDB's register cache layout. */
51
52/* From <x86/context.h>. */
53static int i386nto_gregset_reg_offset[] =
54{
55 7 * 4, /* %eax */
56 6 * 4, /* %ecx */
57 5 * 4, /* %edx */
58 4 * 4, /* %ebx */
59 11 * 4, /* %esp */
60 2 * 4, /* %epb */
61 1 * 4, /* %esi */
62 0 * 4, /* %edi */
63 8 * 4, /* %eip */
64 10 * 4, /* %eflags */
65 9 * 4, /* %cs */
66 12 * 4, /* %ss */
67 -1 /* filler */
1b883d35
KW
68};
69
3d171c85
MK
70/* Given a GDB register number REGNUM, return the offset into
71 Neutrino's register structure or -1 if the register is unknown. */
d737fd7f 72
1b883d35 73static int
3d171c85 74nto_reg_offset (int regnum)
1b883d35 75{
3d171c85
MK
76 if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
77 return i386nto_gregset_reg_offset[regnum];
78
79 return -1;
1b883d35
KW
80}
81
82static void
468e3d51 83i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
1b883d35 84{
875f8d0e
UW
85 struct gdbarch *gdbarch = get_regcache_arch (regcache);
86 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35 87
3d171c85 88 if(tdep->gregset == NULL)
875f8d0e 89 tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
3d171c85
MK
90 i386_collect_gregset);
91
92 gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset);
468e3d51 93 tdep->gregset->supply_regset (tdep->gregset, regcache, -1,
3d171c85 94 gpregs, NUM_GPREGS * 4);
1b883d35
KW
95}
96
97static void
468e3d51 98i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
1b883d35
KW
99{
100 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 101 i387_supply_fxsave (regcache, -1, fpregs);
1b883d35 102 else
468e3d51 103 i387_supply_fsave (regcache, -1, fpregs);
1b883d35
KW
104}
105
106static void
468e3d51 107i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
1b883d35
KW
108{
109 switch (regset)
110 {
3d171c85 111 case NTO_REG_GENERAL:
468e3d51 112 i386nto_supply_gregset (regcache, data);
1b883d35
KW
113 break;
114 case NTO_REG_FLOAT:
468e3d51 115 i386nto_supply_fpregset (regcache, data);
1b883d35
KW
116 break;
117 }
118}
119
120static int
121i386nto_regset_id (int regno)
122{
123 if (regno == -1)
124 return NTO_REG_END;
f6792ef4 125 else if (regno < I386_NUM_GREGS)
1b883d35 126 return NTO_REG_GENERAL;
f6792ef4 127 else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
1b883d35
KW
128 return NTO_REG_FLOAT;
129
130 return -1; /* Error. */
131}
132
133static int
134i386nto_register_area (int regno, int regset, unsigned *off)
135{
136 int len;
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 {
151 unsigned off_adjust, regsize, regset_size;
152
153 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
154 {
155 off_adjust = 32;
156 regsize = 16;
157 regset_size = 512;
158 }
159 else
160 {
161 off_adjust = 28;
162 regsize = 10;
163 regset_size = 128;
164 }
165
166 if (regno == -1)
167 return regset_size;
168
3e8c568d
UW
169 *off = (regno - gdbarch_fp0_regnum (current_gdbarch))
170 * regsize + off_adjust;
1b883d35
KW
171 return 10;
172 /* Why 10 instead of regsize? GDB only stores 10 bytes per FP
173 register so if we're sending a register back to the target,
174 we only want pdebug to write 10 bytes so as not to clobber
175 the reserved 6 bytes in the fxsave structure. */
176 }
177 return -1;
178}
179
180static int
468e3d51 181i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
182{
183 if (regset == NTO_REG_GENERAL)
184 {
185 int regno;
186
187 for (regno = 0; regno < NUM_GPREGS; regno++)
188 {
189 int offset = nto_reg_offset (regno);
190 if (offset != -1)
468e3d51 191 regcache_raw_collect (regcache, regno, data + offset);
1b883d35
KW
192 }
193 }
194 else if (regset == NTO_REG_FLOAT)
195 {
196 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 197 i387_collect_fxsave (regcache, -1, data);
1b883d35 198 else
468e3d51 199 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
200 }
201 else
202 return -1;
203
204 return 0;
205}
206
911bc6ee
MK
207/* Return whether the frame preceding NEXT_FRAME corresponds to a QNX
208 Neutrino sigtramp routine. */
209
1b883d35 210static int
911bc6ee 211i386nto_sigtramp_p (struct frame_info *next_frame)
1b883d35 212{
911bc6ee
MK
213 CORE_ADDR pc = frame_pc_unwind (next_frame);
214 char *name;
215
216 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
217 return name && strcmp ("__signalstub", name) == 0;
218}
219
acd5c798
MK
220#define I386_NTO_SIGCONTEXT_OFFSET 136
221
222/* Assuming NEXT_FRAME is a frame following a QNX Neutrino sigtramp
223 routine, return the address of the associated sigcontext structure. */
224
1b883d35 225static CORE_ADDR
acd5c798 226i386nto_sigcontext_addr (struct frame_info *next_frame)
1b883d35 227{
acd5c798 228 char buf[4];
89929b45 229 CORE_ADDR sp;
acd5c798 230
911bc6ee 231 frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
acd5c798 232 sp = extract_unsigned_integer (buf, 4);
1b883d35 233
acd5c798 234 return sp + I386_NTO_SIGCONTEXT_OFFSET;
1b883d35
KW
235}
236
237static void
47979a4b 238init_i386nto_ops (void)
1b883d35 239{
d737fd7f
KW
240 i386_nto_target.regset_id = i386nto_regset_id;
241 i386_nto_target.supply_gregset = i386nto_supply_gregset;
242 i386_nto_target.supply_fpregset = i386nto_supply_fpregset;
243 i386_nto_target.supply_altregset = nto_dummy_supply_regset;
244 i386_nto_target.supply_regset = i386nto_supply_regset;
245 i386_nto_target.register_area = i386nto_register_area;
246 i386_nto_target.regset_fill = i386nto_regset_fill;
247 i386_nto_target.fetch_link_map_offsets =
17ca283a 248 svr4_ilp32_fetch_link_map_offsets;
1b883d35
KW
249}
250
251static void
252i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
253{
254 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
59215afb 255 static struct target_so_ops nto_svr4_so_ops;
1b883d35 256
d737fd7f
KW
257 /* Deal with our strange signals. */
258 nto_initialize_signals ();
259
1b883d35
KW
260 /* NTO uses ELF. */
261 i386_elf_init_abi (info, gdbarch);
262
71bd6bd4 263 /* Neutrino rewinds to look more normal. Need to override the i386
d3efc286 264 default which is [unfortunately] to decrement the PC. */
1b883d35
KW
265 set_gdbarch_decr_pc_after_break (gdbarch, 0);
266
3d171c85
MK
267 tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
268 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
269 tdep->sizeof_gregset = NUM_GPREGS * 4;
270
911bc6ee 271 tdep->sigtramp_p = i386nto_sigtramp_p;
1b883d35
KW
272 tdep->sigcontext_addr = i386nto_sigcontext_addr;
273 tdep->sc_pc_offset = 56;
274 tdep->sc_sp_offset = 68;
275
276 /* Setjmp()'s return PC saved in EDX (5). */
277 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
278
17ca283a
MK
279 set_solib_svr4_fetch_link_map_offsets
280 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
1b883d35 281
59215afb
UW
282 /* Initialize this lazily, to avoid an initialization order
283 dependency on solib-svr4.c's _initialize routine. */
284 if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
285 {
286 nto_svr4_so_ops = svr4_so_ops;
287
288 /* Our loader handles solib relocations differently than svr4. */
289 nto_svr4_so_ops.relocate_section_addresses
290 = nto_relocate_section_addresses;
1b883d35 291
59215afb
UW
292 /* Supply a nice function to find our solibs. */
293 nto_svr4_so_ops.find_and_open_solib
294 = nto_find_and_open_solib;
1b883d35 295
59215afb
UW
296 /* Our linker code is in libc. */
297 nto_svr4_so_ops.in_dynsym_resolve_code
298 = nto_in_dynsym_resolve_code;
299 }
300 set_solib_ops (gdbarch, &nto_svr4_so_ops);
d737fd7f
KW
301
302 nto_set_target (&i386_nto_target);
1b883d35
KW
303}
304
305void
306_initialize_i386nto_tdep (void)
307{
d737fd7f 308 init_i386nto_ops ();
1b883d35
KW
309 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
310 i386nto_init_abi);
d737fd7f
KW
311 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
312 nto_elf_osabi_sniffer);
1b883d35 313}
This page took 0.37794 seconds and 4 git commands to generate.