Convert to ISO C90 formatting
[external/binutils.git] / bfd / sunos.c
index cbb92b1..bf90792 100644 (file)
@@ -1,23 +1,23 @@
 /* BFD backend for SunOS binaries.
    Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #define TARGETNAME "a.out-sunos-big"
 
@@ -30,60 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfdlink.h"
 #include "libaout.h"
 
-/* Static routines defined in this file.  */
-
-static bfd_boolean sunos_read_dynamic_info PARAMS ((bfd *));
-static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
-static bfd_boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *));
-static long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
-static long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
-static long sunos_canonicalize_dynamic_reloc
-  PARAMS ((bfd *, arelent **, asymbol **));
-static struct bfd_hash_entry *sunos_link_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static struct bfd_link_hash_table *sunos_link_hash_table_create
-  PARAMS ((bfd *));
-static bfd_boolean sunos_create_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
-static bfd_boolean sunos_add_dynamic_symbols
-  PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **,
-          bfd_size_type *, char **));
-static bfd_boolean sunos_add_one_symbol
-  PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
-          bfd_vma, const char *, bfd_boolean, bfd_boolean,
-          struct bfd_link_hash_entry **));
-static bfd_boolean sunos_scan_relocs
-  PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type));
-static bfd_boolean sunos_scan_std_relocs
-  PARAMS ((struct bfd_link_info *, bfd *, asection *,
-          const struct reloc_std_external *, bfd_size_type));
-static bfd_boolean sunos_scan_ext_relocs
-  PARAMS ((struct bfd_link_info *, bfd *, asection *,
-          const struct reloc_ext_external *, bfd_size_type));
-static bfd_boolean sunos_link_dynamic_object
-  PARAMS ((struct bfd_link_info *, bfd *));
-static bfd_boolean sunos_write_dynamic_symbol
-  PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *));
-static bfd_boolean sunos_check_dynamic_reloc
-  PARAMS ((struct bfd_link_info *, bfd *, asection *,
-          struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *,
-          bfd_vma *));
-static bfd_boolean sunos_finish_dynamic_link
-  PARAMS ((bfd *, struct bfd_link_info *));
-
-#define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound
-#define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab
-#define MY_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab
-#define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound
-#define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc
-#define MY_bfd_link_hash_table_create sunos_link_hash_table_create
-#define MY_add_dynamic_symbols sunos_add_dynamic_symbols
-#define MY_add_one_symbol sunos_add_one_symbol
-#define MY_link_dynamic_object sunos_link_dynamic_object
-#define MY_write_dynamic_symbol sunos_write_dynamic_symbol
-#define MY_check_dynamic_reloc sunos_check_dynamic_reloc
-#define MY_finish_dynamic_link sunos_finish_dynamic_link
-
 /* ??? Where should this go?  */
 #define MACHTYPE_OK(mtype) \
   (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
@@ -94,6 +40,31 @@ static bfd_boolean sunos_finish_dynamic_link
    || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
        && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
 
+#define MY_get_dynamic_symtab_upper_bound  sunos_get_dynamic_symtab_upper_bound
+#define MY_canonicalize_dynamic_symtab     sunos_canonicalize_dynamic_symtab
+#define MY_get_synthetic_symtab            _bfd_nodynamic_get_synthetic_symtab
+#define MY_get_dynamic_reloc_upper_bound   sunos_get_dynamic_reloc_upper_bound
+#define MY_canonicalize_dynamic_reloc      sunos_canonicalize_dynamic_reloc
+#define MY_bfd_link_hash_table_create      sunos_link_hash_table_create
+#define MY_add_dynamic_symbols             sunos_add_dynamic_symbols
+#define MY_add_one_symbol                  sunos_add_one_symbol
+#define MY_link_dynamic_object             sunos_link_dynamic_object
+#define MY_write_dynamic_symbol            sunos_write_dynamic_symbol
+#define MY_check_dynamic_reloc             sunos_check_dynamic_reloc
+#define MY_finish_dynamic_link             sunos_finish_dynamic_link
+
+static bfd_boolean sunos_add_dynamic_symbols            (bfd *, struct bfd_link_info *, struct external_nlist **, bfd_size_type *, char **);
+static bfd_boolean sunos_add_one_symbol                 (struct bfd_link_info *, bfd *, const char *, flagword, asection *, bfd_vma, const char *, bfd_boolean, bfd_boolean, struct bfd_link_hash_entry **);
+static bfd_boolean sunos_link_dynamic_object            (struct bfd_link_info *, bfd *);
+static bfd_boolean sunos_write_dynamic_symbol           (bfd *, struct bfd_link_info *, struct aout_link_hash_entry *);
+static bfd_boolean sunos_check_dynamic_reloc            (struct bfd_link_info *, bfd *, asection *, struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *, bfd_vma *);
+static bfd_boolean sunos_finish_dynamic_link            (bfd *, struct bfd_link_info *);
+static struct bfd_link_hash_table *sunos_link_hash_table_create  (bfd *);
+static long        sunos_get_dynamic_symtab_upper_bound (bfd *);
+static long        sunos_canonicalize_dynamic_symtab    (bfd *, asymbol **);
+static long        sunos_get_dynamic_reloc_upper_bound  (bfd *);
+static long        sunos_canonicalize_dynamic_reloc     (bfd *, arelent **, asymbol **);
+
 /* Include the usual a.out support.  */
 #include "aoutf1.h"
 
@@ -121,7 +92,7 @@ struct sunos_dynamic_info
   unsigned long dynrel_count;
   /* Read in dynamic relocs.  This may be reloc_std_external or
      reloc_ext_external.  */
-  PTR dynrel;
+  void * dynrel;
   /* arelent structures for dynamic relocs.  */
   arelent *canonical_dynrel;
 };
@@ -138,8 +109,7 @@ struct sunos_dynamic_info
    structure to FALSE to avoid doing this work again.  */
 
 static bfd_boolean
-sunos_read_dynamic_info (abfd)
-     bfd *abfd;
+sunos_read_dynamic_info (bfd *abfd)
 {
   struct sunos_dynamic_info *info;
   asection *dynsec;
@@ -149,7 +119,7 @@ sunos_read_dynamic_info (abfd)
   struct external_sun4_dynamic_link linkinfo;
   bfd_size_type amt;
 
-  if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
+  if (obj_aout_dynamic_info (abfd) != NULL)
     return TRUE;
 
   if ((abfd->flags & DYNAMIC) == 0)
@@ -159,7 +129,7 @@ sunos_read_dynamic_info (abfd)
     }
 
   amt = sizeof (struct sunos_dynamic_info);
-  info = (struct sunos_dynamic_info *) bfd_zalloc (abfd, amt);
+  info = bfd_zalloc (abfd, amt);
   if (!info)
     return FALSE;
   info->valid = FALSE;
@@ -168,7 +138,7 @@ sunos_read_dynamic_info (abfd)
   info->canonical_dynsym = NULL;
   info->dynrel = NULL;
   info->canonical_dynrel = NULL;
