Home | History | Annotate | Line # | Download | only in gdb
mips-fbsd-tdep.c revision 1.1
      1 /* Target-dependent code for FreeBSD/mips.
      2 
      3    Copyright (C) 2017 Free Software Foundation, Inc.
      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 
     32 /* Shorthand for some register numbers used below.  */
     33 #define MIPS_PC_REGNUM  MIPS_EMBED_PC_REGNUM
     34 #define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM
     35 #define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32
     36 
     37 /* Core file support. */
     38 
     39 /* Number of registers in `struct reg' from <machine/reg.h>.  The
     40    first 38 follow the standard MIPS layout.  The 39th holds
     41    IC_INT_REG on RM7K and RM9K processors.  The 40th is a dummy for
     42    padding.  */
     43 #define MIPS_FBSD_NUM_GREGS	40
     44 
     45 /* Number of registers in `struct fpreg' from <machine/reg.h>.  The
     46    first 32 hold floating point registers.  33 holds the FSR.  The
     47    34th is a dummy for padding.  */
     48 #define MIPS_FBSD_NUM_FPREGS	34
     49 
     50 /* Supply a single register.  If the source register size matches the
     51    size the regcache expects, this can use regcache_raw_supply().  If
     52    they are different, this copies the source register into a buffer
     53    that can be passed to regcache_raw_supply().  */
     54 
     55 static void
     56 mips_fbsd_supply_reg (struct regcache *regcache, int regnum, const void *addr,
     57 		      size_t len)
     58 {
     59   struct gdbarch *gdbarch = get_regcache_arch (regcache);
     60 
     61   if (register_size (gdbarch, regnum) == len)
     62     regcache_raw_supply (regcache, regnum, addr);
     63   else
     64     {
     65       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
     66       gdb_byte buf[MAX_REGISTER_SIZE];
     67       LONGEST val;
     68 
     69       val = extract_signed_integer ((const gdb_byte *) addr, len, byte_order);
     70       store_signed_integer (buf, register_size (gdbarch, regnum), byte_order,
     71 			    val);
     72       regcache_raw_supply (regcache, regnum, buf);
     73     }
     74 }
     75 
     76 /* Collect a single register.  If the destination register size
     77    matches the size the regcache expects, this can use
     78    regcache_raw_supply().  If they are different, this fetches the
     79    register via regcache_raw_supply() into a buffer and then copies it
     80    into the final destination.  */
     81 
     82 static void
     83 mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr,
     84 		       size_t len)
     85 {
     86   struct gdbarch *gdbarch = get_regcache_arch (regcache);
     87 
     88   if (register_size (gdbarch, regnum) == len)
     89     regcache_raw_collect (regcache, regnum, addr);
     90   else
     91     {
     92       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
     93       gdb_byte buf[MAX_REGISTER_SIZE];
     94       LONGEST val;
     95 
     96       regcache_raw_collect (regcache, regnum, buf);
     97       val = extract_signed_integer (buf, register_size (gdbarch, regnum),
     98 				    byte_order);
     99       store_signed_integer ((gdb_byte *) addr, len, byte_order, val);
    100     }
    101 }
    102 
    103 /* Supply the floating-point registers stored in FPREGS to REGCACHE.
    104    Each floating-point register in FPREGS is REGSIZE bytes in
    105    length.  */
    106 
    107 void
    108 mips_fbsd_supply_fpregs (struct regcache *regcache, int regnum,
    109 			 const void *fpregs, size_t regsize)
    110 {
    111   const gdb_byte *regs = (const gdb_byte *) fpregs;
    112   int i;
    113 
    114   for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++)
    115     if (regnum == i || regnum == -1)
    116       mips_fbsd_supply_reg (regcache, i,
    117 			    regs + (i - MIPS_FP0_REGNUM) * regsize, regsize);
    118 }
    119 
    120 /* Supply the general-purpose registers stored in GREGS to REGCACHE.
    121    Each general-purpose register in GREGS is REGSIZE bytes in
    122    length.  */
    123 
    124 void
    125 mips_fbsd_supply_gregs (struct regcache *regcache, int regnum,
    126 			const void *gregs, size_t regsize)
    127 {
    128   const gdb_byte *regs = (const gdb_byte *) gregs;
    129   int i;
    130 
    131   for (i = 0; i <= MIPS_PC_REGNUM; i++)
    132     if (regnum == i || regnum == -1)
    133       mips_fbsd_supply_reg (regcache, i, regs + i * regsize, regsize);
    134 }
    135 
    136 /* Collect the floating-point registers from REGCACHE and store them
    137    in FPREGS.  Each floating-point register in FPREGS is REGSIZE bytes
    138    in length.  */
    139 
    140 void
    141 mips_fbsd_collect_fpregs (const struct regcache *regcache, int regnum,
    142 			  void *fpregs, size_t regsize)
    143 {
    144   gdb_byte *regs = (gdb_byte *) fpregs;
    145   int i;
    146 
    147   for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++)
    148     if (regnum == i || regnum == -1)
    149       mips_fbsd_collect_reg (regcache, i,
    150 			     regs + (i - MIPS_FP0_REGNUM) * regsize, regsize);
    151 }
    152 
    153 /* Collect the general-purpose registers from REGCACHE and store them
    154    in GREGS.  Each general-purpose register in GREGS is REGSIZE bytes
    155    in length.  */
    156 
    157 void
    158 mips_fbsd_collect_gregs (const struct regcache *regcache, int regnum,
    159 			 void *gregs, size_t regsize)
    160 {
    161   gdb_byte *regs = (gdb_byte *) gregs;
    162   int i;
    163 
    164   for (i = 0; i <= MIPS_PC_REGNUM; i++)
    165     if (regnum == i || regnum == -1)
    166       mips_fbsd_collect_reg (regcache, i, regs + i * regsize, regsize);
    167 }
    168 
    169 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
    170    in the floating-point register set REGSET to register cache
    171    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
    172 
    173 static void
    174 mips_fbsd_supply_fpregset (const struct regset *regset,
    175 			   struct regcache *regcache,
    176 			   int regnum, const void *fpregs, size_t len)
    177 {
    178   size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
    179 
    180   gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
    181 
    182   mips_fbsd_supply_fpregs (regcache, regnum, fpregs, regsize);
    183 }
    184 
    185 /* Collect register REGNUM from the register cache REGCACHE and store
    186    it in the buffer specified by FPREGS and LEN in the floating-point
    187    register set REGSET.  If REGNUM is -1, do this for all registers in
    188    REGSET.  */
    189 
    190 static void
    191 mips_fbsd_collect_fpregset (const struct regset *regset,
    192 			    const struct regcache *regcache,
    193 			    int regnum, void *fpregs, size_t len)
    194 {
    195   size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
    196 
    197   gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
    198 
    199   mips_fbsd_collect_fpregs (regcache, regnum, fpregs, regsize);
    200 }
    201 
    202 /* Supply register REGNUM from the buffer specified by GREGS and LEN
    203    in the general-purpose register set REGSET to register cache
    204    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
    205 
    206 static void
    207 mips_fbsd_supply_gregset (const struct regset *regset,
    208 			  struct regcache *regcache, int regnum,
    209 			  const void *gregs, size_t len)
    210 {
    211   size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
    212 
    213   gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
    214 
    215   mips_fbsd_supply_gregs (regcache, regnum, gregs, regsize);
    216 }
    217 
    218 /* Collect register REGNUM from the register cache REGCACHE and store
    219    it in the buffer specified by GREGS and LEN in the general-purpose
    220    register set REGSET.  If REGNUM is -1, do this for all registers in
    221    REGSET.  */
    222 
    223 static void
    224 mips_fbsd_collect_gregset (const struct regset *regset,
    225 			   const struct regcache *regcache,
    226 			   int regnum, void *gregs, size_t len)
    227 {
    228   size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
    229 
    230   gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
    231 
    232   mips_fbsd_collect_gregs (regcache, regnum, gregs, regsize);
    233 }
    234 
    235 /* FreeBSD/mips register sets.  */
    236 
    237 static const struct regset mips_fbsd_gregset =
    238 {
    239   NULL,
    240   mips_fbsd_supply_gregset,
    241   mips_fbsd_collect_gregset,
    242 };
    243 
    244 static const struct regset mips_fbsd_fpregset =
    245 {
    246   NULL,
    247   mips_fbsd_supply_fpregset,
    248   mips_fbsd_collect_fpregset,
    249 };
    250 
    251 /* Iterate over core file register note sections.  */
    252 
    253 static void
    254 mips_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
    255 					iterate_over_regset_sections_cb *cb,
    256 					void *cb_data,
    257 					const struct regcache *regcache)
    258 {
    259   size_t regsize = mips_abi_regsize (gdbarch);
    260 
    261   cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, &mips_fbsd_gregset,
    262       NULL, cb_data);
    263   cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, &mips_fbsd_fpregset,
    264       NULL, cb_data);
    265 }
    266 
    267 /* Signal trampoline support.  */
    268 
    269 #define FBSD_SYS_sigreturn	417
    270 
    271 #define MIPS_INST_LI_V0_SIGRETURN 0x24020000 + FBSD_SYS_sigreturn
    272 #define MIPS_INST_SYSCALL	0x0000000c
    273 #define MIPS_INST_BREAK		0x0000000d
    274 
    275 #define O32_SIGFRAME_UCONTEXT_OFFSET	(16)
    276 #define O32_SIGSET_T_SIZE	(16)
    277 
    278 #define O32_UCONTEXT_ONSTACK	(O32_SIGSET_T_SIZE)
    279 #define O32_UCONTEXT_PC		(O32_UCONTEXT_ONSTACK + 4)
    280 #define O32_UCONTEXT_REGS	(O32_UCONTEXT_PC + 4)
    281 #define O32_UCONTEXT_SR		(O32_UCONTEXT_REGS + 4 * 32)
    282 #define O32_UCONTEXT_LO		(O32_UCONTEXT_SR + 4)
    283 #define O32_UCONTEXT_HI		(O32_UCONTEXT_LO + 4)
    284 #define O32_UCONTEXT_FPUSED	(O32_UCONTEXT_HI + 4)
    285 #define O32_UCONTEXT_FPREGS	(O32_UCONTEXT_FPUSED + 4)
    286 
    287 #define O32_UCONTEXT_REG_SIZE	4
    288 
    289 static void
    290 mips_fbsd_sigframe_init (const struct tramp_frame *self,
    291 			 struct frame_info *this_frame,
    292 			 struct trad_frame_cache *cache,
    293 			 CORE_ADDR func)
    294 {
    295   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    296   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    297   CORE_ADDR sp, ucontext_addr, addr;
    298   int regnum;
    299   gdb_byte buf[4];
    300 
    301   /* We find the appropriate instance of `ucontext_t' at a
    302      fixed offset in the signal frame.  */
    303   sp = get_frame_register_signed (this_frame,
    304 				  MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch));
    305   ucontext_addr = sp + O32_SIGFRAME_UCONTEXT_OFFSET;
    306 
    307   /* PC.  */
    308   regnum = mips_regnum (gdbarch)->pc;
    309   trad_frame_set_reg_addr (cache,
    310 			   regnum + gdbarch_num_regs (gdbarch),
    311 			   ucontext_addr + O32_UCONTEXT_PC);
    312 
    313   /* GPRs.  */
    314   for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + O32_UCONTEXT_REGS;
    315        regnum <= MIPS_RA_REGNUM; regnum++, addr += O32_UCONTEXT_REG_SIZE)
    316     trad_frame_set_reg_addr (cache,
    317 			     regnum + gdbarch_num_regs (gdbarch),
    318 			     addr);
    319 
    320   regnum = MIPS_PS_REGNUM;
    321   trad_frame_set_reg_addr (cache,
    322 			   regnum + gdbarch_num_regs (gdbarch),
    323 			   ucontext_addr + O32_UCONTEXT_SR);
    324 
    325   /* HI and LO.  */
    326   regnum = mips_regnum (gdbarch)->lo;
    327   trad_frame_set_reg_addr (cache,
    328 			   regnum + gdbarch_num_regs (gdbarch),
    329 			   ucontext_addr + O32_UCONTEXT_LO);
    330   regnum = mips_regnum (gdbarch)->hi;
    331   trad_frame_set_reg_addr (cache,
    332 			   regnum + gdbarch_num_regs (gdbarch),
    333 			   ucontext_addr + O32_UCONTEXT_HI);
    334 
    335   if (target_read_memory (ucontext_addr + O32_UCONTEXT_FPUSED, buf, 4) == 0
    336       && extract_unsigned_integer (buf, 4, byte_order) != 0)
    337     {
    338       for (regnum = 0, addr = ucontext_addr + O32_UCONTEXT_FPREGS;
    339 	   regnum < 32; regnum++, addr += O32_UCONTEXT_REG_SIZE)
    340 	trad_frame_set_reg_addr (cache,
    341 				 regnum + gdbarch_fp0_regnum (gdbarch),
    342 				 addr);
    343       trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status,
    344 			       addr);
    345     }
    346 
    347   trad_frame_set_id (cache, frame_id_build (sp, func));
    348 }
    349 
    350 #define MIPS_INST_ADDIU_A0_SP_O32 (0x27a40000 \
    351 				   + O32_SIGFRAME_UCONTEXT_OFFSET)
    352 
    353 static const struct tramp_frame mips_fbsd_sigframe =
    354 {
    355   SIGTRAMP_FRAME,
    356   MIPS_INSN32_SIZE,
    357   {
    358     { MIPS_INST_ADDIU_A0_SP_O32, -1 },	/* addiu   a0, sp, SIGF_UC */
    359     { MIPS_INST_LI_V0_SIGRETURN, -1 },	/* li      v0, SYS_sigreturn */
    360     { MIPS_INST_SYSCALL, -1 },		/* syscall */
    361     { MIPS_INST_BREAK, -1 },		/* break */
    362     { TRAMP_SENTINEL_INSN, -1 }
    363   },
    364   mips_fbsd_sigframe_init
    365 };
    366 
    367 #define N64_SIGFRAME_UCONTEXT_OFFSET	(32)
    368 #define N64_SIGSET_T_SIZE	(16)
    369 
    370 #define N64_UCONTEXT_ONSTACK	(N64_SIGSET_T_SIZE)
    371 #define N64_UCONTEXT_PC		(N64_UCONTEXT_ONSTACK + 8)
    372 #define N64_UCONTEXT_REGS	(N64_UCONTEXT_PC + 8)
    373 #define N64_UCONTEXT_SR		(N64_UCONTEXT_REGS + 8 * 32)
    374 #define N64_UCONTEXT_LO		(N64_UCONTEXT_SR + 8)
    375 #define N64_UCONTEXT_HI		(N64_UCONTEXT_LO + 8)
    376 #define N64_UCONTEXT_FPUSED	(N64_UCONTEXT_HI + 8)
    377 #define N64_UCONTEXT_FPREGS	(N64_UCONTEXT_FPUSED + 8)
    378 
    379 #define N64_UCONTEXT_REG_SIZE	8
    380 
    381 static void
    382 mips64_fbsd_sigframe_init (const struct tramp_frame *self,
    383 			   struct frame_info *this_frame,
    384 			   struct trad_frame_cache *cache,
    385 			   CORE_ADDR func)
    386 {
    387   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    388   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    389   CORE_ADDR sp, ucontext_addr, addr;
    390   int regnum;
    391   gdb_byte buf[4];
    392 
    393   /* We find the appropriate instance of `ucontext_t' at a
    394      fixed offset in the signal frame.  */
    395   sp = get_frame_register_signed (this_frame,
    396 				  MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch));
    397   ucontext_addr = sp + N64_SIGFRAME_UCONTEXT_OFFSET;
    398 
    399   /* PC.  */
    400   regnum = mips_regnum (gdbarch)->pc;
    401   trad_frame_set_reg_addr (cache,
    402 			   regnum + gdbarch_num_regs (gdbarch),
    403 			   ucontext_addr + N64_UCONTEXT_PC);
    404 
    405   /* GPRs.  */
    406   for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + N64_UCONTEXT_REGS;
    407        regnum <= MIPS_RA_REGNUM; regnum++, addr += N64_UCONTEXT_REG_SIZE)
    408     trad_frame_set_reg_addr (cache,
    409 			     regnum + gdbarch_num_regs (gdbarch),
    410 			     addr);
    411 
    412   regnum = MIPS_PS_REGNUM;
    413   trad_frame_set_reg_addr (cache,
    414 			   regnum + gdbarch_num_regs (gdbarch),
    415 			   ucontext_addr + N64_UCONTEXT_SR);
    416 
    417   /* HI and LO.  */
    418   regnum = mips_regnum (gdbarch)->lo;
    419   trad_frame_set_reg_addr (cache,
    420 			   regnum + gdbarch_num_regs (gdbarch),
    421 			   ucontext_addr + N64_UCONTEXT_LO);
    422   regnum = mips_regnum (gdbarch)->hi;
    423   trad_frame_set_reg_addr (cache,
    424 			   regnum + gdbarch_num_regs (gdbarch),
    425 			   ucontext_addr + N64_UCONTEXT_HI);
    426 
    427   if (target_read_memory (ucontext_addr + N64_UCONTEXT_FPUSED, buf, 4) == 0
    428       && extract_unsigned_integer (buf, 4, byte_order) != 0)
    429     {
    430       for (regnum = 0, addr = ucontext_addr + N64_UCONTEXT_FPREGS;
    431 	   regnum < 32; regnum++, addr += N64_UCONTEXT_REG_SIZE)
    432 	trad_frame_set_reg_addr (cache,
    433 				 regnum + gdbarch_fp0_regnum (gdbarch),
    434 				 addr);
    435       trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status,
    436 			       addr);
    437     }
    438 
    439   trad_frame_set_id (cache, frame_id_build (sp, func));
    440 }
    441 
    442 #define MIPS_INST_DADDIU_A0_SP_N64 (0x67a40000 \
    443 				    + N64_SIGFRAME_UCONTEXT_OFFSET)
    444 
    445 static const struct tramp_frame mips64_fbsd_sigframe =
    446 {
    447   SIGTRAMP_FRAME,
    448   MIPS_INSN32_SIZE,
    449   {
    450     { MIPS_INST_DADDIU_A0_SP_N64, -1 },	/* daddiu  a0, sp, SIGF_UC */
    451     { MIPS_INST_LI_V0_SIGRETURN, -1 },	/* li      v0, SYS_sigreturn */
    452     { MIPS_INST_SYSCALL, -1 },		/* syscall */
    453     { MIPS_INST_BREAK, -1 },		/* break */
    454     { TRAMP_SENTINEL_INSN, -1 }
    455   },
    456   mips64_fbsd_sigframe_init
    457 };
    458 
    459 /* Shared library support.  */
    460 
    461 /* FreeBSD/mips uses a slightly different `struct link_map' than the
    462    other FreeBSD platforms as it includes an additional `l_off'
    463    member.  */
    464 
    465 static struct link_map_offsets *
    466 mips_fbsd_ilp32_fetch_link_map_offsets (void)
    467 {
    468   static struct link_map_offsets lmo;
    469   static struct link_map_offsets *lmp = NULL;
    470 
    471   if (lmp == NULL)
    472     {
    473       lmp = &lmo;
    474 
    475       lmo.r_version_offset = 0;
    476       lmo.r_version_size = 4;
    477       lmo.r_map_offset = 4;
    478       lmo.r_brk_offset = 8;
    479       lmo.r_ldsomap_offset = -1;
    480 
    481       lmo.link_map_size = 24;
    482       lmo.l_addr_offset = 0;
    483       lmo.l_name_offset = 8;
    484       lmo.l_ld_offset = 12;
    485       lmo.l_next_offset = 16;
    486       lmo.l_prev_offset = 20;
    487     }
    488 
    489   return lmp;
    490 }
    491 
    492 static struct link_map_offsets *
    493 mips_fbsd_lp64_fetch_link_map_offsets (void)
    494 {
    495   static struct link_map_offsets lmo;
    496   static struct link_map_offsets *lmp = NULL;
    497 
    498   if (lmp == NULL)
    499     {
    500       lmp = &lmo;
    501 
    502       lmo.r_version_offset = 0;
    503       lmo.r_version_size = 4;
    504       lmo.r_map_offset = 8;
    505       lmo.r_brk_offset = 16;
    506       lmo.r_ldsomap_offset = -1;
    507 
    508       lmo.link_map_size = 48;
    509       lmo.l_addr_offset = 0;
    510       lmo.l_name_offset = 16;
    511       lmo.l_ld_offset = 24;
    512       lmo.l_next_offset = 32;
    513       lmo.l_prev_offset = 40;
    514     }
    515 
    516   return lmp;
    517 }
    518 
    519 static void
    520 mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    521 {
    522   enum mips_abi abi = mips_abi (gdbarch);
    523 
    524   /* Generic FreeBSD support.  */
    525   fbsd_init_abi (info, gdbarch);
    526 
    527   set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
    528 
    529   switch (abi)
    530     {
    531       case MIPS_ABI_O32:
    532 	tramp_frame_prepend_unwinder (gdbarch, &mips_fbsd_sigframe);
    533 	break;
    534       case MIPS_ABI_N32:
    535 	break;
    536       case MIPS_ABI_N64:
    537 	tramp_frame_prepend_unwinder (gdbarch, &mips64_fbsd_sigframe);
    538 	break;
    539     }
    540 
    541   set_gdbarch_iterate_over_regset_sections
    542     (gdbarch, mips_fbsd_iterate_over_regset_sections);
    543 
    544   /* FreeBSD/mips has SVR4-style shared libraries.  */
    545   set_solib_svr4_fetch_link_map_offsets
    546     (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
    547 	       mips_fbsd_ilp32_fetch_link_map_offsets :
    548 	       mips_fbsd_lp64_fetch_link_map_offsets));
    549 }
    550 
    551 
    553 /* Provide a prototype to silence -Wmissing-prototypes.  */
    554 void _initialize_mips_fbsd_tdep (void);
    555 
    556 void
    557 _initialize_mips_fbsd_tdep (void)
    558 {
    559   gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD,
    560 			  mips_fbsd_init_abi);
    561 }
    562