* linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp
authorIan Lance Taylor <ian@airs.com>
Mon, 9 May 1994 23:22:00 +0000 (23:22 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 9 May 1994 23:22:00 +0000 (23:22 +0000)
are not NULL, assume the caller has already looked up the symbol
in the hash table and has stored the entry in *hashp.
(generic_link_add_symbol_list): Set h to NULL before calling
_bfd_generic_link_add_one_symbol.
* ecoff.c (ecoff_link_add_externals): Likewise.

bfd/ChangeLog
bfd/ecoff.c
bfd/linker.c

index ab6ca34b74adad7ef82d48d7fda745e066d4f1ef..435aff61a69cb1013add0111163fc427f37b5e35 100644 (file)
@@ -1,5 +1,15 @@
 Mon May  9 11:53:54 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
+       * linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp
+       are not NULL, assume the caller has already looked up the symbol
+       in the hash table and has stored the entry in *hashp.
+       (generic_link_add_symbol_list): Set h to NULL before calling
+       _bfd_generic_link_add_one_symbol.
+       * ecoff.c (ecoff_link_add_externals): Likewise.
+
+       * elfcode.h (assign_file_positions_except_relocs): Don't require
+       page shared between .data and .bss segments to contain zeroes.
+
        * elfcode.h: Include bfdlink.h.  Added several new functions to do
        linking.
        (ELF_R_TYPE): Define.
index 3aa939e5cc64992fdfcee58571771b3bf6ee1a0d..ce4d5f6c6f75a8655ed391281a12bedfb060eb23 100644 (file)
@@ -99,7 +99,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
   struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
   ecoff_data_type *ecoff;
-  asection *regsec;
 
   if (ecoff_mkobject (abfd) == false)
     return NULL;
@@ -108,13 +107,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
   ecoff->gp_size = 8;
   ecoff->sym_filepos = internal_f->f_symptr;
 
-  /* Create the .reginfo section to give programs outside BFD a way to
-     see the information stored in the a.out header.  See the comment
-     in coff/ecoff.h.  */
-  regsec = bfd_make_section (abfd, REGINFO);
-  if (regsec == NULL)
-    return NULL;
-
   if (internal_a != (struct internal_aouthdr *) NULL)
     {
       int i;
@@ -184,15 +176,6 @@ ecoff_new_section_hook (abfd, section)
       /* An Irix 4 shared libary.  */
       section->flags |= SEC_SHARED_LIBRARY;
     }
-  else if (strcmp (section->name, REGINFO) == 0)
-    {
-      /* Setting SEC_SHARED_LIBRARY should make the linker leave the
-        section completely alone.  */
-      section->flags |= (SEC_SHARED_LIBRARY
-                        | SEC_HAS_CONTENTS
-                        | SEC_NEVER_LOAD);
-      section->_raw_size = sizeof (struct ecoff_reginfo);
-    }
 
   /* Probably any other section name is SEC_NEVER_LOAD, but I'm
      uncertain about .init on some systems and I don't know how shared
@@ -2187,12 +2170,21 @@ ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
 {
   struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
   struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
+  register int i;
   asymbol **sym_ptr_ptr;
   size_t c;
   boolean local;
 
   BFD_ASSERT (ibfd->xvec == obfd->xvec);
 
+  /* Copy the GP value and the register masks.  */
+  ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
+  ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
+  ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
+  for (i = 0; i < 3; i++)
+    ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
+
+  /* Copy the version stamp.  */
   oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
 
   /* If there are no symbols, don't copy any debugging information.  */
@@ -2287,8 +2279,7 @@ ecoff_set_arch_mach (abfd, arch, machine)
   return arch == ecoff_backend (abfd)->arch;
 }
 
-/* Get the size of the section headers.  We do not output the .reginfo
-   section.  */
+/* Get the size of the section headers.  */
 
 /*ARGSUSED*/
 int
@@ -2304,8 +2295,7 @@ ecoff_sizeof_headers (abfd, reloc)
   for (current = abfd->sections;
        current != (asection *)NULL; 
        current = current->next) 
-    if (strcmp (current->name, REGINFO) != 0)
-      ++c;
+    ++c;
 
   ret = (bfd_coff_filhsz (abfd)
         + bfd_coff_aoutsz (abfd)
@@ -2313,9 +2303,7 @@ ecoff_sizeof_headers (abfd, reloc)
   return BFD_ALIGN (ret, 16);
 }
 
-/* Get the contents of a section.  This is where we handle reading the
-   .reginfo section, which implicitly holds the contents of an
-   ecoff_reginfo structure.  */
+/* Get the contents of a section.  */
 
 boolean
 ecoff_get_section_contents (abfd, section, location, offset, count)
@@ -2325,26 +2313,8 @@ ecoff_get_section_contents (abfd, section, location, offset, count)
      file_ptr offset;
      bfd_size_type count;
 {
-  ecoff_data_type *tdata = ecoff_data (abfd);
-  struct ecoff_reginfo s;
-  int i;
-
-  if (strcmp (section->name, REGINFO) != 0)
-    return _bfd_generic_get_section_contents (abfd, section, location,
-                                            offset, count);
-
-  s.gp_value = tdata->gp;
-  s.gprmask = tdata->gprmask;
-  for (i = 0; i < 4; i++)
-    s.cprmask[i] = tdata->cprmask[i];
-  s.fprmask = tdata->fprmask;
-
-  /* bfd_get_section_contents has already checked that the offset and
-     size is reasonable.  We don't have to worry about swapping or any
-     such thing; the .reginfo section is defined such that the
-     contents are an ecoff_reginfo structure as seen on the host.  */
-  memcpy (location, ((char *) &s) + offset, (size_t) count);
-  return true;
+  return _bfd_generic_get_section_contents (abfd, section, location,
+                                           offset, count);
 }
 
 /* Calculate the file position for each section, and set
@@ -2369,8 +2339,7 @@ ecoff_compute_section_file_positions (abfd)
       unsigned int alignment_power;
 
       /* Only deal with sections which have contents */
-      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
-         || strcmp (current->name, REGINFO) == 0)
+      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
        continue;
 
       /* For the Alpha ECOFF .pdata section the lnnoptr field is
@@ -2460,8 +2429,6 @@ ecoff_compute_reloc_file_positions (abfd)
        current != (asection *)NULL; 
        current = current->next) 
     {
-      if (strcmp (current->name, REGINFO) == 0)
-       continue;
       if (current->reloc_count == 0)
        current->rel_filepos = 0;
       else
@@ -2490,9 +2457,7 @@ ecoff_compute_reloc_file_positions (abfd)
   return reloc_size;
 }
 
-/* Set the contents of a section.  This is where we handle setting the
-   contents of the .reginfo section, which implicitly holds a
-   ecoff_reginfo structure.  */
+/* Set the contents of a section.  */
 
 boolean
 ecoff_set_section_contents (abfd, section, location, offset, count)
@@ -2516,42 +2481,79 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
   if (count == 0)
     return true;
 
-  if (strcmp (section->name, REGINFO) == 0)
+  if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+      || bfd_write (location, 1, count, abfd) != count)
+    return false;
+
+  return true;
+}
+
+/* Get the GP value for an ECOFF file.  This is a hook used by
+   nlmconv.  */
+
+bfd_vma
+bfd_ecoff_get_gp_value (abfd)
+     bfd *abfd;
+{
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
     {
-      ecoff_data_type *tdata = ecoff_data (abfd);
-      struct ecoff_reginfo s;
-      int i;
+      bfd_set_error (bfd_error_invalid_operation);
+      return 0;
+    }
+  
+  return ecoff_data (abfd)->gp;
+}
 
-      /* If the caller is only changing part of the structure, we must
-        retrieve the current information before the memcpy.  */
-      if (offset != 0 || count != sizeof (struct ecoff_reginfo))
-       {
-         s.gp_value = tdata->gp;
-         s.gprmask = tdata->gprmask;
-         for (i = 0; i < 4; i++)
-           s.cprmask[i] = tdata->cprmask[i];
-         s.fprmask = tdata->fprmask;
-       }
+/* Set the GP value for an ECOFF file.  This is a hook used by the
+   assembler.  */
+
+boolean
+bfd_ecoff_set_gp_value (abfd, gp_value)
+     bfd *abfd;
+     bfd_vma gp_value;
+{
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
 
-      /* bfd_set_section_contents has already checked that the offset
-        and size is reasonable.  We don't have to worry about
-        swapping or any such thing; the .reginfo section is defined
-        such that the contents are an ecoff_reginfo structure as seen
-        on the host.  */
-      memcpy (((char *) &s) + offset, location, (size_t) count);
+  ecoff_data (abfd)->gp = gp_value;
 
-      tdata->gp = s.gp_value;
-      tdata->gprmask = s.gprmask;
-      for (i = 0; i < 4; i++)
-       tdata->cprmask[i] = s.cprmask[i];
-      tdata->fprmask = s.fprmask;
+  return true;
+}
 