-  obj_aout_dynamic_info (abfd) = (PTR) info;
+  obj_aout_dynamic_info (abfd) = (void *) info;
 
   /* This code used to look for the __DYNAMIC symbol to locate the dynamic
      linking information.
@@ -179,7 +149,7 @@ sunos_read_dynamic_info (abfd)
      symbols for the __DYNAMIC symbol.  */
   if ((abfd->flags & DYNAMIC) == 0)
     return TRUE;
-  if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
+  if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (void *) &dyninfo,
                                  (file_ptr) 0,
                                  (bfd_size_type) sizeof dyninfo))
     return TRUE;
@@ -202,7 +172,7 @@ sunos_read_dynamic_info (abfd)
 
   /* This executable appears to be dynamically linked in a way that we
      can understand.  */
-  if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo,
+  if (! bfd_get_section_contents (abfd, dynsec, (void *) &linkinfo,
                                  (file_ptr) dynoff,
                                  (bfd_size_type) sizeof linkinfo))
     return TRUE;
@@ -260,8 +230,7 @@ sunos_read_dynamic_info (abfd)
 /* Return the amount of memory required for the dynamic symbols.  */
 
 static long
-sunos_get_dynamic_symtab_upper_bound (abfd)
-     bfd *abfd;
+sunos_get_dynamic_symtab_upper_bound (bfd *abfd)
 {
   struct sunos_dynamic_info *info;
 
@@ -281,8 +250,7 @@ sunos_get_dynamic_symtab_upper_bound (abfd)
 /* Read the external dynamic symbols.  */
 
 static bfd_boolean
-sunos_slurp_dynamic_symtab (abfd)
-     bfd *abfd;
+sunos_slurp_dynamic_symtab (bfd *abfd)
 {
   struct sunos_dynamic_info *info;
   bfd_size_type amt;
@@ -302,14 +270,14 @@ sunos_slurp_dynamic_symtab (abfd)
     }
 
   /* Get the dynamic nlist structures.  */
-  if (info->dynsym == (struct external_nlist *) NULL)
+  if (info->dynsym == NULL)
     {
       amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE;
-      info->dynsym = (struct external_nlist *) bfd_alloc (abfd, amt);
+      info->dynsym = bfd_alloc (abfd, amt);
       if (info->dynsym == NULL && info->dynsym_count != 0)
        return FALSE;
       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0
-         || bfd_bread ((PTR) info->dynsym, amt, abfd) != amt)
+         || bfd_bread ((void *) info->dynsym, amt, abfd) != amt)
        {
          if (info->dynsym != NULL)
            {
@@ -321,14 +289,14 @@ sunos_slurp_dynamic_symtab (abfd)
     }
 
   /* Get the dynamic strings.  */
-  if (info->dynstr == (char *) NULL)
+  if (info->dynstr == NULL)
     {
       amt = info->dyninfo.ld_symb_size;
-      info->dynstr = (char *) bfd_alloc (abfd, amt);
+      info->dynstr = bfd_alloc (abfd, amt);
       if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
        return FALSE;
       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0
-         || bfd_bread ((PTR) info->dynstr, amt, abfd) != amt)
+         || bfd_bread ((void *) info->dynstr, amt, abfd) != amt)
        {
          if (info->dynstr != NULL)
            {
@@ -345,9 +313,7 @@ sunos_slurp_dynamic_symtab (abfd)
 /* Read in the dynamic symbols.  */
 
 static long
-sunos_canonicalize_dynamic_symtab (abfd, storage)
-     bfd *abfd;
-     asymbol **storage;
+sunos_canonicalize_dynamic_symtab (bfd *abfd, asymbol **storage)
 {
   struct sunos_dynamic_info *info;
   unsigned long i;
@@ -368,11 +334,11 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
     if (info->dyninfo.ld_buckets > info->dynsym_count)
       abort ();
     table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
-    table = (bfd_byte *) bfd_malloc (table_size);
+    table = bfd_malloc (table_size);
     if (table == NULL && table_size != 0)
       abort ();
     if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0
-       || bfd_bread ((PTR) table, table_size, abfd) != table_size)
+       || bfd_bread ((void *) table, table_size, abfd) != table_size)
       abort ();
     for (i = 0; i < info->dynsym_count; i++)
       {
@@ -400,13 +366,13 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
 
   /* Get the asymbol structures corresponding to the dynamic nlist
      structures.  */
-  if (info->canonical_dynsym == (aout_symbol_type *) NULL)
+  if (info->canonical_dynsym == NULL)
     {
       bfd_size_type size;
       bfd_size_type strsize = info->dyninfo.ld_symb_size;
 
       size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type);
-      info->canonical_dynsym = (aout_symbol_type *) bfd_alloc (abfd, size);
+      info->canonical_dynsym = bfd_alloc (abfd, size);
       if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
        return -1;
 
@@ -435,8 +401,7 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
 /* Return the amount of memory required for the dynamic relocs.  */
 
 static long
-sunos_get_dynamic_reloc_upper_bound (abfd)
-     bfd *abfd;
+sunos_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
   struct sunos_dynamic_info *info;
 
@@ -456,17 +421,14 @@ sunos_get_dynamic_reloc_upper_bound (abfd)
 /* Read in the dynamic relocs.  */
 
 static long
-sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
-     bfd *abfd;
-     arelent **storage;
-     asymbol **syms;
+sunos_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage, asymbol **syms)
 {
   struct sunos_dynamic_info *info;
   unsigned long i;
   bfd_size_type size;
 
   /* Get the general dynamic information.  */
-  if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
+  if (obj_aout_dynamic_info (abfd) == NULL)
     {
       if (! sunos_read_dynamic_info (abfd))
        return -1;
@@ -483,11 +445,11 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
   if (info->dynrel == NULL)
     {
       size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd);
-      info->dynrel = (PTR) bfd_alloc (abfd, size);
+      info->dynrel = bfd_alloc (abfd, size);
       if (info->dynrel == NULL && size != 0)
        return -1;
       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0
-         || bfd_bread ((PTR) info->dynrel, size, abfd) != size)
+         || bfd_bread ((void *) info->dynrel, size, abfd) != size)
        {
          if (info->dynrel != NULL)
            {
@@ -500,12 +462,12 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
 
   /* Get the arelent structures corresponding to the dynamic reloc
      information.  */
-  if (info->canonical_dynrel == (arelent *) NULL)
+  if (info->canonical_dynrel == NULL)
     {
       arelent *to;
 
       size = (bfd_size_type) info->dynrel_count * sizeof (arelent);
-      info->canonical_dynrel = (arelent *) bfd_alloc (abfd, size);
+      info->canonical_dynrel = bfd_alloc (abfd, size);
       if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
        return -1;
 
@@ -513,25 +475,25 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
 
       if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
        {
-         register struct reloc_ext_external *p;
+         struct reloc_ext_external *p;
          struct reloc_ext_external *pend;
 
          p = (struct reloc_ext_external *) info->dynrel;
          pend = p + info->dynrel_count;
          for (; p < pend; p++, to++)
-           NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms,
-                                         (bfd_size_type) info->dynsym_count);
+           NAME (aout, swap_ext_reloc_in) (abfd, p, to, syms,
+                                           (bfd_size_type) info->dynsym_count);
        }
       else
        {
-         register struct reloc_std_external *p;
+         struct reloc_std_external *p;
          struct reloc_std_external *pend;
 
          p = (struct reloc_std_external *) info->dynrel;
          pend = p + info->dynrel_count;
          for (; p < pend; p++, to++)
-           NAME(aout,swap_std_reloc_in) (abfd, p, to, syms,
-                                         (bfd_size_type) info->dynsym_count);
+           NAME (aout, swap_std_reloc_in) (abfd, p, to, syms,
+                                           (bfd_size_type) info->dynsym_count);
        }
     }
 
@@ -676,25 +638,23 @@ struct sunos_link_hash_table
 /* Routine to create an entry in an SunOS link hash table.  */
 
 static struct bfd_hash_entry *
-sunos_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+sunos_link_hash_newfunc (struct bfd_hash_entry *entry,
+                        struct bfd_hash_table *table,
+                        const char *string)
 {
   struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry;
 
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct sunos_link_hash_entry *) NULL)
-    ret = ((struct sunos_link_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry)));
-  if (ret == (struct sunos_link_hash_entry *) NULL)
-    return (struct bfd_hash_entry *) ret;
+  if (ret ==  NULL)
+    ret = bfd_hash_allocate (table, sizeof (* ret));
+  if (ret == NULL)
+    return NULL;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct sunos_link_hash_entry *)
-        NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
-                                      table, string));
+        NAME (aout, link_hash_newfunc) ((struct bfd_hash_entry *) ret,
+                                        table, string));
   if (ret != NULL)
     {
       /* Set local fields.  */
@@ -711,20 +671,19 @@ sunos_link_hash_newfunc (entry, table, string)
 /* Create a SunOS link hash table.  */
 
 static struct bfd_link_hash_table *
-sunos_link_hash_table_create (abfd)
-     bfd *abfd;
+sunos_link_hash_table_create (bfd *abfd)
 {
   struct sunos_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct sunos_link_hash_table);
 
-  ret = (struct sunos_link_hash_table *) bfd_malloc (amt);
-  if (ret == (struct sunos_link_hash_table *) NULL)
-    return (struct bfd_link_hash_table *) NULL;
-  if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
-                                        sunos_link_hash_newfunc))
+  ret = bfd_malloc (amt);
+  if (ret ==  NULL)
+    return NULL;
+  if (! NAME (aout, link_hash_table_init) (&ret->root, abfd,
+                                          sunos_link_hash_newfunc))
     {
       free (ret);
-      return (struct bfd_link_hash_table *) NULL;
+      return NULL;
     }
 
   ret->dynobj = NULL;
