]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i386-nto-tdep.c
[gdb/symtab] Make gold index workaround more precise
[thirdparty/binutils-gdb.git] / gdb / i386-nto-tdep.c
CommitLineData
911bc6ee 1/* Target-dependent code for QNX Neutrino x86.
1b883d35 2
b811d2c2 3 Copyright (C) 2003-2020 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
1b883d35 28#include "i386-tdep.h"
1b883d35 29#include "i387-tdep.h"
17ca283a 30#include "nto-tdep.h"
59215afb 31#include "solib.h"
17ca283a 32#include "solib-svr4.h"
1b883d35
KW
33
34#ifndef X86_CPU_FXSR
35#define X86_CPU_FXSR (1L << 12)
36#endif
37
38/* Why 13? Look in our /usr/include/x86/context.h header at the
39 x86_cpu_registers structure and you'll see an 'exx' junk register
40 that is just filler. Don't ask me, ask the kernel guys. */
41#define NUM_GPREGS 13
42
3d171c85
MK
43/* Mapping between the general-purpose registers in `struct xxx'
44 format and GDB's register cache layout. */
45
46/* From <x86/context.h>. */
47static int i386nto_gregset_reg_offset[] =
48{
49 7 * 4, /* %eax */
50 6 * 4, /* %ecx */
51 5 * 4, /* %edx */
52 4 * 4, /* %ebx */
53 11 * 4, /* %esp */
54 2 * 4, /* %epb */
55 1 * 4, /* %esi */
56 0 * 4, /* %edi */
57 8 * 4, /* %eip */
58 10 * 4, /* %eflags */
59 9 * 4, /* %cs */
60 12 * 4, /* %ss */
61 -1 /* filler */
1b883d35
KW
62};
63
3d171c85
MK
64/* Given a GDB register number REGNUM, return the offset into
65 Neutrino's register structure or -1 if the register is unknown. */
d737fd7f 66
1b883d35 67static int
3d171c85 68nto_reg_offset (int regnum)
1b883d35 69{
3d171c85
MK
70 if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
71 return i386nto_gregset_reg_offset[regnum];
72
73 return -1;
1b883d35
KW
74}
75
76static void
468e3d51 77i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
1b883d35 78{
ac7936df 79 struct gdbarch *gdbarch = regcache->arch ();
875f8d0e 80 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35 81
3d171c85 82 gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset);
ecc37a5a
AA
83 i386_gregset.supply_regset (&i386_gregset, regcache, -1,
84 gpregs, NUM_GPREGS * 4);
1b883d35
KW
85}
86
87static void
468e3d51 88i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
1b883d35
KW
89{
90 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 91 i387_supply_fxsave (regcache, -1, fpregs);
1b883d35 92 else
468e3d51 93 i387_supply_fsave (regcache, -1, fpregs);
1b883d35
KW
94}
95
96static void
468e3d51 97i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
1b883d35
KW
98{
99 switch (regset)
100 {
3d171c85 101 case NTO_REG_GENERAL:
468e3d51 102 i386nto_supply_gregset (regcache, data);
1b883d35
KW
103 break;
104 case NTO_REG_FLOAT:
468e3d51 105 i386nto_supply_fpregset (regcache, data);
1b883d35
KW
106 break;
107 }
108}
109
110static int
111i386nto_regset_id (int regno)
112{
113 if (regno == -1)
114 return NTO_REG_END;
f6792ef4 115 else if (regno < I386_NUM_GREGS)
1b883d35 116 return NTO_REG_GENERAL;
90884b2b 117 else if (regno < I386_NUM_GREGS + I387_NUM_REGS)
1b883d35 118 return NTO_REG_FLOAT;
dbfb31a4
AR
119 else if (regno < I386_SSE_NUM_REGS)
120 return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
1b883d35
KW
121
122 return -1; /* Error. */
123}
124
125static int
60441ab9
UW
126i386nto_register_area (struct gdbarch *gdbarch,
127 int regno, int regset, unsigned *off)
1b883d35 128{
dbfb31a4 129 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1b883d35
KW
130
131 *off = 0;
132 if (regset == NTO_REG_GENERAL)
133 {
134 if (regno == -1)
135 return NUM_GPREGS * 4;
136
137 *off = nto_reg_offset (regno);
138 if (*off == -1)
139 return 0;
140 return 4;
141 }
142 else if (regset == NTO_REG_FLOAT)
143 {
dbfb31a4
AR
144 unsigned off_adjust, regsize, regset_size, regno_base;
145 /* The following are flags indicating number in our fxsave_area. */
146 int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
147 && regno <= I387_FISEG_REGNUM (tdep));
148 int second_four = (regno > I387_FISEG_REGNUM (tdep)
149 && regno <= I387_FOP_REGNUM (tdep));
150 int st_reg = (regno >= I387_ST0_REGNUM (tdep)
151 && regno < I387_ST0_REGNUM (tdep) + 8);
152 int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
153 && regno < I387_MXCSR_REGNUM (tdep));
1b883d35
KW
154
155 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
156 {
157 off_adjust = 32;
158 regsize = 16;
159 regset_size = 512;
dbfb31a4
AR
160 /* fxsave_area structure. */
161 if (first_four)
162 {
163 /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
164 registers. */
165 regsize = 2; /* Two bytes each. */
166 off_adjust = 0;
167 regno_base = I387_FCTRL_REGNUM (tdep);
168 }
169 else if (second_four)
170 {
171 /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
172 regsize = 4;
173 off_adjust = 8;
174 regno_base = I387_FISEG_REGNUM (tdep) + 1;
175 }
176 else if (st_reg)
177 {
178 /* ST registers. */
179 regsize = 16;
180 off_adjust = 32;
181 regno_base = I387_ST0_REGNUM (tdep);
182 }
183 else if (xmm_reg)
184 {
185 /* XMM registers. */
186 regsize = 16;
187 off_adjust = 160;
188 regno_base = I387_XMM0_REGNUM (tdep);
189 }
190 else if (regno == I387_MXCSR_REGNUM (tdep))
191 {
192 regsize = 4;
193 off_adjust = 24;
194 regno_base = I387_MXCSR_REGNUM (tdep);
195 }
196 else
197 {
198 /* Whole regset. */
199 gdb_assert (regno == -1);
200 off_adjust = 0;
201 regno_base = 0;
202 regsize = regset_size;
203 }
1b883d35
KW
204 }
205 else
206 {
dbfb31a4
AR
207 regset_size = 108;
208 /* fsave_area structure. */
209 if (first_four || second_four)
210 {
211 /* fpu_control_word, ... , fpu_ds registers. */
212 regsize = 4;
213 off_adjust = 0;
214 regno_base = I387_FCTRL_REGNUM (tdep);
215 }
216 else if (st_reg)
217 {
218 /* One of ST registers. */
219 regsize = 10;
220 off_adjust = 7 * 4;
221 regno_base = I387_ST0_REGNUM (tdep);
222 }
223 else
224 {
225 /* Whole regset. */
226 gdb_assert (regno == -1);
227 off_adjust = 0;
228 regno_base = 0;
229 regsize = regset_size;
230 }
1b883d35
KW
231 }
232
dbfb31a4
AR
233 if (regno != -1)
234 *off = off_adjust + (regno - regno_base) * regsize;
235 else
236 *off = 0;
237 return regsize;
1b883d35
KW
238 }
239 return -1;
240}
241
242static int
468e3d51 243i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
1b883d35
KW
244{
245 if (regset == NTO_REG_GENERAL)
246 {
247 int regno;
248
249 for (regno = 0; regno < NUM_GPREGS; regno++)
250 {
251 int offset = nto_reg_offset (regno);
252 if (offset != -1)
34a79281 253 regcache->raw_collect (regno, data + offset);
1b883d35
KW
254 }
255 }
256 else if (regset == NTO_REG_FLOAT)
257 {
258 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
468e3d51 259 i387_collect_fxsave (regcache, -1, data);
1b883d35 260 else
468e3d51 261 i387_collect_fsave (regcache, -1, data);
1b883d35
KW
262 }
263 else
264 return -1;
265
266 return 0;
267}
268
10458914
DJ
269/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
270 routine. */
911bc6ee 271
1b883d35 272static int
10458914 273i386nto_sigtramp_p (struct frame_info *this_frame)
1b883d35 274{
10458914 275 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 276 const char *name;
911bc6ee
MK
277
278 find_pc_partial_function (pc, &name, NULL, NULL);
1b883d35
KW
279 return name && strcmp ("__signalstub", name) == 0;
280}
281
10458914
DJ
282/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
283 address of the associated sigcontext structure. */
acd5c798 284
1b883d35 285static CORE_ADDR
10458914 286i386nto_sigcontext_addr (struct frame_info *this_frame)
1b883d35 287{
e17a4113
UW
288 struct gdbarch *gdbarch = get_frame_arch (this_frame);
289 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
e362b510 290 gdb_byte buf[4];
19a934d8 291 CORE_ADDR ptrctx;
acd5c798 292
19a934d8
AR
293 /* We store __ucontext_t addr in EDI register. */
294 get_frame_register (this_frame, I386_EDI_REGNUM, buf);
e17a4113 295 ptrctx = extract_unsigned_integer (buf, 4, byte_order);
19a934d8 296 ptrctx += 24 /* Context pointer is at this offset. */;
1b883d35 297
19a934d8 298 return ptrctx;
1b883d35
KW
299}
300
301static void
47979a4b 302init_i386nto_ops (void)
1b883d35 303{
80b1849c
AR
304 nto_regset_id = i386nto_regset_id;
305 nto_supply_gregset = i386nto_supply_gregset;
306 nto_supply_fpregset = i386nto_supply_fpregset;
307 nto_supply_altregset = nto_dummy_supply_regset;
308 nto_supply_regset = i386nto_supply_regset;
309 nto_register_area = i386nto_register_area;
310 nto_regset_fill = i386nto_regset_fill;
311 nto_fetch_link_map_offsets =
17ca283a 312 svr4_ilp32_fetch_link_map_offsets;
1b883d35
KW
313}
314
315static void
316i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
317{
318 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
59215afb 319 static struct target_so_ops nto_svr4_so_ops;
1b883d35 320
d737fd7f
KW
321 /* Deal with our strange signals. */
322 nto_initialize_signals ();
323
1b883d35
KW
324 /* NTO uses ELF. */
325 i386_elf_init_abi (info, gdbarch);
326
71bd6bd4 327 /* Neutrino rewinds to look more normal. Need to override the i386
d3efc286 328 default which is [unfortunately] to decrement the PC. */
1b883d35
KW
329 set_gdbarch_decr_pc_after_break (gdbarch, 0);
330
3d171c85
MK
331 tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
332 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
333 tdep->sizeof_gregset = NUM_GPREGS * 4;
334
911bc6ee 335 tdep->sigtramp_p = i386nto_sigtramp_p;
1b883d35 336 tdep->sigcontext_addr = i386nto_sigcontext_addr;
19a934d8
AR
337 tdep->sc_reg_offset = i386nto_gregset_reg_offset;
338 tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
1b883d35
KW
339
340 /* Setjmp()'s return PC saved in EDX (5). */
341 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
342
17ca283a
MK
343 set_solib_svr4_fetch_link_map_offsets
344 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
1b883d35 345
59215afb
UW
346 /* Initialize this lazily, to avoid an initialization order
347 dependency on solib-svr4.c's _initialize routine. */
348 if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
349 {
350 nto_svr4_so_ops = svr4_so_ops;
351
352 /* Our loader handles solib relocations differently than svr4. */
353 nto_svr4_so_ops.relocate_section_addresses
354 = nto_relocate_section_addresses;
1b883d35 355
59215afb
UW
356 /* Supply a nice function to find our solibs. */
357 nto_svr4_so_ops.find_and_open_solib
358 = nto_find_and_open_solib;
1b883d35 359
59215afb
UW
360 /* Our linker code is in libc. */
361 nto_svr4_so_ops.in_dynsym_resolve_code
362 = nto_in_dynsym_resolve_code;
363 }
364 set_solib_ops (gdbarch, &nto_svr4_so_ops);
53375380
PA
365
366 set_gdbarch_wchar_bit (gdbarch, 32);
367 set_gdbarch_wchar_signed (gdbarch, 0);
1b883d35
KW
368}
369
6c265988 370void _initialize_i386nto_tdep ();
1b883d35 371void
6c265988 372_initialize_i386nto_tdep ()
1b883d35 373{
d737fd7f 374 init_i386nto_ops ();
1b883d35
KW
375 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
376 i386nto_init_abi);
d737fd7f
KW
377 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
378 nto_elf_osabi_sniffer);
1b883d35 379}