-      return true;
+/* Set the register masks for an ECOFF file.  This is a hook used by
+   the assembler.  */
+
+boolean
+bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
+     bfd *abfd;
+     unsigned long gprmask;
+     unsigned long fprmask;
+     unsigned long *cprmask;
+{
+  ecoff_data_type *tdata;
+
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
     }
 
-  if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
-      || bfd_write (location, 1, count, abfd) != count)
-    return false;
+  tdata = ecoff_data (abfd);
+  tdata->gprmask = gprmask;
+  tdata->fprmask = fprmask;
+  if (cprmask != (unsigned long *) NULL)
+    {
+      register int i;
+
+      for (i = 0; i < 3; i++)
+       tdata->cprmask[i] = cprmask[i];
+    }
 
   return true;
 }
@@ -2681,8 +2683,6 @@ ecoff_write_object_contents (abfd)
        current != (asection *)NULL; 
        current = current->next) 
     {
-      if (strcmp (current->name, REGINFO) == 0)
-       continue;
       current->target_index = count;
       ++count;
     }
@@ -2727,12 +2727,6 @@ ecoff_write_object_contents (abfd)
       struct internal_scnhdr section;
       bfd_vma vma;
 
-      if (strcmp (current->name, REGINFO) == 0)
-       {
-         BFD_ASSERT (current->reloc_count == 0);
-         continue;
-       }
-
       ++internal_f.f_nscns;
 
       strncpy (section.s_name, current->name, sizeof section.s_name);
@@ -4150,6 +4144,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
 
       name = ssext + esym.asym.iss;
 
+      h = NULL;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, name, BSF_GLOBAL, section, value,
              (const char *) NULL, true, true,
@@ -4359,11 +4354,6 @@ ecoff_bfd_final_link (abfd, info)
 
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
-      /* Ignore any link_orders for the .reginfo section, which does
-        not really exist.  */
-      if (strcmp (o->name, REGINFO) == 0)
-       continue;
-      
       for (p = o->link_order_head;
           p != (struct bfd_link_order *) NULL;
           p = p->next)
index 276d476d54c3b62399f12fc34deb957528491e4a..5f11daf37263f412f60eb2a0f27c0e53fed5bf00 100644 (file)
@@ -412,6 +412,8 @@ SUBSUBSECTION
 static struct bfd_hash_entry *generic_link_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
           const char *));
+static boolean generic_link_read_symbols
+  PARAMS ((bfd *));
 static boolean generic_link_add_symbols
   PARAMS ((bfd *, struct bfd_link_info *, boolean collect));
 static boolean generic_link_add_object_symbols
@@ -610,6 +612,40 @@ _bfd_generic_link_hash_table_create (abfd)
     }
   return &ret->root;
 }
+
+/* Grab the symbols for an object file when doing a generic link.  We
+   store the symbols in the outsymbols field.  We need to keep them
+   around for the entire link to ensure that we only read them once.
+   If we read them multiple times, we might wind up with relocs and
+   the hash table pointing to different instances of the symbol
+   structure.  */
+
+static boolean
+generic_link_read_symbols (abfd)
+     bfd *abfd;
+{
+  if (abfd->outsymbols == (asymbol **) NULL)
+    {
+      long symsize;
+      long symcount;
+
+      symsize = bfd_get_symtab_upper_bound (abfd);
+      if (symsize < 0)
+       return false;
+      abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize);
+      if (abfd->outsymbols == NULL && symsize != 0)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+      symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols);
+      if (symcount < 0)
+       return false;
+      abfd->symcount = symcount;
+    }
+
+  return true;
+}
 \f
 /* Generic function to add symbols to from an object file to the
    global hash table.  This version does not automatically collect
@@ -676,24 +712,12 @@ generic_link_add_object_symbols (abfd, info, collect)
      struct bfd_link_info *info;
      boolean collect;
 {
-  size_t symsize;
-  asymbol **symbols;
-  bfd_size_type symbol_count;
-  boolean result;
-
-  symsize = get_symtab_upper_bound (abfd);
-  symbols = (asymbol **) malloc (symsize);
-  if (symbols == NULL && symsize != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  symbol_count = bfd_canonicalize_symtab (abfd, symbols);
-
-  result = generic_link_add_symbol_list (abfd, info, symbol_count, symbols,
-                                        collect);
-  free (symbols);
-  return result;
+  if (! generic_link_read_symbols (abfd))
+    return false;
+  return generic_link_add_symbol_list (abfd, info,
+                                      _bfd_generic_link_get_symcount (abfd),
+                                      _bfd_generic_link_get_symbols (abfd),
+                                      collect);
 }
 \f
 /* We build a hash table of all symbols defined in an archive.  */