@@ -751,7 +710,7 @@ sunos_link_hash_table_create (abfd)
 #define sunos_link_hash_traverse(table, func, info)                    \
   (aout_link_hash_traverse                                             \
    (&(table)->root,                                                    \
-    (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
+    (bfd_boolean (*) (struct aout_link_hash_entry *, void *)) (func),  \
     (info)))
 
 /* Get the SunOS link hash table from the info structure.  This is
@@ -759,9 +718,6 @@ sunos_link_hash_table_create (abfd)
 
 #define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash))
 
-static bfd_boolean sunos_scan_dynamic_symbol
-  PARAMS ((struct sunos_link_hash_entry *, PTR));
-
 /* Create the dynamic sections needed if we are linking against a
    dynamic object, or if we are linking PIC compiled code.  ABFD is a
    bfd we can attach the dynamic sections to.  The linker script will
@@ -770,10 +726,9 @@ static bfd_boolean sunos_scan_dynamic_symbol
    of the dynamic linking information.  */
 
 static bfd_boolean
-sunos_create_dynamic_sections (abfd, info, needed)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean needed;
+sunos_create_dynamic_sections (bfd *abfd,
+                              struct bfd_link_info *info,
+                              bfd_boolean needed)
 {
   asection *s;
 
@@ -868,12 +823,11 @@ sunos_create_dynamic_sections (abfd, info, needed)
    backend linker for each object it encounters.  */
 
 static bfd_boolean
-sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct external_nlist **symsp;
-     bfd_size_type *sym_countp;
-     char **stringsp;
+sunos_add_dynamic_symbols (bfd *abfd,
+                          struct bfd_link_info *info,
+                          struct external_nlist **symsp,
+                          bfd_size_type *sym_countp,
+                          char **stringsp)
 {
   bfd *dynobj;
   struct sunos_dynamic_info *dinfo;
@@ -988,7 +942,6 @@ sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
 
       /* For the format of an ld_need entry, see aout/sun4.h.  We
         should probably define structs for this manipulation.  */
-
       name = bfd_get_32 (abfd, buf);
       flags = bfd_get_32 (abfd, buf + 4);
       major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8);
@@ -996,14 +949,14 @@ sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
       need = bfd_get_32 (abfd, buf + 12);
 
       alc = sizeof (struct bfd_link_needed_list);
-      needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, alc);
+      needed = bfd_alloc (abfd, alc);
       if (needed == NULL)
        return FALSE;
       needed->by = abfd;
 
       /* We return the name as [-l]name[.maj][.min].  */
       alc = 30;
-      namebuf = (char *) bfd_malloc (alc + 1);
+      namebuf = bfd_malloc (alc + 1);
       if (namebuf == NULL)
        return FALSE;
       p = namebuf;
@@ -1032,7 +985,7 @@ sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
              char *n;
 
              alc *= 2;
-             n = (char *) bfd_realloc (namebuf, alc + 1);
+             n = bfd_realloc (namebuf, alc + 1);
              if (n == NULL)
                {
                  free (namebuf);
@@ -1064,7 +1017,7 @@ sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
              char *n;
 
              alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf);
-             n = (char *) bfd_realloc (namebuf, alc + 1);
+             n = bfd_realloc (namebuf, alc + 1);
              if (n == NULL)
                {
                  free (namebuf);
@@ -1105,18 +1058,16 @@ sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
    tweaking needed for dynamic linking support.  */
 
 static bfd_boolean
-sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
-                     copy, collect, hashp)
-     struct bfd_link_info *info;
-     bfd *abfd;
-     const char *name;
-     flagword flags;
-     asection *section;
-     bfd_vma value;
-     const char *string;
-     bfd_boolean copy;
-     bfd_boolean collect;
-     struct bfd_link_hash_entry **hashp;
+sunos_add_one_symbol (struct bfd_link_info *info,
+                     bfd *abfd,
+                     const char *name,
+                     flagword flags,
+                     asection *section,
+                     bfd_vma value,
+                     const char *string,
+                     bfd_boolean copy,
+                     bfd_boolean collect,
+                     struct bfd_link_hash_entry **hashp)
 {
   struct sunos_link_hash_entry *h;
   int new_flag;
@@ -1181,25 +1132,21 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
   if ((abfd->flags & DYNAMIC) != 0
       && abfd->xvec == info->hash->creator
       && (h->flags & SUNOS_CONSTRUCTOR) != 0)
-    {
-      /* The existing symbol is a constructor symbol, and this symbol
-        is from a dynamic object.  A constructor symbol is actually a
-        definition, although the type will be bfd_link_hash_undefined
-        at this point.  We want to ignore the definition from the
-        dynamic object.  */
-      section = bfd_und_section_ptr;
-    }
+    /* The existing symbol is a constructor symbol, and this symbol
+       is from a dynamic object.  A constructor symbol is actually a
+       definition, although the type will be bfd_link_hash_undefined
+       at this point.  We want to ignore the definition from the
+       dynamic object.  */
+    section = bfd_und_section_ptr;
   else if ((flags & BSF_CONSTRUCTOR) != 0
           && (abfd->flags & DYNAMIC) == 0
           && h->root.root.type == bfd_link_hash_defined
           && h->root.root.u.def.section->owner != NULL
           && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
-    {
-      /* The existing symbol is defined by a dynamic object, and this
-        is a constructor symbol.  As above, we want to force the use
-        of the constructor symbol from the regular object.  */
-      h->root.root.type = bfd_link_hash_new;
-    }
+    /* The existing symbol is defined by a dynamic object, and this
+       is a constructor symbol.  As above, we want to force the use
+       of the constructor symbol from the regular object.  */
+    h->root.root.type = bfd_link_hash_new;
 
   /* Do the usual procedure for adding a symbol.  */
   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
@@ -1245,14 +1192,15 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
   return TRUE;
 }
 
+extern const bfd_target MY (vec);
+
 /* Return the list of objects needed by BFD.  */
 
 struct bfd_link_needed_list *
-bfd_sunos_get_needed_list (abfd, info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+bfd_sunos_get_needed_list (bfd *abfd ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info)
 {
-  if (info->hash->creator != &MY(vec))
+  if (info->hash->creator != &MY (vec))
     return NULL;
   return sunos_hash_table (info)->needed;
 }
@@ -1261,10 +1209,9 @@ bfd_sunos_get_needed_list (abfd, info)
    this in case some dynamic object refers to this symbol.  */
 
 bfd_boolean
-bfd_sunos_record_link_assignment (output_bfd, info, name)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     const char *name;
+bfd_sunos_record_link_assignment (bfd *output_bfd,
+                                 struct bfd_link_info *info,
+                                 const char *name)
 {
   struct sunos_link_hash_entry *h;
 
@@ -1295,419 +1242,124 @@ bfd_sunos_record_link_assignment (output_bfd, info, name)
   return TRUE;
 }
 
-/* Set up the sizes and contents of the dynamic sections created in
-   sunos_add_dynamic_symbols.  This is called by the SunOS linker
-   emulation before_allocation routine.  We must set the sizes of the
-   sections before the linker sets the addresses of the various
-   sections.  This unfortunately requires reading all the relocs so
-   that we can work out which ones need to become dynamic relocs.  If
-   info->keep_memory is TRUE, we keep the relocs in memory; otherwise,
-   we discard them, and will read them again later.  */
+/* Scan the relocs for an input section using standard relocs.  We
+   need to figure out what to do for each reloc against a dynamic
+   symbol.  If the symbol is in the .text section, an entry is made in
+   the procedure linkage table.  Note that this will do the wrong
+   thing if the symbol is actually data; I don't think the Sun 3
+   native linker handles this case correctly either.  If the symbol is
+   not in the .text section, we must preserve the reloc as a dynamic
+   reloc.  FIXME: We should also handle the PIC relocs here by
+   building global offset table entries.  */
 
-bfd_boolean
-bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
-                                srulesptr)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     asection **sdynptr;
-     asection **sneedptr;
-     asection **srulesptr;
+static bfd_boolean
+sunos_scan_std_relocs (struct bfd_link_info *info,
+                      bfd *abfd,
+                      asection *sec ATTRIBUTE_UNUSED,
+                      const struct reloc_std_external *relocs,
+                      bfd_size_type rel_size)
 {
   bfd *dynobj;
-  bfd_size_type dynsymcount;
-  struct sunos_link_hash_entry *h;
-  asection *s;
-  size_t bucketcount;
-  bfd_size_type hashalloc;
-  size_t i;
-  bfd *sub;
-
-  *sdynptr = NULL;
-  *sneedptr = NULL;
-  *srulesptr = NULL;
-
-  if (info->relocatable)
-    return TRUE;
-
-  if (output_bfd->xvec != &MY(vec))
-    return TRUE;
+  asection *splt = NULL;
+  asection *srel = NULL;
+  struct sunos_link_hash_entry **sym_hashes;
+  const struct reloc_std_external *rel, *relend;
 
-  /* Look through all the input BFD's and read their relocs.  It would
-     be better if we didn't have to do this, but there is no other way
-     to determine the number of dynamic relocs we need, and, more
-     importantly, there is no other way to know which symbols should
-     get an entry in the procedure linkage table.  */
-  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+  /* We only know how to handle m68k plt entries.  */
+  if (bfd_get_arch (abfd) != bfd_arch_m68k)
     {
-      if ((sub->flags & DYNAMIC) == 0
-         && sub->xvec == output_bfd->xvec)
-       {
-         if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
-                                  exec_hdr (sub)->a_trsize)
-             || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
-                                     exec_hdr (sub)->a_drsize))
-           return FALSE;
-       }
+      bfd_set_error (bfd_error_invalid_target);
+      return FALSE;
     }
 
