* configure: Ignore new autoconf configure options.
[binutils-gdb.git] / bfd / sunos.c
index c1a28554e7756304a45ad34ba02c29ac986795e6..25b9072c3066b0e5a75871efe3bd14eeb1ef7fd8 100644 (file)
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 static boolean sunos_read_dynamic_info PARAMS ((bfd *));
 static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
+static 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
@@ -40,7 +41,8 @@ static struct bfd_link_hash_table *sunos_link_hash_table_create
 static boolean sunos_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *, boolean));
 static boolean sunos_add_dynamic_symbols
-  PARAMS ((bfd *, struct bfd_link_info *));
+  PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **,
+          bfd_size_type *, char **));
 static boolean sunos_add_one_symbol
   PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
           bfd_vma, const char *, boolean, boolean,
@@ -89,7 +91,7 @@ struct sunos_dynamic_info
   /* Dynamic information.  */
   struct internal_sun4_dynamic_link dyninfo;
   /* Number of dynamic symbols.  */
-  long dynsym_count;
+  unsigned long dynsym_count;
   /* Read in nlists for dynamic symbols.  */
   struct external_nlist *dynsym;
   /* asymbol structures for dynamic symbols.  */
@@ -97,7 +99,7 @@ struct sunos_dynamic_info
   /* Read in dynamic string table.  */
   char *dynstr;
   /* Number of dynamic relocs.  */
-  long dynrel_count;
+  unsigned long dynrel_count;
   /* Read in dynamic relocs.  This may be reloc_std_external or
      reloc_ext_external.  */
   PTR dynrel;
@@ -122,7 +124,7 @@ sunos_read_dynamic_info (abfd)
 {
   struct sunos_dynamic_info *info;
   asection *dynsec;
-  file_ptr dynoff;
+  bfd_vma dynoff;
   struct external_sun4_dynamic dyninfo;
   unsigned long dynver;
   struct external_sun4_dynamic_link linkinfo;
@@ -139,10 +141,7 @@ sunos_read_dynamic_info (abfd)
   info = ((struct sunos_dynamic_info *)
          bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
   if (!info)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   info->valid = false;
   info->dynsym = NULL;
   info->dynstr = NULL;
@@ -177,7 +176,7 @@ sunos_read_dynamic_info (abfd)
   else
     dynsec = obj_datasec (abfd);
   dynoff -= bfd_get_section_vma (abfd, dynsec);
-  if (dynoff < 0 || dynoff > bfd_section_size (abfd, dynsec))
+  if (dynoff > bfd_section_size (abfd, dynsec))
     return true;
 
   /* This executable appears to be dynamically linked in a way that we
@@ -202,18 +201,34 @@ sunos_read_dynamic_info (abfd)
   info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
   info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
 
+  /* Reportedly the addresses need to be offset by the size of the
+     exec header in an NMAGIC file.  */
+  if (adata (abfd).magic == n_magic)
+    {
+      unsigned long exec_bytes_size = adata (abfd).exec_bytes_size;
+
+      info->dyninfo.ld_need += exec_bytes_size;
+      info->dyninfo.ld_rules += exec_bytes_size;
+      info->dyninfo.ld_rel += exec_bytes_size;
+      info->dyninfo.ld_hash += exec_bytes_size;
+      info->dyninfo.ld_stab += exec_bytes_size;
+      info->dyninfo.ld_symbols += exec_bytes_size;
+    }
+
   /* The only way to get the size of the symbol information appears to
      be to determine the distance between it and the string table.  */
   info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
                        / EXTERNAL_NLIST_SIZE);
   BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
-             == info->dyninfo.ld_symbols - info->dyninfo.ld_stab);
+             == (unsigned long) (info->dyninfo.ld_symbols
+                                 - info->dyninfo.ld_stab));
 
   /* Similarly, the relocs end at the hash table.  */
   info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
                        / obj_reloc_entry_size (abfd));
   BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
-             == info->dyninfo.ld_hash - info->dyninfo.ld_rel);
+             == (unsigned long) (info->dyninfo.ld_hash
+                                 - info->dyninfo.ld_rel));
 
   info->valid = true;
 
@@ -241,28 +256,26 @@ sunos_get_dynamic_symtab_upper_bound (abfd)
   return (info->dynsym_count + 1) * sizeof (asymbol *);
 }
 
-/* Read in the dynamic symbols.  */
+/* Read the external dynamic symbols.  */
 
