* breakpoint.c (break_command_really): Rename local variable
[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 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 128 return NTO_REG_FLOAT;
dbfb31a4
AR
129 else if (regno < I386_SSE_NUM_REGS)
130 return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
1b883d35
KW
131
132 return -1; /* Error. */
133}
134
135static int
60441ab9
UW
136i386nto_register_area (struct gdbarch *gdbarch,
137 int regno, int regset, unsigned *off)
1b883d35 138{
dbfb31a4 139 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35
KW
140 int len;
141
142 *off = 0;
143 if (regset == NTO_REG_GENERAL)
144 {
145 if (regno == -1)
146 return NUM_GPREGS * 4;
147
148 *off = nto_reg_offset (regno);
149 if (*off == -1)
150 return 0;
151 return 4;
152 }
153 else if (regset == NTO_REG_FLOAT)
154 {
dbfb31a4
AR
155 unsigned off_adjust, regsize, regset_size, regno_base;
156 /* The following are flags indicating number in our fxsave_area. */
157 int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
158 && regno <= I387_FISEG_REGNUM (tdep));
159 int second_four = (regno > I387_FISEG_REGNUM (tdep)
160 && regno <= I387_FOP_REGNUM (tdep));
161 int st_reg = (regno >= I387_ST0_REGNUM (tdep)
162 && regno < I387_ST0_REGNUM (tdep) + 8);
163 int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
164 && regno < I387_MXCSR_REGNUM (tdep));
1b883d35
KW
165
166 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
167 {
168 off_adjust = 32;
169 regsize = 16;
170 regset_size = 512;
dbfb31a4
AR
171 /* fxsave_area structure. */
172 if (first_four)
173 {
174 /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
175 registers. */
176 regsize = 2; /* Two bytes each. */
177 off_adjust = 0;
178 regno_base = I387_FCTRL_REGNUM (tdep);
179 }
180 else if (second_four)
181 {
182 /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
183 regsize = 4;
184 off_adjust = 8;
185 regno_base = I387_FISEG_REGNUM (tdep) + 1;
186 }
187 else if (st_reg)
188 {
189 /* ST registers. */
190 regsize = 16;
191 off_adjust = 32;
192 regno_base = I387_ST0_REGNUM (tdep);
193 }
194 else if (xmm_reg)
195 {
196 /* XMM registers. */
197 regsize = 16;
198 off_adjust = 160;
199 regno_base = I387_XMM0_REGNUM (tdep);
200 }
201 else if (regno == I387_MXCSR_REGNUM (tdep))
202 {
203 regsize = 4;
204 off_adjust = 24;
205 regno_base = I387_MXCSR_REGNUM (tdep);
206 }
207 else
208 {
209 /* Whole regset. */
210 gdb_assert (regno == -1);
211 off_adjust = 0;
212 regno_base = 0;
213 regsize = regset_size;
214 }
1b883d35
KW
215 }
216 else
217 {
dbfb31a4
AR
218 regset_size = 108;
219 /* fsave_area structure. */
220 if (first_four || second_four)
221 {
222 /* fpu_control_word, ... , fpu_ds registers. */
223 regsize = 4;
224 off_adjust = 0;
225 regno_base = I387_FCTRL_REGNUM (tdep);
226 }
227 else if (st_reg)
228 {
229 /* One of ST registers. */
230 regsize = 10;
231 off_adjust = 7 * 4;
232 regno_base = I387_ST0_REGNUM (tdep);
233 }
234 else
235 {
236 /* Whole regset. */
237 gdb_assert (regno == -1);
238 off_adjust = 0;
239 regno_base = 0;
240 regsize = regset_size;
241 }
1b883d35
KW
242 }
243
dbfb31a4
AR
244 if (regno != -1)
245 *off = off_adjust + (regno - regno_base) * regsize;
246 else
247 *off = 0;
248 return regsize;
1b883d35
KW
249 }
250 return -1;
251}
252
253static int
468e3d51 254i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
255{
256 if (regset == NTO_REG_GENERAL)
257 {
258 int regno;
259
260 for (regno = 0; regno < NUM_GPREGS; regno++)
261 {
262 int offset = nto_reg_offset (regno);
263 if (offset != -1)
468e3d51 264 regcache_raw_collect (regcache, regno, data + offset);
1b883d35
KW
265 }
266 }
267 else if (regset == NTO_REG_FLOAT)
268 {
269 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 270 i387_collect_fxsave (regcache, -1, data);
1b883d35 271 else
468e3d51 272 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
273 }
274 else
275 return -1;
276
277 return 0;
278}
279
10458914
DJ
280/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
281 routine. */
911bc6ee 282
1b883d35 283static int
10458914 284i386nto_sigtramp_p (struct frame_info *this_frame)
1b883d35 285{
10458914 286 CORE_ADDR pc = get_frame_pc (this_frame);
911bc6ee
MK
287 char *name;
288
289 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
290 return name && strcmp ("__signalstub", name) == 0;
291}
292
acd5c798
MK
293#define I386_NTO_SIGCONTEXT_OFFSET 136
294
10458914
DJ
295/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
296 address of the associated sigcontext structure. */
acd5c798 297
1b883d35 298static CORE_ADDR
10458914 299i386nto_sigcontext_addr (struct frame_info *this_frame)
1b883d35 300{
acd5c798 301 char buf[4];
89929b45 302 CORE_ADDR sp;
acd5c798 303
10458914 304 get_frame_register (this_frame, I386_ESP_REGNUM, buf);
acd5c798 305 sp = extract_unsigned_integer (buf, 4);
1b883d35 306
acd5c798 307 return sp + I386_NTO_SIGCONTEXT_OFFSET;
1b883d35
KW
308}
309
310static void
47979a4b 311init_i386nto_ops (void)
1b883d35 312{
d737fd7f
KW
313 i386_nto_target.regset_id = i386nto_regset_id;
314 i386_nto_target.supply_gregset = i386nto_supply_gregset;
315 i386_nto_target.supply_fpregset = i386nto_supply_fpregset;
316 i386_nto_target.supply_altregset = nto_dummy_supply_regset;
317 i386_nto_target.supply_regset = i386nto_supply_regset;
318 i386_nto_target.register_area = i386nto_register_area;
319 i386_nto_target.regset_fill = i386nto_regset_fill;
320 i386_nto_target.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
KW
345 tdep->sigcontext_addr = i386nto_sigcontext_addr;
346 tdep->sc_pc_offset = 56;
347 tdep->sc_sp_offset = 68;
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);
d737fd7f
KW
374
375 nto_set_target (&i386_nto_target);
1b883d35
KW
376}
377
63807e1d
PA
378/* Provide a prototype to silence -Wmissing-prototypes. */
379extern initialize_file_ftype _initialize_i386nto_tdep;
380
1b883d35
KW
381void
382_initialize_i386nto_tdep (void)
383{
d737fd7f 384 init_i386nto_ops ();
1b883d35
KW
385 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
386 i386nto_init_abi);
d737fd7f
KW
387 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
388 nto_elf_osabi_sniffer);
1b883d35 389}
This page took 0.721732 seconds and 4 git commands to generate.