From 9e9821ddd80c0d0b3dda54d34cc8867f256d4583 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 24 Apr 2017 14:37:12 -0700 Subject: [PATCH] x86-64: Force symbol dynamic if it isn't undefined weak Force symbol dynamic if it isn't undefined weak. Generate relative relocation for GOT reference against non-dynamic symbol in PIC to avoid unnecessary dynamic symbols. bfd/ * elf64-x86-64.c (elf_x86_64_link_hash_entry): Add no_finish_dynamic_symbol. (elf_x86_64_link_hash_newfunc): Set no_finish_dynamic_symbol to 0. (elf_x86_64_allocate_dynrelocs): If a symbol isn't undefined weak symbol, don't make it dynamic. (elf_x86_64_relocate_section): If a symbol isn't dynamic in PIC, set no_finish_dynamic_symbol and generate R_X86_64_RELATIVE relocation for GOT reference. (elf_x86_64_finish_dynamic_symbol): Abort if no_finish_dynamic_symbol isn't 0. ld/ * testsuite/ld-x86-64/no-plt.exp: Also check no-plt-1e.nd. * testsuite/ld-x86-64/no-plt-1e.nd: New file. --- bfd/ChangeLog | 14 ++++++ bfd/elf64-x86-64.c | 66 ++++++++++++++++++++--------- ld/ChangeLog | 5 +++ ld/testsuite/ld-x86-64/no-plt-1e.nd | 7 +++ ld/testsuite/ld-x86-64/no-plt.exp | 2 +- 5 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/no-plt-1e.nd diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 54e2f0dbb97..b902a768a40 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2017-04-24 H.J. Lu + + * elf64-x86-64.c (elf_x86_64_link_hash_entry): Add + no_finish_dynamic_symbol. + (elf_x86_64_link_hash_newfunc): Set no_finish_dynamic_symbol to + 0. + (elf_x86_64_allocate_dynrelocs): If a symbol isn't undefined + weak symbol, don't make it dynamic. + (elf_x86_64_relocate_section): If a symbol isn't dynamic in PIC, + set no_finish_dynamic_symbol and generate R_X86_64_RELATIVE + relocation for GOT reference. + (elf_x86_64_finish_dynamic_symbol): Abort if + no_finish_dynamic_symbol isn't 0. + 2017-04-24 H.J. Lu PR ld/21402 diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 746b847744e..965ceb2f334 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -867,6 +867,9 @@ struct elf_x86_64_link_hash_entry /* TRUE if symbol has non-GOT/non-PLT relocations in text sections. */ unsigned int has_non_got_reloc : 1; + /* Don't call finish_dynamic_symbol on this symbol. */ + unsigned int no_finish_dynamic_symbol : 1; + /* 0: symbol isn't __tls_get_addr. 1: symbol is __tls_get_addr. 2: symbol is unknown. */ @@ -1022,6 +1025,7 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry, eh->has_bnd_reloc = 0; eh->has_got_reloc = 0; eh->has_non_got_reloc = 0; + eh->no_finish_dynamic_symbol = 0; eh->tls_get_addr = 2; eh->func_pointer_refcount = 0; eh->plt_bnd.offset = (bfd_vma) -1; @@ -3218,7 +3222,8 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 && !h->forced_local - && !resolved_to_zero) + && !resolved_to_zero + && h->root.type == bfd_link_hash_undefweak) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -3338,7 +3343,8 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 && !h->forced_local - && !resolved_to_zero) + && !resolved_to_zero + && h->root.type == bfd_link_hash_undefweak) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -3475,6 +3481,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) if (h->dynindx == -1 && ! h->forced_local && ! resolved_to_zero + && h->root.type == bfd_link_hash_undefweak && ! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -4270,6 +4277,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, asection *base_got, *resolved_plt; bfd_vma st_size; bfd_boolean resolved_to_zero; + bfd_boolean relative_reloc; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_X86_64_GNU_VTINHERIT @@ -4637,6 +4645,7 @@ do_ifunc_pointer: if (htab->elf.sgot == NULL) abort (); + relative_reloc = FALSE; if (h != NULL) { bfd_boolean dyn; @@ -4683,6 +4692,17 @@ do_ifunc_pointer: /* Note that this is harmless for the GOTPLT64 case, as -1 | 1 still is -1. */ h->got.offset |= 1; + + if (h->dynindx == -1 + && !h->forced_local + && h->root.type != bfd_link_hash_undefweak + && bfd_link_pic (info)) + { + /* If this symbol isn't dynamic in PIC, + generate R_X86_64_RELATIVE here. */ + eh->no_finish_dynamic_symbol = 1; + relative_reloc = TRUE; + } } } else @@ -4704,30 +4724,32 @@ do_ifunc_pointer: { bfd_put_64 (output_bfd, relocation, base_got->contents + off); + local_got_offsets[r_symndx] |= 1; if (bfd_link_pic (info)) - { - asection *s; - Elf_Internal_Rela outrel; - - /* We need to generate a R_X86_64_RELATIVE reloc - for the dynamic linker. */ - s = htab->elf.srelgot; - if (s == NULL) - abort (); - - outrel.r_offset = (base_got->output_section->vma - + base_got->output_offset - + off); - outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); - outrel.r_addend = relocation; - elf_append_rela (output_bfd, s, &outrel); - } - - local_got_offsets[r_symndx] |= 1; + relative_reloc = TRUE; } } + if (relative_reloc) + { + asection *s; + Elf_Internal_Rela outrel; + + /* We need to generate a R_X86_64_RELATIVE reloc + for the dynamic linker. */ + s = htab->elf.srelgot; + if (s == NULL) + abort (); + + outrel.r_offset = (base_got->output_section->vma + + base_got->output_offset + + off); + outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); + outrel.r_addend = relocation; + elf_append_rela (output_bfd, s, &outrel); + } + if (off >= (bfd_vma) -2) abort (); @@ -5797,6 +5819,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, : get_elf_x86_64_backend_data (output_bfd)); eh = (struct elf_x86_64_link_hash_entry *) h; + if (eh->no_finish_dynamic_symbol) + abort (); /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for resolved undefined weak symbols in executable so that their diff --git a/ld/ChangeLog b/ld/ChangeLog index d40086eeb8c..ed3797e9ede 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2017-04-24 H.J. Lu + + * testsuite/ld-x86-64/no-plt.exp: Also check no-plt-1e.nd. + * testsuite/ld-x86-64/no-plt-1e.nd: New file. + 2017-04-24 H.J. Lu * testsuite/ld-i386/pr12570a.d: Skip for nacl targets. diff --git a/ld/testsuite/ld-x86-64/no-plt-1e.nd b/ld/testsuite/ld-x86-64/no-plt-1e.nd new file mode 100644 index 00000000000..c96760c6e51 --- /dev/null +++ b/ld/testsuite/ld-x86-64/no-plt-1e.nd @@ -0,0 +1,7 @@ +#nm: -g -D +#target: x86_64-*-* + +#failif +#... +[0-9]+ +T +func +#... diff --git a/ld/testsuite/ld-x86-64/no-plt.exp b/ld/testsuite/ld-x86-64/no-plt.exp index 5b5c8177569..9cecd035381 100644 --- a/ld/testsuite/ld-x86-64/no-plt.exp +++ b/ld/testsuite/ld-x86-64/no-plt.exp @@ -111,7 +111,7 @@ run_cc_link_tests [list \ tmpdir/no-plt-func1.o tmpdir/no-plt-extern1.o" \ "" \ {dummy.s} \ - {{readelf -Wr no-plt-1e.rd} {objdump -dwrj.text no-plt-1e.dd}} \ + {{readelf -Wr no-plt-1e.rd} {nm -gD no-plt-1e.nd} {objdump -dwrj.text no-plt-1e.dd}} \ "no-plt-1e" \ ] \ [list \ -- 2.30.2