-static long
-sunos_canonicalize_dynamic_symtab (abfd, storage)
+static boolean
+sunos_slurp_dynamic_symtab (abfd)
      bfd *abfd;
-     asymbol **storage;
 {
   struct sunos_dynamic_info *info;
-  long i;
 
   /* Get the general dynamic information.  */
   if (obj_aout_dynamic_info (abfd) == NULL)
     {
       if (! sunos_read_dynamic_info (abfd))
-         return -1;
+         return false;
     }
 
   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
   if (! info->valid)
     {
       bfd_set_error (bfd_error_no_symbols);
-      return -1;
+      return false;
     }
 
   /* Get the dynamic nlist structures.  */
@@ -273,10 +286,7 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
                                 (info->dynsym_count
                                  * EXTERNAL_NLIST_SIZE)));
       if (info->dynsym == NULL && info->dynsym_count != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return -1;
-       }
+       return false;
       if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0
          || (bfd_read ((PTR) info->dynsym, info->dynsym_count,
                        EXTERNAL_NLIST_SIZE, abfd)
@@ -287,7 +297,7 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
              bfd_release (abfd, info->dynsym);
              info->dynsym = NULL;
            }
-         return -1;
+         return false;
        }
     }
 
@@ -296,10 +306,7 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
     {
       info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
       if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return -1;
-       }
+       return false;
       if (bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0
          || (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size,
                        abfd)
@@ -310,10 +317,28 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
              bfd_release (abfd, info->dynstr);
              info->dynstr = NULL;
            }
-         return -1;
+         return false;
        }
     }
 
+  return true;
+}
+
+/* Read in the dynamic symbols.  */
+
+static long
+sunos_canonicalize_dynamic_symtab (abfd, storage)
+     bfd *abfd;
+     asymbol **storage;
+{
+  struct sunos_dynamic_info *info;
+  unsigned long i;
+
+  if (! sunos_slurp_dynamic_symtab (abfd))
+    return -1;
+
+  info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+
 #ifdef CHECK_DYNAMIC_HASH
   /* Check my understanding of the dynamic hash table by making sure
      that each symbol can be located in the hash table.  */
@@ -325,7 +350,7 @@ 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 *) malloc (table_size);
+    table = (bfd_byte *) bfd_malloc (table_size);
     if (table == NULL && table_size != 0)
       abort ();
     if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
@@ -364,10 +389,7 @@ sunos_canonicalize_dynamic_symtab (abfd, storage)
                                           (info->dynsym_count
                                            * sizeof (aout_symbol_type))));
       if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return -1;
-       }
+       return -1;
 
       if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym,
                                            info->dynsym, info->dynsym_count,
@@ -422,7 +444,7 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
      asymbol **syms;
 {
   struct sunos_dynamic_info *info;
-  long i;
+  unsigned long i;
 
   /* Get the general dynamic information.  */
   if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
@@ -445,10 +467,7 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
                                      (info->dynrel_count
                                       * obj_reloc_entry_size (abfd)));
       if (info->dynrel == NULL && info->dynrel_count != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return -1;
-       }
+       return -1;
       if (bfd_seek (abfd, info->dyninfo.ld_rel, SEEK_SET) != 0
          || (bfd_read ((PTR) info->dynrel, info->dynrel_count,
                        obj_reloc_entry_size (abfd), abfd)
@@ -474,10 +493,7 @@ sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
                                           (info->dynrel_count
                                            * sizeof (arelent))));
       if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return -1;
-       }
+       return -1;
       
       to = info->canonical_dynrel;
 
@@ -629,6 +645,10 @@ struct sunos_link_hash_table
 
   /* The number of buckets in the hash table.  */
   size_t bucketcount;
+
+  /* The list of dynamic objects needed by dynamic objects included in
+     the link.  */
+  struct bfd_link_needed_list *needed;
 };
 
 /* Routine to create an entry in an SunOS link hash table.  */
@@ -647,10 +667,7 @@ sunos_link_hash_newfunc (entry, table, string)
     ret = ((struct sunos_link_hash_entry *)
           bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry)));
   if (ret == (struct sunos_link_hash_entry *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (struct bfd_hash_entry *) ret;
-    }
+    return (struct bfd_hash_entry *) ret;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct sunos_link_hash_entry *)
@@ -680,14 +697,11 @@ sunos_link_hash_table_create (abfd)
   ret = ((struct sunos_link_hash_table *)
         bfd_alloc (abfd, sizeof (struct sunos_link_hash_table)));
   if (ret == (struct sunos_link_hash_table *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (struct bfd_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))
     {
-      free (ret);
+      bfd_release (abfd, ret);
       return (struct bfd_link_hash_table *) NULL;
     }
 
@@ -696,6 +710,7 @@ sunos_link_hash_table_create (abfd)
   ret->dynamic_sections_needed = false;
   ret->dynsymcount = 0;
   ret->bucketcount = 0;
+  ret->needed = NULL;
 
   return &ret->root.root;
 }
