gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / mips-nbsd-tdep.c
CommitLineData
d1180b0f
MK
1/* Target-dependent code for NetBSD/mips.
2
b811d2c2 3 Copyright (C) 2002-2020 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"
03b62bbb 31#include "mips-nbsd-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{
ac7936df 58 size_t regsize = mips_isa_regsize (regcache->arch ());
19ba03f4 59 const char *regs = (const char *) fpregs;
d1180b0f
MK
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)
73e1c03f 67 regcache->raw_supply (i, regs + (i - MIPS_FP0_REGNUM) * regsize);
d1180b0f
MK
68 }
69}
70
71/* Supply register REGNUM from the buffer specified by GREGS and LEN
72 in the general-purpose register set REGSET to register cache
73 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
74
75static void
76mipsnbsd_supply_gregset (const struct regset *regset,
77 struct regcache *regcache, int regnum,
78 const void *gregs, size_t len)
79{
ac7936df 80 size_t regsize = mips_isa_regsize (regcache->arch ());
19ba03f4 81 const char *regs = (const char *) gregs;
d1180b0f
MK
82 int i;
83
84 gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize);
85
86 for (i = 0; i <= MIPS_PC_REGNUM; i++)
87 {
88 if (regnum == i || regnum == -1)
73e1c03f 89 regcache->raw_supply (i, regs + i * regsize);
d1180b0f
MK
90 }
91
92 if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize)
93 {
94 regs += MIPSNBSD_NUM_GREGS * regsize;
95 len -= MIPSNBSD_NUM_GREGS * regsize;
96 mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len);
97 }
98}
99
100/* NetBSD/mips register sets. */
101
3ca7dae4 102static const struct regset mipsnbsd_gregset =
d1180b0f
MK
103{
104 NULL,
f962539a
AA
105 mipsnbsd_supply_gregset,
106 NULL,
107 REGSET_VARIABLE_SIZE
d1180b0f
MK
108};
109
3ca7dae4 110static const struct regset mipsnbsd_fpregset =
d1180b0f
MK
111{
112 NULL,
113 mipsnbsd_supply_fpregset
114};
115
d4036235 116/* Iterate over core file register note sections. */
d1180b0f 117
d4036235
AA
118static void
119mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
120 iterate_over_regset_sections_cb *cb,
121 void *cb_data,
122 const struct regcache *regcache)
d1180b0f
MK
123{
124 size_t regsize = mips_isa_regsize (gdbarch);
d1180b0f 125
a616bb94
AH
126 cb (".reg", MIPSNBSD_NUM_GREGS * regsize, MIPSNBSD_NUM_GREGS * regsize,
127 &mipsnbsd_gregset, NULL, cb_data);
128 cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, MIPSNBSD_NUM_FPREGS * regsize,
129 &mipsnbsd_fpregset, NULL, cb_data);
d1180b0f
MK
130}
131\f
132
45888261
JT
133/* Conveniently, GDB uses the same register numbering as the
134 ptrace register structure used by NetBSD/mips. */
135
136void
28f5035f 137mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
45888261 138{
ac7936df 139 struct gdbarch *gdbarch = regcache->arch ();
45888261
JT
140 int i;
141
2eb4d78b 142 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
45888261
JT
143 {
144 if (regno == i || regno == -1)
145 {
2eb4d78b 146 if (gdbarch_cannot_fetch_register (gdbarch, i))
73e1c03f 147 regcache->raw_supply (i, NULL);
45888261 148 else
73e1c03f
SM
149 regcache->raw_supply
150 (i, regs + (i * mips_isa_regsize (gdbarch)));
45888261
JT
151 }
152 }
153}
154
155void
28f5035f 156mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
45888261 157{
ac7936df 158 struct gdbarch *gdbarch = regcache->arch ();
45888261
JT
159 int i;
160
2eb4d78b 161 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
8d4c1ba3 162 if ((regno == i || regno == -1)
2eb4d78b 163 && ! gdbarch_cannot_store_register (gdbarch, i))
34a79281 164 regcache->raw_collect (i, 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{
ac7936df 171 struct gdbarch *gdbarch = regcache->arch ();
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))
73e1c03f 181 regcache->raw_supply (i, NULL);
45888261 182 else
73e1c03f
SM
183 regcache->raw_supply (i,
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{
ac7936df 194 struct gdbarch *gdbarch = regcache->arch ();
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))
34a79281
SM
202 regcache->raw_collect
203 (i, (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
224c3ddb 264 buf = (gdb_byte *) 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{
dea34e8c 357 nbsd_init_abi (info, gdbarch);
79743962 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}
63807e1d 375
6c265988 376void _initialize_mipsnbsd_tdep ();
45888261 377void
6c265988 378_initialize_mipsnbsd_tdep ()
45888261 379{
1736a7bd 380 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD,
45888261 381 mipsnbsd_init_abi);
45888261 382}
This page took 1.700707 seconds and 4 git commands to generate.