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.
This commit is contained in:
Alan Modra 2011-04-20 00:22:08 +00:00
parent 24f58f47de
commit 02d002477b
9 changed files with 138 additions and 62 deletions

View File

@ -1,3 +1,13 @@
2011-04-20 Alan Modra <amodra@gmail.com>
PR ld/12365
* 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.
2011-04-20 Alan Modra <amodra@gmail.com>
PR ld/12365

View File

@ -1,6 +1,6 @@
/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
@ -1282,6 +1282,20 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
else if (isym->st_shndx == SHN_COMMON)
{
sym->symbol.section = bfd_com_section_ptr;
if ((abfd->flags & BFD_PLUGIN) != 0)
{
asection *xc = bfd_get_section_by_name (abfd, "COMMON");
if (xc == NULL)
{
flagword flags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
| SEC_EXCLUDE);
xc = bfd_make_section_with_flags (abfd, "COMMON", flags);
if (xc == NULL)
goto error_return;
}
sym->symbol.section = xc;
}
/* Elf puts the alignment into the `value' field, and
the size into the `size' field. BFD wants to see the
size in the value field, and doesn't care (at the

View File

@ -3937,18 +3937,31 @@ error_free_dyn:
goto error_free_vers;
if (isym->st_shndx == SHN_COMMON
&& ELF_ST_TYPE (isym->st_info) == STT_TLS
&& !info->relocatable)
&& (abfd->flags & BFD_PLUGIN) != 0)
{
asection *xc = bfd_get_section_by_name (abfd, "COMMON");
if (xc == NULL)
{
flagword sflags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
| SEC_EXCLUDE);
xc = bfd_make_section_with_flags (abfd, "COMMON", sflags);
if (xc == NULL)
goto error_free_vers;
}
sec = xc;
}
else if (isym->st_shndx == SHN_COMMON
&& ELF_ST_TYPE (isym->st_info) == STT_TLS
&& !info->relocatable)
{
asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
if (tcomm == NULL)
{
tcomm = bfd_make_section_with_flags (abfd, ".tcommon",
(SEC_ALLOC
| SEC_IS_COMMON
| SEC_LINKER_CREATED
| SEC_THREAD_LOCAL));
flagword sflags = (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_IS_COMMON
| SEC_LINKER_CREATED);
tcomm = bfd_make_section_with_flags (abfd, ".tcommon", sflags);
if (tcomm == NULL)
goto error_free_vers;
}

View File

@ -1296,7 +1296,7 @@ generic_link_check_archive_element (bfd *abfd,
else
h->u.c.p->section = bfd_make_section_old_way (symbfd,
p->section->name);
h->u.c.p->section->flags = SEC_ALLOC;
h->u.c.p->section->flags |= SEC_ALLOC;
}
else
{
@ -1756,13 +1756,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
if (section == bfd_com_section_ptr)
{
h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
h->u.c.p->section->flags = SEC_ALLOC;
h->u.c.p->section->flags |= SEC_ALLOC;
}
else if (section->owner != abfd)
{
h->u.c.p->section = bfd_make_section_old_way (abfd,
section->name);
h->u.c.p->section->flags = SEC_ALLOC;
h->u.c.p->section->flags |= SEC_ALLOC;
}
else
h->u.c.p->section = section;
@ -1803,13 +1803,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
{
h->u.c.p->section
= bfd_make_section_old_way (abfd, "COMMON");
h->u.c.p->section->flags = SEC_ALLOC;
h->u.c.p->section->flags |= SEC_ALLOC;
}
else if (section->owner != abfd)
{
h->u.c.p->section
= bfd_make_section_old_way (abfd, section->name);
h->u.c.p->section->flags = SEC_ALLOC;
h->u.c.p->section->flags |= SEC_ALLOC;
}
else
h->u.c.p->section = section;

View File

@ -1,3 +1,17 @@
2011-04-20 Alan Modra <amodra@gmail.com>
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 <amodra@gmail.com>
PR ld/12365

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);