GDB (xrefs)
Loading...
Searching...
No Matches
i386-nto-tdep.c
Go to the documentation of this file.
1/* Target-dependent code for QNX Neutrino x86.
2
3 Copyright (C) 2003-2023 Free Software Foundation, Inc.
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
11 the Free Software Foundation; either version 3 of the License, or
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22#include "defs.h"
23#include "frame.h"
24#include "osabi.h"
25#include "regcache.h"
26#include "target.h"
27
28#include "i386-tdep.h"
29#include "i387-tdep.h"
30#include "nto-tdep.h"
31#include "solib.h"
32#include "solib-svr4.h"
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
43/* Mapping between the general-purpose registers in `struct xxx'
44 format and GDB's register cache layout. */
45
46/* From <x86/context.h>. */
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 */
62};
63
64/* Given a GDB register number REGNUM, return the offset into
65 Neutrino's register structure or -1 if the register is unknown. */
66
67static int
69{
70 if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
72
73 return -1;
74}
75
76static void
78{
79 struct gdbarch *gdbarch = regcache->arch ();
80 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
81
84 gpregs, NUM_GPREGS * 4);
85}
86
87static void
89{
91 i387_supply_fxsave (regcache, -1, fpregs);
92 else
93 i387_supply_fsave (regcache, -1, fpregs);
94}
95
96static void
98{
99 switch (regset)
100 {
101 case NTO_REG_GENERAL:
103 break;
104 case NTO_REG_FLOAT:
106 break;
107 }
108}
109
110static int
112{
113 if (regno == -1)
114 return NTO_REG_END;
115 else if (regno < I386_NUM_GREGS)
116 return NTO_REG_GENERAL;
117 else if (regno < I386_NUM_GREGS + I387_NUM_REGS)
118 return NTO_REG_FLOAT;
119 else if (regno < I386_SSE_NUM_REGS)
120 return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
121
122 return -1; /* Error. */
123}
124
125static int
127 int regno, int regset, unsigned *off)
128{
129 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
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 {
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));
154
156 {
157 off_adjust = 32;
158 regsize = 16;
159 regset_size = 512;
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 }
204 }
205 else
206 {
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 }
231 }
232
233 if (regno != -1)
234 *off = off_adjust + (regno - regno_base) * regsize;
235 else
236 *off = 0;
237 return regsize;
238 }
239 return -1;
240}
241
242static int
243i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
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)
253 regcache->raw_collect (regno, data + offset);
254 }
255 }
256 else if (regset == NTO_REG_FLOAT)
257 {
259 i387_collect_fxsave (regcache, -1, data);
260 else
261 i387_collect_fsave (regcache, -1, data);
262 }
263 else
264 return -1;
265
266 return 0;
267}
268
269/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
270 routine. */
271
272static int
274{
275 CORE_ADDR pc = get_frame_pc (this_frame);
276 const char *name;
277
278 find_pc_partial_function (pc, &name, NULL, NULL);
279 return name && strcmp ("__signalstub", name) == 0;
280}
281
282/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
283 address of the associated sigcontext structure. */
284
285static CORE_ADDR
287{
288 struct gdbarch *gdbarch = get_frame_arch (this_frame);
289 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
290 gdb_byte buf[4];
291 CORE_ADDR ptrctx;
292
293 /* We store __ucontext_t addr in EDI register. */
294 get_frame_register (this_frame, I386_EDI_REGNUM, buf);
295 ptrctx = extract_unsigned_integer (buf, 4, byte_order);
296 ptrctx += 24 /* Context pointer is at this offset. */;
297
298 return ptrctx;
299}
300
301static void
314
315static void
317{
318 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
319 static struct target_so_ops nto_svr4_so_ops;
320
321 /* Deal with our strange signals. */
323
324 /* NTO uses ELF. */
326
327 /* Neutrino rewinds to look more normal. Need to override the i386
328 default which is [unfortunately] to decrement the PC. */
330
332 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
333 tdep->sizeof_gregset = NUM_GPREGS * 4;
334
338 tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
339
340 /* Setjmp()'s return PC saved in EDX (5). */
341 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
342
345
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
355
356 /* Supply a nice function to find our solibs. */
357 nto_svr4_so_ops.find_and_open_solib
359
360 /* Our linker code is in libc. */
361 nto_svr4_so_ops.in_dynsym_resolve_code
363 }
364 set_gdbarch_so_ops (gdbarch, &nto_svr4_so_ops);
365
368}
369
371void
373{
375 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
377 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
379}
int regnum
const char *const name
bool find_pc_partial_function(CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr, const struct block **block)
Definition blockframe.c:373
gdbarch * arch() const
Definition regcache.c:231
void raw_collect(int regnum, void *buf) const override
Definition regcache.c:1127
static ULONGEST extract_unsigned_integer(gdb::array_view< const gdb_byte > buf, enum bfd_endian byte_order)
Definition defs.h:480
CORE_ADDR get_frame_pc(frame_info_ptr frame)
Definition frame.c:2712
void get_frame_register(frame_info_ptr frame, int regnum, gdb_byte *buf)
Definition frame.c:1263
struct gdbarch * get_frame_arch(frame_info_ptr this_frame)
Definition frame.c:3027
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition gdbarch.c:1396
void set_gdbarch_wchar_bit(struct gdbarch *gdbarch, int wchar_bit)
Definition gdbarch.c:1680
void set_gdbarch_decr_pc_after_break(struct gdbarch *gdbarch, CORE_ADDR decr_pc_after_break)
Definition gdbarch.c:2913
void set_gdbarch_wchar_signed(struct gdbarch *gdbarch, int wchar_signed)
Definition gdbarch.c:1698
void set_gdbarch_so_ops(struct gdbarch *gdbarch, const struct target_so_ops *so_ops)
Definition gdbarch.c:3380
static int i386nto_regset_fill(const struct regcache *regcache, int regset, char *data)
static int i386nto_register_area(struct gdbarch *gdbarch, int regno, int regset, unsigned *off)
static int i386nto_sigtramp_p(frame_info_ptr this_frame)
static int nto_reg_offset(int regnum)
static int i386nto_regset_id(int regno)
#define NUM_GPREGS
static CORE_ADDR i386nto_sigcontext_addr(frame_info_ptr this_frame)
static void i386nto_supply_gregset(struct regcache *regcache, char *gpregs)
static void i386nto_supply_fpregset(struct regcache *regcache, char *fpregs)
static void i386nto_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
#define X86_CPU_FXSR
static void i386nto_supply_regset(struct regcache *regcache, int regset, char *data)
void _initialize_i386nto_tdep()
static int i386nto_gregset_reg_offset[]
static void init_i386nto_ops(void)
const struct regset i386_gregset
Definition i386-tdep.c:4042
void i386_elf_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
Definition i386-tdep.c:4530
@ I386_EDI_REGNUM
Definition i386-tdep.h:288
#define I386_SSE_NUM_REGS
Definition i386-tdep.h:347
#define I386_NUM_GREGS
Definition i386-tdep.h:344
void i387_supply_fxsave(struct regcache *regcache, int regnum, const void *fxsave)
Definition i387-tdep.c:589
void i387_collect_fxsave(const struct regcache *regcache, int regnum, void *fxsave)
Definition i387-tdep.c:673
void i387_supply_fsave(struct regcache *regcache, int regnum, const void *fsave)
Definition i387-tdep.c:440
void i387_collect_fsave(const struct regcache *regcache, int regnum, void *fsave)
Definition i387-tdep.c:495
#define I387_XMM0_REGNUM(tdep)
Definition i387-tdep.h:66
#define I387_ST0_REGNUM(tdep)
Definition i387-tdep.h:33
#define I387_FOP_REGNUM(tdep)
Definition i387-tdep.h:65
#define I387_NUM_REGS
Definition i387-tdep.h:31
#define I387_FCTRL_REGNUM(tdep)
Definition i387-tdep.h:58
#define I387_MXCSR_REGNUM(tdep)
Definition i387-tdep.h:68
#define I387_FISEG_REGNUM(tdep)
Definition i387-tdep.h:61
info(Component c)
Definition gdbarch.py:41
void nto_dummy_supply_regset(struct regcache *regcache, char *regs)
Definition nto-tdep.c:306
int nto_in_dynsym_resolve_code(CORE_ADDR pc)
Definition nto-tdep.c:298
enum gdb_osabi nto_elf_osabi_sniffer(bfd *abfd)
Definition nto-tdep.c:347
int nto_find_and_open_solib(const char *solib, unsigned o_flags, gdb::unique_xmalloc_ptr< char > *temp_pathname)
Definition nto-tdep.c:93
void nto_relocate_section_addresses(struct so_list *so, struct target_section *sec)
Definition nto-tdep.c:283
void nto_initialize_signals(void)
Definition nto-tdep.c:397
#define nto_regset_id
Definition nto-tdep.h:84
#define nto_supply_regset
Definition nto-tdep.h:92
#define nto_supply_fpregset
Definition nto-tdep.h:88
#define nto_cpuinfo_flags
Definition nto-tdep.h:80
#define nto_register_area
Definition nto-tdep.h:94
#define nto_supply_gregset
Definition nto-tdep.h:86
#define nto_regset_fill
Definition nto-tdep.h:96
@ NTO_REG_FLOAT
Definition nto-tdep.h:125
@ NTO_REG_GENERAL
Definition nto-tdep.h:124
@ NTO_REG_END
Definition nto-tdep.h:128
#define nto_cpuinfo_valid
Definition nto-tdep.h:82
#define nto_supply_altregset
Definition nto-tdep.h:90
#define nto_fetch_link_map_offsets
Definition nto-tdep.h:98
void gdbarch_register_osabi(enum bfd_architecture arch, unsigned long machine, enum gdb_osabi osabi, void(*init_osabi)(struct gdbarch_info, struct gdbarch *))
Definition osabi.c:146
void gdbarch_register_osabi_sniffer(enum bfd_architecture arch, enum bfd_flavour flavour, enum gdb_osabi(*sniffer_fn)(bfd *))
Definition osabi.c:220
@ GDB_OSABI_QNXNTO
Definition osabi.h:38
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
const struct target_so_ops svr4_so_ops
struct link_map_offsets * svr4_ilp32_fetch_link_map_offsets(void)
int * gregset_reg_offset
Definition i386-tdep.h:64
int(* sigtramp_p)(frame_info_ptr)
Definition i386-tdep.h:230
CORE_ADDR(* sigcontext_addr)(frame_info_ptr)
Definition i386-tdep.h:233
size_t sizeof_gregset
Definition i386-tdep.h:66
supply_regset_ftype * supply_regset
Definition regset.h:42
int(* in_dynsym_resolve_code)(CORE_ADDR pc)
Definition solist.h:121
int(* find_and_open_solib)(const char *soname, unsigned o_flags, gdb::unique_xmalloc_ptr< char > *temp_pathname)
Definition solist.h:130
void(* relocate_section_addresses)(struct so_list *so, struct target_section *)
Definition solist.h:87