aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2011-04-20 00:11:33 +0000
committerAlan Modra <amodra@gmail.com>2011-04-20 00:11:33 +0000
commit24f58f47de96a6c061fc6eeb37a699c03dde970a (patch)
tree6d218f4096841f46c906ecab5f7090df8723161e /ld
parent43a8278ee9e14776343b7b3692650b130c301363 (diff)
downloadfsf-binutils-gdb-24f58f47de96a6c061fc6eeb37a699c03dde970a.zip
fsf-binutils-gdb-24f58f47de96a6c061fc6eeb37a699c03dde970a.tar.gz
fsf-binutils-gdb-24f58f47de96a6c061fc6eeb37a699c03dde970a.tar.bz2
PR ld/12365
include/ * bfdlink.h (struct bfd_link_callbacks): Modify multiple_definition and multiple_common parameters to pass in a bfd_link_hash_entry pointer rather than name,bfd etc. found in the hash entry. bfd/ * elflink.c (_bfd_elf_merge_symbol): Update multiple_common calls. * linker.c (_bfd_generic_link_add_one_symbol): Likewise. Call multiple_definition regardless of allow_multiple_definition. * simple.c (simple_dummy_multiple_definition): Update. * xcofflink.c (xcoff_link_add_symbols): Update multiple_definition calls. ld/ * 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 passing NULL nbfd. (multiple_common): Similarly. * plugin.c (orig_allow_multiple_defs): Delete. (plugin_call_all_symbols_read): Don't twiddle allow_multiple_definition. (plugin_multiple_definition): Update.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog12
-rw-r--r--ld/ldmain.c87
-rw-r--r--ld/plugin.c39
3 files changed, 96 insertions, 42 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 26164a9..ab16c69 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,15 @@
+2011-04-20 Alan Modra <amodra@gmail.com>
+
+ 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
+ passing NULL nbfd.
+ (multiple_common): Similarly.
+ * plugin.c (orig_allow_multiple_defs): Delete.
+ (plugin_call_all_symbols_read): Don't twiddle allow_multiple_definition.
+ (plugin_multiple_definition): Update.
+
2011-04-18 Kai Tietz <ktietz@redhat.com>
* deffilep.y (def_aligncomm): Avoid duplets.
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 52a4b04..b7e725b 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -123,11 +123,11 @@ static char *get_emulation
static bfd_boolean add_archive_element
(struct bfd_link_info *, bfd *, const char *, bfd **);
static bfd_boolean multiple_definition
- (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma);
static bfd_boolean multiple_common
- (struct bfd_link_info *, const char *, bfd *, enum bfd_link_hash_type,
- bfd_vma, bfd *, enum bfd_link_hash_type, bfd_vma);
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd *, enum bfd_link_hash_type, bfd_vma);
static bfd_boolean add_to_set
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
@@ -937,15 +937,44 @@ add_archive_element (struct bfd_link_info *info,
multiple times. */
static bfd_boolean
-multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name,
- bfd *obfd,
- asection *osec,
- bfd_vma oval,
+multiple_definition (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
asection *nsec,
bfd_vma nval)
{
+ const char *name;
+ bfd *obfd;
+ asection *osec;
+ bfd_vma oval;
+
+ if (info->allow_multiple_definition)
+ return TRUE;
+
+ switch (h->type)
+ {
+ case bfd_link_hash_defined:
+ osec = h->u.def.section;
+ oval = h->u.def.value;
+ obfd = h->u.def.section->owner;
+ break;
+ case bfd_link_hash_indirect:
+ osec = bfd_ind_section_ptr;
+ oval = 0;
+ obfd = NULL;
+ break;
+ default:
+ abort ();
+ }
+
+ /* Ignore a redefinition of an absolute symbol to the
+ same value; it's harmless. */
+ if (h->type == bfd_link_hash_defined
+ && bfd_is_abs_section (osec)
+ && bfd_is_abs_section (nsec)
+ && nval == oval)
+ return TRUE;
+
/* If either section has the output_section field set to
bfd_abs_section_ptr, it means that the section is being
discarded, and this is not really a multiple definition at all.
@@ -959,6 +988,14 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
&& bfd_is_abs_section (nsec->output_section)))
return TRUE;
+ name = h->root.string;
+ if (nbfd == NULL)
+ {
+ nbfd = obfd;
+ nsec = osec;
+ nval = oval;
+ obfd = NULL;
+ }
einfo (_("%X%C: multiple definition of `%T'\n"),
nbfd, nsec, nval, name);
if (obfd != NULL)
@@ -980,17 +1017,41 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
static bfd_boolean
multiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name,
- bfd *obfd,
- enum bfd_link_hash_type otype,
- bfd_vma osize,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
enum bfd_link_hash_type ntype,
bfd_vma nsize)
{
- if (! config.warn_common)
+ const char *name;
+ bfd *obfd;
+ enum bfd_link_hash_type otype;
+ bfd_vma osize;
+
+ if (!config.warn_common)
return TRUE;
+ name = h->root.string;
+ otype = h->type;
+ if (otype == bfd_link_hash_common)
+ {
+ obfd = h->u.c.p->section->owner;
+ osize = h->u.c.size;
+ }
+ else if (otype == bfd_link_hash_defined
+ || otype == bfd_link_hash_defweak)
+ {
+ obfd = h->u.def.section->owner;
+ osize = 0;
+ }
+ else
+ {
+ /* FIXME: It would nice if we could report the BFD which defined
+ an indirect symbol, but we don't have anywhere to store the
+ information. */
+ obfd = NULL;
+ osize = 0;
+ }
+
if (ntype == bfd_link_hash_defined
|| ntype == bfd_link_hash_defweak
|| ntype == bfd_link_hash_indirect)
diff --git a/ld/plugin.c b/ld/plugin.c
index 07f3afe..b363bc1 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -97,10 +97,8 @@ static const char *error_plugin = NULL;
cases when establishing symbol resolutions. */
static struct bfd_hash_table *non_ironly_hash = NULL;
-/* State of linker "notice" and "multiple_definition" interfaces
- before we poked at them. */
+/* State of linker "notice" interface before we poked at it. */
static bfd_boolean orig_notice_all;
-static bfd_boolean orig_allow_multiple_defs;
/* Original linker callbacks, and the plugin version. */
static const struct bfd_link_callbacks *orig_callbacks;
@@ -138,9 +136,8 @@ static bfd_boolean plugin_notice (struct bfd_link_info *info,
const char *name, bfd *abfd,
asection *section, bfd_vma value);
static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
- const char *name,
- bfd *obfd, asection *osec,
- bfd_vma oval, bfd *nbfd,
+ struct bfd_link_hash_entry *h,
+ bfd *nbfd,
asection *nsec,
bfd_vma nval);
@@ -847,12 +844,6 @@ plugin_call_all_symbols_read (void)
/* Disable any further file-claiming. */
no_more_claiming = TRUE;
- /* If --allow-multiple-definition is in effect, we need to disable it,
- as the plugin infrastructure relies on the multiple_definition
- callback to swap out the dummy IR-only BFDs for new real ones
- when it starts opening the files added during this callback. */
- orig_allow_multiple_defs = link_info.allow_multiple_definition;
- link_info.allow_multiple_definition = FALSE;
plugin_callbacks.multiple_definition = &plugin_multiple_definition;
while (curplug)
@@ -949,28 +940,18 @@ plugin_notice (struct bfd_link_info *info,
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, const char *name,
- bfd *obfd, asection *osec, bfd_vma oval,
+plugin_multiple_definition (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
bfd *nbfd, asection *nsec, bfd_vma nval)
{
- if (is_ir_dummy_bfd (obfd))
+ if (h->type == bfd_link_hash_defined
+ && is_ir_dummy_bfd (h->u.def.section->owner))
{
- struct bfd_link_hash_entry *blhe
- = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
- if (!blhe)
- einfo (_("%P%X: %s: can't find IR symbol '%s'\n"), nbfd->filename,
- name);
- else if (blhe->type != bfd_link_hash_defined)
- einfo (_("%P%x: %s: bad IR symbol type %d\n"), name, blhe->type);
/* Replace it with new details. */
- blhe->u.def.section = nsec;
- blhe->u.def.value = nval;
+ h->u.def.section = nsec;
+ h->u.def.value = nval;
return TRUE;
}
- if (orig_allow_multiple_defs)
- return TRUE;
-
- return (*orig_callbacks->multiple_definition) (info, name, obfd, osec, oval,
- nbfd, nsec, nval);
+ return (*orig_callbacks->multiple_definition) (info, h, nbfd, nsec, nval);
}