aboutsummaryrefslogtreecommitdiff
path: root/bfd/ecoff.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-08-05 10:46:57 +0930
committerAlan Modra <amodra@gmail.com>2014-08-05 10:46:57 +0930
commit13e570f80cbfb299a8858ce6830e91a6cb40ab7b (patch)
tree771ad9d8322d503019dff64816234bd09566e21c /bfd/ecoff.c
parent241fd515ad94fa11d4608d4fe8108c382792d3be (diff)
downloadgdb-13e570f80cbfb299a8858ce6830e91a6cb40ab7b.zip
gdb-13e570f80cbfb299a8858ce6830e91a6cb40ab7b.tar.gz
gdb-13e570f80cbfb299a8858ce6830e91a6cb40ab7b.tar.bz2
Fix LTO vs. COFF archives
Avoid scan of symbols on objects in coff archives since we don't need to do anything special with common symbols. The scan is quite useless, and breaks LTO due to slim LTO objects not having symbols available until after the plugin has claimed them. Instead we can add objects based on their archive symbol map. Also, rip out the archive symbol hash table used by the generic linker. Using a hash breaks one feature of unix archive linking; The first object file in an archive defining any given symbol should be the object extracted to satisfy that symbol. What's more a hash isn't much faster except in pathological cases where object file ordering causes many scans of the archive. See the comment which I'm removing from elf_link_add_archive_symbols. Finally, tidy elflink.c archive handling a little. PR 13557 * linker.c (struct archive_list, struct archive_hash_entry, struct archive_hash_table, archive_hash_newfunc, archive_hash_table_init, archive_hash_lookup, archive_hash_allocate, archive_hash_table_free): Delete. (_bfd_generic_link_add_archive_symbols): Add h and name params to checkfn. Rewrite using a straight-forward scan over archive map. (generic_link_check_archive_element_no_collect, generic_link_check_archive_element_collect, generic_link_check_archive_element): Add h and name params. * aoutx.h (aout_link_check_archive_element): Likewise. * pdp11.c (aout_link_check_archive_element): Likewise. * xcofflink.c (xcoff_link_check_archive_element): Likewise. * cofflink.c (coff_link_check_archive_element): Likewise. Don't scan symbols, simply add archive element whenever h is undefined. (coff_link_check_ar_symbols): Delete. * ecoff.c (read_ext_syms_and_strs): Delete. (reread_ext_syms_and_strs): Delete. (ecoff_link_check_archive_element): Add h and name param. Don't scan symbols, simply add based on h. Use ecoff_link_add_object_symbols. * elflink.c (elf_link_is_defined_archive_symbol): Don't test archive_pass. (elf_link_add_archive_symbols): Delete "defined" array, merge functionality into "included". Make "included" a char array. Don't set or test archive_pass. * libbfd-in.h (_bfd_generic_link_add_archive_symbols): Update. * libbfd.h: Regenerate.
Diffstat (limited to 'bfd/ecoff.c')
-rw-r--r--bfd/ecoff.c164
1 files changed, 11 insertions, 153 deletions
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index cf38e3e..6a9d206 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -3497,171 +3497,29 @@ ecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
return FALSE;
}
-/* Factored out from ecoff_link_check_archive_element. */
-
-static bfd_boolean
-read_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size,
- bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd,
- const struct ecoff_backend_data * const backend)
-{
- if (! ecoff_slurp_symbolic_header (abfd))
- return FALSE;
-
- /* If there are no symbols, we don't want it. */
- if (bfd_get_symcount (abfd) == 0)
- return TRUE;
-
- *symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
-
- *external_ext_size = backend->debug_swap.external_ext_size;
- *esize = (*symhdr)->iextMax * *external_ext_size;
- *external_ext = bfd_malloc (*esize);
- if (*external_ext == NULL && *esize != 0)
- return FALSE;
-
- if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbExtOffset, SEEK_SET) != 0
- || bfd_bread (*external_ext, *esize, abfd) != *esize)
- return FALSE;
-
- *ssext = (char *) bfd_malloc ((bfd_size_type) (*symhdr)->issExtMax);
- if (*ssext == NULL && (*symhdr)->issExtMax != 0)
- return FALSE;
-
- if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbSsExtOffset, SEEK_SET) != 0
- || (bfd_bread (*ssext, (bfd_size_type) (*symhdr)->issExtMax, abfd)
- != (bfd_size_type) (*symhdr)->issExtMax))
- return FALSE;
- return TRUE;
-}
-
-static bfd_boolean
-reread_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size,
- bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd,
- const struct ecoff_backend_data * const backend)
-{
- if (*external_ext != NULL)
- free (*external_ext);
- *external_ext = NULL;
- if (*ssext != NULL)
- free (*ssext);
- *ssext = NULL;
- return read_ext_syms_and_strs (symhdr, external_ext_size, esize,
- external_ext, ssext, abfd, backend);
-}
-
/* This is called if we used _bfd_generic_link_add_archive_symbols
because we were not dealing with an ECOFF archive. */
static bfd_boolean
ecoff_link_check_archive_element (bfd *abfd,
struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
+ const char *name,
bfd_boolean *pneeded)
{
- const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- void (* const swap_ext_in) (bfd *, void *, EXTR *)
- = backend->debug_swap.swap_ext_in;
- HDRR *symhdr;
- bfd_size_type external_ext_size = 0;
- void * external_ext = NULL;
- bfd_size_type esize = 0;
- char *ssext = NULL;
- char *ext_ptr;
- char *ext_end;
-
*pneeded = FALSE;
- /* Read in the external symbols and external strings. */
- if (!read_ext_syms_and_strs (&symhdr, &external_ext_size, &esize,
- &external_ext, &ssext, abfd, backend))
- goto error_return;
-
- /* If there are no symbols, we don't want it. */
- if (bfd_get_symcount (abfd) == 0)
- goto successful_return;
-
- /* Look through the external symbols to see if they define some
- symbol that is currently undefined. */
- ext_ptr = (char *) external_ext;
- ext_end = ext_ptr + esize;
- for (; ext_ptr < ext_end; ext_ptr += external_ext_size)
- {
- EXTR esym;
- bfd_boolean def;
- const char *name;
- bfd *oldbfd;
- struct bfd_link_hash_entry *h;
-
- (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
-
- /* See if this symbol defines something. */
- if (esym.asym.st != stGlobal
- && esym.asym.st != stLabel
- && esym.asym.st != stProc)
- continue;
-
- switch (esym.asym.sc)
- {
- case scText:
- case scData:
- case scBss:
- case scAbs:
- case scSData:
- case scSBss:
- case scRData:
- case scCommon:
- case scSCommon:
- case scInit:
- case scFini:
- case scRConst:
- def = TRUE;
- break;
- default:
- def = FALSE;
- break;
- }
-
- if (! def)
- continue;
-
- name = ssext + esym.asym.iss;
- h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
-
- /* Unlike the generic linker, we do not pull in elements because
- of common symbols. */
- if (h == NULL
- || h->type != bfd_link_hash_undefined)
- continue;
-
- /* Include this element. */
- oldbfd = abfd;
- if (!(*info->callbacks
- ->add_archive_element) (info, abfd, name, &abfd))
- goto error_return;
- /* Potentially, the add_archive_element hook may have set a
- substitute BFD for us. */
- if (abfd != oldbfd
- && !reread_ext_syms_and_strs (&symhdr, &external_ext_size, &esize,
- &external_ext, &ssext, abfd, backend))
- goto error_return;
- if (! ecoff_link_add_externals (abfd, info, external_ext, ssext))
- goto error_return;
+ /* Unlike the generic linker, we do not pull in elements because
+ of common symbols. */
+ if (h->type != bfd_link_hash_undefined)
+ return TRUE;
- *pneeded = TRUE;
- goto successful_return;
- }
+ /* Include this element. */
+ if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd))
+ return FALSE;
+ *pneeded = TRUE;
- successful_return:
- if (external_ext != NULL)
- free (external_ext);
- if (ssext != NULL)
- free (ssext);
- return TRUE;
- error_return:
- if (external_ext != NULL)
- free (external_ext);
- if (ssext != NULL)
- free (ssext);
- return FALSE;
+ return ecoff_link_add_object_symbols (abfd, info);
}
/* Add the symbols from an archive file to the global hash table.