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.
This commit is contained in:
parent
f98b2e334f
commit
451875b4f9
|
@ -1,3 +1,22 @@
|
|||
2018-02-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
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.
|
||||
|
||||
2018-02-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elfxx-x86.c (elf_x86_allocate_dynrelocs): Check bfd_link_dll,
|
||||
|
|
|
@ -1812,7 +1812,7 @@ do_relocation:
|
|||
|
||||
size_reloc = FALSE;
|
||||
do_size:
|
||||
if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type,
|
||||
if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
|
||||
R_386_32))
|
||||
{
|
||||
struct elf_dyn_relocs *p;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -179,6 +179,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
asection *s = htab->elf.splt;
|
||||
asection *second_s = htab->plt_second;
|
||||
asection *got_s = htab->plt_got;
|
||||
bfd_boolean use_plt;
|
||||
|
||||
/* If this is the first .plt entry, make room for the special
|
||||
first entry. The .plt section is used by prelink to undo
|
||||
|
@ -196,12 +197,19 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
}
|
||||
|
||||
/* If this symbol is not defined in a regular file, and we are
|
||||
not generating a shared library, then set the symbol to this
|
||||
location in the .plt. This is required to make function
|
||||
pointers compare as equal between the normal executable and
|
||||
the shared library. */
|
||||
if (! bfd_link_dll (info)
|
||||
&& !h->def_regular)
|
||||
generating PDE, then set the symbol to this location in the
|
||||
.plt. This is required to make function pointers compare
|
||||
as equal between PDE and the shared library.
|
||||
|
||||
NB: If PLT is PC-relative, we can use the .plt in PIE for
|
||||
function address. */
|
||||
if (h->def_regular)
|
||||
use_plt = FALSE;
|
||||
else if (htab->pcrel_plt)
|
||||
use_plt = ! bfd_link_dll (info);
|
||||
else
|
||||
use_plt = bfd_link_pde (info);
|
||||
if (use_plt)
|
||||
{
|
||||
if (use_plt_got)
|
||||
{
|
||||
|
@ -771,6 +779,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
|
|||
ret->dt_reloc_sz = DT_RELASZ;
|
||||
ret->dt_reloc_ent = DT_RELAENT;
|
||||
ret->got_entry_size = 8;
|
||||
ret->pcrel_plt = TRUE;
|
||||
ret->tls_get_addr = "__tls_get_addr";
|
||||
}
|
||||
if (ABI_64_P (abfd))
|
||||
|
@ -798,6 +807,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
|
|||
ret->dt_reloc_ent = DT_RELENT;
|
||||
ret->sizeof_reloc = sizeof (Elf32_External_Rel);
|
||||
ret->got_entry_size = 4;
|
||||
ret->pcrel_plt = FALSE;
|
||||
ret->pointer_r_type = R_386_32;
|
||||
ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
|
||||
ret->dynamic_interpreter_size
|
||||
|
|
|
@ -76,14 +76,11 @@
|
|||
into the shared library. However, if we are linking with -Bsymbolic,
|
||||
we do not need to copy a reloc against a global symbol which is
|
||||
defined in an object we are including in the link (i.e., DEF_REGULAR
|
||||
is set). At this point we have not seen all the input files, so it
|
||||
is possible that DEF_REGULAR is not set now but will be set later (it
|
||||
is never cleared). In case of a weak definition, DEF_REGULAR may be
|
||||
cleared later by a strong definition in a shared library. We account
|
||||
for that possibility below by storing information in the relocs_copied
|
||||
field of the hash table entry. A similar situation occurs when
|
||||
creating shared libraries and symbol visibility changes render the
|
||||
symbol local.
|
||||
is set).
|
||||
|
||||
If PCREL_PLT is true, don't generate dynamic relocation in PIE for
|
||||
PC-relative relocation against a dynamic function definition in data
|
||||
section when PLT address can be used.
|
||||
|
||||
If on the other hand, we are creating an executable, we may need to
|
||||
keep relocations for symbols satisfied by a dynamic library if we
|
||||
|
@ -91,23 +88,30 @@
|
|||
|
||||
We also need to generate dynamic pointer relocation against
|
||||
STT_GNU_IFUNC symbol in the non-code section. */
|
||||
#define NEED_DYNAMIC_RELOCATION_P(INFO, H, SEC, R_TYPE, POINTER_TYPE) \
|
||||
#define NEED_DYNAMIC_RELOCATION_P(INFO, PCREL_PLT, H, SEC, R_TYPE, \
|
||||
POINTER_TYPE) \
|
||||
((bfd_link_pic (INFO) \
|
||||
&& (! X86_PCREL_TYPE_P (R_TYPE) \
|
||||
|| ((H) != NULL \
|
||||
&& (! (bfd_link_pie (INFO) \
|
||||
|| SYMBOLIC_BIND ((INFO), (H))) \
|
||||
|| (H)->root.type == bfd_link_hash_defweak \
|
||||
|| !(H)->def_regular)))) \
|
||||
|| ((H) != NULL \
|
||||
&& (H)->type == STT_GNU_IFUNC \
|
||||
&& (R_TYPE) == POINTER_TYPE \
|
||||
&& ((SEC)->flags & SEC_CODE) == 0) \
|
||||
|| (ELIMINATE_COPY_RELOCS \
|
||||
&& !bfd_link_pic (INFO) \
|
||||
&& (H) != NULL \
|
||||
&& ((H)->root.type == bfd_link_hash_defweak \
|
||||
|| !(H)->def_regular)))
|
||||
|| (!(bfd_link_pie (INFO) \
|
||||
&& (PCREL_PLT) \
|
||||
&& (H)->plt.refcount > 0 \
|
||||
&& ((SEC)->flags & SEC_CODE) == 0 \
|
||||
&& (H)->type == STT_FUNC \
|
||||
&& (H)->def_dynamic) \
|
||||
&& !(H)->def_regular))))) \
|
||||
|| ((H) != NULL \
|
||||
&& (H)->type == STT_GNU_IFUNC \
|
||||
&& (R_TYPE) == POINTER_TYPE \
|
||||
&& ((SEC)->flags & SEC_CODE) == 0) \
|
||||
|| (ELIMINATE_COPY_RELOCS \
|
||||
&& !bfd_link_pic (INFO) \
|
||||
&& (H) != NULL \
|
||||
&& ((H)->root.type == bfd_link_hash_defweak \
|
||||
|| !(H)->def_regular)))
|
||||
|
||||
/* TRUE if dynamic relocation should be generated. Don't copy a
|
||||
pc-relative relocation into the output file if the symbol needs
|
||||
|
@ -482,6 +486,14 @@ struct elf_x86_link_hash_table
|
|||
/* TRUE if GOT is referenced. */
|
||||
unsigned int got_referenced : 1;
|
||||
|
||||
/* TRUE if PLT is PC-relative. PLT in PDE and PC-relative PLT in PIE
|
||||
can be used as function 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. */
|
||||
unsigned int pcrel_plt : 1;
|
||||
|
||||
bfd_vma (*r_info) (bfd_vma, bfd_vma);
|
||||
bfd_vma (*r_sym) (bfd_vma);
|
||||
bfd_boolean (*is_reloc_section) (const char *);
|
||||
|
|
12
ld/ChangeLog
12
ld/ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2018-02-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
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.
|
||||
|
||||
2018-02-14 Maciej W. Rozycki <macro@mips.com>
|
||||
|
||||
* ldlex.h (ldlex_command): Remove prototype.
|
||||
|
|
|
@ -1273,6 +1273,14 @@ if { [isnative]
|
|||
{} \
|
||||
"pr21997-1.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr22842.so" \
|
||||
"-shared" \
|
||||
"-fPIC" \
|
||||
{ pr22842a.c } \
|
||||
{} \
|
||||
"pr22842.so" \
|
||||
] \
|
||||
]
|
||||
|
||||
run_ld_link_exec_tests [list \
|
||||
|
@ -1371,6 +1379,14 @@ if { [isnative]
|
|||
"pr21997-1-pie-2" \
|
||||
"pass.out" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr22842" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
|
||||
"" \
|
||||
{ pr22842b.S } \
|
||||
"pr22842" \
|
||||
"pass.out" \
|
||||
] \
|
||||
]
|
||||
|
||||
if { [at_least_gcc_version 5 0] } {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
test (void)
|
||||
{
|
||||
static int count;
|
||||
if (count)
|
||||
printf("PASS\n");
|
||||
count++;
|
||||
}
|
||||
|
||||
void
|
||||
foo (void (*bar) (void))
|
||||
{
|
||||
if (bar != test)
|
||||
abort ();
|
||||
bar ();
|
||||
test ();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
.text
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
leal 4(%esp), %ecx
|
||||
andl $-16, %esp
|
||||
pushl -4(%ecx)
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
call __x86.get_pc_thunk.bx
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %ebx
|
||||
subl $12, %esp
|
||||
movl bar@GOT(%ebx), %eax
|
||||
addl (%eax), %eax
|
||||
pushl %eax
|
||||
call foo@PLT
|
||||
addl $16, %esp
|
||||
leal -8(%ebp), %esp
|
||||
xorl %eax, %eax
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
leal -4(%ecx), %esp
|
||||
ret
|
||||
.size main, .-main
|
||||
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
|
||||
.globl __x86.get_pc_thunk.bx
|
||||
.hidden __x86.get_pc_thunk.bx
|
||||
.type __x86.get_pc_thunk.bx, @function
|
||||
__x86.get_pc_thunk.bx:
|
||||
movl (%esp), %ebx
|
||||
ret
|
||||
|
||||
.data
|
||||
.p2align 2
|
||||
bar:
|
||||
.long test - .
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
test (void)
|
||||
{
|
||||
static int count;
|
||||
if (count)
|
||||
printf("PASS\n");
|
||||
count++;
|
||||
}
|
||||
|
||||
void
|
||||
foo (void (*bar) (void))
|
||||
{
|
||||
if (bar != test)
|
||||
abort ();
|
||||
bar ();
|
||||
test ();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#failif
|
||||
#...
|
||||
[0-9a-f ]+R_X86_64_NONE.*
|
||||
#...
|
|
@ -0,0 +1,20 @@
|
|||
.text
|
||||
.globl main
|
||||
.type main,@function
|
||||
main:
|
||||
pushq %rax
|
||||
movslq bar(%rip), %rax
|
||||
leaq bar(%rip), %rdi
|
||||
addq %rax, %rdi
|
||||
|
||||
callq foo
|
||||
xorl %eax, %eax
|
||||
popq %rcx
|
||||
retq
|
||||
|
||||
.data
|
||||
.p2align 2
|
||||
bar:
|
||||
.long test - .
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,4 @@
|
|||
#failif
|
||||
#...
|
||||
[0-9a-f ]+R_X86_64_PC32 +[0-9a-f]+ +test \+ 0
|
||||
#...
|
|
@ -1190,6 +1190,23 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
{{readelf -drW pr22791-2.rd}} \
|
||||
"pr22791-2" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr22842.so" \
|
||||
"-shared" \
|
||||
"-fPIC" \
|
||||
{ pr22842a.c } \
|
||||
{} \
|
||||
"pr22842.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr22842" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
|
||||
"" \
|
||||
{ pr22842b.S } \
|
||||
{{readelf -rW pr22842a.rd} \
|
||||
{readelf -rW pr22842b.rd}} \
|
||||
"pr22842" \
|
||||
] \
|
||||
]
|
||||
|
||||
if {[istarget "x86_64-*-linux*-gnux32"]} {
|
||||
|
@ -1524,6 +1541,14 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
"pass.out" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr22842" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
|
||||
"" \
|
||||
{ pr22842b.S } \
|
||||
"pr22842" \
|
||||
"pass.out" \
|
||||
] \
|
||||
]
|
||||
|
||||
# Run-time tests which require working ifunc attribute support.
|
||||
|
|
Loading…
Reference in New Issue