Home | History | Annotate | Line # | Download | only in gdb
i386-netbsd-tdep.c revision 1.1
      1 /* Target-dependent code for NetBSD/i386.
      2 
      3    Copyright (C) 1988-2023 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 "arch-utils.h"
     22 #include "frame.h"
     23 #include "gdbcore.h"
     24 #include "regcache.h"
     25 #include "regset.h"
     26 #include "osabi.h"
     27 #include "symtab.h"
     28 #include "trad-frame.h"
     29 #include "tramp-frame.h"
     30 #include "frame-unwind.h"
     31 
     32 #include "i386-tdep.h"
     33 #include "i387-tdep.h"
     34 #include "netbsd-tdep.h"
     35 #include "solib-svr4.h"
     36 
     37 /* From <machine/reg.h>.  */
     38 static int i386nbsd_r_reg_offset[] =
     39 {
     40   0 * 4,			/* %eax */
     41   1 * 4,			/* %ecx */
     42   2 * 4,			/* %edx */
     43   3 * 4,			/* %ebx */
     44   4 * 4,			/* %esp */
     45   5 * 4,			/* %ebp */
     46   6 * 4,			/* %esi */
     47   7 * 4,			/* %edi */
     48   8 * 4,			/* %eip */
     49   9 * 4,			/* %eflags */
     50   10 * 4,			/* %cs */
     51   11 * 4,			/* %ss */
     52   12 * 4,			/* %ds */
     53   13 * 4,			/* %es */
     54   14 * 4,			/* %fs */
     55   15 * 4			/* %gs */
     56 };
     57 
     58 /* From <machine/signal.h>.  */
     59 static int i386nbsd_sc_reg_offset[] =
     60 {
     61   10 * 4,			/* %eax */
     62   9 * 4,			/* %ecx */
     63   8 * 4,			/* %edx */
     64   7 * 4,			/* %ebx */
     65   14 * 4,			/* %esp */
     66   6 * 4,			/* %ebp */
     67   5 * 4,			/* %esi */
     68   4 * 4,			/* %edi */
     69   11 * 4,			/* %eip */
     70   13 * 4,			/* %eflags */
     71   12 * 4,			/* %cs */
     72   15 * 4,			/* %ss */
     73   3 * 4,			/* %ds */
     74   2 * 4,			/* %es */
     75   1 * 4,			/* %fs */
     76   0 * 4				/* %gs */
     77 };
     78 
     79 /* From <machine/mcontext.h>.  */
     80 static int i386nbsd_mc_reg_offset[] =
     81 {
     82   11 * 4,			/* %eax */
     83   10 * 4,			/* %ecx */
     84   9 * 4,			/* %edx */
     85   8 * 4,			/* %ebx */
     86   7 * 4,			/* %esp */
     87   6 * 4,			/* %ebp */
     88   5 * 4,			/* %esi */
     89   4 * 4,			/* %edi */
     90   14 * 4,			/* %eip */
     91   16 * 4,			/* %eflags */
     92   15 * 4,			/* %cs */
     93   18 * 4,			/* %ss */
     94   3 * 4,			/* %ds */
     95   2 * 4,			/* %es */
     96   1 * 4,			/* %fs */
     97   0 * 4				/* %gs */
     98 };
     99 
    100 static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
    101 					  frame_info_ptr,
    102 					  struct trad_frame_cache *,
    103 					  CORE_ADDR);
    104 
    105 static const struct tramp_frame i386nbsd_sigtramp_sc16 =
    106 {
    107   SIGTRAMP_FRAME,
    108   1,
    109   {
    110    /* leal  0x10(%esp), %eax */
    111    { 0x8d, ULONGEST_MAX },
    112    { 0x44, ULONGEST_MAX },
    113    { 0x24, ULONGEST_MAX },
    114    { 0x10, ULONGEST_MAX },
    115 
    116    /* pushl %eax */
    117    { 0x50, ULONGEST_MAX },
    118 
    119    /* pushl %eax */
    120    { 0x50, ULONGEST_MAX },
    121 
    122    /* movl  $0x127, %eax		# __sigreturn14 */
    123    { 0xb8, ULONGEST_MAX },
    124    { 0x27, ULONGEST_MAX },
    125    {0x01, ULONGEST_MAX },
    126    {0x00, ULONGEST_MAX },
    127    {0x00, ULONGEST_MAX },
    128 
    129    /* int   $0x80 */
    130    { 0xcd, ULONGEST_MAX },
    131    { 0x80, ULONGEST_MAX},
    132 
    133    /* movl  $0x1, %eax		# exit */
    134    { 0xb8, ULONGEST_MAX },
    135    { 0x01, ULONGEST_MAX },
    136    {0x00, ULONGEST_MAX },
    137    {0x00, ULONGEST_MAX },
    138    {0x00, ULONGEST_MAX },
    139 
    140    /* int   $0x80 */
    141    { 0xcd, ULONGEST_MAX },
    142    { 0x80, ULONGEST_MAX},
    143 
    144    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    145   },
    146   i386nbsd_sigtramp_cache_init
    147 };
    148 
    149 static const struct tramp_frame i386nbsd_sigtramp_sc2 =
    150 {
    151   SIGTRAMP_FRAME,
    152   1,
    153   {
    154    /* leal  0x0c(%esp), %eax */
    155    { 0x8d, ULONGEST_MAX },
    156    { 0x44, ULONGEST_MAX },
    157    { 0x24, ULONGEST_MAX },
    158    { 0x0c, ULONGEST_MAX },
    159    /* movl  %eax, 0x4(%esp) */
    160    { 0x89, ULONGEST_MAX },
    161    { 0x44, ULONGEST_MAX },
    162    { 0x24, ULONGEST_MAX },
    163    { 0x04, ULONGEST_MAX },
    164    /* movl  $0x127, %eax		# __sigreturn14 */
    165    { 0xb8, ULONGEST_MAX },
    166    { 0x27, ULONGEST_MAX },
    167    {0x01, ULONGEST_MAX },
    168    {0x00, ULONGEST_MAX },
    169    {0x00, ULONGEST_MAX },
    170    /* int   $0x80 */
    171    { 0xcd, ULONGEST_MAX },
    172    { 0x80, ULONGEST_MAX},
    173    /* movl  %eax, 0x4(%esp) */
    174    { 0x89, ULONGEST_MAX },
    175    { 0x44, ULONGEST_MAX },
    176    { 0x24, ULONGEST_MAX },
    177    { 0x04, ULONGEST_MAX },
    178    /* movl  $0x1, %eax */
    179    { 0xb8, ULONGEST_MAX },
    180    { 0x01, ULONGEST_MAX },
    181    {0x00, ULONGEST_MAX },
    182    {0x00, ULONGEST_MAX },
    183    {0x00, ULONGEST_MAX },
    184    /* int   $0x80 */
    185    { 0xcd, ULONGEST_MAX },
    186    { 0x80, ULONGEST_MAX},
    187    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    188   },
    189   i386nbsd_sigtramp_cache_init
    190 };
    191 
    192 static const struct tramp_frame i386nbsd_sigtramp_si2 =
    193 {
    194   SIGTRAMP_FRAME,
    195   1,
    196   {
    197    /* movl  8(%esp),%eax */
    198    { 0x8b, ULONGEST_MAX },
    199    { 0x44, ULONGEST_MAX },
    200    { 0x24, ULONGEST_MAX },
    201    { 0x08, ULONGEST_MAX },
    202    /* movl  %eax, 0x4(%esp) */
    203    { 0x89, ULONGEST_MAX },
    204    { 0x44, ULONGEST_MAX },
    205    { 0x24, ULONGEST_MAX },
    206    { 0x04, ULONGEST_MAX },
    207    /* movl  $0x134, %eax            # setcontext */
    208    { 0xb8, ULONGEST_MAX },
    209    { 0x34, ULONGEST_MAX },
    210    { 0x01, ULONGEST_MAX },
    211    { 0x00, ULONGEST_MAX },
    212    { 0x00, ULONGEST_MAX },
    213    /* int   $0x80 */
    214    { 0xcd, ULONGEST_MAX },
    215    { 0x80, ULONGEST_MAX },
    216    /* movl  %eax, 0x4(%esp) */
    217    { 0x89, ULONGEST_MAX },
    218    { 0x44, ULONGEST_MAX },
    219    { 0x24, ULONGEST_MAX },
    220    { 0x04, ULONGEST_MAX },
    221    /* movl  $0x1, %eax */
    222    { 0xb8, ULONGEST_MAX },
    223    { 0x01, ULONGEST_MAX },
    224    { 0x00, ULONGEST_MAX },
    225    { 0x00, ULONGEST_MAX },
    226    { 0x00, ULONGEST_MAX },
    227    /* int   $0x80 */
    228    { 0xcd, ULONGEST_MAX },
    229    { 0x80, ULONGEST_MAX },
    230    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    231   },
    232   i386nbsd_sigtramp_cache_init
    233 };
    234 
    235 static const struct tramp_frame i386nbsd_sigtramp_si31 =
    236 {
    237   SIGTRAMP_FRAME,
    238   1,
    239   {
    240    /* leal  0x8c(%esp), %eax */
    241    { 0x8d, ULONGEST_MAX },
    242    { 0x84, ULONGEST_MAX },
    243    { 0x24, ULONGEST_MAX },
    244    { 0x8c, ULONGEST_MAX },
    245    { 0x00, ULONGEST_MAX },
    246    { 0x00, ULONGEST_MAX },
    247    { 0x00, ULONGEST_MAX },
    248    /* movl  %eax, 0x4(%esp) */
    249    { 0x89, ULONGEST_MAX },
    250    { 0x44, ULONGEST_MAX },
    251    { 0x24, ULONGEST_MAX },
    252    { 0x04, ULONGEST_MAX },
    253    /* movl  $0x134, %eax            # setcontext */
    254    { 0xb8, ULONGEST_MAX },
    255    { 0x34, ULONGEST_MAX },
    256    { 0x01, ULONGEST_MAX },
    257    { 0x00, ULONGEST_MAX },
    258    { 0x00, ULONGEST_MAX },
    259    /* int   $0x80 */
    260    { 0xcd, ULONGEST_MAX },
    261    { 0x80, ULONGEST_MAX},
    262    /* movl  %eax, 0x4(%esp) */
    263    { 0x89, ULONGEST_MAX },
    264    { 0x44, ULONGEST_MAX },
    265    { 0x24, ULONGEST_MAX },
    266    { 0x04, ULONGEST_MAX },
    267    /* movl  $0x1, %eax */
    268    { 0xb8, ULONGEST_MAX },
    269    { 0x01, ULONGEST_MAX },
    270    {0x00, ULONGEST_MAX },
    271    {0x00, ULONGEST_MAX },
    272    {0x00, ULONGEST_MAX },
    273    /* int   $0x80 */
    274    { 0xcd, ULONGEST_MAX },
    275    { 0x80, ULONGEST_MAX},
    276    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    277   },
    278   i386nbsd_sigtramp_cache_init
    279 };
    280 
    281 static const struct tramp_frame i386nbsd_sigtramp_si4 =
    282 {
    283   SIGTRAMP_FRAME,
    284   1,
    285   {
    286    /* leal  0x8c(%esp), %eax */
    287    { 0x8d, ULONGEST_MAX },
    288    { 0x84, ULONGEST_MAX },
    289    { 0x24, ULONGEST_MAX },
    290    { 0x8c, ULONGEST_MAX },
    291    { 0x00, ULONGEST_MAX },
    292    { 0x00, ULONGEST_MAX },
    293    { 0x00, ULONGEST_MAX },
    294    /* movl  %eax, 0x4(%esp) */
    295    { 0x89, ULONGEST_MAX },
    296    { 0x44, ULONGEST_MAX },
    297    { 0x24, ULONGEST_MAX },
    298    { 0x04, ULONGEST_MAX },
    299    /* movl  $0x134, %eax            # setcontext */
    300    { 0xb8, ULONGEST_MAX },
    301    { 0x34, ULONGEST_MAX },
    302    { 0x01, ULONGEST_MAX },
    303    { 0x00, ULONGEST_MAX },
    304    { 0x00, ULONGEST_MAX },
    305    /* int   $0x80 */
    306    { 0xcd, ULONGEST_MAX },
    307    { 0x80, ULONGEST_MAX},
    308    /* movl   $0xffffffff,0x4(%esp) */
    309    { 0xc7, ULONGEST_MAX },
    310    { 0x44, ULONGEST_MAX },
    311    { 0x24, ULONGEST_MAX },
    312    { 0x04, ULONGEST_MAX },
    313    { 0xff, ULONGEST_MAX },
    314    { 0xff, ULONGEST_MAX },
    315    { 0xff, ULONGEST_MAX },
    316    { 0xff, ULONGEST_MAX },
    317    /* movl  $0x1, %eax */
    318    { 0xb8, ULONGEST_MAX },
    319    { 0x01, ULONGEST_MAX },
    320    {0x00, ULONGEST_MAX },
    321    {0x00, ULONGEST_MAX },
    322    {0x00, ULONGEST_MAX },
    323    /* int   $0x80 */
    324    { 0xcd, ULONGEST_MAX },
    325    { 0x80, ULONGEST_MAX},
    326    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    327   },
    328   i386nbsd_sigtramp_cache_init
    329 };
    330 
    331 static void
    332 i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
    333 			      frame_info_ptr this_frame,
    334 			      struct trad_frame_cache *this_cache,
    335 			      CORE_ADDR func)
    336 {
    337   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    338   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    339   CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
    340   CORE_ADDR base;
    341   int *reg_offset;
    342   int num_regs;
    343   int i;
    344 
    345   if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
    346     {
    347       reg_offset = i386nbsd_sc_reg_offset;
    348       num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
    349 
    350       /* Read in the sigcontext address.  */
    351       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
    352     }
    353   else
    354     {
    355       reg_offset = i386nbsd_mc_reg_offset;
    356       num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
    357 
    358       /* Read in the ucontext address.  */
    359       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
    360       /* offsetof(ucontext_t, uc_mcontext) == 36 */
    361       base += 36;
    362     }
    363 
    364   for (i = 0; i < num_regs; i++)
    365     if (reg_offset[i] != -1)
    366       trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
    367 
    368   /* Construct the frame ID using the function start.  */
    369   trad_frame_set_id (this_cache, frame_id_build (sp, func));
    370 }
    371 
    372 
    374 /* From <machine/frame.h>.  Note that %esp and %ess are only saved in
    375    a trap frame when entering the kernel from user space.  */
    376 static int i386nbsd_tf_reg_offset[] =
    377 {
    378   10 * 4,			/* %eax */
    379    9 * 4,			/* %ecx */
    380    8 * 4,			/* %edx */
    381    7 * 4,			/* %ebx */
    382   -1,				/* %esp */
    383    6 * 4,			/* %ebp */
    384    5 * 4,			/* %esi */
    385    4 * 4,			/* %edi */
    386   13 * 4,			/* %eip */
    387   15 * 4,			/* %eflags */
    388   14 * 4,			/* %cs */
    389   -1,				/* %ss */
    390    3 * 4,			/* %ds */
    391    2 * 4,			/* %es */
    392    1 * 4,			/* %fs */
    393    0 * 4			/* %gs */
    394 };
    395 
    396 static struct trad_frame_cache *
    397 i386nbsd_trapframe_cache(frame_info_ptr this_frame, void **this_cache)
    398 {
    399   struct trad_frame_cache *cache;
    400   CORE_ADDR func, sp, addr, tmp;
    401   ULONGEST cs;
    402   const char *name;
    403   int i;
    404   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    405   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    406 
    407   if (*this_cache)
    408     return (struct trad_frame_cache *)*this_cache;
    409 
    410   cache = trad_frame_cache_zalloc (this_frame);
    411   *this_cache = cache;
    412 
    413   func = get_frame_func (this_frame);
    414   sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
    415 
    416   find_pc_partial_function (func, &name, NULL, NULL);
    417   if (name && (strncmp (name, "Xintr", 5) == 0 ||
    418                strncmp (name, "Xhandle", 7) == 0))
    419     {
    420       /* It's an interrupt frame. */
    421       tmp = read_memory_unsigned_integer (sp + 4, 4, byte_order);
    422       if (tmp < 15)
    423         {
    424           /* Reasonable value for 'ppl': already on interrupt stack. */
    425           addr = sp + 8;
    426         }
    427       else
    428         {
    429           /* Switch to previous stack. */
    430           addr = tmp + 4;
    431         }
    432     }
    433   else
    434     {
    435       /* It's a trap frame. */
    436       addr = sp + 4;
    437     }
    438 
    439   for (i = 0; i < ARRAY_SIZE (i386nbsd_tf_reg_offset); i++)
    440     if (i386nbsd_tf_reg_offset[i] != -1)
    441       trad_frame_set_reg_addr (cache, i, addr + i386nbsd_tf_reg_offset[i]);
    442 
    443   /* Read %cs from trap frame.  */
    444   addr += i386nbsd_tf_reg_offset[I386_CS_REGNUM];
    445   cs = read_memory_unsigned_integer (addr, 4, byte_order);
    446   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
    447     {
    448       /* Trap from user space; terminate backtrace.  */
    449       trad_frame_set_id (cache, outer_frame_id);
    450     }
    451   else
    452     {
    453       /* Construct the frame ID using the function start.  */
    454       trad_frame_set_id (cache, frame_id_build (sp + 8, func));
    455     }
    456 
    457   return cache;
    458 }
    459 
    460 static void
    461 i386nbsd_trapframe_this_id (frame_info_ptr this_frame,
    462 			    void **this_cache, struct frame_id *this_id)
    463 {
    464   struct trad_frame_cache *cache =
    465     i386nbsd_trapframe_cache (this_frame, this_cache);
    466 
    467   trad_frame_get_id (cache, this_id);
    468 }
    469 
    470 static struct value *
    471 i386nbsd_trapframe_prev_register (frame_info_ptr this_frame,
    472 				  void **this_cache, int regnum)
    473 {
    474   struct trad_frame_cache *cache =
    475     i386nbsd_trapframe_cache (this_frame, this_cache);
    476 
    477   return trad_frame_get_register (cache, this_frame, regnum);
    478 }
    479 
    480 static int
    481 i386nbsd_trapframe_sniffer (const struct frame_unwind *self,
    482 			    frame_info_ptr this_frame,
    483 			    void **this_prologue_cache)
    484 {
    485   ULONGEST cs;
    486   const char *name;
    487 
    488   /* Check Current Privilege Level and bail out if we're not executing
    489      in kernel space.  */
    490   cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM);
    491   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
    492     return 0;
    493 
    494 
    495   find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
    496   return (name && ((strcmp (name, "alltraps") == 0)
    497 	        || (strcmp (name, "calltrap") == 0)
    498 		|| (strcmp (name, "syscall1") == 0)
    499 		|| (strcmp (name, "Xdoreti") == 0)
    500 		|| (strncmp (name, "Xintr", 5) == 0)
    501 		|| (strncmp (name, "Xhandle", 7) == 0)
    502 		|| (strncmp (name, "Xpreempt", 8) == 0)
    503 		|| (strncmp (name, "Xrecurse", 8) == 0)
    504 		|| (strncmp (name, "Xresume", 7) == 0)
    505 		|| (strncmp (name, "Xsoft", 5) == 0)
    506 		|| (strncmp (name, "Xstray", 6) == 0)
    507 		|| (strncmp (name, "Xsyscall", 8) == 0)
    508 		|| (strncmp (name, "Xtrap", 5) == 0)
    509 	    ));
    510 }
    511 
    512 const struct frame_unwind i386nbsd_trapframe_unwind = {
    513   /* FIXME: kettenis/20051219: This really is more like an interrupt
    514      frame, but SIGTRAMP_FRAME would print <signal handler called>,
    515      which really is not what we want here.  */
    516   "i386 trapframe",
    517   NORMAL_FRAME,
    518   default_frame_unwind_stop_reason,
    519   i386nbsd_trapframe_this_id,
    520   i386nbsd_trapframe_prev_register,
    521   NULL,
    522   i386nbsd_trapframe_sniffer
    523 };
    524 
    525 static void
    526 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    527 {
    528   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
    529 
    530   /* Obviously NetBSD is BSD-based.  */
    531   i386bsd_init_abi (info, gdbarch);
    532 
    533   nbsd_init_abi (info, gdbarch);
    534 
    535   /* NetBSD has a different `struct reg'.  */
    536   tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
    537   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
    538   tdep->sizeof_gregset = 16 * 4;
    539 
    540   /* NetBSD uses -freg-struct-return by default.  */
    541   tdep->struct_return = reg_struct_return;
    542 
    543   /* NetBSD uses tramp_frame sniffers for signal trampolines.  */
    544   tdep->sigcontext_addr= 0;
    545   tdep->sigtramp_start = 0;
    546   tdep->sigtramp_end = 0;
    547   tdep->sigtramp_p = 0;
    548   tdep->sc_reg_offset = 0;
    549   tdep->sc_num_regs = 0;
    550 
    551   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
    552   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
    553   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
    554   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
    555   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
    556 
    557   /* Unwind kernel trap frames correctly.  */
    558   frame_unwind_prepend_unwinder (gdbarch, &i386nbsd_trapframe_unwind);
    559 }
    560 
    561 /* NetBSD ELF.  */
    562 
    563 static void
    564 i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    565 {
    566   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
    567 
    568   /* It's still NetBSD.  */
    569   i386nbsd_init_abi (info, gdbarch);
    570 
    571   /* But ELF-based.  */
    572   i386_elf_init_abi (info, gdbarch);
    573 
    574   /* NetBSD ELF uses SVR4-style shared libraries.  */
    575   set_solib_svr4_fetch_link_map_offsets
    576     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
    577 
    578   /* NetBSD ELF uses -fpcc-struct-return by default.  */
    579   tdep->struct_return = pcc_struct_return;
    580 }
    581 
    582 void _initialize_i386nbsd_tdep ();
    583 void
    584 _initialize_i386nbsd_tdep ()
    585 {
    586   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
    587 			  i386nbsdelf_init_abi);
    588 }
    589