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