non_ir_ref_dynamic

dynamic_ref_after_ir_def is a little odd compared to other symbol
flags in that as the name suggests, it is set only for certain
references after a definition.  It turns out that setting a flag for
any non-ir reference from a dynamic object can be used to solve the
problem for which this flag was invented, which I think is a cleaner.
This patch does that, and sets non_ir_ref only for regular object
references.

include/
	* bfdlink.h (struct bfd_link_hash_entry): Update non_ir_ref
	comment.  Rename dynamic_ref_after_ir_def to non_ir_ref_dynamic.
ld/
	* plugin.c (is_visible_from_outside): Use non_ir_ref_dynamic.
	(plugin_notice): Set non_ir_ref for references from regular
	objects, non_ir_ref_dynamic for references from dynamic objects.
bfd/
	* elf64-ppc.c (add_symbol_adjust): Transfer non_ir_ref_dynamic.
	* elflink.c (elf_link_add_object_symbols): Update to use
	non_ir_ref_dynamic.
	(elf_link_input_bfd): Test non_ir_ref_dynamic in addition to
	non_ir_ref.
	* linker.c (_bfd_generic_link_add_one_symbol): Likewise.
This commit is contained in:
Alan Modra
2017-05-16 07:56:41 +09:30
parent 8cc2a97960
commit 4070765b1a
8 changed files with 69 additions and 41 deletions

View File

@ -1,3 +1,12 @@
2017-05-16 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (add_symbol_adjust): Transfer non_ir_ref_dynamic.
* elflink.c (elf_link_add_object_symbols): Update to use
non_ir_ref_dynamic.
(elf_link_input_bfd): Test non_ir_ref_dynamic in addition to
non_ir_ref.
* linker.c (_bfd_generic_link_add_one_symbol): Likewise.
2017-05-15 Maciej W. Rozycki <macro@imgtec.com> 2017-05-15 Maciej W. Rozycki <macro@imgtec.com>
* elfxx-mips.c (print_mips_ases): Handle MIPS16e2 ASE. * elfxx-mips.c (print_mips_ases): Handle MIPS16e2 ASE.

View File

@ -5119,6 +5119,7 @@ add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
/* Propagate reference flags from entry symbol to function /* Propagate reference flags from entry symbol to function
descriptor symbol. */ descriptor symbol. */
fdh->elf.root.non_ir_ref |= eh->elf.root.non_ir_ref; fdh->elf.root.non_ir_ref |= eh->elf.root.non_ir_ref;
fdh->elf.root.non_ir_ref_dynamic |= eh->elf.root.non_ir_ref_dynamic;
fdh->elf.ref_regular |= eh->elf.ref_regular; fdh->elf.ref_regular |= eh->elf.ref_regular;
fdh->elf.ref_regular_nonweak |= eh->elf.ref_regular_nonweak; fdh->elf.ref_regular_nonweak |= eh->elf.ref_regular_nonweak;

View File

