C++: dlsym casts in gdb/linux-thread-db.c and gdb/gdbserver/thread-db.c
[deliverable/binutils-gdb.git] / gdb / mipsnbsd-tdep.c
CommitLineData
d1180b0f
MK
1/* Target-dependent code for NetBSD/mips.
2
32d0add0 3 Copyright (C) 2002-2015 Free Software Foundation, Inc.
e4cd0d6a 4
45888261
JT
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
45888261
JT
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/>. */
45888261
JT
21
22#include "defs.h"
23#include "gdbcore.h"
24#include "regcache.h"
d1180b0f 25#include "regset.h"
45888261
JT
26#include "target.h"
27#include "value.h"
28#include "osabi.h"
29
3d9b49b0 30#include "nbsd-tdep.h"
45888261 31#include "mipsnbsd-tdep.h"
1777c7b4 32#include "mips-tdep.h"
45888261
JT
33
34#include "solib-svr4.h"
35
d1180b0f
MK
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
53static void
54mipsnbsd_supply_fpregset (const struct regset *regset,
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
76static void
77mipsnbsd_supply_gregset (const struct regset *regset,
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
3ca7dae4 103static const struct regset mipsnbsd_gregset =
d1180b0f
MK
104{
105 NULL,
f962539a
AA
106 mipsnbsd_supply_gregset,
107 NULL,
108 REGSET_VARIABLE_SIZE
d1180b0f
MK
109};
110
3ca7dae4 111static const struct regset mipsnbsd_fpregset =
d1180b0f
MK
112{
113 NULL,
114 mipsnbsd_supply_fpregset
115};
116
d4036235 117/* Iterate over core file register note sections. */
d1180b0f 118
d4036235
AA
119static void
120mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
121 iterate_over_regset_sections_cb *cb,
122 void *cb_data,
123 const struct regcache *regcache)
d1180b0f
MK
124{
125 size_t regsize = mips_isa_regsize (gdbarch);
d1180b0f 126
d4036235
AA
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);
d1180b0f
MK
131}
132\f
133
45888261
JT
134/* Conveniently, GDB uses the same register numbering as the
135 ptrace register structure used by NetBSD/mips. */
136
137void
28f5035f 138mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
45888261 139{
2eb4d78b 140 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
141 int i;
142
2eb4d78b 143 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
45888261
JT
144 {
145 if (regno == i || regno == -1)
146 {
2eb4d78b 147 if (gdbarch_cannot_fetch_register (gdbarch, i))
28f5035f 148 regcache_raw_supply (regcache, i, NULL);
45888261 149 else
28f5035f 150 regcache_raw_supply (regcache, i,
2eb4d78b 151 regs + (i * mips_isa_regsize (gdbarch)));
45888261
JT
152 }
153 }
154}
155
156void
28f5035f 157mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
45888261 158{
2eb4d78b 159 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
160 int i;
161
2eb4d78b 162 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
8d4c1ba3 163 if ((regno == i || regno == -1)
2eb4d78b 164 && ! gdbarch_cannot_store_register (gdbarch, i))
28f5035f 165 regcache_raw_collect (regcache, i,
2eb4d78b 166 regs + (i * mips_isa_regsize (gdbarch)));
45888261
JT
167}
168
169void
025bb325
MS
170mipsnbsd_supply_fpreg (struct regcache *regcache,
171 const char *fpregs, int regno)
45888261 172{
2eb4d78b 173 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
174 int i;
175
2eb4d78b
UW
176 for (i = gdbarch_fp0_regnum (gdbarch);
177 i <= mips_regnum (gdbarch)->fp_implementation_revision;
56cea623 178 i++)
45888261
JT
179 {
180 if (regno == i || regno == -1)
181 {
2eb4d78b 182 if (gdbarch_cannot_fetch_register (gdbarch, i))
28f5035f 183 regcache_raw_supply (regcache, i, NULL);
45888261 184 else
28f5035f 185 regcache_raw_supply (regcache, i,
3e8c568d 186 fpregs
2eb4d78b
UW
187 + ((i - gdbarch_fp0_regnum (gdbarch))
188 * mips_isa_regsize (gdbarch)));
45888261
JT
189 }
190 }
191}
192
193void
28f5035f 194mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno)
45888261 195{
2eb4d78b 196 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
197 int i;
198
2eb4d78b
UW
199 for (i = gdbarch_fp0_regnum (gdbarch);
200 i <= mips_regnum (gdbarch)->fp_control_status;
56cea623 201 i++)
8d4c1ba3 202 if ((regno == i || regno == -1)
2eb4d78b 203 && ! gdbarch_cannot_store_register (gdbarch, i))
28f5035f 204 regcache_raw_collect (regcache, i,
2eb4d78b
UW
205 fpregs + ((i - gdbarch_fp0_regnum (gdbarch))
206 * mips_isa_regsize (gdbarch)));
45888261
JT
207}
208
ac61d2db
SA
209#if 0
210
45888261
JT
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
230static 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
237static 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
ac61d2db
SA
244#endif
245
45888261 246/* Figure out where the longjmp will land. We expect that we have
4c7d22cb
MK
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
45888261
JT
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)
74ed0bb4
MD
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))
45888261
JT
257
258static int
60ade65d 259mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
45888261 260{
74ed0bb4 261 struct gdbarch *gdbarch = get_frame_arch (frame);
e17a4113 262 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
45888261 263 CORE_ADDR jb_addr;
948f8e3d 264 gdb_byte *buf;
45888261 265
74ed0bb4 266 buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch));
45888261 267
60ade65d 268 jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
45888261 269
74ed0bb4
MD
270 if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf,
271 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)))
45888261
JT
272 return 0;
273
e17a4113
UW
274 *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch),
275 byte_order);
45888261
JT
276 return 1;
277}
278
279static int
64a3914f 280mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
45888261 281{
4c7d22cb 282 return (regno == MIPS_ZERO_REGNUM
64a3914f 283 || regno == mips_regnum (gdbarch)->fp_implementation_revision);
45888261
JT
284}
285
286static int
64a3914f 287mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
45888261 288{
4c7d22cb 289 return (regno == MIPS_ZERO_REGNUM
64a3914f 290 || regno == mips_regnum (gdbarch)->fp_implementation_revision);
45888261
JT
291}
292
fabe86c8
MK
293/* Shared library support. */
294
295/* NetBSD/mips uses a slightly different `struct link_map' than the
45888261 296 other NetBSD platforms. */
fabe86c8 297
45888261 298static struct link_map_offsets *
fabe86c8 299mipsnbsd_ilp32_fetch_link_map_offsets (void)
45888261
JT
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
e4cd0d6a
MK
308 lmo.r_version_offset = 0;
309 lmo.r_version_size = 4;
45888261 310 lmo.r_map_offset = 4;
7cd25cfc 311 lmo.r_brk_offset = 8;
e4cd0d6a 312 lmo.r_ldsomap_offset = -1;
45888261 313
fabe86c8 314 /* Everything we need is in the first 24 bytes. */
45888261 315 lmo.link_map_size = 24;
4c7d22cb 316 lmo.l_addr_offset = 4;
45888261 317 lmo.l_name_offset = 8;
cc10cae3 318 lmo.l_ld_offset = 12;
45888261 319 lmo.l_next_offset = 16;
45888261 320 lmo.l_prev_offset = 20;
45888261
JT
321 }
322
323 return lmp;
324}
325
326static struct link_map_offsets *
fabe86c8 327mipsnbsd_lp64_fetch_link_map_offsets (void)
45888261
JT
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
e4cd0d6a
MK
336 lmo.r_version_offset = 0;
337 lmo.r_version_size = 4;
338 lmo.r_map_offset = 8;
7cd25cfc 339 lmo.r_brk_offset = 16;
e4cd0d6a 340 lmo.r_ldsomap_offset = -1;
45888261 341
fabe86c8 342 /* Everything we need is in the first 40 bytes. */
45888261 343 lmo.link_map_size = 48;
45888261 344 lmo.l_addr_offset = 0;
45888261 345 lmo.l_name_offset = 16;
cc10cae3 346 lmo.l_ld_offset = 24;
45888261 347 lmo.l_next_offset = 32;
45888261 348 lmo.l_prev_offset = 40;
45888261
JT
349 }
350
351 return lmp;
352}
fabe86c8 353\f
45888261
JT
354
355static void
356mipsnbsd_init_abi (struct gdbarch_info info,
357 struct gdbarch *gdbarch)
358{
d4036235
AA
359 set_gdbarch_iterate_over_regset_sections
360 (gdbarch, mipsnbsd_iterate_over_regset_sections);
d1180b0f 361
45888261
JT
362 set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
363
364 set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
365 set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
366
367 set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
368
fabe86c8
MK
369 /* NetBSD/mips has SVR4-style shared libraries. */
370 set_solib_svr4_fetch_link_map_offsets
371 (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
372 mipsnbsd_ilp32_fetch_link_map_offsets :
373 mipsnbsd_lp64_fetch_link_map_offsets));
45888261 374}
d1180b0f
MK
375\f
376
63807e1d
PA
377/* Provide a prototype to silence -Wmissing-prototypes. */
378extern initialize_file_ftype _initialize_mipsnbsd_tdep;
379
45888261
JT
380void
381_initialize_mipsnbsd_tdep (void)
382{
05816f70 383 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
45888261 384 mipsnbsd_init_abi);
45888261 385}
This page took 1.464976 seconds and 4 git commands to generate.