From 6f6fd151cbf226bbaa66e44977f57b7c6dc33d89 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 21 Apr 2020 05:23:51 -0700 Subject: [PATCH] elf: Strip zero-sized dynamic sections ELF size_dynamic_sections is called by the ELF backend linker after all the linker input files have been seen but before the section sizes have been set. After the sections sizes have been set, target-specific, global optimizations may make some dynamic sections zero-sized if they are no longer needed. Add ELF strip_zero_sized_dynamic_sections so that ELF backend linker can strip zero-sized dynamic sections after the sections sizes have been set. bfd/ PR ld/25849 * elf-bfd.h (elf_backend_data): Add elf_backend_strip_zero_sized_dynamic_sections. (_bfd_elf_strip_zero_sized_dynamic_sections): New prototype. * elf64-alpha.c (elf_backend_strip_zero_sized_dynamic_sections): New macro. * elflink.c (_bfd_elf_strip_zero_sized_dynamic_sections): New function. * elfxx-target.h (elf_backend_strip_zero_sized_dynamic_sections): New macro. (elfNN_bed): Add elf_backend_strip_zero_sized_dynamic_sections. ld/ PR ld/25849 * ldelfgen.c (ldelf_map_segments): Call elf_backend_strip_zero_sized_dynamic_sections. * testsuite/ld-alpha/tlsbinr.rd: Updated. --- bfd/ChangeLog | 14 +++++ bfd/elf-bfd.h | 8 +++ bfd/elf64-alpha.c | 3 + bfd/elflink.c | 98 +++++++++++++++++++++++++++++++ bfd/elfxx-target.h | 4 ++ ld/ChangeLog | 7 +++ ld/ldelfgen.c | 13 +++++ ld/testsuite/ld-alpha/tlsbinr.rd | 99 +++++++++++++++----------------- 8 files changed, 194 insertions(+), 52 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a15a0f3775..8bc7ee979d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2020-04-21 H.J. Lu + + PR ld/25849 + * elf-bfd.h (elf_backend_data): Add + elf_backend_strip_zero_sized_dynamic_sections. + (_bfd_elf_strip_zero_sized_dynamic_sections): New prototype. + * elf64-alpha.c (elf_backend_strip_zero_sized_dynamic_sections): + New macro. + * elflink.c (_bfd_elf_strip_zero_sized_dynamic_sections): New + function. + * elfxx-target.h (elf_backend_strip_zero_sized_dynamic_sections): + New macro. + (elfNN_bed): Add elf_backend_strip_zero_sized_dynamic_sections. + 2020-04-21 H.J. Lu * elf64-alpha.c (alpha_elf_reloc_entry): Replace reltext with diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b08502cd1c..3ae98425e8 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1083,6 +1083,12 @@ struct elf_backend_data bfd_boolean (*elf_backend_size_dynamic_sections) (bfd *output_bfd, struct bfd_link_info *info); + /* The STRIP_ZERO_SIZED_DYNAMIC_SECTIONS function is called by the + ELF backend linker to strip zero-sized dynamic sections after + the section sizes have been set. */ + bfd_boolean (*elf_backend_strip_zero_sized_dynamic_sections) + (struct bfd_link_info *info); + /* Set TEXT_INDEX_SECTION and DATA_INDEX_SECTION, the output sections we keep to use as a base for relocs and symbols. */ void (*elf_backend_init_index_section) @@ -2520,6 +2526,8 @@ extern bfd_boolean bfd_elf_link_add_symbols (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_add_dynamic_entry (struct bfd_link_info *, bfd_vma, bfd_vma); +extern bfd_boolean _bfd_elf_strip_zero_sized_dynamic_sections + (struct bfd_link_info *); extern int bfd_elf_add_dt_needed_tag (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_link_check_relocs diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 9f79d8e3fb..8f73212dae 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -5538,6 +5538,9 @@ static const struct elf_size_info alpha_elf_size_info = #define elf_backend_special_sections \ elf64_alpha_special_sections +#define elf_backend_strip_zero_sized_dynamic_sections \ + _bfd_elf_strip_zero_sized_dynamic_sections + /* A few constants that determine how the .plt section is set up. */ #define elf_backend_want_got_plt 0 #define elf_backend_plt_readonly 0 diff --git a/bfd/elflink.c b/bfd/elflink.c index eb6b3eeca5..6624864bf5 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3501,6 +3501,104 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, return TRUE; } +/* Strip zero-sized dynamic sections. */ + +bfd_boolean +_bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info) +{ + struct elf_link_hash_table *hash_table; + const struct elf_backend_data *bed; + asection *s, *sdynamic, **pp; + asection *rela_dyn, *rel_dyn; + Elf_Internal_Dyn dyn; + bfd_byte *extdyn, *next; + void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *); + bfd_boolean strip_zero_sized; + bfd_boolean strip_zero_sized_plt; + + if (bfd_link_relocatable (info)) + return TRUE; + + hash_table = elf_hash_table (info); + if (!is_elf_hash_table (hash_table)) + return FALSE; + + if (!hash_table->dynobj) + return TRUE; + + sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic"); + if (!sdynamic) + return TRUE; + + bed = get_elf_backend_data (hash_table->dynobj); + swap_dyn_in = bed->s->swap_dyn_in; + + strip_zero_sized = FALSE; + strip_zero_sized_plt = FALSE; + + /* Strip zero-sized dynamic sections. */ + rela_dyn = bfd_get_section_by_name (info->output_bfd, ".rela.dyn"); + rel_dyn = bfd_get_section_by_name (info->output_bfd, ".rel.dyn"); + for (pp = &info->output_bfd->sections; (s = *pp) != NULL;) + if (s->size == 0 + && (s == rela_dyn + || s == rel_dyn + || s == hash_table->srelplt->output_section + || s == hash_table->splt->output_section)) + { + *pp = s->next; + info->output_bfd->section_count--; + strip_zero_sized = TRUE; + if (s == rela_dyn) + s = rela_dyn; + if (s == rel_dyn) + s = rel_dyn; + else if (s == hash_table->splt->output_section) + { + s = hash_table->splt; + strip_zero_sized_plt = TRUE; + } + else + s = hash_table->srelplt; + s->flags |= SEC_EXCLUDE; + s->output_section = bfd_abs_section_ptr; + } + else + pp = &s->next; + + if (strip_zero_sized_plt) + for (extdyn = sdynamic->contents; + extdyn < sdynamic->contents + sdynamic->size; + extdyn = next) + { + next = extdyn + bed->s->sizeof_dyn; + swap_dyn_in (hash_table->dynobj, extdyn, &dyn); + switch (dyn.d_tag) + { + default: + break; + case DT_JMPREL: + case DT_PLTRELSZ: + case DT_PLTREL: + /* Strip DT_PLTRELSZ, DT_JMPREL and DT_PLTREL entries if + the procedure linkage table (the .plt section) has been + removed. */ + memmove (extdyn, next, + sdynamic->size - (next - sdynamic->contents)); + next = extdyn; + } + } + + if (strip_zero_sized) + { + /* Regenerate program headers. */ + elf_seg_map (info->output_bfd) = NULL; + return _bfd_elf_map_sections_to_segments (info->output_bfd, info); + } + + return TRUE; +} + /* Add a DT_NEEDED entry for this dynamic object. Returns -1 on error, 1 if a DT_NEEDED tag already exists, and 0 on success. */ diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 1ae17f45ee..b41fcde0ca 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -485,6 +485,9 @@ #ifndef elf_backend_size_dynamic_sections #define elf_backend_size_dynamic_sections 0 #endif +#ifndef elf_backend_strip_zero_sized_dynamic_sections +#define elf_backend_strip_zero_sized_dynamic_sections 0 +#endif #ifndef elf_backend_init_index_section #define elf_backend_init_index_section _bfd_void_bfd_link #endif @@ -831,6 +834,7 @@ static struct elf_backend_data elfNN_bed = elf_backend_adjust_dynamic_symbol, elf_backend_always_size_sections, elf_backend_size_dynamic_sections, + elf_backend_strip_zero_sized_dynamic_sections, elf_backend_init_index_section, elf_backend_relocate_section, elf_backend_finish_dynamic_symbol, diff --git a/ld/ChangeLog b/ld/ChangeLog index dffd363494..1169f93373 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2020-04-21 H.J. Lu + + PR ld/25849 + * ldelfgen.c (ldelf_map_segments): Call + elf_backend_strip_zero_sized_dynamic_sections. + * testsuite/ld-alpha/tlsbinr.rd: Updated. + 2020-04-20 Alan Modra * testsuite/ld-powerpc/tlsopt5.s: Rename foo to aaaaa. diff --git a/ld/ldelfgen.c b/ld/ldelfgen.c index 21739b19ca..c0568f169f 100644 --- a/ld/ldelfgen.c +++ b/ld/ldelfgen.c @@ -73,6 +73,19 @@ ldelf_map_segments (bfd_boolean need_layout) if (tries == 0) einfo (_("%F%P: looping in map_segments")); + + if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour + && lang_phdr_list == NULL) + { + /* If we don't have user supplied phdrs, strip zero-sized dynamic + sections and regenerate program headers. */ + const struct elf_backend_data *bed + = get_elf_backend_data (link_info.output_bfd); + if (bed->elf_backend_strip_zero_sized_dynamic_sections + && !bed->elf_backend_strip_zero_sized_dynamic_sections + (&link_info)) + einfo (_("%F%P: failed to strip zero-sized dynamic sections")); + } } /* We want to emit CTF early if and only if we are not targetting ELF with this diff --git a/ld/testsuite/ld-alpha/tlsbinr.rd b/ld/testsuite/ld-alpha/tlsbinr.rd index d6a70f9102..ea51686640 100644 --- a/ld/testsuite/ld-alpha/tlsbinr.rd +++ b/ld/testsuite/ld-alpha/tlsbinr.rd @@ -16,8 +16,6 @@ Section Headers: +\[[ 0-9]+\] \.dynsym +.* +\[[ 0-9]+\] \.dynstr +.* +\[[ 0-9]+\] \.rela\.dyn +.* - +\[[ 0-9]+\] \.rela\.plt +.* - +\[[ 0-9]+\] \.plt +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 0+ +AX +0 +0 +16 +\[[ 0-9]+\] \.text +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 0+ +AX +0 +0 4096 +\[[ 0-9]+\] \.eh_frame +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 +A +0 +0 +8 +\[[ 0-9]+\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 0+ WAT +0 +0 +4 @@ -70,59 +68,56 @@ Symbol table '\.symtab' contains [0-9]+ entries: [0-9 ]+: [0-9a-f]+ +0 +SECTION +LOCAL +DEFAULT +9 [0-9 ]+: [0-9a-f]+ +0 +SECTION +LOCAL +DEFAULT +10 [0-9 ]+: [0-9a-f]+ +0 +SECTION +LOCAL +DEFAULT +11 -[0-9 ]+: [0-9a-f]+ +0 +SECTION +LOCAL +DEFAULT +12 -[0-9 ]+: [0-9a-f]+ +0 +SECTION +LOCAL +DEFAULT +13 .* FILE +LOCAL +DEFAULT +ABS .* -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl1 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl3 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl4 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl5 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl6 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl7 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +10 sl8 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl1 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl3 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl4 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl5 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl6 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl7 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +8 sl8 .* FILE +LOCAL +DEFAULT +ABS .* -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl1 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl3 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl4 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl5 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl6 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl7 -[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +11 bl8 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl1 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl3 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl4 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl5 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl6 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl7 +[0-9 ]+: [0-9a-f]+ +0 +TLS +LOCAL +DEFAULT +9 bl8 .* FILE +LOCAL +DEFAULT +ABS .* -[0-9 ]+: [0-9a-f]+ +0 +OBJECT +LOCAL +DEFAULT +12 _DYNAMIC -[0-9 ]+: [0-9a-f]+ +0 +OBJECT +LOCAL +DEFAULT +7 _PROCEDURE_LINKAGE_TABLE_ -[0-9 ]+: [0-9a-f]+ +0 +OBJECT +LOCAL +DEFAULT +13 _GLOBAL_OFFSET_TABLE_ -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg8 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg8 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg6 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg3 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg3 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh3 +[0-9 ]+: [0-9a-f]+ +0 +OBJECT +LOCAL +DEFAULT +10 _DYNAMIC +[0-9 ]+: [0-9a-f]+ +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_ +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg8 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg8 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg6 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg3 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg3 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh3 [0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +UND sG2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg4 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg5 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg5 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg4 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg5 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg5 [0-9 ]+: [0-9a-f]+ +0 +FUNC +GLOBAL +DEFAULT +UND __tls_get_addr -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh7 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh8 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg1 -[0-9 ]+: [0-9a-f]+ +52 +FUNC +GLOBAL +DEFAULT +8 _start -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh4 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg7 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh5 -[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_start -[0-9 ]+: [0-9a-f]+ +136 +FUNC +GLOBAL +DEFAULT +\[STD GPLOAD\] +8 fn2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh7 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh8 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg1 +[0-9 ]+: [0-9a-f]+ +52 +FUNC +GLOBAL +DEFAULT +6 _start +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh4 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg7 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh5 +[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +11 __bss_start +[0-9 ]+: [0-9a-f]+ +136 +FUNC +GLOBAL +DEFAULT +\[STD GPLOAD\] +6 fn2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg2 [0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +UND sG1 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh1 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg6 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +10 sg7 -[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +13 _edata -[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +10 sh6 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg2 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg1 -[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +11 bg4 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh1 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg6 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +8 sg7 +[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata +[0-9 ]+: [0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +11 _end +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +HIDDEN +8 sh6 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg2 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg1 +[0-9 ]+: [0-9a-f]+ +0 +TLS +GLOBAL +DEFAULT +9 bg4 -- 2.34.1