@ -4939,7 +4939,7 @@ error_free_dyn:
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
bfd_size_type size; bfd_size_type size;
unsigned int alignment_power; unsigned int alignment_power;
unsigned int dynamic_ref_after_ir_def; unsigned int non_ir_ref_dynamic;
for (p = htab->root.table.table[i]; p != NULL; p = p->next) for (p = htab->root.table.table[i]; p != NULL; p = p->next)
{ {
@ -4961,10 +4961,10 @@ error_free_dyn:
size = 0; size = 0;
alignment_power = 0; alignment_power = 0;
} }
/* Preserve dynamic_ref_after_ir_def so that this symbol /* Preserve non_ir_ref_dynamic so that this symbol
will be exported when the dynamic lib becomes needed will be exported when the dynamic lib becomes needed
in the second pass. */ in the second pass. */
dynamic_ref_after_ir_def = h->root.dynamic_ref_after_ir_def; non_ir_ref_dynamic = h->root.non_ir_ref_dynamic;
memcpy (p, old_ent, htab->root.table.entsize); memcpy (p, old_ent, htab->root.table.entsize);
old_ent = (char *) old_ent + htab->root.table.entsize; old_ent = (char *) old_ent + htab->root.table.entsize;
h = (struct elf_link_hash_entry *) p; h = (struct elf_link_hash_entry *) p;
@ -4981,7 +4981,7 @@ error_free_dyn:
if (alignment_power > h->root.u.c.p->alignment_power) if (alignment_power > h->root.u.c.p->alignment_power)
h->root.u.c.p->alignment_power = alignment_power; h->root.u.c.p->alignment_power = alignment_power;
} }
h->root.dynamic_ref_after_ir_def = dynamic_ref_after_ir_def; h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
} }
} }
@ -10472,7 +10472,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
linker may attach linker created dynamic sections linker may attach linker created dynamic sections
to the plugin bfd. Symbols defined in linker to the plugin bfd. Symbols defined in linker
created sections are not plugin symbols. */ created sections are not plugin symbols. */
if (h->root.non_ir_ref if ((h->root.non_ir_ref
|| h->root.non_ir_ref_dynamic)
&& (h->root.type == bfd_link_hash_defined && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak) || h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->flags && (h->root.u.def.section->flags

View File

@ -1735,7 +1735,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
otherwise add a warning. */ otherwise add a warning. */
if ((!info->lto_plugin_active if ((!info->lto_plugin_active
&& (h->u.undef.next != NULL || info->hash->undefs_tail == h)) && (h->u.undef.next != NULL || info->hash->undefs_tail == h))
|| h->non_ir_ref) || h->non_ir_ref
|| h->non_ir_ref_dynamic)
{ {
(*info->callbacks->warning) (info, string, h->root.string, (*info->callbacks->warning) (info, string, h->root.string,
hash_entry_bfd (h), NULL, 0); hash_entry_bfd (h), NULL, 0);

View File

@ -1,3 +1,8 @@
2017-05-16 Alan Modra <amodra@gmail.com>
* bfdlink.h (struct bfd_link_hash_entry): Update non_ir_ref
comment. Rename dynamic_ref_after_ir_def to non_ir_ref_dynamic.
2017-05-15 Maciej W. Rozycki <macro@imgtec.com> 2017-05-15 Maciej W. Rozycki <macro@imgtec.com>
Matthew Fortune <matthew.fortune@imgtec.com> Matthew Fortune <matthew.fortune@imgtec.com>

View File

@ -100,13 +100,13 @@ struct bfd_link_hash_entry
/* Type of this entry. */ /* Type of this entry. */
ENUM_BITFIELD (bfd_link_hash_type) type : 8; ENUM_BITFIELD (bfd_link_hash_type) type : 8;
/* Symbol is referenced in a normal object file, as distict from a LTO /* Symbol is referenced in a normal regular object file,
IR object file. */ as distinct from a LTO IR object file. */
unsigned int non_ir_ref : 1; unsigned int non_ir_ref : 1;
/* Symbol is referenced in a dynamic object after it has been defined /* Symbol is referenced in a normal dynamic object file,
in an IR object. */ as distinct from a LTO IR object file. */
unsigned int dynamic_ref_after_ir_def : 1; unsigned int non_ir_ref_dynamic : 1;
/* Symbol is a built-in define. These will be overridden by PROVIDE /* Symbol is a built-in define. These will be overridden by PROVIDE
in a linker script. */ in a linker script. */

View File

@ -1,3 +1,9 @@
2017-05-16 Alan Modra <amodra@gmail.com>
* plugin.c (is_visible_from_outside): Use non_ir_ref_dynamic.
(plugin_notice): Set non_ir_ref for references from regular
objects, non_ir_ref_dynamic for references from dynamic objects.
2017-05-15 Maciej W. Rozycki <macro@imgtec.com> 2017-05-15 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/ld-mips-elf/mips16e2-pcrel-0.d: New test. * testsuite/ld-mips-elf/mips16e2-pcrel-0.d: New test.

View File

@ -629,7 +629,7 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym,
if (bfd_link_relocatable (&link_info)) if (bfd_link_relocatable (&link_info))
return TRUE; return TRUE;
if (blhe->dynamic_ref_after_ir_def if (blhe->non_ir_ref_dynamic
|| link_info.export_dynamic || link_info.export_dynamic
|| bfd_link_dll (&link_info)) || bfd_link_dll (&link_info))
{ {
@ -1266,9 +1266,10 @@ plugin_call_cleanup (void)
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF /* To determine which symbols should be resolved LDPR_PREVAILING_DEF
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
the linker adds them to the linker hash table. Mark those the linker adds them to the linker hash table. Mark those
referenced from a non-IR file with non_ir_ref. We have to referenced from a non-IR file with non_ir_ref or
notice_all symbols, because we won't necessarily know until later non_ir_ref_dynamic as appropriate. We have to notice_all symbols,
which ones will be contributed by IR files. */ because we won't necessarily know until later which ones will be
contributed by IR files. */
static bfd_boolean static bfd_boolean
plugin_notice (struct bfd_link_info *info, plugin_notice (struct bfd_link_info *info,
struct bfd_link_hash_entry *h, struct bfd_link_hash_entry *h,
@ -1283,6 +1284,7 @@ plugin_notice (struct bfd_link_info *info,
if (h != NULL) if (h != NULL)
{ {
bfd *sym_bfd; bfd *sym_bfd;
bfd_boolean ref = FALSE;
if (h->type == bfd_link_hash_warning) if (h->type == bfd_link_hash_warning)
h = h->u.i.link; h = h->u.i.link;
@ -1298,13 +1300,17 @@ plugin_notice (struct bfd_link_info *info,
{ {
/* ??? Some of this is questionable. See comments in /* ??? Some of this is questionable. See comments in
_bfd_generic_link_add_one_symbol for case IND. */ _bfd_generic_link_add_one_symbol for case IND. */
if (h->type != bfd_link_hash_new) if (h->type != bfd_link_hash_new
|| inh->type == bfd_link_hash_new)
{ {
h->non_ir_ref = TRUE; if ((abfd->flags & DYNAMIC) == 0)
inh->non_ir_ref = TRUE; inh->non_ir_ref = TRUE;
else
inh->non_ir_ref_dynamic = TRUE;
} }
else if (inh->type == bfd_link_hash_new)
inh->non_ir_ref = TRUE; if (h->type != bfd_link_hash_new)
ref = TRUE;
} }
/* Nothing to do here for warning symbols. */ /* Nothing to do here for warning symbols. */
@ -1318,34 +1324,18 @@ plugin_notice (struct bfd_link_info *info,
/* If this is a ref, set non_ir_ref. */ /* If this is a ref, set non_ir_ref. */
else if (bfd_is_und_section (section)) else if (bfd_is_und_section (section))
{ {
if (h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_defined)
{
/* Check if the symbol is referenced in a dynamic object
after it has been defined in an IR object. */
if ((abfd->flags & DYNAMIC) != 0
&& is_ir_dummy_bfd (h->u.def.section->owner))
h->dynamic_ref_after_ir_def = TRUE;
}
/* Replace the undefined dummy bfd with the real one. */ /* Replace the undefined dummy bfd with the real one. */
else if ((h->type == bfd_link_hash_undefined if ((h->type == bfd_link_hash_undefined
|| h->type == bfd_link_hash_undefweak) || h->type == bfd_link_hash_undefweak)
&& (h->u.undef.abfd == NULL && (h->u.undef.abfd == NULL
|| (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
h->u.undef.abfd = abfd; h->u.undef.abfd = abfd;
h->non_ir_ref = TRUE; ref = TRUE;
} }
/* Otherwise, it must be a new def. */ /* Otherwise, it must be a new def. */
else else
{ {
/* A common symbol should be merged with other commons or
defs with the same name. In particular, a common ought
to be overridden by a def in a -flto object. In that
sense a common is also a ref. */
if (bfd_is_com_section (section))
h->non_ir_ref = TRUE;
/* Ensure any symbol defined in an IR dummy BFD takes on a /* Ensure any symbol defined in an IR dummy BFD takes on a
new value from a real BFD. Weak symbols are not normally new value from a real BFD. Weak symbols are not normally
overridden by a new weak definition, and strong symbols overridden by a new weak definition, and strong symbols
@ -1360,6 +1350,21 @@ plugin_notice (struct bfd_link_info *info,
h->type = bfd_link_hash_undefweak; h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = sym_bfd; h->u.undef.abfd = sym_bfd;
} }
/* A common symbol should be merged with other commons or
defs with the same name. In particular, a common ought
to be overridden by a def in a -flto object. In that
sense a common is also a ref. */
if (bfd_is_com_section (section))
ref = TRUE;
}
if (ref)
{
if ((abfd->flags & DYNAMIC) == 0)
h->non_ir_ref = TRUE;
else
h->non_ir_ref_dynamic = TRUE;
} }
} }