PR ld/12365

PR ld/12696
include/
	* bfdlink.h (ENUM_BITFIELD): Define.
	(struct bfd_link_hash_entry): Make "type" a bitfield.  Add "non_ir_ref".
	(struct bfd_link_callbacks <notice>): Pass bfd_link_hash_entry pointer
	rather than "name".
bfd/
	* coff-aux.c (coff_m68k_aux_link_add_one_symbol): Update "notice" call.
	* linker.c (_bfd_link_hash_newfunc): Clear bitfields.
	(_bfd_generic_link_add_one_symbol): Update "notice" call.
	* elflink.c (_bfd_elf_merge_symbol): Don't skip weak redefs when
	it is a redef of an IR symbol in a real BFD.
ld/
	* ldmain.c (notice): Delete "name" param, add "h".
	* plugin.c (plugin_notice): Likewise.  Set non_ir_ref.  Handle
	redefinitions of IR symbols in real BFDs.
	(plugin_multiple_definition, plugin_multiple_common): Delete.
	(non_ironly_hash, init_non_ironly_hash): Delete.
	(is_visible_from_outside): Traverse entry_symbol chain.
	(get_symbols): Use non_ir_ref flag rather than hash lookup.
This commit is contained in:
Alan Modra
2011-04-24 10:02:14 +00:00
parent 90556b8c94
commit 35ed3f940b
9 changed files with 95 additions and 128 deletions

View File

@@ -1,3 +1,13 @@
2011-04-24 Alan Modra <amodra@gmail.com>
PR ld/12365
PR ld/12696
* coff-aux.c (coff_m68k_aux_link_add_one_symbol): Update "notice" call.
* linker.c (_bfd_link_hash_newfunc): Clear bitfields.
(_bfd_generic_link_add_one_symbol): Update "notice" call.
* elflink.c (_bfd_elf_merge_symbol): Don't skip weak redefs when
it is a redef of an IR symbol in a real BFD.
2011-04-22 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_readonly_dynrelocs): Warn relocation

View File

@@ -1,5 +1,5 @@
/* BFD back-end for Apple M68K COFF A/UX 3.x files.
Copyright 1996, 1997, 2000, 2002, 2005, 2007, 2008
Copyright 1996, 1997, 2000, 2002, 2005, 2007, 2008, 2011
Free Software Foundation, Inc.
Written by Richard Henderson <rth@tamu.edu>.
@@ -105,7 +105,7 @@ coff_m68k_aux_link_add_one_symbol (info, abfd, name, flags, section, value,
&& (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
!= (struct bfd_hash_entry *) NULL))
{
if (! (*info->callbacks->notice) (info, name, abfd, section, value))
if (! (*info->callbacks->notice) (info, h, abfd, section, value))
return FALSE;
}

View File

@@ -1427,7 +1427,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
/* Skip weak definitions of symbols that are already defined. */
if (newdef && olddef && newweak)
{
*skip = TRUE;
/* Don't skip new non-IR weak syms. */
if (!((oldbfd->flags & BFD_PLUGIN) != 0
&& (abfd->flags & BFD_PLUGIN) == 0))
*skip = TRUE;
/* Merge st_other. If the symbol already has a dynamic index,
but visibility says it should not be visible, turn it into a

View File

@@ -465,10 +465,8 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry;
/* Initialize the local fields. */
h->type = bfd_link_hash_new;
memset (&h->u.undef.next, 0,
(sizeof (struct bfd_link_hash_entry)
- offsetof (struct bfd_link_hash_entry, u.undef.next)));
memset ((char *) &h->root + sizeof (h->root), 0,
sizeof (*h) - sizeof (h->root));
}
return entry;
@@ -1609,8 +1607,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
{
if (! (*info->callbacks->notice) (info, h->root.string, abfd, section,
value))
if (! (*info->callbacks->notice) (info, h, abfd, section, value))
return FALSE;
}

View File

@@ -1,3 +1,12 @@
2011-04-24 Alan Modra <amodra@gmail.com>
PR ld/12365
PR ld/12696
* bfdlink.h (ENUM_BITFIELD): Define.
(struct bfd_link_hash_entry): Make "type" a bitfield. Add "non_ir_ref".
(struct bfd_link_callbacks <notice>): Pass bfd_link_hash_entry pointer
rather than "name".
2011-04-20 Alan Modra <amodra@gmail.com>
PR ld/12365

View File

@@ -24,6 +24,12 @@
#ifndef BFDLINK_H
#define BFDLINK_H
#if (__GNUC__ * 1000 + __GNUC_MINOR__ > 2000)
#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
#else
#define ENUM_BITFIELD(TYPE) unsigned int
#endif
/* Which symbols to strip during a link. */
enum bfd_link_strip
{
@@ -91,7 +97,9 @@ struct bfd_link_hash_entry
struct bfd_hash_entry root;
/* Type of this entry. */
enum bfd_link_hash_type type;
ENUM_BITFIELD (bfd_link_hash_type) type : 8;
unsigned int non_ir_ref : 1;
/* A union of information depending upon the type. */
union
@@ -570,11 +578,11 @@ struct bfd_link_callbacks
(struct bfd_link_info *, const char *name,
bfd *abfd, asection *section, bfd_vma address);
/* A function which is called when a symbol in notice_hash is
defined or referenced. NAME is the symbol. ABFD, SECTION and
ADDRESS are the value of the symbol. If SECTION is
defined or referenced. H is the symbol. ABFD, SECTION and
ADDRESS are the (new) value of the symbol. If SECTION is
bfd_und_section, this is a reference. */
bfd_boolean (*notice)
(struct bfd_link_info *, const char *name,
(struct bfd_link_info *, struct bfd_link_hash_entry *h,
bfd *abfd, asection *section, bfd_vma address);
/* Error or warning link info message. */
void (*einfo)

View File

@@ -1,3 +1,15 @@
2011-04-24 Alan Modra <amodra@gmail.com>
PR ld/12365
PR ld/12696
* ldmain.c (notice): Delete "name" param, add "h".
* plugin.c (plugin_notice): Likewise. Set non_ir_ref. Handle
redefinitions of IR symbols in real BFDs.
(plugin_multiple_definition, plugin_multiple_common): Delete.
(non_ironly_hash, init_non_ironly_hash): Delete.
(is_visible_from_outside): Traverse entry_symbol chain.
(get_symbols): Use non_ir_ref flag rather than hash lookup.
2011-04-21 Tristan Gingold <gingold@adacore.com>
* scripttempl/alphavms.sc: Add dwarf2 embedding marks.

View File

@@ -150,7 +150,8 @@ static bfd_boolean reloc_dangerous
static bfd_boolean unattached_reloc
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
static bfd_boolean notice
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma);
static struct bfd_link_callbacks link_callbacks =
{
@@ -1479,18 +1480,21 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
static bfd_boolean
notice (struct bfd_link_info *info,
const char *name,
struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
bfd_vma value)
{
if (name == NULL)
const char *name;
if (h == NULL)
{
if (command_line.cref || nocrossref_list != NULL)
return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value);
return TRUE;
}
name = h->root.string;
if (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
{

View File

@@ -90,13 +90,6 @@ static plugin_t *called_plugin = NULL;
/* Last plugin to cause an error, if any. */
static const char *error_plugin = NULL;
/* A hash table that records symbols referenced by non-IR files. Used
at get_symbols time to determine whether any prevailing defs from
IR files are referenced only from other IR files, so tthat we can
we can distinguish the LDPR_PREVAILING_DEF and LDPR_PREVAILING_DEF_IRONLY
cases when establishing symbol resolutions. */
static struct bfd_hash_table *non_ironly_hash = NULL;
/* State of linker "notice" interface before we poked at it. */
static bfd_boolean orig_notice_all;
@@ -133,18 +126,8 @@ static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
/* Forward references. */
static bfd_boolean plugin_notice (struct bfd_link_info *info,
const char *name, bfd *abfd,
struct bfd_link_hash_entry *h, bfd *abfd,
asection *section, bfd_vma value);
static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
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)
@@ -438,6 +421,8 @@ static inline bfd_boolean
is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
struct bfd_link_hash_entry *blhe)
{
struct bfd_sym_chain *sym;
/* Section's owner may be NULL if it is the absolute
section, fortunately is_ir_dummy_bfd handles that. */
if (!is_ir_dummy_bfd (section->owner))
@@ -466,6 +451,12 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
return (lsym->visibility == LDPV_DEFAULT
|| lsym->visibility == LDPV_PROTECTED);
}
for (sym = &entry_symbol; sym != NULL; sym = sym->next)
if (sym->name
&& strcmp (sym->name, blhe->root.string) == 0)
return TRUE;
return FALSE;
}
@@ -520,9 +511,8 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
even potentially-referenced, perhaps in a future final link if
this is a partial one, perhaps dynamically at load-time if the
symbol is externally visible. */
ironly = (!is_visible_from_outside (&syms[n], owner_sec, blhe)
&& !bfd_hash_lookup (non_ironly_hash, syms[n].name,
FALSE, FALSE));
ironly = !(blhe->non_ir_ref
|| is_visible_from_outside (&syms[n], owner_sec, blhe));
/* If it was originally undefined or common, then it has been
resolved; determine how. */
@@ -740,27 +730,6 @@ plugin_active_plugins_p (void)
return plugins_list != NULL;
}
/* Init the non_ironly hash table. */
static void
init_non_ironly_hash (void)
{
struct bfd_sym_chain *sym;
non_ironly_hash
= (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init_n (non_ironly_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
for (sym = &entry_symbol; sym != NULL; sym = sym->next)
if (sym->name
&& !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
einfo (_("%P%X: hash table failure adding symbol %s\n"),
sym->name);
}
/* Load up and initialise all plugins after argument parsing. */
int
plugin_load_plugins (void)
@@ -814,7 +783,6 @@ plugin_load_plugins (void)
plugin_callbacks.notice = &plugin_notice;
link_info.notice_all = TRUE;
link_info.callbacks = &plugin_callbacks;
init_non_ironly_hash ();
return 0;
}
@@ -888,9 +856,6 @@ plugin_call_all_symbols_read (void)
/* Disable any further file-claiming. */
no_more_claiming = TRUE;
plugin_callbacks.multiple_definition = &plugin_multiple_definition;
plugin_callbacks.multiple_common = &plugin_multiple_common;
while (curplug)
{
if (curplug->all_symbols_read_handler)
@@ -934,88 +899,47 @@ plugin_call_cleanup (void)
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
the linker adds them to the linker hash table. If we see a symbol
being referenced from a non-IR file, we add it to the non_ironly hash
table. If we can't find it there at get_symbols time, we know that
it was referenced only by IR files. We have to notice_all symbols,
because we won't necessarily know until later which ones will be
contributed by IR files. */
the linker adds them to the linker hash table. Mark those
referenced from a non-IR file with non_ir_ref. We have to
notice_all symbols, because we won't necessarily know until later
which ones will be contributed by IR files. */
static bfd_boolean
plugin_notice (struct bfd_link_info *info,
const char *name,
struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
bfd_vma value)
{
if (name != NULL)
if (h != NULL)
{
/* No further processing if this def/ref is from an IR dummy BFD. */
if (is_ir_dummy_bfd (abfd))
return TRUE;
/* We only care about refs, not defs, indicated by section
pointing to the undefined section (according to the bfd
linker notice callback interface definition). */
/* If this is a ref, set non_ir_ref. */
if (bfd_is_und_section (section))
{
/* This is a ref from a non-IR file, so note the ref'd
symbol in the non-IR-only hash. */
if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
abfd->filename, name);
}
h->non_ir_ref = TRUE;
/* Otherwise, it must be a new def. Ensure any symbol defined
in an IR dummy BFD takes on a new value from a real BFD.
Weak symbols are not normally overridden by a new weak
definition, and strong symbols will normally cause multiple
definition errors. Avoid this by making the symbol appear
to be undefined. */
else if (((h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_defined)
&& is_ir_dummy_bfd (h->u.def.section->owner))
|| (h->type == bfd_link_hash_common
&& is_ir_dummy_bfd (h->u.c.p->section->owner)))
h->type = bfd_link_hash_undefweak;
}
/* Continue with cref/nocrossref/trace-sym processing. */
if (name == NULL
if (h == NULL
|| orig_notice_all
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
return (*orig_callbacks->notice) (info, name, abfd, section, value);
&& bfd_hash_lookup (info->notice_hash, h->root.string,
FALSE, FALSE) != NULL))
return (*orig_callbacks->notice) (info, h, abfd, section, value);
return TRUE;
}
/* When we add new object files to the link at all symbols read time,
these contain the real code and symbols generated from the IR files,
and so duplicate all the definitions already supplied by the dummy
IR-only BFDs that we created at claim files time. We use the linker's
multiple-definitions callback hook to fix up the clash, discarding
the symbol from the IR-only BFD in favour of the symbol from the
real BFD. We return true if this was not-really-a-clash because
we've fixed it up, or anyway if --allow-multiple-definition was in
effect (before we disabled it to ensure we got called back). */
static bfd_boolean
plugin_multiple_definition (struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
bfd *nbfd, asection *nsec, bfd_vma nval)
{
if (h->type == bfd_link_hash_defined
&& is_ir_dummy_bfd (h->u.def.section->owner))
{
/* Replace it with new details. */
h->u.def.section = nsec;
h->u.def.value = nval;
return TRUE;
}
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);
}