GDB (xrefs)
/tmp/gdb-7.10/gdb/mipsnbsd-tdep.c
Go to the documentation of this file.
1 /* Target-dependent code for NetBSD/mips.
2 
3  Copyright (C) 2002-2015 Free Software Foundation, Inc.
4 
5  Contributed by Wasabi Systems, Inc.
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 "gdbcore.h"
24 #include "regcache.h"
25 #include "regset.h"
26 #include "target.h"
27 #include "value.h"
28 #include "osabi.h"
29 
30 #include "nbsd-tdep.h"
31 #include "mipsnbsd-tdep.h"
32 #include "mips-tdep.h"
33 
34 #include "solib-svr4.h"
35 
36 /* Shorthand for some register numbers used below. */
37 #define MIPS_PC_REGNUM MIPS_EMBED_PC_REGNUM
38 #define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM
39 #define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32
40 
41 /* Core file support. */
42 
43 /* Number of registers in `struct reg' from <machine/reg.h>. */
44 #define MIPSNBSD_NUM_GREGS 38
45 
46 /* Number of registers in `struct fpreg' from <machine/reg.h>. */
47 #define MIPSNBSD_NUM_FPREGS 33
48 
49 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
50  in the floating-point register set REGSET to register cache
51  REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
52 
53 static void
55  struct regcache *regcache,
56  int regnum, const void *fpregs, size_t len)
57 {
58  size_t regsize = mips_isa_regsize (get_regcache_arch (regcache));
59  const char *regs = fpregs;
60  int i;
61 
62  gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize);
63 
64  for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++)
65  {
66  if (regnum == i || regnum == -1)
67  regcache_raw_supply (regcache, i,
68  regs + (i - MIPS_FP0_REGNUM) * regsize);
69  }
70 }
71 
72 /* Supply register REGNUM from the buffer specified by GREGS and LEN
73  in the general-purpose register set REGSET to register cache
74  REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
75 
76 static void
78  struct regcache *regcache, int regnum,
79  const void *gregs, size_t len)
80 {
81  size_t regsize = mips_isa_regsize (get_regcache_arch (regcache));
82  const char *regs = gregs;
83  int i;
84 
85  gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize);
86 
87  for (i = 0; i <= MIPS_PC_REGNUM; i++)
88  {
89  if (regnum == i || regnum == -1)
90  regcache_raw_supply (regcache, i, regs + i * regsize);
91  }
92 
93  if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize)
94  {
95  regs += MIPSNBSD_NUM_GREGS * regsize;
96  len -= MIPSNBSD_NUM_GREGS * regsize;
97  mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len);
98  }
99 }
100 
101 /* NetBSD/mips register sets. */
102 
103 static const struct regset mipsnbsd_gregset =
104 {
105  NULL,
107  NULL,
109 };
110 
111 static const struct regset mipsnbsd_fpregset =
112 {
113  NULL,
115 };
116 
117 /* Iterate over core file register note sections. */
118 
119 static void
122  void *cb_data,
123  const struct regcache *regcache)
124 {
125  size_t regsize = mips_isa_regsize (gdbarch);
126 
127  cb (".reg", MIPSNBSD_NUM_GREGS * regsize, &mipsnbsd_gregset,
128  NULL, cb_data);
129  cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, &mipsnbsd_fpregset,
130  NULL, cb_data);
131 }
132 
133 
134 /* Conveniently, GDB uses the same register numbering as the
135  ptrace register structure used by NetBSD/mips. */
136 
137 void
138 mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
139 {
140  struct gdbarch *gdbarch = get_regcache_arch (regcache);
141  int i;
142 
143  for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
144  {
145  if (regno == i || regno == -1)
146  {
147  if (gdbarch_cannot_fetch_register (gdbarch, i))
148  regcache_raw_supply (regcache, i, NULL);
149  else
150  regcache_raw_supply (regcache, i,
151  regs + (i * mips_isa_regsize (gdbarch)));
152  }
153  }
154 }
155 
156 void
157 mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
158 {
159  struct gdbarch *gdbarch = get_regcache_arch (regcache);
160  int i;
161 
162  for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
163  if ((regno == i || regno == -1)
164  && ! gdbarch_cannot_store_register (gdbarch, i))
165  regcache_raw_collect (regcache, i,
166  regs + (i * mips_isa_regsize (gdbarch)));
167 }
168 
169 void
171  const char *fpregs, int regno)
172 {
173  struct gdbarch *gdbarch = get_regcache_arch (regcache);
174  int i;
175 
176  for (i = gdbarch_fp0_regnum (gdbarch);
177  i <= mips_regnum (gdbarch)->fp_implementation_revision;
178  i++)
179  {
180  if (regno == i || regno == -1)
181  {
182  if (gdbarch_cannot_fetch_register (gdbarch, i))
183  regcache_raw_supply (regcache, i, NULL);
184  else
185  regcache_raw_supply (regcache, i,
186  fpregs
187  + ((i - gdbarch_fp0_regnum (gdbarch))
188  * mips_isa_regsize (gdbarch)));
189  }
190  }
191 }
192 
193 void
194 mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno)
195 {
196  struct gdbarch *gdbarch = get_regcache_arch (regcache);
197  int i;
198 
199  for (i = gdbarch_fp0_regnum (gdbarch);
200  i <= mips_regnum (gdbarch)->fp_control_status;
201  i++)
202  if ((regno == i || regno == -1)
203  && ! gdbarch_cannot_store_register (gdbarch, i))
204  regcache_raw_collect (regcache, i,
205  fpregs + ((i - gdbarch_fp0_regnum (gdbarch))
206  * mips_isa_regsize (gdbarch)));
207 }
208 
209 #if 0
210 
211 /* Under NetBSD/mips, signal handler invocations can be identified by the
212  designated code sequence that is used to return from a signal handler.
213  In particular, the return address of a signal handler points to the
214  following code sequence:
215 
216  addu a0, sp, 16
217  li v0, 295 # __sigreturn14
218  syscall
219 
220  Each instruction has a unique encoding, so we simply attempt to match
221  the instruction the PC is pointing to with any of the above instructions.
222  If there is a hit, we know the offset to the start of the designated
223  sequence and can then check whether we really are executing in the
224  signal trampoline. If not, -1 is returned, otherwise the offset from the
225  start of the return sequence is returned. */
226 
227 #define RETCODE_NWORDS 3
228 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
229 
230 static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
231 {
232  0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
233  0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
234  0x0c, 0x00, 0x00, 0x00, /* syscall */
235 };
236 
237 static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
238 {
239  0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
240  0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
241  0x00, 0x00, 0x00, 0x0c, /* syscall */
242 };
243 
244 #endif
245 
246 /* Figure out where the longjmp will land. We expect that we have
247  just entered longjmp and haven't yet setup the stack frame, so the
248  args are still in the argument regs. MIPS_A0_REGNUM points at the
249  jmp_buf structure from which we extract the PC that we will land
250  at. The PC is copied into *pc. This routine returns true on
251  success. */
252 
253 #define NBSD_MIPS_JB_PC (2 * 4)
254 #define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch) mips_isa_regsize (gdbarch)
255 #define NBSD_MIPS_JB_OFFSET(gdbarch) (NBSD_MIPS_JB_PC * \
256  NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))
257 
258 static int
260 {
261  struct gdbarch *gdbarch = get_frame_arch (frame);
262  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
263  CORE_ADDR jb_addr;
264  gdb_byte *buf;
265 
266  buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch));
267 
268  jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
269 
270  if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf,
271  NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)))
272  return 0;
273 
275  byte_order);
276  return 1;
277 }
278 
279 static int
281 {
282  return (regno == MIPS_ZERO_REGNUM
283  || regno == mips_regnum (gdbarch)->fp_implementation_revision);
284 }
285 
286 static int
288 {
289  return (regno == MIPS_ZERO_REGNUM
290  || regno == mips_regnum (gdbarch)->fp_implementation_revision);
291 }
292 
293 /* Shared library support. */
294 
295 /* NetBSD/mips uses a slightly different `struct link_map' than the
296  other NetBSD platforms. */
297 
298 static struct link_map_offsets *
300 {
301  static struct link_map_offsets lmo;
302  static struct link_map_offsets *lmp = NULL;
303 
304  if (lmp == NULL)
305  {
306  lmp = &lmo;
307 
308  lmo.r_version_offset = 0;
309  lmo.r_version_size = 4;
310  lmo.r_map_offset = 4;
311  lmo.r_brk_offset = 8;
312  lmo.r_ldsomap_offset = -1;
313 
314  /* Everything we need is in the first 24 bytes. */
315  lmo.link_map_size = 24;
316  lmo.l_addr_offset = 4;
317  lmo.l_name_offset = 8;
318  lmo.l_ld_offset = 12;
319  lmo.l_next_offset = 16;
320  lmo.l_prev_offset = 20;
321  }
322 
323  return lmp;
324 }
325 
326 static struct link_map_offsets *
328 {
329  static struct link_map_offsets lmo;
330  static struct link_map_offsets *lmp = NULL;
331 
332  if (lmp == NULL)
333  {
334  lmp = &lmo;
335 
336  lmo.r_version_offset = 0;
337  lmo.r_version_size = 4;
338  lmo.r_map_offset = 8;
339  lmo.r_brk_offset = 16;
340  lmo.r_ldsomap_offset = -1;
341 
342  /* Everything we need is in the first 40 bytes. */
343  lmo.link_map_size = 48;
344  lmo.l_addr_offset = 0;
345  lmo.l_name_offset = 16;
346  lmo.l_ld_offset = 24;
347  lmo.l_next_offset = 32;
348  lmo.l_prev_offset = 40;
349  }
350 
351  return lmp;
352 }
353 
354 
355 static void
357  struct gdbarch *gdbarch)
358 {
361 
363 
366 
368 
369  /* NetBSD/mips has SVR4-style shared libraries. */
371  (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
374 }
375 
376 
377 /* Provide a prototype to silence -Wmissing-prototypes. */
379 
380 void
382 {
383  gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
385 }
void set_gdbarch_cannot_fetch_register(struct gdbarch *gdbarch, gdbarch_cannot_fetch_register_ftype cannot_fetch_register)
Definition: gdbarch.c:2349
ULONGEST extract_unsigned_integer(const gdb_byte *, int, enum bfd_endian)
Definition: findvar.c:84
void set_gdbarch_get_longjmp_target(struct gdbarch *gdbarch, gdbarch_get_longjmp_target_ftype get_longjmp_target)
Definition: gdbarch.c:2390
static struct link_map_offsets * mipsnbsd_lp64_fetch_link_map_offsets(void)
bfd_vma CORE_ADDR
Definition: common-types.h:41
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
static void mipsnbsd_supply_gregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len)
Definition: mipsnbsd-tdep.c:77
int gdbarch_ptr_bit(struct gdbarch *gdbarch)
Definition: gdbarch.c:1690
int mips_isa_regsize(struct gdbarch *gdbarch)
Definition: mips-tdep.c:242
#define MIPSNBSD_NUM_GREGS
Definition: mipsnbsd-tdep.c:44
const struct mips_regnum * mips_regnum(struct gdbarch *gdbarch)
Definition: mips-tdep.c:199
Definition: regset.h:34
static void mipsnbsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
void initialize_file_ftype(void)
Definition: defs.h:281
initialize_file_ftype _initialize_mipsnbsd_tdep
static int mipsnbsd_get_longjmp_target(struct frame_info *frame, CORE_ADDR *pc)
static struct link_map_offsets * mipsnbsd_ilp32_fetch_link_map_offsets(void)
int gdbarch_cannot_store_register(struct gdbarch *gdbarch, int regnum)
Definition: gdbarch.c:2356
int gdbarch_cannot_fetch_register(struct gdbarch *gdbarch, int regnum)
Definition: gdbarch.c:2339
#define MIPSNBSD_NUM_FPREGS
Definition: mipsnbsd-tdep.c:47
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition: gdbarch.c:1420
void set_gdbarch_cannot_store_register(struct gdbarch *gdbarch, gdbarch_cannot_store_register_ftype cannot_store_register)
Definition: gdbarch.c:2366
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
Definition: solib-svr4.c:3108
static int mipsnbsd_cannot_store_register(struct gdbarch *gdbarch, int regno)
#define REGSET_VARIABLE_SIZE
Definition: regset.h:52
#define gdb_assert(expr)
Definition: gdb_assert.h:33
void mipsnbsd_fill_fpreg(const struct regcache *regcache, char *fpregs, int regno)
#define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch)
static void mipsnbsd_supply_fpregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *fpregs, size_t len)
Definition: mipsnbsd-tdep.c:54
int fp_implementation_revision
Definition: mips-tdep.h:64
int regnum
Definition: aarch64-tdep.c:69
void( iterate_over_regset_sections_cb)(const char *sect_name, int size, const struct regset *regset, const char *human_name, void *cb_data)
Definition: gdbarch.h:98
ULONGEST get_frame_register_unsigned(struct frame_info *frame, int regnum)
Definition: frame.c:1194
void set_gdbarch_software_single_step(struct gdbarch *gdbarch, gdbarch_software_single_step_ftype software_single_step)
Definition: gdbarch.c:3026
bfd_byte gdb_byte
Definition: common-types.h:38
#define RETCODE_SIZE
#define NBSD_MIPS_JB_OFFSET(gdbarch)
void mipsnbsd_supply_reg(struct regcache *regcache, const char *regs, int regno)
void mipsnbsd_supply_fpreg(struct regcache *regcache, const char *fpregs, int regno)
int gdbarch_fp0_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:2032
static int mipsnbsd_cannot_fetch_register(struct gdbarch *gdbarch, int regno)
int target_read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition: target.c:1393
void mipsnbsd_fill_reg(const struct regcache *regcache, char *regs, int regno)
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
#define MIPS_FSR_REGNUM
Definition: mipsnbsd-tdep.c:39
#define MIPS_PC_REGNUM
Definition: mipsnbsd-tdep.c:37
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1071
int gdbarch_pc_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:1998
static void mipsnbsd_iterate_over_regset_sections(struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache)
void set_gdbarch_iterate_over_regset_sections(struct gdbarch *gdbarch, gdbarch_iterate_over_regset_sections_ftype iterate_over_regset_sections)
Definition: gdbarch.c:3398
#define MIPS_FP0_REGNUM
Definition: mipsnbsd-tdep.c:38
int fp_control_status
Definition: mips-tdep.h:65
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
int mips_software_single_step(struct frame_info *frame)
Definition: mips-tdep.c:4175
struct gdbarch * get_frame_arch(struct frame_info *this_frame)
Definition: frame.c:2535
const ULONGEST const LONGEST len
Definition: target.h:309