x86: Use correct .reg-xstate section size
[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,
106 mipsnbsd_supply_gregset
107};
108
3ca7dae4 109static const struct regset mipsnbsd_fpregset =
d1180b0f
MK
110{
111 NULL,
112 mipsnbsd_supply_fpregset
113};
114
d4036235 115/* Iterate over core file register note sections. */
d1180b0f 116
d4036235
AA
117static void
118mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
119 iterate_over_regset_sections_cb *cb,
120 void *cb_data,
121 const struct regcache *regcache)
d1180b0f
MK
122{
123 size_t regsize = mips_isa_regsize (gdbarch);
d1180b0f 124
d4036235
AA
125 cb (".reg", MIPSNBSD_NUM_GREGS * regsize, &mipsnbsd_gregset,
126 NULL, cb_data);
127 cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, &mipsnbsd_fpregset,
128 NULL, cb_data);
d1180b0f
MK
129}
130\f
131
45888261
JT
132/* Conveniently, GDB uses the same register numbering as the
133 ptrace register structure used by NetBSD/mips. */
134
135void
28f5035f 136mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
45888261 137{
2eb4d78b 138 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
139 int i;
140
2eb4d78b 141 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
45888261
JT
142 {
143 if (regno == i || regno == -1)
144 {
2eb4d78b 145 if (gdbarch_cannot_fetch_register (gdbarch, i))
28f5035f 146 regcache_raw_supply (regcache, i, NULL);
45888261 147 else
28f5035f 148 regcache_raw_supply (regcache, i,
2eb4d78b 149 regs + (i * mips_isa_regsize (gdbarch)));
45888261
JT
150 }
151 }
152}
153
154void
28f5035f 155mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
45888261 156{
2eb4d78b 157 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
158 int i;
159
2eb4d78b 160 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
8d4c1ba3 161 if ((regno == i || regno == -1)
2eb4d78b 162 && ! gdbarch_cannot_store_register (gdbarch, i))
28f5035f 163 regcache_raw_collect (regcache, i,
2eb4d78b 164 regs + (i * mips_isa_regsize (gdbarch)));
45888261
JT
165}
166
167void
025bb325
MS
168mipsnbsd_supply_fpreg (struct regcache *regcache,
169 const char *fpregs, int regno)
45888261 170{
2eb4d78b 171 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
172 int i;
173
2eb4d78b
UW
174 for (i = gdbarch_fp0_regnum (gdbarch);
175 i <= mips_regnum (gdbarch)->fp_implementation_revision;
56cea623 176 i++)
45888261
JT
177 {
178 if (regno == i || regno == -1)
179 {
2eb4d78b 180 if (gdbarch_cannot_fetch_register (gdbarch, i))
28f5035f 181 regcache_raw_supply (regcache, i, NULL);
45888261 182 else
28f5035f 183 regcache_raw_supply (regcache, i,
3e8c568d 184 fpregs
2eb4d78b
UW
185 + ((i - gdbarch_fp0_regnum (gdbarch))
186 * mips_isa_regsize (gdbarch)));
45888261
JT
187 }
188 }
189}
190
191void
28f5035f 192mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno)
45888261 193{
2eb4d78b 194 struct gdbarch *gdbarch = get_regcache_arch (regcache);
45888261
JT
195 int i;
196
2eb4d78b
UW
197 for (i = gdbarch_fp0_regnum (gdbarch);
198 i <= mips_regnum (gdbarch)->fp_control_status;
56cea623 199 i++)
8d4c1ba3 200 if ((regno == i || regno == -1)
2eb4d78b 201 && ! gdbarch_cannot_store_register (gdbarch, i))
28f5035f 202 regcache_raw_collect (regcache, i,
2eb4d78b
UW
203 fpregs + ((i - gdbarch_fp0_regnum (gdbarch))
204 * mips_isa_regsize (gdbarch)));
45888261
JT
205}
206
ac61d2db
SA
207#if 0
208
45888261
JT
209/* Under NetBSD/mips, signal handler invocations can be identified by the
210 designated code sequence that is used to return from a signal handler.
211 In particular, the return address of a signal handler points to the
212 following code sequence:
213
214 addu a0, sp, 16
215 li v0, 295 # __sigreturn14
216 syscall
217
218 Each instruction has a unique encoding, so we simply attempt to match
219 the instruction the PC is pointing to with any of the above instructions.
220 If there is a hit, we know the offset to the start of the designated
221 sequence and can then check whether we really are executing in the
222 signal trampoline. If not, -1 is returned, otherwise the offset from the
223 start of the return sequence is returned. */
224
225#define RETCODE_NWORDS 3
226#define RETCODE_SIZE (RETCODE_NWORDS * 4)
227
228static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
229{
230 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
231 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
232 0x0c, 0x00, 0x00, 0x00, /* syscall */
233};
234
235static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
236{
237 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
238 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
239 0x00, 0x00, 0x00, 0x0c, /* syscall */
240};
241
ac61d2db
SA
242#endif
243
45888261 244/* Figure out where the longjmp will land. We expect that we have
4c7d22cb
MK
245 just entered longjmp and haven't yet setup the stack frame, so the
246 args are still in the argument regs. MIPS_A0_REGNUM points at the
45888261
JT
247 jmp_buf structure from which we extract the PC that we will land
248 at. The PC is copied into *pc. This routine returns true on
249 success. */
250
251#define NBSD_MIPS_JB_PC (2 * 4)
74ed0bb4
MD
252#define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch) mips_isa_regsize (gdbarch)
253#define NBSD_MIPS_JB_OFFSET(gdbarch) (NBSD_MIPS_JB_PC * \
254 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))
45888261
JT
255
256static int
60ade65d 257mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
45888261 258{
74ed0bb4 259 struct gdbarch *gdbarch = get_frame_arch (frame);
e17a4113 260 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
45888261 261 CORE_ADDR jb_addr;
948f8e3d 262 gdb_byte *buf;
45888261 263
74ed0bb4 264 buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch));
45888261 265
60ade65d 266 jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
45888261 267
74ed0bb4
MD
268 if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf,
269 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)))
45888261
JT
270 return 0;
271
e17a4113
UW
272 *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch),
273 byte_order);
45888261
JT
274 return 1;
275}
276
277static int
64a3914f 278mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
45888261 279{
4c7d22cb 280 return (regno == MIPS_ZERO_REGNUM
64a3914f 281 || regno == mips_regnum (gdbarch)->fp_implementation_revision);
45888261
JT
282}
283
284static int
64a3914f 285mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
45888261 286{
4c7d22cb 287 return (regno == MIPS_ZERO_REGNUM
64a3914f 288 || regno == mips_regnum (gdbarch)->fp_implementation_revision);
45888261
JT
289}
290
fabe86c8
MK
291/* Shared library support. */
292
293/* NetBSD/mips uses a slightly different `struct link_map' than the
45888261 294 other NetBSD platforms. */
fabe86c8 295
45888261 296static struct link_map_offsets *
fabe86c8 297mipsnbsd_ilp32_fetch_link_map_offsets (void)
45888261
JT
298{
299 static struct link_map_offsets lmo;
300 static struct link_map_offsets *lmp = NULL;
301
302 if (lmp == NULL)
303 {
304 lmp = &lmo;
305
e4cd0d6a
MK
306 lmo.r_version_offset = 0;
307 lmo.r_version_size = 4;
45888261 308 lmo.r_map_offset = 4;
7cd25cfc 309 lmo.r_brk_offset = 8;
e4cd0d6a 310 lmo.r_ldsomap_offset = -1;
45888261 311
fabe86c8 312 /* Everything we need is in the first 24 bytes. */
45888261 313 lmo.link_map_size = 24;
4c7d22cb 314 lmo.l_addr_offset = 4;
45888261 315 lmo.l_name_offset = 8;
cc10cae3 316 lmo.l_ld_offset = 12;
45888261 317 lmo.l_next_offset = 16;
45888261 318 lmo.l_prev_offset = 20;
45888261
JT
319 }
320
321 return lmp;
322}
323
324static struct link_map_offsets *
fabe86c8 325mipsnbsd_lp64_fetch_link_map_offsets (void)
45888261
JT
326{
327 static struct link_map_offsets lmo;
328 static struct link_map_offsets *lmp = NULL;
329
330 if (lmp == NULL)
331 {
332 lmp = &lmo;
333
e4cd0d6a
MK
334 lmo.r_version_offset = 0;
335 lmo.r_version_size = 4;
336 lmo.r_map_offset = 8;
7cd25cfc 337 lmo.r_brk_offset = 16;
e4cd0d6a 338 lmo.r_ldsomap_offset = -1;
45888261 339
fabe86c8 340 /* Everything we need is in the first 40 bytes. */
45888261 341 lmo.link_map_size = 48;
45888261 342 lmo.l_addr_offset = 0;
45888261 343 lmo.l_name_offset = 16;
cc10cae3 344 lmo.l_ld_offset = 24;
45888261 345 lmo.l_next_offset = 32;
45888261 346 lmo.l_prev_offset = 40;
45888261
JT
347 }
348
349 return lmp;
350}
fabe86c8 351\f
45888261
JT
352
353static void
354mipsnbsd_init_abi (struct gdbarch_info info,
355 struct gdbarch *gdbarch)
356{
d4036235
AA
357 set_gdbarch_iterate_over_regset_sections
358 (gdbarch, mipsnbsd_iterate_over_regset_sections);
d1180b0f 359
45888261
JT
360 set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
361
362 set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
363 set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
364
365 set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
366
fabe86c8
MK
367 /* NetBSD/mips has SVR4-style shared libraries. */
368 set_solib_svr4_fetch_link_map_offsets
369 (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
370 mipsnbsd_ilp32_fetch_link_map_offsets :
371 mipsnbsd_lp64_fetch_link_map_offsets));
45888261 372}
d1180b0f
MK
373\f
374
63807e1d
PA
375/* Provide a prototype to silence -Wmissing-prototypes. */
376extern initialize_file_ftype _initialize_mipsnbsd_tdep;
377
45888261
JT
378void
379_initialize_mipsnbsd_tdep (void)
380{
05816f70 381 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
45888261 382 mipsnbsd_init_abi);
45888261 383}
This page took 1.114319 seconds and 4 git commands to generate.