-  dynobj = sunos_hash_table (info)->dynobj;
-  dynsymcount = sunos_hash_table (info)->dynsymcount;
+  dynobj = NULL;
 
-  /* If there were no dynamic objects in the link, and we don't need
-     to build a global offset table, there is nothing to do here.  */
-  if (! sunos_hash_table (info)->dynamic_sections_needed
-      && ! sunos_hash_table (info)->got_needed)
-    return TRUE;
+  sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
 
-  /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it.  */
-  h = sunos_link_hash_lookup (sunos_hash_table (info),
-                             "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE);
-  if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
+  relend = relocs + rel_size / RELOC_STD_SIZE;
+  for (rel = relocs; rel < relend; rel++)
     {
-      h->flags |= SUNOS_DEF_REGULAR;
-      if (h->dynindx == -1)
+      int r_index;
+      struct sunos_link_hash_entry *h;
+
+      /* We only want relocs against external symbols.  */
+      if (bfd_header_big_endian (abfd))
        {
-         ++sunos_hash_table (info)->dynsymcount;
-         h->dynindx = -2;
+         if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0)
+           continue;
        }
-      h->root.root.type = bfd_link_hash_defined;
-      h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
-
-      /* If the .got section is more than 0x1000 bytes, we set
-        __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
-        so that 13 bit relocations have a greater chance of working.  */
-      s = bfd_get_section_by_name (dynobj, ".got");
-      BFD_ASSERT (s != NULL);
-      if (s->size >= 0x1000)
-       h->root.root.u.def.value = 0x1000;
       else
-       h->root.root.u.def.value = 0;
-
-      sunos_hash_table (info)->got_base = h->root.root.u.def.value;
-    }
-
-  /* If there are any shared objects in the link, then we need to set
-     up the dynamic linking information.  */
-  if (sunos_hash_table (info)->dynamic_sections_needed)
-    {
-      *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
-
-      /* The .dynamic section is always the same size.  */
-      s = *sdynptr;
-      BFD_ASSERT (s != NULL);
-      s->size = (sizeof (struct external_sun4_dynamic)
-                     + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
-                     + sizeof (struct external_sun4_dynamic_link));
-
-      /* Set the size of the .dynsym and .hash sections.  We counted
-        the number of dynamic symbols as we read the input files.  We
-        will build the dynamic symbol table (.dynsym) and the hash
-        table (.hash) when we build the final symbol table, because
-        until then we do not know the correct value to give the
-        symbols.  We build the dynamic symbol string table (.dynstr)
-        in a traversal of the symbol table using
-        sunos_scan_dynamic_symbol.  */
-      s = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (s != NULL);
-      s->size = dynsymcount * sizeof (struct external_nlist);
-      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->size);
-      if (s->contents == NULL && s->size != 0)
-       return FALSE;
+       {
+         if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0)
+           continue;
+       }
 
