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