aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/coff-aux.c62
-rw-r--r--bfd/elflink.c2
-rw-r--r--bfd/linker.c82
4 files changed, 89 insertions, 67 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e2855ad..8fda279 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
2014-08-12 Alan Modra <amodra@gmail.com>
+ * coff-aux.c (coff_m68k_aux_link_add_one_symbol): Only call "notice"
+ here when not calling the generic add_symbol function. Formatting.
+ Correct handling of indirect symbols. Update notice call.
+ * elflink.c (_bfd_elf_notice_as_needed): Update notice call.
+ * linker.c (_bfd_generic_link_add_one_symbol): Create indirect
+ symbols early. Update notice call. Add comments regarding weak
+ symbols vs. indirect.
+
+2014-08-12 Alan Modra <amodra@gmail.com>
+
PR ld/16746
* linker.c (_bfd_generic_link_add_one_symbol <WARN>): Handle
!lto_plugin_active.
diff --git a/bfd/coff-aux.c b/bfd/coff-aux.c
index e79c77a..d95b98b 100644
--- a/bfd/coff-aux.c
+++ b/bfd/coff-aux.c
@@ -73,20 +73,17 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
bfd_boolean collect,
struct bfd_link_hash_entry **hashp)
{
- struct bfd_link_hash_entry *h;
+ struct bfd_link_hash_entry *h, *inh, *t;
- if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 &&
- !bfd_is_und_section (section) &&
- !bfd_is_com_section (section))
+ if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0
+ && !bfd_is_und_section (section)
+ && !bfd_is_com_section (section))
{
/* The new symbol is a definition or an indirect definition */
/* This bit copied from linker.c */
if (hashp != NULL && *hashp != NULL)
- {
- h = *hashp;
- BFD_ASSERT (strcmp (h->root.string, name) == 0);
- }
+ h = *hashp;
else
{
h = bfd_link_hash_lookup (info->hash, name, TRUE, copy, FALSE);
@@ -98,37 +95,46 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
}
}
- if (info->notice_hash != (struct bfd_hash_table *) NULL
- && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
- != (struct bfd_hash_entry *) NULL))
- {
- if (! (*info->callbacks->notice) (info, h, abfd, section, value,
- flags, string))
- return FALSE;
- }
-
if (hashp != (struct bfd_link_hash_entry **) NULL)
*hashp = h;
/* end duplication from linker.c */
- if (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_indirect)
+ t = h;
+ inh = NULL;
+ if (h->type == bfd_link_hash_indirect)
{
- asection *msec;
+ inh = h->u.i.link;
+ t = inh;
+ }
- if (h->type == bfd_link_hash_defined)
- msec = h->u.def.section;
- else
- msec = bfd_ind_section_ptr;
+ if (t->type == bfd_link_hash_defined)
+ {
+ asection *msec = t->u.def.section;
+ bfd_boolean special = FALSE;
if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section))
{
- h->u.def.section = section;
- h->u.def.value = value;
- return TRUE;
+ t->u.def.section = section;
+ t->u.def.value = value;
+ special = TRUE;
}
else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec))
- return TRUE;
+ special = TRUE;
+
+ if (special)
+ {
+ if (info->notice_all
+ || (info->notice_hash != NULL
+ && bfd_hash_lookup (info->notice_hash, name,
+ FALSE, FALSE) != NULL))
+ {
+ if (!(*info->callbacks->notice) (info, h, inh,
+ abfd, section, value, flags))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
}
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 69a87a6..de0a734 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3299,7 +3299,7 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
struct bfd_link_info *info,
enum notice_asneeded_action act)
{
- return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
+ return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
}
/* Add symbols from an ELF object file to the linker hash table. */
diff --git a/bfd/linker.c b/bfd/linker.c
index 1a5ecef..abdf5b0 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1442,13 +1442,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
{
enum link_row row;
struct bfd_link_hash_entry *h;
+ struct bfd_link_hash_entry *inh = NULL;
bfd_boolean cycle;
BFD_ASSERT (section != NULL);
if (bfd_is_ind_section (section)
|| (flags & BSF_INDIRECT) != 0)
- row = INDR_ROW;
+ {
+ row = INDR_ROW;
+ /* Create the indirect symbol here. This is for the benefit of
+ the plugin "notice" function.
+ STRING is the name of the symbol we want to indirect to. */
+ inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
+ copy, FALSE);
+ if (inh == NULL)
+ return FALSE;
+ }
else if ((flags & BSF_WARNING) != 0)
row = WARN_ROW;
else if ((flags & BSF_CONSTRUCTOR) != 0)
@@ -1493,8 +1503,8 @@ _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,
- abfd, section, value, flags, string))
+ if (! (*info->callbacks->notice) (info, h, inh,
+ abfd, section, value, flags))
return FALSE;
}
@@ -1728,44 +1738,40 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
return FALSE;
/* Fall through. */
case IND:
- /* Create an indirect symbol. */
- {
- struct bfd_link_hash_entry *inh;
-
- /* STRING is the name of the symbol we want to indirect
- to. */
- inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
- copy, FALSE);
- if (inh == NULL)
+ if (inh->type == bfd_link_hash_indirect
+ && inh->u.i.link == h)
+ {
+ (*_bfd_error_handler)
+ (_("%B: indirect symbol `%s' to `%s' is a loop"),
+ abfd, name, string);
+ bfd_set_error (bfd_error_invalid_operation);
return FALSE;
- if (inh->type == bfd_link_hash_indirect
- && inh->u.i.link == h)
- {
- (*_bfd_error_handler)
- (_("%B: indirect symbol `%s' to `%s' is a loop"),
- abfd, name, string);
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
- if (inh->type == bfd_link_hash_new)
- {
- inh->type = bfd_link_hash_undefined;
- inh->u.undef.abfd = abfd;
- bfd_link_add_undef (info->hash, inh);
- }
+ }
+ if (inh->type == bfd_link_hash_new)
+ {
+ inh->type = bfd_link_hash_undefined;
+ inh->u.undef.abfd = abfd;
+ bfd_link_add_undef (info->hash, inh);
+ }
- /* If the indirect symbol has been referenced, we need to
- push the reference down to the symbol we are
- referencing. */
- if (h->type != bfd_link_hash_new)
- {
- row = UNDEF_ROW;
- cycle = TRUE;
- }
+ /* If the indirect symbol has been referenced, we need to
+ push the reference down to the symbol we are referencing. */
+ if (h->type != bfd_link_hash_new)
+ {
+ /* ??? If inh->type == bfd_link_hash_undefweak this
+ converts inh to bfd_link_hash_undefined. */
+ row = UNDEF_ROW;
+ cycle = TRUE;
+ }
- h->type = bfd_link_hash_indirect;
- h->u.i.link = inh;
- }
+ h->type = bfd_link_hash_indirect;
+ h->u.i.link = inh;
+ /* Not setting h = h->u.i.link here means that when cycle is
+ set above we'll always go to REFC, and then cycle again
+ to the indirected symbol. This means that any successful
+ change of an existing symbol to indirect counts as a
+ reference. ??? That may not be correct when the existing
+ symbol was defweak. */
break;
case SET: