]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/mips-fbsd-tdep.c
Automatic Copyright Year update after running gdb/copyright.py
[thirdparty/binutils-gdb.git] / gdb / mips-fbsd-tdep.c
CommitLineData
387360da
JB
1/* Target-dependent code for FreeBSD/mips.
2
4a94e368 3 Copyright (C) 2017-2022 Free Software Foundation, Inc.
387360da
JB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "osabi.h"
22#include "regset.h"
23#include "trad-frame.h"
24#include "tramp-frame.h"
25
26#include "fbsd-tdep.h"
27#include "mips-tdep.h"
28#include "mips-fbsd-tdep.h"
29
30#include "solib-svr4.h"
31
387360da
JB
32/* Core file support. */
33
34/* Number of registers in `struct reg' from <machine/reg.h>. The
35 first 38 follow the standard MIPS layout. The 39th holds
36 IC_INT_REG on RM7K and RM9K processors. The 40th is a dummy for
37 padding. */
38#define MIPS_FBSD_NUM_GREGS 40
39
40/* Number of registers in `struct fpreg' from <machine/reg.h>. The
41 first 32 hold floating point registers. 33 holds the FSR. The
7755ddb7
JB
42 34th holds FIR on FreeBSD 12.0 and newer kernels. On older kernels
43 it was a zero-filled dummy for padding. */
387360da
JB
44#define MIPS_FBSD_NUM_FPREGS 34
45
b057297a
AH
46/* Supply a single register. The register size might not match, so use
47 regcache->raw_supply_integer (). */
387360da
JB
48
49static void
50mips_fbsd_supply_reg (struct regcache *regcache, int regnum, const void *addr,
51 size_t len)
52{
b057297a 53 regcache->raw_supply_integer (regnum, (const gdb_byte *) addr, len, true);
387360da
JB
54}
55
b057297a
AH
56/* Collect a single register. The register size might not match, so use
57 regcache->raw_collect_integer (). */
387360da
JB
58
59static void
60mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr,
61 size_t len)
62{
b057297a 63 regcache->raw_collect_integer (regnum, (gdb_byte *) addr, len, true);
387360da
JB
64}
65
66/* Supply the floating-point registers stored in FPREGS to REGCACHE.
67 Each floating-point register in FPREGS is REGSIZE bytes in
68 length. */
69
70void
71mips_fbsd_supply_fpregs (struct regcache *regcache, int regnum,
72 const void *fpregs, size_t regsize)
73{
ac7936df 74 struct gdbarch *gdbarch = regcache->arch ();
387360da 75 const gdb_byte *regs = (const gdb_byte *) fpregs;
7755ddb7 76 int i, fp0num;
387360da 77
f7241d4f 78 fp0num = mips_regnum (gdbarch)->fp0;
7755ddb7
JB
79 for (i = 0; i <= 32; i++)
80 if (regnum == fp0num + i || regnum == -1)
81 mips_fbsd_supply_reg (regcache, fp0num + i,
82 regs + i * regsize, regsize);
83 if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
84 mips_fbsd_supply_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
85 regs + 32 * regsize, regsize);
86 if ((regnum == mips_regnum (gdbarch)->fp_implementation_revision
87 || regnum == -1)
88 && extract_unsigned_integer (regs + 33 * regsize, regsize,
89 gdbarch_byte_order (gdbarch)) != 0)
90 mips_fbsd_supply_reg (regcache,
91 mips_regnum (gdbarch)->fp_implementation_revision,
92 regs + 33 * regsize, regsize);
387360da
JB
93}
94
95/* Supply the general-purpose registers stored in GREGS to REGCACHE.
96 Each general-purpose register in GREGS is REGSIZE bytes in
97 length. */
98
99void
100mips_fbsd_supply_gregs (struct regcache *regcache, int regnum,
101 const void *gregs, size_t regsize)
102{
ac7936df 103 struct gdbarch *gdbarch = regcache->arch ();
387360da
JB
104 const gdb_byte *regs = (const gdb_byte *) gregs;
105 int i;
106
f7241d4f 107 for (i = 0; i <= mips_regnum (gdbarch)->pc; i++)
387360da
JB
108 if (regnum == i || regnum == -1)
109 mips_fbsd_supply_reg (regcache, i, regs + i * regsize, regsize);
110}
111
112/* Collect the floating-point registers from REGCACHE and store them
113 in FPREGS. Each floating-point register in FPREGS is REGSIZE bytes
114 in length. */
115
116void
117mips_fbsd_collect_fpregs (const struct regcache *regcache, int regnum,
118 void *fpregs, size_t regsize)
119{
ac7936df 120 struct gdbarch *gdbarch = regcache->arch ();
387360da 121 gdb_byte *regs = (gdb_byte *) fpregs;
7755ddb7 122 int i, fp0num;
387360da 123
f7241d4f 124 fp0num = mips_regnum (gdbarch)->fp0;
7755ddb7
JB
125 for (i = 0; i < 32; i++)
126 if (regnum == fp0num + i || regnum == -1)
127 mips_fbsd_collect_reg (regcache, fp0num + i,
128 regs + i * regsize, regsize);
129 if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
130 mips_fbsd_collect_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
131 regs + 32 * regsize, regsize);
132 if (regnum == mips_regnum (gdbarch)->fp_implementation_revision
133 || regnum == -1)
134 mips_fbsd_collect_reg (regcache,
135 mips_regnum (gdbarch)->fp_implementation_revision,
136 regs + 33 * regsize, regsize);
387360da
JB
137}
138
139/* Collect the general-purpose registers from REGCACHE and store them
140 in GREGS. Each general-purpose register in GREGS is REGSIZE bytes
141 in length. */
142
143void
144mips_fbsd_collect_gregs (const struct regcache *regcache, int regnum,
145 void *gregs, size_t regsize)
146{
ac7936df 147 struct gdbarch *gdbarch = regcache->arch ();
387360da
JB
148 gdb_byte *regs = (gdb_byte *) gregs;
149 int i;
150
f7241d4f 151 for (i = 0; i <= mips_regnum (gdbarch)->pc; i++)
387360da
JB
152 if (regnum == i || regnum == -1)
153 mips_fbsd_collect_reg (regcache, i, regs + i * regsize, regsize);
154}
155
156/* Supply register REGNUM from the buffer specified by FPREGS and LEN
157 in the floating-point register set REGSET to register cache
158 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
159
160static void
161mips_fbsd_supply_fpregset (const struct regset *regset,
162 struct regcache *regcache,
163 int regnum, const void *fpregs, size_t len)
164{
ac7936df 165 size_t regsize = mips_abi_regsize (regcache->arch ());
387360da
JB
166
167 gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
168
169 mips_fbsd_supply_fpregs (regcache, regnum, fpregs, regsize);
170}
171
172/* Collect register REGNUM from the register cache REGCACHE and store
173 it in the buffer specified by FPREGS and LEN in the floating-point
174 register set REGSET. If REGNUM is -1, do this for all registers in
175 REGSET. */
176
177static void
178mips_fbsd_collect_fpregset (const struct regset *regset,
179 const struct regcache *regcache,
180 int regnum, void *fpregs, size_t len)
181{
ac7936df 182 size_t regsize = mips_abi_regsize (regcache->arch ());
387360da
JB
183
184 gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
185
186 mips_fbsd_collect_fpregs (regcache, regnum, fpregs, regsize);
187}
188
189/* Supply register REGNUM from the buffer specified by GREGS and LEN
190 in the general-purpose register set REGSET to register cache
191 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
192
193static void
194mips_fbsd_supply_gregset (const struct regset *regset,
195 struct regcache *regcache, int regnum,
196 const void *gregs, size_t len)
197{
ac7936df 198 size_t regsize = mips_abi_regsize (regcache->arch ());
387360da
JB
199
200 gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
201
202 mips_fbsd_supply_gregs (regcache, regnum, gregs, regsize);
203}
204
205/* Collect register REGNUM from the register cache REGCACHE and store
206 it in the buffer specified by GREGS and LEN in the general-purpose
207 register set REGSET. If REGNUM is -1, do this for all registers in
208 REGSET. */
209
210static void
211mips_fbsd_collect_gregset (const struct regset *regset,
212 const struct regcache *regcache,
213 int regnum, void *gregs, size_t len)
214{
ac7936df 215 size_t regsize = mips_abi_regsize (regcache->arch ());
387360da
JB
216
217 gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
218
219 mips_fbsd_collect_gregs (regcache, regnum, gregs, regsize);
220}
221
222/* FreeBSD/mips register sets. */
223
224static const struct regset mips_fbsd_gregset =
225{
226 NULL,
227 mips_fbsd_supply_gregset,
228 mips_fbsd_collect_gregset,
229};
230
231static const struct regset mips_fbsd_fpregset =
232{
233 NULL,
234 mips_fbsd_supply_fpregset,
235 mips_fbsd_collect_fpregset,
236};
237
238/* Iterate over core file register note sections. */
239
240static void
241mips_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
242 iterate_over_regset_sections_cb *cb,
243 void *cb_data,
244 const struct regcache *regcache)
245{
246 size_t regsize = mips_abi_regsize (gdbarch);
247
a616bb94
AH
248 cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, MIPS_FBSD_NUM_GREGS * regsize,
249 &mips_fbsd_gregset, NULL, cb_data);
250 cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, MIPS_FBSD_NUM_FPREGS * regsize,
251 &mips_fbsd_fpregset, NULL, cb_data);
387360da
JB
252}
253
254/* Signal trampoline support. */
255
256#define FBSD_SYS_sigreturn 417
257
258#define MIPS_INST_LI_V0_SIGRETURN 0x24020000 + FBSD_SYS_sigreturn
259#define MIPS_INST_SYSCALL 0x0000000c
260#define MIPS_INST_BREAK 0x0000000d
261
262#define O32_SIGFRAME_UCONTEXT_OFFSET (16)
263#define O32_SIGSET_T_SIZE (16)
264
265#define O32_UCONTEXT_ONSTACK (O32_SIGSET_T_SIZE)
266#define O32_UCONTEXT_PC (O32_UCONTEXT_ONSTACK + 4)
267#define O32_UCONTEXT_REGS (O32_UCONTEXT_PC + 4)
268#define O32_UCONTEXT_SR (O32_UCONTEXT_REGS + 4 * 32)
269#define O32_UCONTEXT_LO (O32_UCONTEXT_SR + 4)
270#define O32_UCONTEXT_HI (O32_UCONTEXT_LO + 4)
271#define O32_UCONTEXT_FPUSED (O32_UCONTEXT_HI + 4)
272#define O32_UCONTEXT_FPREGS (O32_UCONTEXT_FPUSED + 4)
273
274#define O32_UCONTEXT_REG_SIZE 4
275
276static void
277mips_fbsd_sigframe_init (const struct tramp_frame *self,
278 struct frame_info *this_frame,
279 struct trad_frame_cache *cache,
280 CORE_ADDR func)
281{
282 struct gdbarch *gdbarch = get_frame_arch (this_frame);
283 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
284 CORE_ADDR sp, ucontext_addr, addr;
285 int regnum;
286 gdb_byte buf[4];
287
288 /* We find the appropriate instance of `ucontext_t' at a
289 fixed offset in the signal frame. */
290 sp = get_frame_register_signed (this_frame,
291 MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch));
292 ucontext_addr = sp + O32_SIGFRAME_UCONTEXT_OFFSET;
293
294 /* PC. */
295 regnum = mips_regnum (gdbarch)->pc;
296 trad_frame_set_reg_addr (cache,
297 regnum + gdbarch_num_regs (gdbarch),
298 ucontext_addr + O32_UCONTEXT_PC);
299
300 /* GPRs. */
301 for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + O32_UCONTEXT_REGS;
302 regnum <= MIPS_RA_REGNUM; regnum++, addr += O32_UCONTEXT_REG_SIZE)
303 trad_frame_set_reg_addr (cache,
304 regnum + gdbarch_num_regs (gdbarch),
305 addr);
306
307 regnum = MIPS_PS_REGNUM;
308 trad_frame_set_reg_addr (cache,
309 regnum + gdbarch_num_regs (gdbarch),
310 ucontext_addr + O32_UCONTEXT_SR);
311
312 /* HI and LO. */
313 regnum = mips_regnum (gdbarch)->lo;
314 trad_frame_set_reg_addr (cache,
315 regnum + gdbarch_num_regs (gdbarch),
316 ucontext_addr + O32_UCONTEXT_LO);
317 regnum = mips_regnum (gdbarch)->hi;
318 trad_frame_set_reg_addr (cache,
319 regnum + gdbarch_num_regs (gdbarch),
320 ucontext_addr + O32_UCONTEXT_HI);
321
1c33cd7f
YQ
322 if (target_read_memory (ucontext_addr + O32_UCONTEXT_FPUSED, buf, 4) == 0
323 && extract_unsigned_integer (buf, 4, byte_order) != 0)
387360da
JB
324 {
325 for (regnum = 0, addr = ucontext_addr + O32_UCONTEXT_FPREGS;
326 regnum < 32; regnum++, addr += O32_UCONTEXT_REG_SIZE)
327 trad_frame_set_reg_addr (cache,
328 regnum + gdbarch_fp0_regnum (gdbarch),
329 addr);
330 trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status,
331 addr);
332 }
333
334 trad_frame_set_id (cache, frame_id_build (sp, func));
335}
336
337#define MIPS_INST_ADDIU_A0_SP_O32 (0x27a40000 \
338 + O32_SIGFRAME_UCONTEXT_OFFSET)
339
340static const struct tramp_frame mips_fbsd_sigframe =
341{
342 SIGTRAMP_FRAME,
343 MIPS_INSN32_SIZE,
344 {
7bc02706
TT
345 { MIPS_INST_ADDIU_A0_SP_O32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */
346 { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
347 { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
348 { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
349 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
387360da
JB
350 },
351 mips_fbsd_sigframe_init
352};
353
354#define N64_SIGFRAME_UCONTEXT_OFFSET (32)
355#define N64_SIGSET_T_SIZE (16)
356
357#define N64_UCONTEXT_ONSTACK (N64_SIGSET_T_SIZE)
358#define N64_UCONTEXT_PC (N64_UCONTEXT_ONSTACK + 8)
359#define N64_UCONTEXT_REGS (N64_UCONTEXT_PC + 8)
360#define N64_UCONTEXT_SR (N64_UCONTEXT_REGS + 8 * 32)
361#define N64_UCONTEXT_LO (N64_UCONTEXT_SR + 8)
362#define N64_UCONTEXT_HI (N64_UCONTEXT_LO + 8)
363#define N64_UCONTEXT_FPUSED (N64_UCONTEXT_HI + 8)
364#define N64_UCONTEXT_FPREGS (N64_UCONTEXT_FPUSED + 8)
365
366#define N64_UCONTEXT_REG_SIZE 8
367
368static void
369mips64_fbsd_sigframe_init (const struct tramp_frame *self,
370 struct frame_info *this_frame,
371 struct trad_frame_cache *cache,
372 CORE_ADDR func)
373{
374 struct gdbarch *gdbarch = get_frame_arch (this_frame);
375 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
376 CORE_ADDR sp, ucontext_addr, addr;
377 int regnum;
378 gdb_byte buf[4];
379
380 /* We find the appropriate instance of `ucontext_t' at a
381 fixed offset in the signal frame. */
382 sp = get_frame_register_signed (this_frame,
383 MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch));
384 ucontext_addr = sp + N64_SIGFRAME_UCONTEXT_OFFSET;
385
386 /* PC. */
387 regnum = mips_regnum (gdbarch)->pc;
388 trad_frame_set_reg_addr (cache,
389 regnum + gdbarch_num_regs (gdbarch),
390 ucontext_addr + N64_UCONTEXT_PC);
391
392 /* GPRs. */
393 for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + N64_UCONTEXT_REGS;
394 regnum <= MIPS_RA_REGNUM; regnum++, addr += N64_UCONTEXT_REG_SIZE)
395 trad_frame_set_reg_addr (cache,
396 regnum + gdbarch_num_regs (gdbarch),
397 addr);
398
399 regnum = MIPS_PS_REGNUM;
400 trad_frame_set_reg_addr (cache,
401 regnum + gdbarch_num_regs (gdbarch),
402 ucontext_addr + N64_UCONTEXT_SR);
403
404 /* HI and LO. */
405 regnum = mips_regnum (gdbarch)->lo;
406 trad_frame_set_reg_addr (cache,
407 regnum + gdbarch_num_regs (gdbarch),
408 ucontext_addr + N64_UCONTEXT_LO);
409 regnum = mips_regnum (gdbarch)->hi;
410 trad_frame_set_reg_addr (cache,
411 regnum + gdbarch_num_regs (gdbarch),
412 ucontext_addr + N64_UCONTEXT_HI);
413
1c33cd7f
YQ
414 if (target_read_memory (ucontext_addr + N64_UCONTEXT_FPUSED, buf, 4) == 0
415 && extract_unsigned_integer (buf, 4, byte_order) != 0)
387360da
JB
416 {
417 for (regnum = 0, addr = ucontext_addr + N64_UCONTEXT_FPREGS;
418 regnum < 32; regnum++, addr += N64_UCONTEXT_REG_SIZE)
419 trad_frame_set_reg_addr (cache,
420 regnum + gdbarch_fp0_regnum (gdbarch),
421 addr);
422 trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status,
423 addr);
424 }
425
426 trad_frame_set_id (cache, frame_id_build (sp, func));
427}
428
a80a6471
JB
429#define MIPS_INST_ADDIU_A0_SP_N32 (0x27a40000 \
430 + N64_SIGFRAME_UCONTEXT_OFFSET)
431
432static const struct tramp_frame mipsn32_fbsd_sigframe =
433{
434 SIGTRAMP_FRAME,
435 MIPS_INSN32_SIZE,
436 {
7bc02706
TT
437 { MIPS_INST_ADDIU_A0_SP_N32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */
438 { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
439 { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
440 { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
441 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
a80a6471
JB
442 },
443 mips64_fbsd_sigframe_init
444};
445
387360da
JB
446#define MIPS_INST_DADDIU_A0_SP_N64 (0x67a40000 \
447 + N64_SIGFRAME_UCONTEXT_OFFSET)
448
449static const struct tramp_frame mips64_fbsd_sigframe =
450{
451 SIGTRAMP_FRAME,
452 MIPS_INSN32_SIZE,
453 {
7bc02706
TT
454 { MIPS_INST_DADDIU_A0_SP_N64, ULONGEST_MAX }, /* daddiu a0, sp, SIGF_UC */
455 { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
456 { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
457 { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
458 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
387360da
JB
459 },
460 mips64_fbsd_sigframe_init
461};
462
463/* Shared library support. */
464
ed810cc7
JB
465/* FreeBSD/mips can use an alternate routine in the runtime linker to
466 resolve functions. */
467
468static CORE_ADDR
469mips_fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
470{
471 struct bound_minimal_symbol msym
472 = lookup_bound_minimal_symbol ("_mips_rtld_bind");
473 if (msym.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (msym) == pc)
474 return frame_unwind_caller_pc (get_current_frame ());
475
476 return fbsd_skip_solib_resolver (gdbarch, pc);
477}
478
387360da
JB
479/* FreeBSD/mips uses a slightly different `struct link_map' than the
480 other FreeBSD platforms as it includes an additional `l_off'
481 member. */
482
483static struct link_map_offsets *
484mips_fbsd_ilp32_fetch_link_map_offsets (void)
485{
486 static struct link_map_offsets lmo;
487 static struct link_map_offsets *lmp = NULL;
488
489 if (lmp == NULL)
490 {
491 lmp = &lmo;
492
493 lmo.r_version_offset = 0;
494 lmo.r_version_size = 4;
495 lmo.r_map_offset = 4;
496 lmo.r_brk_offset = 8;
497 lmo.r_ldsomap_offset = -1;
498
499 lmo.link_map_size = 24;
500 lmo.l_addr_offset = 0;
501 lmo.l_name_offset = 8;
502 lmo.l_ld_offset = 12;
503 lmo.l_next_offset = 16;
504 lmo.l_prev_offset = 20;
505 }
506
507 return lmp;
508}
509
510static struct link_map_offsets *
511mips_fbsd_lp64_fetch_link_map_offsets (void)
512{
513 static struct link_map_offsets lmo;
514 static struct link_map_offsets *lmp = NULL;
515
516 if (lmp == NULL)
517 {
518 lmp = &lmo;
519
520 lmo.r_version_offset = 0;
521 lmo.r_version_size = 4;
522 lmo.r_map_offset = 8;
523 lmo.r_brk_offset = 16;
524 lmo.r_ldsomap_offset = -1;
525
526 lmo.link_map_size = 48;
527 lmo.l_addr_offset = 0;
528 lmo.l_name_offset = 16;
529 lmo.l_ld_offset = 24;
530 lmo.l_next_offset = 32;
531 lmo.l_prev_offset = 40;
532 }
533
534 return lmp;
535}
536
537static void
538mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
539{
540 enum mips_abi abi = mips_abi (gdbarch);
541
542 /* Generic FreeBSD support. */
543 fbsd_init_abi (info, gdbarch);
544
545 set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
546
547 switch (abi)
548 {
549 case MIPS_ABI_O32:
550 tramp_frame_prepend_unwinder (gdbarch, &mips_fbsd_sigframe);
551 break;
552 case MIPS_ABI_N32:
a80a6471 553 tramp_frame_prepend_unwinder (gdbarch, &mipsn32_fbsd_sigframe);
387360da
JB
554 break;
555 case MIPS_ABI_N64:
556 tramp_frame_prepend_unwinder (gdbarch, &mips64_fbsd_sigframe);
557 break;
558 }
559
560 set_gdbarch_iterate_over_regset_sections
561 (gdbarch, mips_fbsd_iterate_over_regset_sections);
562
ed810cc7
JB
563 set_gdbarch_skip_solib_resolver (gdbarch, mips_fbsd_skip_solib_resolver);
564
387360da
JB
565 /* FreeBSD/mips has SVR4-style shared libraries. */
566 set_solib_svr4_fetch_link_map_offsets
567 (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
568 mips_fbsd_ilp32_fetch_link_map_offsets :
569 mips_fbsd_lp64_fetch_link_map_offsets));
570}
387360da 571
6c265988 572void _initialize_mips_fbsd_tdep ();
387360da 573void
6c265988 574_initialize_mips_fbsd_tdep ()
387360da 575{
c988ac1d 576 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD,
387360da
JB
577 mips_fbsd_init_abi);
578}