-      /* The number of buckets is just the number of symbols divided
-        by four.  To compute the final size of the hash table, we
-        must actually compute the hash table.  Normally we need
-        exactly as many entries in the hash table as there are
-        dynamic symbols, but if some of the buckets are not used we
-        will need additional entries.  In the worst case, every
-        symbol will hash to the same bucket, and we will need
-        BUCKETCOUNT - 1 extra entries.  */
-      if (dynsymcount >= 4)
-       bucketcount = dynsymcount / 4;
-      else if (dynsymcount > 0)
-       bucketcount = dynsymcount;
+      /* Get the symbol index.  */
+      if (bfd_header_big_endian (abfd))
+       r_index = ((rel->r_index[0] << 16)
+                  | (rel->r_index[1] << 8)
+                  | rel->r_index[2]);
       else
-       bucketcount = 1;
-      s = bfd_get_section_by_name (dynobj, ".hash");
-      BFD_ASSERT (s != NULL);
-      hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
-      s->contents = (bfd_byte *) bfd_zalloc (dynobj, hashalloc);
-      if (s->contents == NULL && dynsymcount > 0)
-       return FALSE;
-      for (i = 0; i < bucketcount; i++)
-       PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
-      s->size = bucketcount * HASH_ENTRY_SIZE;
+       r_index = ((rel->r_index[2] << 16)
+                  | (rel->r_index[1] << 8)
+                  | rel->r_index[0]);
 
-      sunos_hash_table (info)->bucketcount = bucketcount;
+      /* Get the hash table entry.  */
+      h = sym_hashes[r_index];
+      if (h == NULL)
+       /* This should not normally happen, but it will in any case
+          be caught in the relocation phase.  */
+       continue;
 
-      /* Scan all the symbols, place them in the dynamic symbol table,
-        and build the dynamic hash table.  We reuse dynsymcount as a
-        counter for the number of symbols we have added so far.  */
-      sunos_hash_table (info)->dynsymcount = 0;
-      sunos_link_hash_traverse (sunos_hash_table (info),
-                               sunos_scan_dynamic_symbol,
-                               (PTR) info);
-      BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
+      /* At this point common symbols have already been allocated, so
+        we don't have to worry about them.  We need to consider that
+        we may have already seen this symbol and marked it undefined;
+        if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
+        will be zero.  */
+      if (h->root.root.type != bfd_link_hash_defined
+         && h->root.root.type != bfd_link_hash_defweak
+         && h->root.root.type != bfd_link_hash_undefined)
+       continue;
 
-      /* The SunOS native linker seems to align the total size of the
-        symbol strings to a multiple of 8.  I don't know if this is
-        important, but it can't hurt much.  */
-      s = bfd_get_section_by_name (dynobj, ".dynstr");
-      BFD_ASSERT (s != NULL);
-      if ((s->size & 7) != 0)
+      if ((h->flags & SUNOS_DEF_DYNAMIC) == 0
+         || (h->flags & SUNOS_DEF_REGULAR) != 0)
+       continue;
+
+      if (dynobj == NULL)
        {
-         bfd_size_type add;
-         bfd_byte *contents;
+         asection *sgot;
 
-         add = 8 - (s->size & 7);
-         contents = (bfd_byte *) bfd_realloc (s->contents,
-                                              s->size + add);
-         if (contents == NULL)
+         if (! sunos_create_dynamic_sections (abfd, info, FALSE))
            return FALSE;
-         memset (contents + s->size, 0, (size_t) add);
-         s->contents = contents;
-         s->size += add;
+         dynobj = sunos_hash_table (info)->dynobj;
+         splt = bfd_get_section_by_name (dynobj, ".plt");
+         srel = bfd_get_section_by_name (dynobj, ".dynrel");
+         BFD_ASSERT (splt != NULL && srel != NULL);
+
+         sgot = bfd_get_section_by_name (dynobj, ".got");
+         BFD_ASSERT (sgot != NULL);
+         if (sgot->size == 0)
+           sgot->size = BYTES_IN_WORD;
+         sunos_hash_table (info)->got_needed = TRUE;
        }
-    }
 