@@ -826,12 +841,17 @@ sunos_create_dynamic_sections (abfd, info, needed)
    set.  */
 
 static boolean
-sunos_add_dynamic_symbols (abfd, info)
+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;
 {
   asection *s;
   bfd *dynobj;
+  struct sunos_dynamic_info *dinfo;
+  unsigned long need;
 
   /* We do not want to include the sections in a dynamic object in the
      output file.  We hack by simply clobbering the list of sections
@@ -896,6 +916,81 @@ sunos_add_dynamic_symbols (abfd, info)
        return false;
     }
 
+  /* Pick up the dynamic symbols and return them to the caller.  */
+  if (! sunos_slurp_dynamic_symtab (abfd))
+    return false;
+
+  dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+  *symsp = dinfo->dynsym;
+  *sym_countp = dinfo->dynsym_count;
+  *stringsp = dinfo->dynstr;
+
+  /* Record information about any other objects needed by this one.  */
+  need = dinfo->dyninfo.ld_need;
+  while (need != 0)
+    {
+      bfd_byte buf[16];
+      unsigned long name, flags;
+      unsigned short major_vno, minor_vno;
+      struct bfd_link_needed_list *needed, **pp;
+      bfd_byte b;
+
+      if (bfd_seek (abfd, need, SEEK_SET) != 0
+         || bfd_read (buf, 1, 16, abfd) != 16)
+       return false;
+
+      /* 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 = bfd_get_16 (abfd, buf + 8);
+      minor_vno = bfd_get_16 (abfd, buf + 10);
+      need = bfd_get_32 (abfd, buf + 12);
+
+      needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof (struct bfd_link_needed_list));
+      if (needed == NULL)
+       return false;
+      needed->by = abfd;
+
+      /* We return the name as [-l]name[.maj][.min].  */
+
+      if ((flags & 0x80000000) != 0)
+       bfd_alloc_grow (abfd, "-l", 2);
+      if (bfd_seek (abfd, name, SEEK_SET) != 0)
+       return false;
+      do
+       {
+         if (bfd_read (&b, 1, 1, abfd) != 1)
+           return false;
+         bfd_alloc_grow (abfd, &b, 1);
+       }
+      while (b != '\0');
+      if (major_vno != 0)
+       {
+         char verbuf[30];
+
+         sprintf (verbuf, ".%d", major_vno);
+         bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
+         if (minor_vno != 0)
+           {
+             sprintf (verbuf, ".%d", minor_vno);
+             bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
+           }
+       }
+      needed->name = bfd_alloc_finish (abfd);
+      if (needed->name == NULL)
+       return false;
+
+      needed->next = NULL;
+
+      for (pp = &sunos_hash_table (info)->needed;
+          *pp != NULL;
+          pp = &(*pp)->next)
+       ;
+      *pp = needed;
+    }
+
   return true;
 }
 
@@ -927,7 +1022,7 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
          sections will be needed.  This will ensure that the dynamic
          sections are mapped to the right output section.  It does no
          harm to create these sections if they are not needed.  */
-      if (! sunos_create_dynamic_sections (abfd, info, info->shared))
+      if (! sunos_create_dynamic_sections (abfd, info, false))
        return false;
     }
 
@@ -961,18 +1056,25 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
             reference.  */
          section = bfd_und_section_ptr;
        }
-      else if ((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)
-              || (h->root.root.type == bfd_link_hash_common
-                  && ((h->root.root.u.c.p->section->owner->flags & DYNAMIC)
-                      != 0)))
+      else if (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 definition is from a dynamic object.  We
             want to override it with the definition we just found.
             Clobber the existing definition.  */
          h->root.root.type = bfd_link_hash_new;
        }
+      else if (h->root.root.type == bfd_link_hash_common
+              && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
+       {
+         /* The existing definition is from a dynamic object.  We
+            want to override it with the definition we just found.
+            Clobber the existing definition.  We can't set it to new,
+            because it is on the undefined list.  */
+         h->root.root.type = bfd_link_hash_undefined;
+         h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner;
+       }
     }
 
   /* Do the usual procedure for adding a symbol.  */
