GDB (xrefs)
/tmp/gdb-7.10/gdb/i386-nto-tdep.c
Go to the documentation of this file.
1 /* Target-dependent code for QNX Neutrino x86.
2 
3  Copyright (C) 2003-2015 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 
67 static int
69 {
70  if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
72 
73  return -1;
74 }
75 
76 static void
77 i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
78 {
79  struct gdbarch *gdbarch = get_regcache_arch (regcache);
80  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
81 
83  i386_gregset.supply_regset (&i386_gregset, regcache, -1,
84  gpregs, NUM_GPREGS * 4);
85 }
86 
87 static void
88 i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
89 {
91  i387_supply_fxsave (regcache, -1, fpregs);
92  else
93  i387_supply_fsave (regcache, -1, fpregs);
94 }
95 
96 static void
97 i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
98 {
99  switch (regset)
100  {
101  case NTO_REG_GENERAL:
102  i386nto_supply_gregset (regcache, data);
103  break;
104  case NTO_REG_FLOAT:
105  i386nto_supply_fpregset (regcache, data);
106  break;
107  }
108 }
109 
110 static int
111 i386nto_regset_id (int regno)
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 
125 static int
127  int regno, int regset, unsigned *off)
128 {
129  struct gdbarch_tdep *tdep = 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 
242 static int
243 i386nto_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 (regcache, 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 
272 static int
273 i386nto_sigtramp_p (struct frame_info *this_frame)
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 
285 static 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 
301 static void
303 {
313 }
314 
315 static void
317 {
318  struct gdbarch_tdep *tdep = 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. */
325  i386_elf_init_abi (info, gdbarch);
326 
327  /* Neutrino rewinds to look more normal. Need to override the i386
328  default which is [unfortunately] to decrement the PC. */
329  set_gdbarch_decr_pc_after_break (gdbarch, 0);
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_solib_ops (gdbarch, &nto_svr4_so_ops);
365 }
366 
367 /* Provide a prototype to silence -Wmissing-prototypes. */
369 
370 void
372 {
373  init_i386nto_ops ();
374  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
376  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
378 }
void i387_collect_fsave(const struct regcache *regcache, int regnum, void *fsave)
Definition: i387-tdep.c:502
static void i386nto_supply_gregset(struct regcache *regcache, char *gpregs)
Definition: i386-nto-tdep.c:77
ULONGEST extract_unsigned_integer(const gdb_byte *, int, enum bfd_endian)
Definition: findvar.c:84
#define I386_NUM_GREGS
Definition: i386-tdep.h:320
#define X86_CPU_FXSR
Definition: i386-nto-tdep.c:35
int jb_pc_offset
Definition: i386-tdep.h:199
#define I387_FOP_REGNUM(tdep)
Definition: i387-tdep.h:61
#define nto_cpuinfo_valid
Definition: nto-tdep.h:81
CORE_ADDR get_frame_pc(struct frame_info *frame)
Definition: frame.c:2217
#define nto_regset_id
Definition: nto-tdep.h:83
bfd_vma CORE_ADDR
Definition: common-types.h:41
int sc_num_regs
Definition: i386-tdep.h:216
static int i386nto_register_area(struct gdbarch *gdbarch, int regno, int regset, unsigned *off)
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
void set_solib_ops(struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
Definition: solib.c:76
void i387_supply_fxsave(struct regcache *regcache, int regnum, const void *fxsave)
Definition: i387-tdep.c:595
#define I386_SSE_NUM_REGS
Definition: i386-tdep.h:323
static int i386nto_regset_fill(const struct regcache *regcache, int regset, char *data)
static int nto_reg_offset(int regnum)
Definition: i386-nto-tdep.c:68
void(* relocate_section_addresses)(struct so_list *so, struct target_section *)
Definition: solist.h:84
struct m32c_reg * pc
Definition: m32c-tdep.c:111
void gdbarch_register_osabi_sniffer(enum bfd_architecture arch, enum bfd_flavour flavour, enum gdb_osabi(*sniffer_fn)(bfd *))
Definition: osabi.c:225
static int i386nto_sigtramp_p(struct frame_info *this_frame)
CORE_ADDR(* sigcontext_addr)(struct frame_info *)
Definition: alpha-tdep.h:82
struct link_map_offsets * svr4_ilp32_fetch_link_map_offsets(void)
Definition: solib-svr4.c:3149
static int i386nto_regset_id(int regno)
void i387_supply_fsave(struct regcache *regcache, int regnum, const void *fsave)
Definition: i387-tdep.c:447
static void i386nto_supply_regset(struct regcache *regcache, int regset, char *data)
Definition: i386-nto-tdep.c:97
#define I387_ST0_REGNUM(tdep)
Definition: i387-tdep.h:32
struct gdbarch_tdep * gdbarch_tdep(struct gdbarch *gdbarch)
Definition: gdbarch.c:1402
initialize_file_ftype _initialize_i386nto_tdep
Definition: regset.h:34
#define nto_supply_gregset
Definition: nto-tdep.h:85
const char *const name
Definition: aarch64-tdep.c:68
int(* in_dynsym_resolve_code)(CORE_ADDR pc)
Definition: solist.h:127
#define nto_register_area
Definition: nto-tdep.h:93
void i387_collect_fxsave(const struct regcache *regcache, int regnum, void *fxsave)
Definition: i387-tdep.c:678
#define nto_regset_fill
Definition: nto-tdep.h:95
#define nto_supply_regset
Definition: nto-tdep.h:91
void initialize_file_ftype(void)
Definition: defs.h:281
void nto_initialize_signals(void)
Definition: nto-tdep.c:376
void set_gdbarch_decr_pc_after_break(struct gdbarch *gdbarch, CORE_ADDR decr_pc_after_break)
Definition: gdbarch.c:2764
#define I387_XMM0_REGNUM(tdep)
Definition: i387-tdep.h:62
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition: gdbarch.c:1420
#define I387_FISEG_REGNUM(tdep)
Definition: i387-tdep.h:57
static void init_i386nto_ops(void)
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
Definition: solib-svr4.c:3108
#define nto_fetch_link_map_offsets
Definition: nto-tdep.h:97
int find_pc_partial_function(CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr)
Definition: blockframe.c:321
#define NUM_GPREGS
Definition: i386-nto-tdep.c:41
#define nto_supply_altregset
Definition: nto-tdep.h:89
#define gdb_assert(expr)
Definition: gdb_assert.h:33
int nto_find_and_open_solib(char *solib, unsigned o_flags, char **temp_pathname)
Definition: nto-tdep.c:85
static void i386nto_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
int nto_in_dynsym_resolve_code(CORE_ADDR pc)
Definition: nto-tdep.c:320
const struct regset i386_gregset
Definition: i386-tdep.c:3819
int regnum
Definition: aarch64-tdep.c:69
enum gdb_osabi nto_elf_osabi_sniffer(bfd *abfd)
Definition: nto-tdep.c:334
supply_regset_ftype * supply_regset
Definition: regset.h:42
int * gregset_reg_offset
Definition: i386-tdep.h:59
bfd_byte gdb_byte
Definition: common-types.h:38
struct target_so_ops svr4_so_ops
Definition: solib-svr4.c:3208
static int i386nto_gregset_reg_offset[]
Definition: i386-nto-tdep.c:47
int(* sigtramp_p)(struct frame_info *)
Definition: i386-tdep.h:209
static void i386nto_supply_fpregset(struct regcache *regcache, char *fpregs)
Definition: i386-nto-tdep.c:88
void nto_relocate_section_addresses(struct so_list *so, struct target_section *sec)
Definition: nto-tdep.c:305
void i386_elf_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
Definition: i386-tdep.c:4332
int offset
Definition: agent.c:65
void get_frame_register(struct frame_info *frame, int regnum, gdb_byte *buf)
Definition: frame.c:1085
size_t sizeof_gregset
Definition: i386-tdep.h:61
static CORE_ADDR i386nto_sigcontext_addr(struct frame_info *this_frame)
#define I387_MXCSR_REGNUM(tdep)
Definition: i387-tdep.h:64
int * sc_reg_offset
Definition: i386-tdep.h:215
int(* find_and_open_solib)(char *soname, unsigned o_flags, char **temp_pathname)
Definition: solist.h:136
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1071
void nto_dummy_supply_regset(struct regcache *regcache, char *regs)
Definition: nto-tdep.c:328
#define I387_FCTRL_REGNUM(tdep)
Definition: i387-tdep.h:54
#define nto_supply_fpregset
Definition: nto-tdep.h:87
#define nto_cpuinfo_flags
Definition: nto-tdep.h:79
#define I387_NUM_REGS
Definition: i387-tdep.h:30
int gregset_num_regs
Definition: i386-tdep.h:60
enum bfd_endian byte_order
Definition: gdbarch.c:128
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:148
struct gdbarch * get_frame_arch(struct frame_info *this_frame)
Definition: frame.c:2535