diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-02-14 03:50:40 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-02-14 03:50:55 -0800 |
commit | 451875b4f976a527395e9303224c7881b65e12ed (patch) | |
tree | 15ebc416aa1dd49b234ad02dfdf8a9ebe4f92f11 /bfd/elf64-x86-64.c | |
parent | f98b2e334fcca666afaee3c6546b9fc91a4963d4 (diff) | |
download | gdb-451875b4f976a527395e9303224c7881b65e12ed.zip gdb-451875b4f976a527395e9303224c7881b65e12ed.tar.gz gdb-451875b4f976a527395e9303224c7881b65e12ed.tar.bz2 |
x86-64: Use PLT address for PC-relative reloc
Since PLT in PDE and PC-relative PLT in PIE can be used as function
address, there is no need for dynamic PC-relative relocation against
a dynamic function definition in PIE. Linker should resolve PC-relative
reference to its PLT address.
NB: i386 has non-PIC PLT and PIC PLT. Only non-PIC PLT in PDE can
be used as function address. PIC PLT in PIE can't be used as
function address.
bfd/
PR ld/22842
* elf32-i386.c (elf_i386_check_relocs): Pass FALSE for non
PC-relative PLT to NEED_DYNAMIC_RELOCATION_P.
* elf64-x86-64.c (elf_x86_64_check_relocs): Create PLT for
R_X86_64_PC32 reloc against dynamic function in data section.
Pass TRUE for PC-relative PLT to NEED_DYNAMIC_RELOCATION_P.
(elf_x86_64_relocate_section): Use PLT for R_X86_64_PC32 reloc
against dynamic function in data section.
* elfxx-x86.c (elf_x86_allocate_dynrelocs): Use PLT in PIE as
function address only if pcrel_plt is true.
(_bfd_x86_elf_link_hash_table_create): Set pcrel_plt.
* elfxx-x86.h (NEED_DYNAMIC_RELOCATION_P): Add PCREL_PLT for
PC-relative PLT. If PLT is PC-relative, don't generate dynamic
PC-relative relocation against a function definition in data
secton in PIE. Remove the obsolete comments.
(elf_x86_link_hash_table): Add pcrel_plt.
ld/
PR ld/22842
* testsuite/ld-i386/i386.exp: Run PR ld/22842 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr22842a.c: New file.
* testsuite/ld-i386/pr22842b.S: Likewise.
* testsuite/ld-x86-64/pr22842a.c: Likewise.
* testsuite/ld-x86-64/pr22842a.rd: Likewise.
* testsuite/ld-x86-64/pr22842b.S: Likewise.
* testsuite/ld-x86-64/pr22842b.rd: Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 0e4bb2e..00ed5d1 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2135,7 +2135,17 @@ pointer: as pointer, make sure that PLT is used if foo is a function defined in a shared library. */ if ((sec->flags & SEC_CODE) == 0) - h->pointer_equality_needed = 1; + { + h->pointer_equality_needed = 1; + if (bfd_link_pie (info) + && h->type == STT_FUNC + && !h->def_regular + && h->def_dynamic) + { + h->needs_plt = 1; + h->plt.refcount = 1; + } + } } else if (r_type != R_X86_64_PC32_BND && r_type != R_X86_64_PC64) @@ -2173,7 +2183,7 @@ pointer: size_reloc = FALSE; do_size: - if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type, + if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, htab->pointer_r_type)) { struct elf_dyn_relocs *p; @@ -2968,6 +2978,7 @@ do_ifunc_pointer: break; } +use_plt: if (h->plt.offset != (bfd_vma) -1) { if (htab->plt_second != NULL) @@ -3046,6 +3057,15 @@ do_ifunc_pointer: return elf_x86_64_need_pic (info, input_bfd, input_section, h, NULL, NULL, howto); } + /* Since x86-64 has PC-relative PLT, we can use PLT in PIE + as function address. */ + else if (h != NULL + && (input_section->flags & SEC_CODE) == 0 + && bfd_link_pie (info) + && h->type == STT_FUNC + && !h->def_regular + && h->def_dynamic) + goto use_plt; /* Fall through. */ case R_X86_64_8: |