@@ -1015,6 +1117,19 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
   return true;
 }
 
+/* Return the list of objects needed by BFD.  */
+
+/*ARGSUSED*/
+struct bfd_link_needed_list *
+bfd_sunos_get_needed_list (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  if (info->hash->creator != &MY(vec))
+    return NULL;
+  return sunos_hash_table (info)->needed;
+}
+
 /* Record an assignment made to a symbol by a linker script.  We need
    this in case some dynamic object refers to this symbol.  */
 
@@ -1026,6 +1141,9 @@ bfd_sunos_record_link_assignment (output_bfd, info, name)
 {
   struct sunos_link_hash_entry *h;
 
+  if (output_bfd->xvec != &MY(vec))
+    return true;
+
   /* This is called after we have examined all the input objects.  If
      the symbol does not exist, it merely means that no object refers
      to it, and we can just ignore it at this point.  */
@@ -1034,12 +1152,17 @@ bfd_sunos_record_link_assignment (output_bfd, info, name)
   if (h == NULL)
     return true;
 
-  h->flags |= SUNOS_DEF_REGULAR;
-
-  if (h->dynindx == -1)
+  /* In a shared library, the __DYNAMIC symbol does not appear in the
+     dynamic symbol table.  */
+  if (! info->shared || strcmp (name, "__DYNAMIC") != 0)
     {
-      ++sunos_hash_table (info)->dynsymcount;
-      h->dynindx = -2;
+      h->flags |= SUNOS_DEF_REGULAR;
+
+      if (h->dynindx == -1)
+       {
+         ++sunos_hash_table (info)->dynsymcount;
+         h->dynindx = -2;
+       }
     }
 
   return true;
@@ -1076,6 +1199,9 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
   *sneedptr = NULL;
   *srulesptr = NULL;
 
+  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
@@ -1083,7 +1209,8 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
      get an entry in the procedure linkage table.  */
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
-      if ((sub->flags & DYNAMIC) == 0)
+      if ((sub->flags & DYNAMIC) == 0
+         && sub->xvec == output_bfd->xvec)
        {
          if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
                                   exec_hdr (sub)->a_trsize)
@@ -1136,10 +1263,7 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
   s->_raw_size = dynsymcount * sizeof (struct external_nlist);
   s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
   if (s->contents == NULL && s->_raw_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    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
@@ -1159,10 +1283,7 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
   hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
   s->contents = (bfd_byte *) bfd_alloc (dynobj, hashalloc);
   if (s->contents == NULL && dynsymcount > 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   memset (s->contents, 0, hashalloc);
   for (i = 0; i < bucketcount; i++)
     PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
@@ -1190,13 +1311,10 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
       bfd_byte *contents;
 
       add = 8 - (s->_raw_size & 7);
-      contents = (bfd_byte *) realloc (s->contents,
-                                      (size_t) (s->_raw_size + add));
+      contents = (bfd_byte *) bfd_realloc (s->contents,
+                                          (size_t) (s->_raw_size + add));
       if (contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       memset (contents + s->_raw_size, 0, (size_t) add);
       s->contents = contents;
       s->_raw_size += add;
@@ -1210,10 +1328,7 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
     {
       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
       if (s->contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
 
       /* Fill in the first entry in the table.  */
       switch (bfd_get_arch (dynobj))
@@ -1236,10 +1351,7 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
     {
       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
       if (s->contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
     }
   /* We use the reloc_count field to keep track of how many of the
      relocs we have output so far.  */
@@ -1249,10 +1361,7 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
   s = bfd_get_section_by_name (dynobj, ".got");
   s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
   if (s->contents == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
   *sneedptr = bfd_get_section_by_name (dynobj, ".need");
@@ -1277,7 +1386,7 @@ sunos_scan_relocs (info, abfd, sec, rel_size)
     return true;
 
   if (! info->keep_memory)
-    relocs = free_relocs = malloc ((size_t) rel_size);
+    relocs = free_relocs = bfd_malloc ((size_t) rel_size);
   else
     {
       struct aout_section_data_struct *n;
@@ -1289,15 +1398,12 @@ sunos_scan_relocs (info, abfd, sec, rel_size)
       else
        {
          set_aout_section_data (sec, n);
-         relocs = malloc ((size_t) rel_size);
+         relocs = bfd_malloc ((size_t) rel_size);
          aout_section_data (sec)->relocs = relocs;
        }
     }
   if (relocs == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
       || bfd_read (relocs, 1, rel_size, abfd) != rel_size)
@@ -1426,10 +1532,12 @@ sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
        }
 
       BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
-      BFD_ASSERT ((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);
+      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.  */
@@ -1518,7 +1626,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
   relend = relocs + rel_size / RELOC_EXT_SIZE;
   for (rel = relocs; rel < relend; rel++)
     {
-      int r_index;
+      unsigned int r_index;
       int r_extern;
       int r_type;
       struct sunos_link_hash_entry *h = NULL;
@@ -1553,15 +1661,6 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
              continue;
            }
        }
-      else
-       {
-         if (r_index >= bfd_get_symcount (abfd))
-           {
-             /* This is abnormal, but should be caught in the
-                 relocation phase.  */
-             continue;
-           }
-       }
 
       /* If this is a base relative reloc, we need to make an entry in
          the .got section.  */
@@ -1589,6 +1688,13 @@ 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;
+               }
+
              if (adata (abfd).local_got_offsets == NULL)
                {
                  adata (abfd).local_got_offsets =
@@ -1596,10 +1702,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
                                            (bfd_get_symcount (abfd)
                                             * sizeof (bfd_vma)));
                  if (adata (abfd).local_got_offsets == NULL)
-                   {
-                     bfd_set_error (bfd_error_no_memory);
-                     return false;
-                   }
+                   return false;
                }
 
              if (adata (abfd).local_got_offsets[r_index] != 0)
@@ -1626,7 +1729,27 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
          defined in dynamic objects but not in regular objects.  We
          only need to consider relocs against external symbols.  */
       if (! r_extern)
-       continue;
+       {
+         /* But, if we are creating a shared library, we need to
+             generate an absolute reloc.  */
+         if (info->shared)
+           {
+             if (dynobj == NULL)
+               {
+                 if (! sunos_create_dynamic_sections (abfd, info, true))
+                   return false;
+                 dynobj = sunos_hash_table (info)->dynobj;
+                 splt = bfd_get_section_by_name (dynobj, ".plt");
+                 sgot = bfd_get_section_by_name (dynobj, ".got");
+                 srel = bfd_get_section_by_name (dynobj, ".dynrel");
+                 BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+               }
+
+             srel->_raw_size += RELOC_EXT_SIZE;
+           }
+
+         continue;
+       }
 
       /* At this point common symbols have already been allocated, so
         we don't have to worry about them.  We need to consider that
@@ -1639,6 +1762,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
        continue;
 
       if (r_type != RELOC_JMP_TBL
+         && ! info->shared
          && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
              || (h->flags & SUNOS_DEF_REGULAR) != 0))
        continue;
@@ -1660,6 +1784,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
       BFD_ASSERT (r_type == RELOC_JMP_TBL
                  || (h->flags & SUNOS_REF_REGULAR) != 0);
       BFD_ASSERT (r_type == RELOC_JMP_TBL
+                 || info->shared
                  || h->plt_offset != 0
                  || ((h->root.root.type == bfd_link_hash_defined
                       || h->root.root.type == bfd_link_hash_defweak)
@@ -1670,24 +1795,28 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
       /* This reloc is against a symbol defined only by a dynamic
         object, or it is a jump table reloc from PIC compiled code.  */
 
-      if (h->root.root.type == bfd_link_hash_undefined)
+      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->_raw_size += RELOC_EXT_SIZE;
        }
-      else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
+      else if (r_type != RELOC_JMP_TBL
+              && (h->root.root.u.def.section->flags & SEC_CODE) == 0)
        {
          bfd *sub;
 
          /* This reloc is not in the .text section.  It must be
             copied into the dynamic relocs.  We mark the symbol as
             being undefined.  */
-         BFD_ASSERT (r_type != RELOC_JMP_TBL);
          srel->_raw_size += RELOC_EXT_SIZE;
-         sub = h->root.root.u.def.section->owner;
-         h->root.root.type = bfd_link_hash_undefined;
-         h->root.root.u.undef.abfd = sub;
+         if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+           {
+             sub = h->root.root.u.def.section->owner;
+             h->root.root.type = bfd_link_hash_undefined;
+             h->root.root.u.undef.abfd = sub;
+           }
        }
       else
        {
@@ -1704,6 +1833,8 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
 
              if ((h->flags & SUNOS_DEF_REGULAR) == 0)
                {
+                 if (h->root.root.type == bfd_link_hash_undefined)
+                   h->root.root.type = bfd_link_hash_defined;
                  h->root.root.u.def.section = splt;
                  h->root.root.u.def.value = splt->_raw_size;
                }
@@ -1716,6 +1847,11 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
              if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
                srel->_raw_size += RELOC_EXT_SIZE;
            }
+
+         /* If we are creating a shared library, we need to copy over
+             any reloc other than a jump table reloc.  */
+         if (info->shared && r_type != RELOC_JMP_TBL)
+           srel->_raw_size += RELOC_EXT_SIZE;
        }
     }
 
@@ -1736,8 +1872,14 @@ sunos_scan_dynamic_symbol (h, data)
      part of the regular symbol table.  This is all symbols which are
      not defined in a regular object file.  For some reason symbols
      which are referenced by a regular object and defined by a dynamic
-     object do not seem to show up in the regular symbol table.  */
-  if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+     object do not seem to show up in the regular symbol table.  It is
+     possible for a symbol to have only SUNOS_REF_REGULAR set here, it
+     is an undefined symbol which was turned into a common symbol
+     because it was found in an archive object which was not included
+     in the link.  */
+  if ((h->flags & SUNOS_DEF_REGULAR) == 0
+      && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+      && strcmp (h->root.root.root.string, "__DYNAMIC") != 0)
     h->root.written = true;
 
   /* If this symbol is defined by a dynamic object and referenced by a
@@ -1794,16 +1936,10 @@ 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);
-      if (s->contents == NULL)
-       contents = (bfd_byte *) malloc (len + 1);
-      else
-       contents = (bfd_byte *) realloc (s->contents,
-                                        (size_t) (s->_raw_size + len + 1));
+      contents = (bfd_byte *) bfd_realloc (s->contents,
+                                          s->_raw_size + len + 1);
       if (contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       s->contents = contents;
 
       h->dynstr_index = s->_raw_size;
@@ -1972,9 +2108,9 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
 
       s = bfd_get_section_by_name (dynobj, ".dynrel");
 
-      r_address = (h->root.root.u.def.section->output_section->vma
-                  + h->root.root.u.def.section->output_offset
-                  + h->root.root.u.def.value);
+      r_address = (splt->output_section->vma
+                  + splt->output_offset
+                  + h->plt_offset);
 
       switch (bfd_get_arch (output_bfd))
        {
@@ -2024,6 +2160,8 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
          result of a JMP_TBL reloc from PIC compiled code.  */
       if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
        {
+         BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
+                     < s->_raw_size);
          p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
          if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE)
            {
@@ -2059,16 +2197,18 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
                  erel->r_index[0] = h->dynindx >> 16;
                  erel->r_index[1] = h->dynindx >> 8;
                  erel->r_index[2] = h->dynindx;
-                 erel->r_type[0] = (RELOC_EXT_BITS_EXTERN_BIG
-                                    | (22 << RELOC_EXT_BITS_TYPE_SH_BIG));
+                 erel->r_type[0] =
+                   (RELOC_EXT_BITS_EXTERN_BIG
+                    | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
                }
              else
                {
                  erel->r_index[2] = h->dynindx >> 16;
                  erel->r_index[1] = h->dynindx >> 8;
                  erel->r_index[0] = h->dynindx;
-                 erel->r_type[0] = (RELOC_EXT_BITS_EXTERN_LITTLE
-                                    | (22 << RELOC_EXT_BITS_TYPE_SH_LITTLE));
+                 erel->r_type[0] =
+                   (RELOC_EXT_BITS_EXTERN_LITTLE
+                    | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
                }
              PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend);
            }
@@ -2101,8 +2241,10 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
   struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
   bfd *dynobj;
   boolean baserel;
+  boolean jmptbl;
   asection *s;
   bfd_byte *p;
+  long indx;
 
   *skip = false;
 
@@ -2125,9 +2267,15 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
 
       srel = (struct reloc_std_external *) reloc;
       if (input_bfd->xvec->header_byteorder_big_p)
-       baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
+       {
+         baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
+         jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+       }
       else
-       baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+       {
+         baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+         jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+       }
     }
   else
     {
@@ -2144,6 +2292,7 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
       baserel = (r_type == RELOC_BASE10
                 || r_type == RELOC_BASE13
                 || r_type == RELOC_BASE22);
+      jmptbl = r_type == RELOC_JMP_TBL;
     }
 
   if (baserel)
