*** empty log message ***
[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{
3d171c85 84 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1b883d35 85
3d171c85
MK
86 if(tdep->gregset == NULL)
87 tdep->gregset = regset_alloc (current_gdbarch, i386_supply_gregset,
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;
f6792ef4 125 else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
1b883d35
KW
126 return NTO_REG_FLOAT;
127
128 return -1; /* Error. */
129}
130
131static int
132i386nto_register_area (int regno, int regset, unsigned *off)
133{
134 int len;
135
136 *off = 0;
137 if (regset == NTO_REG_GENERAL)
138 {
139 if (regno == -1)
140 return NUM_GPREGS * 4;
141
142 *off = nto_reg_offset (regno);
143 if (*off == -1)
144 return 0;
145 return 4;
146 }
147 else if (regset == NTO_REG_FLOAT)
148 {
149 unsigned off_adjust, regsize, regset_size;
150
151 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
152 {
153 off_adjust = 32;
154 regsize = 16;
155 regset_size = 512;
156 }
157 else
158 {
159 off_adjust = 28;
160 regsize = 10;
161 regset_size = 128;
162 }
163
164 if (regno == -1)
165 return regset_size;
166
3e8c568d
UW
167 *off = (regno - gdbarch_fp0_regnum (current_gdbarch))
168 * regsize + off_adjust;
1b883d35
KW
169 return 10;
170 /* Why 10 instead of regsize? GDB only stores 10 bytes per FP
171 register so if we're sending a register back to the target,
172 we only want pdebug to write 10 bytes so as not to clobber
173 the reserved 6 bytes in the fxsave structure. */
174 }
175 return -1;
176}
177
178static int
468e3d51 179i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
180{
181 if (regset == NTO_REG_GENERAL)
182 {
183 int regno;
184
185 for (regno = 0; regno < NUM_GPREGS; regno++)
186 {
187 int offset = nto_reg_offset (regno);
188 if (offset != -1)
468e3d51 189 regcache_raw_collect (regcache, regno, data + offset);
1b883d35
KW
190 }
191 }
192 else if (regset == NTO_REG_FLOAT)
193 {
194 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 195 i387_collect_fxsave (regcache, -1, data);
1b883d35 196 else
468e3d51 197 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
198 }
199 else
200 return -1;
201
202 return 0;
203}
204
911bc6ee
MK
205/* Return whether the frame preceding NEXT_FRAME corresponds to a QNX
206 Neutrino sigtramp routine. */
207
1b883d35 208static int
911bc6ee 209i386nto_sigtramp_p (struct frame_info *next_frame)
1b883d35 210{
911bc6ee
MK
211 CORE_ADDR pc = frame_pc_unwind (next_frame);
212 char *name;
213
214 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
215 return name && strcmp ("__signalstub", name) == 0;
216}
217
acd5c798
MK
218#define I386_NTO_SIGCONTEXT_OFFSET 136
219
220/* Assuming NEXT_FRAME is a frame following a QNX Neutrino sigtramp
221 routine, return the address of the associated sigcontext structure. */
222
1b883d35 223static CORE_ADDR
acd5c798 224i386nto_sigcontext_addr (struct frame_info *next_frame)
1b883d35 225{
acd5c798 226 char buf[4];
89929b45 227 CORE_ADDR sp;
acd5c798 228
911bc6ee 229 frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
acd5c798 230 sp = extract_unsigned_integer (buf, 4);
1b883d35 231
acd5c798 232 return sp + I386_NTO_SIGCONTEXT_OFFSET;
1b883d35
KW
233}
234
235static void
47979a4b 236init_i386nto_ops (void)
1b883d35 237{
d737fd7f
KW
238 i386_nto_target.regset_id = i386nto_regset_id;
239 i386_nto_target.supply_gregset = i386nto_supply_gregset;
240 i386_nto_target.supply_fpregset = i386nto_supply_fpregset;
241 i386_nto_target.supply_altregset = nto_dummy_supply_regset;
242 i386_nto_target.supply_regset = i386nto_supply_regset;
243 i386_nto_target.register_area = i386nto_register_area;
244 i386_nto_target.regset_fill = i386nto_regset_fill;
245 i386_nto_target.fetch_link_map_offsets =
17ca283a 246 svr4_ilp32_fetch_link_map_offsets;
1b883d35
KW
247}
248
249static void
250i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
251{
252 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
253
d737fd7f
KW
254 /* Deal with our strange signals. */
255 nto_initialize_signals ();
256
1b883d35
KW
257 /* NTO uses ELF. */
258 i386_elf_init_abi (info, gdbarch);
259
71bd6bd4 260 /* Neutrino rewinds to look more normal. Need to override the i386
d3efc286 261 default which is [unfortunately] to decrement the PC. */
1b883d35
KW
262 set_gdbarch_decr_pc_after_break (gdbarch, 0);
263
3d171c85
MK
264 tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
265 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
266 tdep->sizeof_gregset = NUM_GPREGS * 4;
267
911bc6ee 268 tdep->sigtramp_p = i386nto_sigtramp_p;
1b883d35
KW
269 tdep->sigcontext_addr = i386nto_sigcontext_addr;
270 tdep->sc_pc_offset = 56;
271 tdep->sc_sp_offset = 68;
272
273 /* Setjmp()'s return PC saved in EDX (5). */
274 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
275
17ca283a
MK
276 set_solib_svr4_fetch_link_map_offsets
277 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
1b883d35
KW
278
279 /* Our loader handles solib relocations slightly differently than svr4. */
280 TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses;
281
282 /* Supply a nice function to find our solibs. */
283 TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib;
284
d737fd7f
KW
285 /* Our linker code is in libc. */
286 TARGET_SO_IN_DYNSYM_RESOLVE_CODE = nto_in_dynsym_resolve_code;
287
288 nto_set_target (&i386_nto_target);
1b883d35
KW
289}
290
291void
292_initialize_i386nto_tdep (void)
293{
d737fd7f 294 init_i386nto_ops ();
1b883d35
KW
295 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
296 i386nto_init_abi);
d737fd7f
KW
297 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
298 nto_elf_osabi_sniffer);
1b883d35 299}
This page took 0.322939 seconds and 4 git commands to generate.