-  /* Now that we have worked out the sizes of the procedure linkage
-     table and the dynamic relocs, allocate storage for them.  */
-  s = bfd_get_section_by_name (dynobj, ".plt");
-  BFD_ASSERT (s != NULL);
-  if (s->size != 0)
-    {
-      s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
-      if (s->contents == NULL)
-       return FALSE;
+      BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
+      BFD_ASSERT (h->plt_offset != 0
+                 || ((h->root.root.type == bfd_link_hash_defined
+                      || h->root.root.type == bfd_link_hash_defweak)
+                     ? (h->root.root.u.def.section->owner->flags
+                        & DYNAMIC) != 0
+                     : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
 
-      /* Fill in the first entry in the table.  */
-      switch (bfd_get_arch (dynobj))
+      /* This reloc is against a symbol defined only by a dynamic
+        object.  */
+      if (h->root.root.type == bfd_link_hash_undefined)
+       /* Presumably this symbol was marked as being undefined by
+          an earlier reloc.  */
+       srel->size += RELOC_STD_SIZE;
+      else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
        {
-       case bfd_arch_sparc:
-         memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
-         break;
-
-       case bfd_arch_m68k:
-         memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
-         break;
-
-       default:
-         abort ();
-       }
-    }
-
-  s = bfd_get_section_by_name (dynobj, ".dynrel");
-  if (s->size != 0)
-    {
-      s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
-      if (s->contents == NULL)
-       return FALSE;
-    }
-  /* We use the reloc_count field to keep track of how many of the
-     relocs we have output so far.  */
-  s->reloc_count = 0;
-
-  /* Make space for the global offset table.  */
-  s = bfd_get_section_by_name (dynobj, ".got");
-  s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
-  if (s->contents == NULL)
-    return FALSE;
-
-  *sneedptr = bfd_get_section_by_name (dynobj, ".need");
-  *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
-
-  return TRUE;
-}
-
-/* Scan the relocs for an input section.  */
-
-static bfd_boolean
-sunos_scan_relocs (info, abfd, sec, rel_size)
-     struct bfd_link_info *info;
-     bfd *abfd;
-     asection *sec;
-     bfd_size_type rel_size;
-{
-  PTR relocs;
-  PTR free_relocs = NULL;
-
-  if (rel_size == 0)
-    return TRUE;
-
-  if (! info->keep_memory)
-    relocs = free_relocs = bfd_malloc (rel_size);
-  else
-    {
-      struct aout_section_data_struct *n;
-      bfd_size_type amt = sizeof (struct aout_section_data_struct);
-
-      n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt);
-      if (n == NULL)
-       relocs = NULL;
-      else
-       {
-         set_aout_section_data (sec, n);
-         relocs = bfd_malloc (rel_size);
-         aout_section_data (sec)->relocs = relocs;
-       }
-    }
-  if (relocs == NULL)
-    return FALSE;
-
-  if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
-      || bfd_bread (relocs, rel_size, abfd) != rel_size)
-    goto error_return;
-
-  if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
-    {
-      if (! sunos_scan_std_relocs (info, abfd, sec,
-                                  (struct reloc_std_external *) relocs,
-                                  rel_size))
-       goto error_return;
-    }
-  else
-    {
-      if (! sunos_scan_ext_relocs (info, abfd, sec,
-                                  (struct reloc_ext_external *) relocs,
-                                  rel_size))
-       goto error_return;
-    }
-
-  if (free_relocs != NULL)
-    free (free_relocs);
-
-  return TRUE;
-
- error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  return FALSE;
-}
-
-/* Scan the relocs for an input section using standard relocs.  We
-   need to figure out what to do for each reloc against a dynamic
-   symbol.  If the symbol is in the .text section, an entry is made in
-   the procedure linkage table.  Note that this will do the wrong
-   thing if the symbol is actually data; I don't think the Sun 3
-   native linker handles this case correctly either.  If the symbol is
-   not in the .text section, we must preserve the reloc as a dynamic
-   reloc.  FIXME: We should also handle the PIC relocs here by
-   building global offset table entries.  */
-
-static bfd_boolean
-sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
-     struct bfd_link_info *info;
-     bfd *abfd;
-     asection *sec ATTRIBUTE_UNUSED;
-     const struct reloc_std_external *relocs;
-     bfd_size_type rel_size;
-{
-  bfd *dynobj;
-  asection *splt = NULL;
-  asection *srel = NULL;
-  struct sunos_link_hash_entry **sym_hashes;
-  const struct reloc_std_external *rel, *relend;
-
-  /* We only know how to handle m68k plt entries.  */
-  if (bfd_get_arch (abfd) != bfd_arch_m68k)
-    {
-      bfd_set_error (bfd_error_invalid_target);
-      return FALSE;
-    }
-
-  dynobj = NULL;
-
-  sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
-
-  relend = relocs + rel_size / RELOC_STD_SIZE;
-  for (rel = relocs; rel < relend; rel++)
-    {
-      int r_index;
-      struct sunos_link_hash_entry *h;
-
-      /* We only want relocs against external symbols.  */
-      if (bfd_header_big_endian (abfd))
-       {
-         if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0)
-           continue;
-       }
-      else
-       {
-         if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0)
-           continue;
-       }
-
-      /* Get the symbol index.  */
-      if (bfd_header_big_endian (abfd))
-       r_index = ((rel->r_index[0] << 16)
-                  | (rel->r_index[1] << 8)
-                  | rel->r_index[2]);
-      else
-       r_index = ((rel->r_index[2] << 16)
-                  | (rel->r_index[1] << 8)
-                  | rel->r_index[0]);
-
-      /* Get the hash table entry.  */
-      h = sym_hashes[r_index];
-      if (h == NULL)
-       {
-         /* This should not normally happen, but it will in any case
-            be caught in the relocation phase.  */
-         continue;
-       }
-
-      /* At this point common symbols have already been allocated, so
-        we don't have to worry about them.  We need to consider that
-        we may have already seen this symbol and marked it undefined;
-        if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
-        will be zero.  */
-      if (h->root.root.type != bfd_link_hash_defined
-         && h->root.root.type != bfd_link_hash_defweak
-         && h->root.root.type != bfd_link_hash_undefined)
-       continue;
-
-      if ((h->flags & SUNOS_DEF_DYNAMIC) == 0
-         || (h->flags & SUNOS_DEF_REGULAR) != 0)
-       continue;
-
-      if (dynobj == NULL)
-       {
-         asection *sgot;
-
-         if (! sunos_create_dynamic_sections (abfd, info, FALSE))
-           return FALSE;
-         dynobj = sunos_hash_table (info)->dynobj;
-         splt = bfd_get_section_by_name (dynobj, ".plt");
-         srel = bfd_get_section_by_name (dynobj, ".dynrel");
-         BFD_ASSERT (splt != NULL && srel != NULL);
-
-         sgot = bfd_get_section_by_name (dynobj, ".got");
-         BFD_ASSERT (sgot != NULL);
-         if (sgot->size == 0)
-           sgot->size = BYTES_IN_WORD;
-         sunos_hash_table (info)->got_needed = TRUE;
-       }
-
-      BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
-      BFD_ASSERT (h->plt_offset != 0
-                 || ((h->root.root.type == bfd_link_hash_defined
-                      || h->root.root.type == bfd_link_hash_defweak)
-                     ? (h->root.root.u.def.section->owner->flags
-                        & DYNAMIC) != 0
-                     : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
-
-      /* This reloc is against a symbol defined only by a dynamic
-        object.  */
-
-      if (h->root.root.type == bfd_link_hash_undefined)
-       {
-         /* Presumably this symbol was marked as being undefined by
-            an earlier reloc.  */
-         srel->size += RELOC_STD_SIZE;
-       }
-      else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
-       {
-         bfd *sub;
+         bfd *sub;
 
          /* This reloc is not in the .text section.  It must be
             copied into the dynamic relocs.  We mark the symbol as
@@ -1755,12 +1407,11 @@ sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
    Otherwise, we must preserve the reloc as a dynamic reloc.  */
 
 static bfd_boolean
-sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
-     struct bfd_link_info *info;
-     bfd *abfd;
-     asection *sec ATTRIBUTE_UNUSED;
-     const struct reloc_ext_external *relocs;
-     bfd_size_type rel_size;
+sunos_scan_ext_relocs (struct bfd_link_info *info,
+                      bfd *abfd,
+                      asection *sec ATTRIBUTE_UNUSED,
+                      const struct reloc_ext_external *relocs,
+                      bfd_size_type rel_size)
 {
   bfd *dynobj;
   struct sunos_link_hash_entry **sym_hashes;
@@ -1852,18 +1503,15 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
          else
            {
              if (r_index >= bfd_get_symcount (abfd))
-               {
-                 /* This is abnormal, but should be caught in the
-                    relocation phase.  */
-                 continue;
-               }
+               /* This is abnormal, but should be caught in the
+                  relocation phase.  */
+               continue;
 
              if (adata (abfd).local_got_offsets == NULL)
                {
                  amt = bfd_get_symcount (abfd);
                  amt *= sizeof (bfd_vma);
-                 adata (abfd).local_got_offsets =
-                   (bfd_vma *) bfd_zalloc (abfd, amt);
+                 adata (abfd).local_got_offsets = bfd_zalloc (abfd, amt);
                  if (adata (abfd).local_got_offsets == NULL)
                    return FALSE;
                }
@@ -1977,11 +1625,10 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
 
       if (r_type != RELOC_JMP_TBL
          && h->root.root.type == bfd_link_hash_undefined)
-       {
-         /* Presumably this symbol was marked as being undefined by
-            an earlier reloc.  */
-         srel->size += RELOC_EXT_SIZE;
-       }
+       /* Presumably this symbol was marked as being undefined by
+          an earlier reloc.  */
+       srel->size += RELOC_EXT_SIZE;
+
       else if (r_type != RELOC_JMP_TBL
               && (h->root.root.u.def.section->flags & SEC_CODE) == 0)
        {
@@ -2038,13 +1685,75 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
   return TRUE;
 }
 
+/* Scan the relocs for an input section.  */
+
+static bfd_boolean
+sunos_scan_relocs (struct bfd_link_info *info,
+                  bfd *abfd,
+                  asection *sec,
+                  bfd_size_type rel_size)
+{
+  void * relocs;
+  void * free_relocs = NULL;
+
+  if (rel_size == 0)
+    return TRUE;
+
+  if (! info->keep_memory)
+    relocs = free_relocs = bfd_malloc (rel_size);
+  else
+    {
+      struct aout_section_data_struct *n;
+      bfd_size_type amt = sizeof (struct aout_section_data_struct);
+
+      n = bfd_alloc (abfd, amt);
+      if (n == NULL)
+       relocs = NULL;
+      else
+       {
+         set_aout_section_data (sec, n);
+         relocs = bfd_malloc (rel_size);
+         aout_section_data (sec)->relocs = relocs;
+       }
+    }
+  if (relocs == NULL)
+    return FALSE;
+
+  if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+      || bfd_bread (relocs, rel_size, abfd) != rel_size)
+    goto error_return;
+
+  if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
+    {
+      if (! sunos_scan_std_relocs (info, abfd, sec,
+                                  (struct reloc_std_external *) relocs,
+                                  rel_size))
+       goto error_return;
+    }
+  else
+    {
+      if (! sunos_scan_ext_relocs (info, abfd, sec,
+                                  (struct reloc_ext_external *) relocs,
+                                  rel_size))
+       goto error_return;
+    }
+
+  if (free_relocs != NULL)
+    free (free_relocs);
+
+  return TRUE;
+
+ error_return:
+  if (free_relocs != NULL)
+    free (free_relocs);
+  return FALSE;
+}
+
 /* Build the hash table of dynamic symbols, and to mark as written all
    symbols from dynamic objects which we do not plan to write out.  */
 
 static bfd_boolean
-sunos_scan_dynamic_symbol (h, data)
-     struct sunos_link_hash_entry *h;
-     PTR data;
+sunos_scan_dynamic_symbol (struct sunos_link_hash_entry *h, void * data)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) data;
 
@@ -2068,7 +1777,6 @@ sunos_scan_dynamic_symbol (h, data)
   /* If this symbol is defined by a dynamic object and referenced by a
      regular object, see whether we gave it a reasonable value while
      scanning the relocs.  */
-
   if ((h->flags & SUNOS_DEF_REGULAR) == 0
       && (h->flags & SUNOS_DEF_DYNAMIC) != 0
       && (h->flags & SUNOS_REF_REGULAR) != 0)
@@ -2119,8 +1827,7 @@ sunos_scan_dynamic_symbol (h, data)
         There are no debugging symbols in the dynamic symbols.  */
       s = bfd_get_section_by_name (dynobj, ".dynstr");
       BFD_ASSERT (s != NULL);
-      contents = (bfd_byte *) bfd_realloc (s->contents,
-                                          s->size + len + 1);
+      contents = bfd_realloc (s->contents, s->size + len + 1);
       if (contents == NULL)
        return FALSE;
       s->contents = contents;
@@ -2161,14 +1868,234 @@ sunos_scan_dynamic_symbol (h, data)
   return TRUE;
 }
 
+/* Set up the sizes and contents of the dynamic sections created in
+   sunos_add_dynamic_symbols.  This is called by the SunOS linker
+   emulation before_allocation routine.  We must set the sizes of the
+   sections before the linker sets the addresses of the various
+   sections.  This unfortunately requires reading all the relocs so
+   that we can work out which ones need to become dynamic relocs.  If
+   info->keep_memory is TRUE, we keep the relocs in memory; otherwise,
+   we discard them, and will read them again later.  */
+
+bfd_boolean
+bfd_sunos_size_dynamic_sections (bfd *output_bfd,
+                                struct bfd_link_info *info,
+                                asection **sdynptr,
+                                asection **sneedptr,
+                                asection **srulesptr)
+{
+  bfd *dynobj;
+  bfd_size_type dynsymcount;
+  struct sunos_link_hash_entry *h;
+  asection *s;
+  size_t bucketcount;
+  bfd_size_type hashalloc;
+  size_t i;
+  bfd *sub;
+
+  *sdynptr = NULL;
+  *sneedptr = NULL;
+  *srulesptr = NULL;
+
+  if (info->relocatable)
+    return TRUE;
+
+  if (output_bfd->xvec != &MY(vec))
+    return TRUE;
+
+  /* Look through all the input BFD's and read their relocs.  It would
+     be better if we didn't have to do this, but there is no other way
+     to determine the number of dynamic relocs we need, and, more
+     importantly, there is no other way to know which symbols should
+     get an entry in the procedure linkage table.  */
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+    {
+      if ((sub->flags & DYNAMIC) == 0
+         && sub->xvec == output_bfd->xvec)
+       {
+         if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
+                                  exec_hdr (sub)->a_trsize)
+             || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
+                                     exec_hdr (sub)->a_drsize))
+           return FALSE;
+       }
+    }
+
+  dynobj = sunos_hash_table (info)->dynobj;
+  dynsymcount = sunos_hash_table (info)->dynsymcount;
+
+  /* If there were no dynamic objects in the link, and we don't need
+     to build a global offset table, there is nothing to do here.  */
+  if (! sunos_hash_table (info)->dynamic_sections_needed
+      && ! sunos_hash_table (info)->got_needed)
+    return TRUE;
+
+  /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it.  */
+  h = sunos_link_hash_lookup (sunos_hash_table (info),
+                             "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE);
+  if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
+    {
+      h->flags |= SUNOS_DEF_REGULAR;
+      if (h->dynindx == -1)
+       {
+         ++sunos_hash_table (info)->dynsymcount;
+         h->dynindx = -2;
+       }
+      h->root.root.type = bfd_link_hash_defined;
+      h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
+
+      /* If the .got section is more than 0x1000 bytes, we set
+        __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
+        so that 13 bit relocations have a greater chance of working.  */
+      s = bfd_get_section_by_name (dynobj, ".got");
+      BFD_ASSERT (s != NULL);
+      if (s->size >= 0x1000)
+       h->root.root.u.def.value = 0x1000;
+      else
+       h->root.root.u.def.value = 0;
+
+      sunos_hash_table (info)->got_base = h->root.root.u.def.value;
+    }
+
+  /* If there are any shared objects in the link, then we need to set
+     up the dynamic linking information.  */
+  if (sunos_hash_table (info)->dynamic_sections_needed)
+    {
+      *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
+
+      /* The .dynamic section is always the same size.  */
+      s = *sdynptr;
+      BFD_ASSERT (s != NULL);
+      s->size = (sizeof (struct external_sun4_dynamic)
+                     + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
+                     + sizeof (struct external_sun4_dynamic_link));
+
+      /* Set the size of the .dynsym and .hash sections.  We counted
+        the number of dynamic symbols as we read the input files.  We
+        will build the dynamic symbol table (.dynsym) and the hash
+        table (.hash) when we build the final symbol table, because
+        until then we do not know the correct value to give the
+        symbols.  We build the dynamic symbol string table (.dynstr)
+        in a traversal of the symbol table using
+        sunos_scan_dynamic_symbol.  */
+      s = bfd_get_section_by_name (dynobj, ".dynsym");
+      BFD_ASSERT (s != NULL);
+      s->size = dynsymcount * sizeof (struct external_nlist);
+      s->contents = bfd_alloc (output_bfd, s->size);
+      if (s->contents == NULL && s->size != 0)
+       return FALSE;
+
+      /* The number of buckets is just the number of symbols divided
+        by four.  To compute the final size of the hash table, we
+        must actually compute the hash table.  Normally we need
+        exactly as many entries in the hash table as there are
+        dynamic symbols, but if some of the buckets are not used we
+        will need additional entries.  In the worst case, every
+        symbol will hash to the same bucket, and we will need
+        BUCKETCOUNT - 1 extra entries.  */
+      if (dynsymcount >= 4)
+       bucketcount = dynsymcount / 4;
+      else if (dynsymcount > 0)
+       bucketcount = dynsymcount;
+      else
+       bucketcount = 1;
+      s = bfd_get_section_by_name (dynobj, ".hash");
+      BFD_ASSERT (s != NULL);
+      hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
+      s->contents = bfd_zalloc (dynobj, hashalloc);
+      if (s->contents == NULL && dynsymcount > 0)
+       return FALSE;
+      for (i = 0; i < bucketcount; i++)
+       PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
+      s->size = bucketcount * HASH_ENTRY_SIZE;
+
+      sunos_hash_table (info)->bucketcount = bucketcount;
+
+      /* Scan all the symbols, place them in the dynamic symbol table,
+        and build the dynamic hash table.  We reuse dynsymcount as a
+        counter for the number of symbols we have added so far.  */
+      sunos_hash_table (info)->dynsymcount = 0;
+      sunos_link_hash_traverse (sunos_hash_table (info),
+                               sunos_scan_dynamic_symbol,
+                               (void *) info);
+      BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
+
+      /* The SunOS native linker seems to align the total size of the
+        symbol strings to a multiple of 8.  I don't know if this is
+        important, but it can't hurt much.  */
+      s = bfd_get_section_by_name (dynobj, ".dynstr");
+      BFD_ASSERT (s != NULL);
+      if ((s->size & 7) != 0)
+       {
+         bfd_size_type add;
+         bfd_byte *contents;
+
+         add = 8 - (s->size & 7);
+         contents = bfd_realloc (s->contents, s->size + add);
+         if (contents == NULL)
+           return FALSE;
+         memset (contents + s->size, 0, (size_t) add);
+         s->contents = contents;
+         s->size += add;
+       }
+    }
+
+  /* Now that we have worked out the sizes of the procedure linkage
+     table and the dynamic relocs, allocate storage for them.  */
+  s = bfd_get_section_by_name (dynobj, ".plt");
+  BFD_ASSERT (s != NULL);
+  if (s->size != 0)
+    {
+      s->contents = bfd_alloc (dynobj, s->size);
+      if (s->contents == NULL)
+       return FALSE;
+
+      /* Fill in the first entry in the table.  */
+      switch (bfd_get_arch (dynobj))
+       {
+       case bfd_arch_sparc:
+         memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
+         break;
+
+       case bfd_arch_m68k:
+         memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
+         break;
+
+       default:
+         abort ();
+       }
+    }
+
+  s = bfd_get_section_by_name (dynobj, ".dynrel");
+  if (s->size != 0)
+    {
+      s->contents = bfd_alloc (dynobj, s->size);
+      if (s->contents == NULL)
+       return FALSE;
+    }
+  /* We use the reloc_count field to keep track of how many of the
+     relocs we have output so far.  */
+  s->reloc_count = 0;
+
+  /* Make space for the global offset table.  */
+  s = bfd_get_section_by_name (dynobj, ".got");
+  s->contents = bfd_alloc (dynobj, s->size);
+  if (s->contents == NULL)
+    return FALSE;
+
+  *sneedptr = bfd_get_section_by_name (dynobj, ".need");
+  *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
+
+  return TRUE;
+}
+
 /* Link a dynamic object.  We actually don't have anything to do at
    this point.  This entry point exists to prevent the regular linker
    code from doing anything with the object.  */
 
 static bfd_boolean