@@ -2198,21 +2347,35 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
         already initialized the GOT entry.  */
       if ((*got_offsetp & 1) == 0)
        {
-         PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
+         if (h == NULL
+             || (! info->shared
+                 && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
+                     || (h->flags & SUNOS_DEF_REGULAR) != 0)))
+           PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
+         else
+           PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp);
 
-         if (h != NULL
-             && (h->flags & SUNOS_DEF_DYNAMIC) != 0
-             && (h->flags & SUNOS_DEF_REGULAR) == 0)
+         if (info->shared
+             || (h != NULL
+                 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+                 && (h->flags & SUNOS_DEF_REGULAR) == 0))
            {
-             /* We need to create a GLOB_DAT reloc to tell the
+             /* We need to create a GLOB_DAT or 32 reloc to tell the
                  dynamic linker to fill in this entry in the table.  */
 
              s = bfd_get_section_by_name (dynobj, ".dynrel");
              BFD_ASSERT (s != NULL);
+             BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
+                         < s->_raw_size);
 
              p = (s->contents
                   + s->reloc_count * obj_reloc_entry_size (dynobj));
 
+             if (h != NULL)
+               indx = h->dynindx;
+             else
+               indx = 0;
+
              if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
                {
                  struct reloc_std_external *srel;
@@ -2225,25 +2388,31 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
                            srel->r_address);
                  if (dynobj->xvec->header_byteorder_big_p)
                    {
-                     srel->r_index[0] = h->dynindx >> 16;
-                     srel->r_index[1] = h->dynindx >> 8;
-                     srel->r_index[2] = h->dynindx;
-                     srel->r_type[0] =
-                       (RELOC_STD_BITS_EXTERN_BIG
-                        | RELOC_STD_BITS_BASEREL_BIG
-                        | RELOC_STD_BITS_RELATIVE_BIG
-                        | (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
+                     srel->r_index[0] = indx >> 16;
+                     srel->r_index[1] = indx >> 8;
+                     srel->r_index[2] = indx;
+                     if (h == NULL)
+                       srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
+                     else
+                       srel->r_type[0] =
+                         (RELOC_STD_BITS_EXTERN_BIG
+                          | RELOC_STD_BITS_BASEREL_BIG
+                          | RELOC_STD_BITS_RELATIVE_BIG
+                          | (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
                    }
                  else
                    {
-                     srel->r_index[2] = h->dynindx >> 16;
-                     srel->r_index[1] = h->dynindx >> 8;
-                     srel->r_index[0] = h->dynindx;
-                     srel->r_type[0] =
-                       (RELOC_STD_BITS_EXTERN_LITTLE
-                        | RELOC_STD_BITS_BASEREL_LITTLE
-                        | RELOC_STD_BITS_RELATIVE_LITTLE
-                        | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
+                     srel->r_index[2] = indx >> 16;
+                     srel->r_index[1] = indx >> 8;
+                     srel->r_index[0] = indx;
+                     if (h == NULL)
+                       srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
+                     else
+                       srel->r_type[0] =
+                         (RELOC_STD_BITS_EXTERN_LITTLE
+                          | RELOC_STD_BITS_BASEREL_LITTLE
+                          | RELOC_STD_BITS_RELATIVE_LITTLE
+                          | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
                    }
                }
              else
@@ -2258,21 +2427,30 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
                            erel->r_address);
                  if (dynobj->xvec->header_byteorder_big_p)
                    {
-                     erel->r_index[0] = h->dynindx >> 16;
-                     erel->r_index[1] = h->dynindx >> 8;
-                     erel->r_index[2] = h->dynindx;
-                     erel->r_type[0] =
-                       (RELOC_EXT_BITS_EXTERN_BIG
-                        | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
+                     erel->r_index[0] = indx >> 16;
+                     erel->r_index[1] = indx >> 8;
+                     erel->r_index[2] = indx;
+                     if (h == NULL)
+                       erel->r_type[0] =
+                         RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
+                     else
+                       erel->r_type[0] =
+                         (RELOC_EXT_BITS_EXTERN_BIG
+                          | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
                    }
                  else
                    {
-                     erel->r_index[2] = h->dynindx >> 16;
-                     erel->r_index[1] = h->dynindx >> 8;
-                     erel->r_index[0] = h->dynindx;
-                     erel->r_type[0] =
-                       (RELOC_EXT_BITS_EXTERN_LITTLE
-                        | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
+                     erel->r_index[2] = indx >> 16;
+                     erel->r_index[1] = indx >> 8;
+                     erel->r_index[0] = indx;
+                     if (h == NULL)
+                       erel->r_type[0] =
+                         RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
+                     else
+                       erel->r_type[0] =
+                         (RELOC_EXT_BITS_EXTERN_LITTLE
+                          | (RELOC_GLOB_DAT
+                             << RELOC_EXT_BITS_TYPE_SH_LITTLE));
                    }
                  PUT_WORD (dynobj, 0, erel->r_addend);
                }
@@ -2289,25 +2467,44 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
       return true;
     }
 
-  if (! sunos_hash_table (info)->dynamic_sections_needed
-      || h == NULL
-      || h->dynindx == -1
-      || h->root.root.type != bfd_link_hash_undefined
-      || (h->flags & SUNOS_DEF_REGULAR) != 0
-      || (h->flags & SUNOS_DEF_DYNAMIC) == 0
-      || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
+  if (! sunos_hash_table (info)->dynamic_sections_needed)
     return true;
+  if (! info->shared)
+    {
+      if (h == NULL
+         || h->dynindx == -1
+         || h->root.root.type != bfd_link_hash_undefined
+         || (h->flags & SUNOS_DEF_REGULAR) != 0
+         || (h->flags & SUNOS_DEF_DYNAMIC) == 0
+         || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
+       return true;
+    }
+  else
+    {
+      if (h != NULL
+         && (h->dynindx == -1
+             || jmptbl
+             || strcmp (h->root.root.root.string,
+                        "__GLOBAL_OFFSET_TABLE_") == 0))
+       return true;
+    }
 
   /* It looks like this is a reloc we are supposed to copy.  */
 
   s = bfd_get_section_by_name (dynobj, ".dynrel");
   BFD_ASSERT (s != NULL);
+  BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->_raw_size);
 
   p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj);
 
   /* Copy the reloc over.  */
   memcpy (p, reloc, obj_reloc_entry_size (dynobj));
 
+  if (h != NULL)
+    indx = h->dynindx;
+  else
+    indx = 0;
+
   /* Adjust the address and symbol index.  */
   if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
     {
@@ -2321,15 +2518,15 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
                srel->r_address);
       if (dynobj->xvec->header_byteorder_big_p)
        {
-         srel->r_index[0] = h->dynindx >> 16;
-         srel->r_index[1] = h->dynindx >> 8;
-         srel->r_index[2] = h->dynindx;
+         srel->r_index[0] = indx >> 16;
+         srel->r_index[1] = indx >> 8;
+         srel->r_index[2] = indx;
        }
       else
        {
-         srel->r_index[2] = h->dynindx >> 16;
-         srel->r_index[1] = h->dynindx >> 8;
-         srel->r_index[0] = h->dynindx;
+         srel->r_index[2] = indx >> 16;
+         srel->r_index[1] = indx >> 8;
+         srel->r_index[0] = indx;
        }
     }
   else
@@ -2344,21 +2541,22 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
                erel->r_address);
       if (dynobj->xvec->header_byteorder_big_p)
        {
-         erel->r_index[0] = h->dynindx >> 16;
-         erel->r_index[1] = h->dynindx >> 8;
-         erel->r_index[2] = h->dynindx;
+         erel->r_index[0] = indx >> 16;
+         erel->r_index[1] = indx >> 8;
+         erel->r_index[2] = indx;
        }
       else
        {
-         erel->r_index[2] = h->dynindx >> 16;
-         erel->r_index[1] = h->dynindx >> 8;
-         erel->r_index[0] = h->dynindx;
+         erel->r_index[2] = indx >> 16;
+         erel->r_index[1] = indx >> 8;
+         erel->r_index[0] = indx;
        }
     }
 
   ++s->reloc_count;
 
-  *skip = true;
+  if (h != NULL)
+    *skip = true;
 
   return true;
 }
@@ -2410,12 +2608,15 @@ sunos_finish_dynamic_link (abfd, info)
        }
     }
 
-  /* The first entry in the .got section is the address of the dynamic
-     information.  */
+  /* The first entry in the .got section is the address of the
+     dynamic information, unless this is a shared library.  */
   s = bfd_get_section_by_name (dynobj, ".got");
   BFD_ASSERT (s != NULL);
-  PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
-           s->contents);
+  if (info->shared)
+    PUT_WORD (dynobj, 0, s->contents);
+  else
+    PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
+             s->contents);
 
   for (o = dynobj->sections; o != NULL; o = o->next)
     {