diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5102221c41..c26ab49a0e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2017-01-24 Maciej W. Rozycki + + PR ld/20828 + * elflink.c (bfd_elf_record_link_assignment): Revert last + change and don't ever clear `forced_local'. Set `mark' + unconditionally. + (elf_gc_sweep_symbol_info, elf_gc_sweep_symbol): Reorder within + file. + (elf_gc_sweep): Move the call to `elf_gc_sweep_symbol'... + (bfd_elf_size_dynamic_sections): ... here. + * elf32-ppc.c (ppc_elf_tls_setup): Don't clear `forced_local' + and set `mark' instead in `__tls_get_addr_opt' processing. + * elf64-ppc.c (ppc64_elf_tls_setup): Likewise. + 2017-01-24 Alan Modra * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Merge two cases diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 7d69ea0dda..353845a443 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -5287,7 +5287,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) tga->root.type = bfd_link_hash_indirect; tga->root.u.i.link = &opt->root; ppc_elf_copy_indirect_symbol (info, opt, tga); - opt->forced_local = 0; + opt->mark = 1; if (opt->dynindx != -1) { /* Use __tls_get_addr_opt in dynamic relocations. */ diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 1e9429cf88..1c77cc6284 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -8324,7 +8324,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info) tga_fd->root.type = bfd_link_hash_indirect; tga_fd->root.u.i.link = &opt_fd->root; ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd); - opt_fd->forced_local = 0; + opt_fd->mark = 1; if (opt_fd->dynindx != -1) { /* Use __tls_get_addr_opt in dynamic relocations. */ @@ -8341,7 +8341,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info) tga->root.type = bfd_link_hash_indirect; tga->root.u.i.link = &opt->root; ppc64_elf_copy_indirect_symbol (info, opt, tga); - opt->forced_local = 0; + opt->mark = 1; _bfd_elf_link_hash_hide_symbol (info, opt, tga->forced_local); htab->tls_get_addr = (struct ppc_link_hash_entry *) opt; diff --git a/bfd/elflink.c b/bfd/elflink.c index d7ed8ce6b4..9c71d57813 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -671,17 +671,15 @@ bfd_elf_record_link_assignment (bfd *output_bfd, /* If this symbol is not being provided by the linker script, and it is currently defined by a dynamic object, but not by a regular object, - then undo any forced local marking that may have been set by input - section garbage collection and clear out any version information - because the symbol will not be associated with the dynamic object - any more. */ + then clear out any version information because the symbol will not be + associated with the dynamic object any more. */ if (!provide && h->def_dynamic && !h->def_regular) - { - h->forced_local = 0; - h->verinfo.verdef = NULL; - } + h->verinfo.verdef = NULL; + + /* Make sure this symbol is not garbage collected. */ + h->mark = 1; h->def_regular = 1; @@ -5876,6 +5874,38 @@ bfd_elf_stack_segment_size (bfd *output_bfd, return TRUE; } +/* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */ + +struct elf_gc_sweep_symbol_info +{ + struct bfd_link_info *info; + void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *, + bfd_boolean); +}; + +static bfd_boolean +elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data) +{ + if (!h->mark + && (((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && !((h->def_regular || ELF_COMMON_DEF_P (h)) + && h->root.u.def.section->gc_mark)) + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak)) + { + struct elf_gc_sweep_symbol_info *inf; + + inf = (struct elf_gc_sweep_symbol_info *) data; + (*inf->hide_symbol) (inf->info, h, TRUE); + h->def_regular = 0; + h->ref_regular = 0; + h->ref_regular_nonweak = 0; + } + + return TRUE; +} + /* Set up the sizes and contents of the ELF dynamic sections. This is called by the ELF linker emulation before_allocation routine. We must set the sizes of the sections before the linker sets the @@ -5906,6 +5936,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, bed = get_elf_backend_data (output_bfd); + if (info->gc_sections && bed->can_gc_sections) + { + struct elf_gc_sweep_symbol_info sweep_info; + unsigned long section_sym_count; + + /* Remove the symbols that were in the swept sections from the + dynamic symbol table. GCFIXME: Anyone know how to get them + out of the static symbol table as well? */ + sweep_info.info = info; + sweep_info.hide_symbol = bed->elf_backend_hide_symbol; + elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, + &sweep_info); + + _bfd_elf_link_renumber_dynsyms (output_bfd, info, §ion_sym_count); + } + /* Any syms created from now on start with -1 in got.refcount/offset and plt.refcount/offset. */ elf_hash_table (info)->init_got_refcount @@ -12853,38 +12899,6 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, return TRUE; } -/* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */ - -struct elf_gc_sweep_symbol_info -{ - struct bfd_link_info *info; - void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *, - bfd_boolean); -}; - -static bfd_boolean -elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data) -{ - if (!h->mark - && (((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && !((h->def_regular || ELF_COMMON_DEF_P (h)) - && h->root.u.def.section->gc_mark)) - || h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak)) - { - struct elf_gc_sweep_symbol_info *inf; - - inf = (struct elf_gc_sweep_symbol_info *) data; - (*inf->hide_symbol) (inf->info, h, TRUE); - h->def_regular = 0; - h->ref_regular = 0; - h->ref_regular_nonweak = 0; - } - - return TRUE; -} - /* The sweep phase of garbage collection. Remove all garbage sections. */ typedef bfd_boolean (*gc_sweep_hook_fn) @@ -12896,8 +12910,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) bfd *sub; const struct elf_backend_data *bed = get_elf_backend_data (abfd); gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook; - unsigned long section_sym_count; - struct elf_gc_sweep_symbol_info sweep_info; for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { @@ -12963,15 +12975,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) } } - /* Remove the symbols that were in the swept sections from the dynamic - symbol table. GCFIXME: Anyone know how to get them out of the - static symbol table as well? */ - sweep_info.info = info; - sweep_info.hide_symbol = bed->elf_backend_hide_symbol; - elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, - &sweep_info); - - _bfd_elf_link_renumber_dynsyms (abfd, info, §ion_sym_count); return TRUE; }