i386: Allow copy relocs for building PIE
This patch allows copy relocs for R_386_GOTOFF relocations in PIE. For extern int glob_a; int foo () { return glob_a; } compiler now can optimize it from call __x86.get_pc_thunk.ax addl $_GLOBAL_OFFSET_TABLE_, %eax movl glob_a@GOT(%eax), %eax movl (%eax), %eax ret to call __x86.get_pc_thunk.ax addl $_GLOBAL_OFFSET_TABLE_, %eax movl glob_a@GOTOFF(%eax), %eax ret bfd/ PR ld/18289 * elf32-i386.c (elf_i386_link_hash_entry): Add gotoff_ref. (elf_i386_link_hash_newfunc): Initialize gotoff_ref to 0. (elf_i386_create_dynamic_sections): Always allow copy relocs for building executables. (elf_i386_copy_indirect_symbol): Also copy gotoff_ref. (elf_i386_check_relocs): Set gotoff_ref for R_386_GOTOFF. (elf_i386_adjust_dynamic_symbol): Also allocate copy relocs for PIE and R_386_GOTOFF. (elf_i386_relocate_section): Allow R_386_GOTOFF in executable. ld/testsuite/ PR ld/18289 * ld-i386/copyreloc-lib.c: New file. * ld-i386/copyreloc-main.S: Likewise. * ld-i386/copyreloc-main.out: Likewise. * ld-i386/copyreloc-main1.rd: Likewise. * ld-i386/copyreloc-main2.rd: Likewise. * ld-i386/dummy.c: Likewise. * ld-i386/pr17689.out: Likewise. * ld-i386/pr17689.rd: Likewise. * ld-i386/pr17689a.c: Likewise. * ld-i386/pr17689b.S: Likewise. * ld-i386/pr17827.rd: Likewise. * ld-i386/pr17827ver.rd: Likewise. * ld-i386/i386.exp: Run copyreloc tests.
This commit is contained in:
parent
712e55b924
commit
d5597ebccc
|
@ -1,3 +1,16 @@
|
|||
2015-04-22 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/18289
|
||||
* elf32-i386.c (elf_i386_link_hash_entry): Add gotoff_ref.
|
||||
(elf_i386_link_hash_newfunc): Initialize gotoff_ref to 0.
|
||||
(elf_i386_create_dynamic_sections): Always allow copy relocs for
|
||||
building executables.
|
||||
(elf_i386_copy_indirect_symbol): Also copy gotoff_ref.
|
||||
(elf_i386_check_relocs): Set gotoff_ref for R_386_GOTOFF.
|
||||
(elf_i386_adjust_dynamic_symbol): Also allocate copy relocs for
|
||||
PIE and R_386_GOTOFF.
|
||||
(elf_i386_relocate_section): Allow R_386_GOTOFF in executable.
|
||||
|
||||
2015-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf.c (assign_section_numbers): Always set up sh_name.
|
||||
|
|
|
@ -756,6 +756,9 @@ struct elf_i386_link_hash_entry
|
|||
(GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
|
||||
unsigned char tls_type;
|
||||
|
||||
/* Symbol is referenced by R_386_GOTOFF relocation. */
|
||||
unsigned int gotoff_ref : 1;
|
||||
|
||||
/* Information about the GOT PLT entry. Filled when there are both
|
||||
GOT and PLT relocations against the same function. */
|
||||
union gotplt_union plt_got;
|
||||
|
@ -879,6 +882,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
eh = (struct elf_i386_link_hash_entry *) entry;
|
||||
eh->dyn_relocs = NULL;
|
||||
eh->tls_type = GOT_UNKNOWN;
|
||||
eh->gotoff_ref = 0;
|
||||
eh->plt_got.offset = (bfd_vma) -1;
|
||||
eh->tlsdesc_got = (bfd_vma) -1;
|
||||
}
|
||||
|
@ -1022,13 +1026,28 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
|
|||
return FALSE;
|
||||
|
||||
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
|
||||
if (!info->shared)
|
||||
htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss");
|
||||
|
||||
if (!htab->sdynbss
|
||||
|| (!info->shared && !htab->srelbss))
|
||||
if (!htab->sdynbss)
|
||||
abort ();
|
||||
|
||||
if (info->executable)
|
||||
{
|
||||
/* Always allow copy relocs for building executables. */
|
||||
asection *s = bfd_get_linker_section (dynobj, ".rel.bss");
|
||||
if (s == NULL)
|
||||
{
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
|
||||
s = bfd_make_section_anyway_with_flags (dynobj,
|
||||
".rel.bss",
|
||||
(bed->dynamic_sec_flags
|
||||
| SEC_READONLY));
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (dynobj, s,
|
||||
bed->s->log_file_align))
|
||||
return FALSE;
|
||||
}
|
||||
htab->srelbss = s;
|
||||
}
|
||||
|
||||
if (get_elf_i386_backend_data (dynobj)->is_vxworks
|
||||
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
||||
&htab->srelplt2))
|
||||
|
@ -1101,6 +1120,10 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info,
|
|||
eind->tls_type = GOT_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Copy gotoff_ref so that elf_i386_adjust_dynamic_symbol will
|
||||
generate a R_386_COPY reloc. */
|
||||
edir->gotoff_ref |= eind->gotoff_ref;
|
||||
|
||||
if (ELIMINATE_COPY_RELOCS
|
||||
&& ind->root.type != bfd_link_hash_indirect
|
||||
&& dir->dynamic_adjusted)
|
||||
|
@ -1475,6 +1498,7 @@ elf_i386_check_relocs (bfd *abfd,
|
|||
unsigned int r_type;
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
struct elf_i386_link_hash_entry *eh;
|
||||
Elf_Internal_Sym *isym;
|
||||
const char *name;
|
||||
bfd_boolean size_reloc;
|
||||
|
@ -1524,6 +1548,7 @@ elf_i386_check_relocs (bfd *abfd,
|
|||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
|
||||
eh = (struct elf_i386_link_hash_entry *) h;
|
||||
if (h != NULL)
|
||||
{
|
||||
/* Create the ifunc sections for static executables. If we
|
||||
|
@ -1535,11 +1560,12 @@ elf_i386_check_relocs (bfd *abfd,
|
|||
default:
|
||||
break;
|
||||
|
||||
case R_386_GOTOFF:
|
||||
eh->gotoff_ref = 1;
|
||||
case R_386_32:
|
||||
case R_386_PC32:
|
||||
case R_386_PLT32:
|
||||
case R_386_GOT32:
|
||||
case R_386_GOTOFF:
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
|
||||
|
@ -1791,7 +1817,7 @@ do_size:
|
|||
relocations we need for this symbol. */
|
||||
if (h != NULL)
|
||||
{
|
||||
head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
|
||||
head = &eh->dyn_relocs;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2175,12 +2201,14 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
only references to the symbol are via the global offset table.
|
||||
For such cases we need not do anything here; the relocations will
|
||||
be handled correctly by relocate_section. */
|
||||
if (info->shared)
|
||||
if (!info->executable)
|
||||
return TRUE;
|
||||
|
||||
/* If there are no references to this symbol that do not use the
|
||||
GOT, we don't need to generate a copy reloc. */
|
||||
if (!h->non_got_ref)
|
||||
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
|
||||
reloc. */
|
||||
eh = (struct elf_i386_link_hash_entry *) h;
|
||||
if (!h->non_got_ref && !eh->gotoff_ref)
|
||||
return TRUE;
|
||||
|
||||
/* If -z nocopyreloc was given, we won't generate them either. */
|
||||
|
@ -2194,14 +2222,15 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
if (htab == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* If there aren't any dynamic relocs in read-only sections, then
|
||||
we can keep the dynamic relocs and avoid the copy reloc. This
|
||||
doesn't work on VxWorks, where we can not have dynamic relocations
|
||||
(other than copy and jump slot relocations) in an executable. */
|
||||
/* If there aren't any dynamic relocs in read-only sections nor
|
||||
R_386_GOTOFF relocation, then we can keep the dynamic relocs and
|
||||
avoid the copy reloc. This doesn't work on VxWorks, where we can
|
||||
not have dynamic relocations (other than copy and jump slot
|
||||
relocations) in an executable. */
|
||||
if (ELIMINATE_COPY_RELOCS
|
||||
&& !eh->gotoff_ref
|
||||
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
|
||||
{
|
||||
eh = (struct elf_i386_link_hash_entry *) h;
|
||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||
{
|
||||
s = p->sec->output_section;
|
||||
|
@ -3718,7 +3747,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|
|||
symbol for shared library since it may not be local when
|
||||
used as function address or with copy relocation. We also
|
||||
need to make sure that a symbol is referenced locally. */
|
||||
if (info->shared && h)
|
||||
if (!info->executable && h)
|
||||
{
|
||||
if (!h->def_regular)
|
||||
{
|
||||
|
@ -3746,8 +3775,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|
|||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
else if (!info->executable
|
||||
&& !SYMBOL_REFERENCES_LOCAL (info, h)
|
||||
else if (!SYMBOL_REFERENCES_LOCAL (info, h)
|
||||
&& (h->type == STT_FUNC
|
||||
|| h->type == STT_OBJECT)
|
||||
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
2015-04-22 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/18289
|
||||
* ld-i386/copyreloc-lib.c: New file.
|
||||
* ld-i386/copyreloc-main.S: Likewise.
|
||||
* ld-i386/copyreloc-main.out: Likewise.
|
||||
* ld-i386/copyreloc-main1.rd: Likewise.
|
||||
* ld-i386/copyreloc-main2.rd: Likewise.
|
||||
* ld-i386/dummy.c: Likewise.
|
||||
* ld-i386/pr17689.out: Likewise.
|
||||
* ld-i386/pr17689.rd: Likewise.
|
||||
* ld-i386/pr17689a.c: Likewise.
|
||||
* ld-i386/pr17689b.S: Likewise.
|
||||
* ld-i386/pr17827.rd: Likewise.
|
||||
* ld-i386/pr17827ver.rd: Likewise.
|
||||
* ld-i386/i386.exp: Run copyreloc tests.
|
||||
|
||||
2015-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* ld-mmix/bspec1.d: Don't hardcode offset of .shstrtab section.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
int a_glob = 2;
|
|
@ -0,0 +1,24 @@
|
|||
.section .text.startup,"ax",@progbits
|
||||
.p2align 4,,15
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
.cfi_startproc
|
||||
call __x86.get_pc_thunk.ax
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %eax
|
||||
cmpl $2, a_glob@GOTOFF(%eax)
|
||||
setne %al
|
||||
movzbl %al, %eax
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size main, .-main
|
||||
.section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
|
||||
.globl __x86.get_pc_thunk.ax
|
||||
.hidden __x86.get_pc_thunk.ax
|
||||
.type __x86.get_pc_thunk.ax, @function
|
||||
__x86.get_pc_thunk.ax:
|
||||
.cfi_startproc
|
||||
movl (%esp), %eax
|
||||
ret
|
||||
.cfi_endproc
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,3 @@
|
|||
#...
|
||||
[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +a_glob
|
||||
#...
|
|
@ -0,0 +1,4 @@
|
|||
#failif
|
||||
#...
|
||||
[0-9a-f ]+R_386_NONE.*
|
||||
#...
|
|
@ -0,0 +1 @@
|
|||
/* An empty file. */
|
|
@ -335,6 +335,78 @@ if { [isnative]
|
|||
{{readelf {-Wr} plt-main.rd}} \
|
||||
"plt-main" \
|
||||
] \
|
||||
[list \
|
||||
"Build copyreloc-lib.so" \
|
||||
"-shared" \
|
||||
"-fPIC" \
|
||||
{ copyreloc-lib.c } \
|
||||
{} \
|
||||
"copyreloc-lib.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build copyreloc-main with PIE and GOTOFF (1)" \
|
||||
"tmpdir/copyreloc-lib.so -pie" \
|
||||
"" \
|
||||
{ copyreloc-main.S } \
|
||||
{{readelf {-Wr} copyreloc-main1.rd}} \
|
||||
"copyreloc-main" \
|
||||
] \
|
||||
[list \
|
||||
"Build copyreloc-main with PIE and GOTOFF (2)" \
|
||||
"tmpdir/copyreloc-lib.so -pie" \
|
||||
"" \
|
||||
{ copyreloc-main.S } \
|
||||
{{readelf {-Wr} copyreloc-main2.rd}} \
|
||||
"copyreloc-main" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17689.so" \
|
||||
"-shared" \
|
||||
"-fPIC" \
|
||||
{ pr17689a.c } \
|
||||
{} \
|
||||
"pr17689.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17689ver.so" \
|
||||
"-shared -Wl,--version-script,pr17689a.t" \
|
||||
"-fPIC" \
|
||||
{ pr17689a.c } \
|
||||
{} \
|
||||
"pr17689ver.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17689.a" \
|
||||
"" \
|
||||
"" \
|
||||
{ pr17689b.S } \
|
||||
{} \
|
||||
"pr17689.a" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17689 with PIE and GOTOFF" \
|
||||
"tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
|
||||
"" \
|
||||
{ dummy.c } \
|
||||
{{readelf {-Wr} pr17689.rd}} \
|
||||
"pr17689" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17689ver with PIE and GOTOFF" \
|
||||
"tmpdir/pr17689b.o tmpdir/pr17689ver.so -pie" \
|
||||
"" \
|
||||
{ dummy.c } \
|
||||
{{readelf {-Wr} pr17689ver.rd}} \
|
||||
"pr17689ver" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr17827 with PIE and GOTOFF" \
|
||||
"tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
|
||||
"" \
|
||||
{ dummy.c } \
|
||||
{{readelf {-Wr} pr17827.rd}} \
|
||||
"pr17827" \
|
||||
] \
|
||||
]
|
||||
|
||||
run_ld_link_exec_tests [] [list \
|
||||
|
@ -357,5 +429,29 @@ if { [isnative]
|
|||
"plt-main.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run copyreloc-main with PIE and GOTOFF" \
|
||||
"tmpdir/copyreloc-lib.so -pie" \
|
||||
"" \
|
||||
{ copyreloc-main.S } \
|
||||
"copyreloc-main" \
|
||||
"copyreloc-main.out" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr17689 with PIE and GOTOFF" \
|
||||
"tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
|
||||
"" \
|
||||
{ dummy.c } \
|
||||
"pr17689" \
|
||||
"pr17689.out" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr17689ver with PIE and GOTOFF" \
|
||||
"tmpdir/pr17689b.o tmpdir/pr17689ver.so -pie" \
|
||||
"" \
|
||||
{ dummy.c } \
|
||||
"pr17689ver" \
|
||||
"pr17689.out" \
|
||||
] \
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
PASS
|
||||
PASS
|
|
@ -0,0 +1,3 @@
|
|||
#...
|
||||
[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +bar
|
||||
#...
|
|
@ -0,0 +1,10 @@
|
|||
#include <stdio.h>
|
||||
|
||||
char *bar = "PASS";
|
||||
extern char *bar_alias __attribute__ ((weak, alias ("bar")));
|
||||
|
||||
void
|
||||
foo (char *x)
|
||||
{
|
||||
printf ("%s\n", x);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
VERSION {
|
||||
global:
|
||||
bar_alias; bar; foo;
|
||||
local:
|
||||
*;
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
.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
|
||||
pushl bar_alias@GOTOFF(%ebx)
|
||||
call foo@PLT
|
||||
popl %eax
|
||||
movl ptr@GOTOFF(%ebx), %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
|
||||
.globl ptr
|
||||
.section .data.rel.local,"aw",@progbits
|
||||
.align 4
|
||||
.type ptr, @object
|
||||
.size ptr, 4
|
||||
ptr:
|
||||
.long bar_alias
|
||||
.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
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,3 @@
|
|||
#...
|
||||
[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +bar@VERSION
|
||||
#...
|
|
@ -0,0 +1,4 @@
|
|||
#failif
|
||||
#...
|
||||
[0-9a-f ]+R_386_NONE.*
|
||||
#...
|
Loading…
Reference in New Issue