From 4070765b1a1640ff8f43483cd9ee06727f658dfe Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 16 May 2017 07:56:41 +0930 Subject: [PATCH] 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. --- bfd/ChangeLog | 9 +++++++ bfd/elf64-ppc.c | 1 + bfd/elflink.c | 11 ++++---- bfd/linker.c | 3 ++- include/ChangeLog | 5 ++++ include/bfdlink.h | 10 ++++---- ld/ChangeLog | 6 +++++ ld/plugin.c | 65 +++++++++++++++++++++++++---------------------- 8 files changed, 69 insertions(+), 41 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 52c192d4bbd..8b3f1a5b121 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2017-05-16 Alan Modra + + * 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 * elfxx-mips.c (print_mips_ases): Handle MIPS16e2 ASE. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index a20d9b3a285..a2cc373b9f2 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -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 descriptor symbol. */ 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_nonweak |= eh->elf.ref_regular_nonweak; diff --git a/bfd/elflink.c b/bfd/elflink.c index ba50b685e9c..8eaf533b752 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4939,7 +4939,7 @@ error_free_dyn: struct elf_link_hash_entry *h; bfd_size_type size; 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) { @@ -4961,10 +4961,10 @@ error_free_dyn: size = 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 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); old_ent = (char *) old_ent + htab->root.table.entsize; h = (struct elf_link_hash_entry *) p; @@ -4981,7 +4981,7 @@ error_free_dyn: if (alignment_power > h->root.u.c.p->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 to the plugin bfd. Symbols defined in linker 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_defweak) && (h->root.u.def.section->flags diff --git a/bfd/linker.c b/bfd/linker.c index 2f56b465cb3..1f493a3e317 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1735,7 +1735,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, otherwise add a warning. */ if ((!info->lto_plugin_active && (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, hash_entry_bfd (h), NULL, 0); diff --git a/include/ChangeLog b/include/ChangeLog index 67bf02fbe76..84257609e41 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2017-05-16 Alan Modra + + * 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 Matthew Fortune diff --git a/include/bfdlink.h b/include/bfdlink.h index cb4bad9fb5a..41f5338dc85 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -100,13 +100,13 @@ struct bfd_link_hash_entry /* Type of this entry. */ ENUM_BITFIELD (bfd_link_hash_type) type : 8; - /* Symbol is referenced in a normal object file, as distict from a LTO - IR object file. */ + /* Symbol is referenced in a normal regular object file, + as distinct from a LTO IR object file. */ unsigned int non_ir_ref : 1; - /* Symbol is referenced in a dynamic object after it has been defined - in an IR object. */ - unsigned int dynamic_ref_after_ir_def : 1; + /* Symbol is referenced in a normal dynamic object file, + as distinct from a LTO IR object file. */ + unsigned int non_ir_ref_dynamic : 1; /* Symbol is a built-in define. These will be overridden by PROVIDE in a linker script. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index a8dad5ca1c2..9fdd75805f4 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2017-05-16 Alan Modra + + * 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 * testsuite/ld-mips-elf/mips16e2-pcrel-0.d: New test. diff --git a/ld/plugin.c b/ld/plugin.c index 164b5db5d6d..087cedceed0 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -629,7 +629,7 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym, if (bfd_link_relocatable (&link_info)) return TRUE; - if (blhe->dynamic_ref_after_ir_def + if (blhe->non_ir_ref_dynamic || link_info.export_dynamic || bfd_link_dll (&link_info)) { @@ -1266,9 +1266,10 @@ 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. 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. */ + referenced from a non-IR file with non_ir_ref or + non_ir_ref_dynamic as appropriate. 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, struct bfd_link_hash_entry *h, @@ -1283,6 +1284,7 @@ plugin_notice (struct bfd_link_info *info, if (h != NULL) { bfd *sym_bfd; + bfd_boolean ref = FALSE; if (h->type == bfd_link_hash_warning) h = h->u.i.link; @@ -1298,13 +1300,17 @@ plugin_notice (struct bfd_link_info *info, { /* ??? Some of this is questionable. See comments in _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; - inh->non_ir_ref = TRUE; + if ((abfd->flags & DYNAMIC) == 0) + 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. */ @@ -1318,34 +1324,18 @@ plugin_notice (struct bfd_link_info *info, /* If this is a ref, set non_ir_ref. */ 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. */ - else if ((h->type == bfd_link_hash_undefined - || h->type == bfd_link_hash_undefweak) - && (h->u.undef.abfd == NULL - || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) + if ((h->type == bfd_link_hash_undefined + || h->type == bfd_link_hash_undefweak) + && (h->u.undef.abfd == NULL + || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) h->u.undef.abfd = abfd; - h->non_ir_ref = TRUE; + ref = TRUE; } /* Otherwise, it must be a new def. */ 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 new value from a real BFD. Weak symbols are not normally 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->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; } } -- 2.30.2