@@ -1005,25 +1029,15 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
      boolean *pneeded;
      boolean collect;
 {
-  size_t symsize;
-  asymbol **symbols = NULL;
-  bfd_size_type symbol_count;
   asymbol **pp, **ppend;
 
   *pneeded = false;
 
-  symsize = get_symtab_upper_bound (abfd);
-  symbols = (asymbol **) malloc (symsize);
-  if (symbols == NULL && symsize != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
-
-  symbol_count = bfd_canonicalize_symtab (abfd, symbols);
+  if (! generic_link_read_symbols (abfd))
+    return false;
 
-  pp = symbols;
-  ppend = symbols + symbol_count;
+  pp = _bfd_generic_link_get_symbols (abfd);
+  ppend = pp + _bfd_generic_link_get_symcount (abfd);
   for (; pp < ppend; pp++)
     {
       asymbol *p;
@@ -1052,15 +1066,20 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
 
       if (! bfd_is_com_section (p->section))
        {
+         bfd_size_type symcount;
+         asymbol **symbols;
+
          /* This object file defines this symbol, so pull it in.  */
          if (! (*info->callbacks->add_archive_element) (info, abfd,
                                                         bfd_asymbol_name (p)))
-           goto error_return;
-         if (! generic_link_add_symbol_list (abfd, info, symbol_count,
+           return false;
+         symcount = _bfd_generic_link_get_symcount (abfd);
+         symbols = _bfd_generic_link_get_symbols (abfd);
+         if (! generic_link_add_symbol_list (abfd, info, symcount,
                                              symbols, collect))
-           goto error_return;
+           return false;
          *pneeded = true;
-         goto successful_return;
+         return true;
        }
 
       /* P is a common symbol.  */
@@ -1077,9 +1096,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
                 file.  This is for the -u option in the linker.  */
              if (! (*info->callbacks->add_archive_element)
                  (info, abfd, bfd_asymbol_name (p)))
-               goto error_return;
+               return false;
              *pneeded = true;
-             goto successful_return;
+             return true;
            }
 
          /* Turn the symbol into a common symbol but do not link in
@@ -1110,16 +1129,7 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
     }
 
   /* This archive element is not needed.  */
-
- successful_return:
-  if (symbols != NULL)
-    free (symbols);
   return true;
-
- error_return:
-  if (symbols != NULL)
-    free (symbols);
-  return false;
 }
 
 /* Add the symbols from an object file to the global hash table.  ABFD
@@ -1174,6 +1184,7 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
          else
            string = NULL;
 
+         h = NULL;
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, name, p->flags, bfd_get_section (p),
                  p->value, string, false, collect,
@@ -1202,6 +1213,11 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
                  if (bfd_is_com_section (bfd_get_section (p)))
                    p->flags |= BSF_OLD_COMMON;
                }
+
+             /* Store a back pointer from the symbol to the hash
+                table entry for the benefit of relaxation code until
+                it gets rewritten to not use asymbol structures.  */
+             p->udata = (PTR) h;
            }
        }
     }
@@ -1282,7 +1298,8 @@ static const enum link_action link_action[8][7] =
    COLLECT is true if we should automatically collect gcc constructor
      or destructor names as collect2 does.
    HASHP, if not NULL, is a place to store the created hash table
-     entry.  */
+     entry; if *HASHP is not NULL, the caller has already looked up
+     the hash table entry, and stored it in *HASHP.
 
 boolean
 _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
@@ -1323,12 +1340,20 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
   else
     row = DEF_ROW;
 