-sunos_link_dynamic_object (info, abfd)
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     bfd *abfd ATTRIBUTE_UNUSED;
+sunos_link_dynamic_object (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          bfd *abfd ATTRIBUTE_UNUSED)
 {
   return TRUE;
 }
@@ -2177,10 +2104,9 @@ sunos_link_dynamic_object (info, abfd)
    over the symbol table.  */
 
 static bfd_boolean
-sunos_write_dynamic_symbol (output_bfd, info, harg)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     struct aout_link_hash_entry *harg;
+sunos_write_dynamic_symbol (bfd *output_bfd,
+                           struct bfd_link_info *info,
+                           struct aout_link_hash_entry *harg)
 {
   struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
   int type;
@@ -2410,16 +2336,14 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
    reloc.  */
 
 static bfd_boolean
-sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
-                          contents, skip, relocationp)
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     struct aout_link_hash_entry *harg;
-     PTR reloc;
-     bfd_byte *contents ATTRIBUTE_UNUSED;
-     bfd_boolean *skip;
-     bfd_vma *relocationp;
+sunos_check_dynamic_reloc (struct bfd_link_info *info,
+                          bfd *input_bfd,
+                          asection *input_section,
+                          struct aout_link_hash_entry *harg,
+                          void * reloc,
+                          bfd_byte *contents ATTRIBUTE_UNUSED,
+                          bfd_boolean *skip,
+                          bfd_vma *relocationp)
 {
   struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
   bfd *dynobj;
@@ -2774,9 +2698,7 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
 /* Finish up the dynamic linking information.  */
 
 static bfd_boolean
-sunos_finish_dynamic_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+sunos_finish_dynamic_link (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *o;