From 02d002477b60cff9f0f5abbd5fc27e2889b13421 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 20 Apr 2011 00:22:08 +0000 Subject: PR ld/12365 bfd/ * elfcode.h (elf_slurp_symbol_table): Put common plugin IR symbols in their own common section. * elflink.c (elf_link_add_object_symbols): Likewise. * linker.c (generic_link_check_archive_element): Don't lose flags if common section is pre-existing. (_bfd_generic_link_add_one_symbol): Likewise. ld/ * ldfile.c (ldfile_try_open_bfd): Move code creating and switching to plugin IR BFD.. * ldmain.c (add_archive_element): ..and similar code here.. * plugin.c (plugin_maybe_claim): ..to here. New function. (plugin_call_claim_file): Make static. (asymbol_from_plugin_symbol): Set ELF st_shndx for common syms. (plugin_multiple_common): New function. (plugin_call_all_symbols_read): Hook in plugin_multiple_common. * plugin.h (plugin_call_claim_file): Don't declare. (plugin_maybe_claim): Declare. --- ld/ChangeLog | 14 +++++++++++++ ld/ldfile.c | 28 +++---------------------- ld/ldmain.c | 23 +++----------------- ld/plugin.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- ld/plugin.h | 4 ++-- 5 files changed, 88 insertions(+), 49 deletions(-) (limited to 'ld') diff --git a/ld/ChangeLog b/ld/ChangeLog index ab16c69..31acf59 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,6 +1,20 @@ 2011-04-20 Alan Modra PR ld/12365 + * ldfile.c (ldfile_try_open_bfd): Move code creating and switching + to plugin IR BFD.. + * ldmain.c (add_archive_element): ..and similar code here.. + * plugin.c (plugin_maybe_claim): ..to here. New function. + (plugin_call_claim_file): Make static. + (asymbol_from_plugin_symbol): Set ELF st_shndx for common syms. + (plugin_multiple_common): New function. + (plugin_call_all_symbols_read): Hook in plugin_multiple_common. + * plugin.h (plugin_call_claim_file): Don't declare. + (plugin_maybe_claim): Declare. + +2011-04-20 Alan Modra + + PR ld/12365 * ldmain.c (multiple_definition): Take a bfd_link_hash_entry pointer arg rather than "name", "obfd", "osec", "oval". Add code removed from linker.c. Hack around xcofflink.c oddity in diff --git a/ld/ldfile.c b/ld/ldfile.c index 96a3856..c4b8912 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -1,6 +1,7 @@ /* Linker file opening and searching. Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -320,35 +321,12 @@ success: if (fd >= 0) { struct ld_plugin_input_file file; - int claimed = 0; file.name = attempt; file.offset = 0; file.filesize = lseek (fd, 0, SEEK_END); file.fd = fd; - /* We create a dummy BFD, initially empty, to house - whatever symbols the plugin may want to add. */ - file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd); - if (plugin_call_claim_file (&file, &claimed)) - einfo (_("%P%F: %s: plugin reported error claiming file\n"), - plugin_error_plugin ()); - /* fd belongs to us, not the plugin; but we don't need it. */ - close (fd); - if (claimed) - { - /* Discard the real file's BFD and substitute the dummy one. */ - bfd_close (entry->the_bfd); - entry->the_bfd = file.handle; - entry->claimed = TRUE; - bfd_make_readable (entry->the_bfd); - } - else - { - /* If plugin didn't claim the file, we don't need the dummy - bfd. Can't avoid speculatively creating it, alas. */ - bfd_close_all_done (file.handle); - entry->claimed = FALSE; - } + plugin_maybe_claim (&file, entry); } } #endif /* ENABLE_PLUGINS */ diff --git a/ld/ldmain.c b/ld/ldmain.c index b7e725b..0de7890 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -813,7 +813,7 @@ add_archive_element (struct bfd_link_info *info, if (fd >= 0) { struct ld_plugin_input_file file; - int claimed = 0; + /* Offset and filesize must refer to the individual archive member, not the whole file, and must exclude the header. Fortunately for us, that is how the data is stored in the @@ -822,29 +822,12 @@ add_archive_element (struct bfd_link_info *info, file.offset = abfd->origin; file.filesize = arelt_size (abfd); file.fd = fd; - /* We create a dummy BFD, initially empty, to house - whatever symbols the plugin may want to add. */ - file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd); - if (plugin_call_claim_file (&file, &claimed)) - einfo (_("%P%F: %s: plugin reported error claiming file\n"), - plugin_error_plugin ()); - /* fd belongs to us, not the plugin; but we don't need it. */ - close (fd); - if (claimed) + plugin_maybe_claim (&file, input); + if (input->claimed) { - /* Substitute the dummy BFD. */ - input->the_bfd = file.handle; - input->claimed = TRUE; input->claim_archive = TRUE; - bfd_make_readable (input->the_bfd); *subsbfd = input->the_bfd; } - else - { - /* Abandon the dummy BFD. */ - bfd_close_all_done (file.handle); - input->claimed = FALSE; - } } } #endif /* ENABLE_PLUGINS */ diff --git a/ld/plugin.c b/ld/plugin.c index b363bc1..f45064e 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -140,6 +140,11 @@ static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info, bfd *nbfd, asection *nsec, bfd_vma nval); +static bfd_boolean plugin_multiple_common (struct bfd_link_info *info, + struct bfd_link_hash_entry *h, + bfd *nbfd, + enum bfd_link_hash_type ntype, + bfd_vma nsize); #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) @@ -312,7 +317,10 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, asym->value = ldsym->size; /* For ELF targets, set alignment of common symbol to 1. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; + { + ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; + ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; + } break; default: @@ -812,7 +820,7 @@ plugin_load_plugins (void) } /* Call 'claim file' hook for all plugins. */ -int +static int plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) { plugin_t *curplug = plugins_list; @@ -835,6 +843,42 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) return plugin_error_p () ? -1 : 0; } +void +plugin_maybe_claim (struct ld_plugin_input_file *file, + lang_input_statement_type *entry) +{ + int claimed = 0; + + /* We create a dummy BFD, initially empty, to house whatever symbols + the plugin may want to add. */ + file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename, + entry->the_bfd); + if (plugin_call_claim_file (file, &claimed)) + einfo (_("%P%F: %s: plugin reported error claiming file\n"), + plugin_error_plugin ()); + /* fd belongs to us, not the plugin; but we don't need it. */ + close (file->fd); + if (claimed) + { + /* Discard the real file's BFD and substitute the dummy one. */ + + /* BFD archive handling caches elements so we can't call + bfd_close for archives. */ + if (entry->the_bfd->my_archive == NULL) + bfd_close (entry->the_bfd); + entry->the_bfd = file->handle; + entry->claimed = TRUE; + bfd_make_readable (entry->the_bfd); + } + else + { + /* If plugin didn't claim the file, we don't need the dummy bfd. + Can't avoid speculatively creating it, alas. */ + bfd_close_all_done (file->handle); + entry->claimed = FALSE; + } +} + /* Call 'all symbols read' hook for all plugins. */ int plugin_call_all_symbols_read (void) @@ -845,6 +889,7 @@ plugin_call_all_symbols_read (void) no_more_claiming = TRUE; plugin_callbacks.multiple_definition = &plugin_multiple_definition; + plugin_callbacks.multiple_common = &plugin_multiple_common; while (curplug) { @@ -955,3 +1000,22 @@ plugin_multiple_definition (struct bfd_link_info *info, return (*orig_callbacks->multiple_definition) (info, h, nbfd, nsec, nval); } + +static bfd_boolean +plugin_multiple_common (struct bfd_link_info *info, + struct bfd_link_hash_entry *h, + bfd *nbfd, enum bfd_link_hash_type ntype, bfd_vma nsize) +{ + if (h->type == bfd_link_hash_common + && is_ir_dummy_bfd (h->u.c.p->section->owner) + && ntype == bfd_link_hash_common + && !is_ir_dummy_bfd (nbfd)) + { + /* Arrange to have it replaced. */ + ASSERT (nsize != 0); + h->u.c.size = 0; + return TRUE; + } + + return (*orig_callbacks->multiple_common) (info, h, nbfd, ntype, nsize); +} diff --git a/ld/plugin.h b/ld/plugin.h index 7b39e72..ee29b7c 100644 --- a/ld/plugin.h +++ b/ld/plugin.h @@ -50,8 +50,8 @@ extern int plugin_load_plugins (void); extern const char *plugin_error_plugin (void); /* Call 'claim file' hook for all plugins. */ -extern int plugin_call_claim_file (const struct ld_plugin_input_file *file, - int *claimed); +extern void plugin_maybe_claim (struct ld_plugin_input_file *, + lang_input_statement_type *); /* Call 'all symbols read' hook for all plugins. */ extern int plugin_call_all_symbols_read (void); -- cgit v1.1