-  h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
-  if (h == (struct bfd_link_hash_entry *) NULL)
+  if (hashp != NULL && *hashp != NULL)
     {
-      if (hashp != (struct bfd_link_hash_entry **) NULL)
-       *hashp = NULL;
-      return false;
+      h = *hashp;
+      BFD_ASSERT (strcmp (h->name, name) == 0);
+    }
+  else
+    {
+      h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
+      if (h == NULL)
+       {
+         if (hashp != NULL)
+           *hashp = NULL;
+         return false;
+       }
     }
 
   if (info->notice_hash != (struct bfd_hash_table *) NULL
@@ -1576,8 +1601,7 @@ _bfd_generic_final_link (abfd, info)
   abfd->symcount = 0;
   outsymalloc = 0;
 
-  /* Build the output symbol table.  This also reads in the symbols
-     for all the input BFDs, keeping them in the outsymbols field.  */
+  /* Build the output symbol table.  */
   for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
     if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
       return false;
@@ -1609,24 +1633,30 @@ _bfd_generic_final_link (abfd, info)
                {
                  asection *input_section;
                  bfd *input_bfd;
-                 bfd_size_type relsize;
+                 long relsize;
                  arelent **relocs;
-                 bfd_size_type reloc_count;
+                 asymbol **symbols;
+                 long reloc_count;
 
                  input_section = p->u.indirect.section;
                  input_bfd = input_section->owner;
                  relsize = bfd_get_reloc_upper_bound (input_bfd,
                                                       input_section);
+                 if (relsize < 0)
+                   return false;
                  relocs = (arelent **) malloc ((size_t) relsize);
                  if (!relocs && relsize != 0)
                    {
                      bfd_set_error (bfd_error_no_memory);
                      return false;
                    }
-                 reloc_count =
-                   bfd_canonicalize_reloc (input_bfd, input_section,
-                                           relocs,
-                                           bfd_get_outsymbols (input_bfd));
+                 symbols = _bfd_generic_link_get_symbols (input_bfd);
+                 reloc_count = bfd_canonicalize_reloc (input_bfd,
+                                                       input_section,
+                                                       relocs,
+                                                       symbols);
+                 if (reloc_count < 0)
+                   return false;
                  BFD_ASSERT (reloc_count == input_section->reloc_count);
                  o->reloc_count += reloc_count;
                  free (relocs);
@@ -1722,23 +1752,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
      struct bfd_link_info *info;
      size_t *psymalloc;
 {
-  size_t symsize;
   asymbol **sym_ptr;
   asymbol **sym_end;
 
-  /* Do not clobber outsymbols if they have already been created.  */
-  if (input_bfd->outsymbols == NULL)
-    {
-      symsize = get_symtab_upper_bound (input_bfd);
-      input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize);
-      if (!input_bfd->outsymbols)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
-      input_bfd->symcount = bfd_canonicalize_symtab (input_bfd,
-                                                    input_bfd->outsymbols);
-    }
+  if (! generic_link_read_symbols (input_bfd))
+    return false;
 
   /* Create a filename symbol if we are supposed to.  */
   if (info->create_object_symbols_section != (asection *) NULL)
@@ -1772,8 +1790,8 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
 
   /* Adjust the values of the globally visible symbols, and write out
      local symbols.  */
-  sym_ptr = bfd_get_outsymbols (input_bfd);
-  sym_end = sym_ptr + bfd_get_symcount (input_bfd);
+  sym_ptr = _bfd_generic_link_get_symbols (input_bfd);
+  sym_end = sym_ptr + _bfd_generic_link_get_symcount (input_bfd);
   for (; sym_ptr < sym_end; sym_ptr++)
     {
       asymbol *sym;
@@ -2252,20 +2270,8 @@ default_indirect_link_order (output_bfd, info, output_section, link_order)
      retrieved them by this point, but we may be being called by a
      specific linker when linking different types of object files
      together.  */
-  if (bfd_get_outsymbols (input_bfd) == (asymbol **) NULL)
-    {
-      size_t symsize;
-
-      symsize = get_symtab_upper_bound (input_bfd);
-      input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize);
-      if (!input_bfd->outsymbols)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
-      input_bfd->symcount = bfd_canonicalize_symtab (input_bfd,
-                                                    input_bfd->outsymbols);
-    }
+  if (! generic_link_read_symbols (input_bfd))
+    return false;
 
   /* Get and relocate the section contents.  */
   contents = (bfd_byte *) malloc (bfd_section_size (input_bfd, input_section));
@@ -2276,7 +2282,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order)
     }
   new_contents = (bfd_get_relocated_section_contents
                  (output_bfd, info, link_order, contents, info->relocateable,
-                  bfd_get_outsymbols (input_bfd)));
+                  _bfd_generic_link_get_symbols (input_bfd)));
   if (!new_contents)
     goto error_return;