Skip PLT for function pointer initialization

We use its PLT entry to initialize function pointer at run-time.  If
there is no other usage for the PLT entry, we can generate run-time
function pointer relocations in read-write section, which can be
resolved by dynamic linker, to initialize function pointers.  It avoids
the extra indirect branch overhead in PLT.

bfd/

	PR ld/18900
	* elf32-i386.c (elf_i386_link_hash_entry): Add
	func_pointer_refcount.
	(elf_i386_link_hash_newfunc): Clear func_pointer_refcount.
	(elf_i386_get_local_sym_hash): Likewise.
	(elf_i386_copy_indirect_symbol): Also copy
	func_pointer_refcount.
	(elf_i386_check_relocs): Increment func_pointer_refcount.
	(elf_i386_gc_sweep_hook): Decrement func_pointer_refcount.
	(elf_i386_allocate_dynrelocs): Don't create the PLT entry if
	there are only function pointer relocations which can be
	resolved at run-time.  Keep dynanamic relocations for run-time
	function pointer initialization.
	(elf_i386_relocate_section): Copy dynamic function pointer
	relocations.
	* elf64-x86-64.c (elf_x86_64_link_hash_entry): Add
	func_pointer_refcount.
	(elf_x86_64_link_hash_newfunc): Clear func_pointer_refcount.
	(elf_x86_64_get_local_sym_hash): Likewise.
	(elf_x86_64_copy_indirect_symbol): Also copy
	func_pointer_refcount.
	(elf_x86_64_check_relocs): Increment func_pointer_refcount.
	(elf_x86_64_gc_sweep_hook): Decrement func_pointer_refcount.
	(elf_x86_64_allocate_dynrelocs): Don't create the PLT entry if
	there are only function pointer relocations which can be
	resolved at run-time.  Keep dynanamic relocations for run-time
	function pointer initialization.
	(elf_x86_64_relocate_section): Copy dynamic function pointer
	relocations.

ld/testsuite/

	PR ld/18900
	* ld-i386/i386.exp: Run tests for PR ld/18900.
	* ld-x86-64/x86-64.exp: Likewise.
	* ld-i386/pr18900.out: New file.
	* ld-i386/pr18900a.c: Likewise.
	* ld-i386/pr18900a.c: Likewise.
	* ld-i386/pr18900a.rd: Likewise.
	* ld-i386/pr18900b.c: Likewise.
	* ld-i386/pr18900b.rd: Likewise.
	* ld-i386/pr18900c.c: Likewise.
	* ld-x86-64/pr18900.out: Likewise.
	* ld-x86-64/pr18900a.c: Likewise.
	* ld-x86-64/pr18900a.rd: Likewise.
	* ld-x86-64/pr18900b.c: Likewise.
	* ld-x86-64/pr18900b.rd: Likewise.
	* ld-x86-64/pr18900c.c: Likewise.
	* ld-x86-64/mpx3.dd: Updated.
This commit is contained in:
H.J. Lu
2015-09-01 05:06:16 -07:00
parent b07bca4ecd
commit 04ebc307f9
19 changed files with 349 additions and 33 deletions

View File

@ -1,3 +1,35 @@
2015-09-01 H.J. Lu <hongjiu.lu@intel.com>
PR ld/18900
* elf32-i386.c (elf_i386_link_hash_entry): Add
func_pointer_refcount.
(elf_i386_link_hash_newfunc): Clear func_pointer_refcount.
(elf_i386_get_local_sym_hash): Likewise.
(elf_i386_copy_indirect_symbol): Also copy
func_pointer_refcount.
(elf_i386_check_relocs): Increment func_pointer_refcount.
(elf_i386_gc_sweep_hook): Decrement func_pointer_refcount.
(elf_i386_allocate_dynrelocs): Don't create the PLT entry if
there are only function pointer relocations which can be
resolved at run-time. Keep dynanamic relocations for run-time
function pointer initialization.
(elf_i386_relocate_section): Copy dynamic function pointer
relocations.
* elf64-x86-64.c (elf_x86_64_link_hash_entry): Add
func_pointer_refcount.
(elf_x86_64_link_hash_newfunc): Clear func_pointer_refcount.
(elf_x86_64_get_local_sym_hash): Likewise.
(elf_x86_64_copy_indirect_symbol): Also copy
func_pointer_refcount.
(elf_x86_64_check_relocs): Increment func_pointer_refcount.
(elf_x86_64_gc_sweep_hook): Decrement func_pointer_refcount.
(elf_x86_64_allocate_dynrelocs): Don't create the PLT entry if
there are only function pointer relocations which can be
resolved at run-time. Keep dynanamic relocations for run-time
function pointer initialization.
(elf_x86_64_relocate_section): Copy dynamic function pointer
relocations.
2015-09-01 Alan Modra <amodra@gmail.com> 2015-09-01 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_maybe_function_sym): Adjust symbol value * elf64-ppc.c (ppc64_elf_maybe_function_sym): Adjust symbol value

View File

@ -759,6 +759,10 @@ struct elf_i386_link_hash_entry
/* Symbol is referenced by R_386_GOTOFF relocation. */ /* Symbol is referenced by R_386_GOTOFF relocation. */
unsigned int gotoff_ref : 1; unsigned int gotoff_ref : 1;
/* Reference count of C/C++ function pointer relocations in read-write
section which can be resolved at run-time. */
bfd_signed_vma func_pointer_refcount;
/* Information about the GOT PLT entry. Filled when there are both /* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */ GOT and PLT relocations against the same function. */
union gotplt_union plt_got; union gotplt_union plt_got;
@ -883,6 +887,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
eh->dyn_relocs = NULL; eh->dyn_relocs = NULL;
eh->tls_type = GOT_UNKNOWN; eh->tls_type = GOT_UNKNOWN;
eh->gotoff_ref = 0; eh->gotoff_ref = 0;
eh->func_pointer_refcount = 0;
eh->plt_got.offset = (bfd_vma) -1; eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1; eh->tlsdesc_got = (bfd_vma) -1;
} }
@ -952,6 +957,7 @@ elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab,
ret->elf.indx = sec->id; ret->elf.indx = sec->id;
ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info); ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info);
ret->elf.dynindx = -1; ret->elf.dynindx = -1;
ret->func_pointer_refcount = 0;
ret->plt_got.offset = (bfd_vma) -1; ret->plt_got.offset = (bfd_vma) -1;
*slot = ret; *slot = ret;
} }
@ -1138,7 +1144,15 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info,
dir->pointer_equality_needed |= ind->pointer_equality_needed; dir->pointer_equality_needed |= ind->pointer_equality_needed;
} }
else else
_bfd_elf_link_hash_copy_indirect (info, dir, ind); {
if (eind->func_pointer_refcount > 0)
{
edir->func_pointer_refcount += eind->func_pointer_refcount;
eind->func_pointer_refcount = 0;
}
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
} }
/* Return TRUE if the TLS access code sequence support transition /* Return TRUE if the TLS access code sequence support transition
@ -1759,7 +1773,13 @@ elf_i386_check_relocs (bfd *abfd,
refers to is in a shared lib. */ refers to is in a shared lib. */
h->plt.refcount += 1; h->plt.refcount += 1;
if (r_type != R_386_PC32) if (r_type != R_386_PC32)
h->pointer_equality_needed = 1; {
h->pointer_equality_needed = 1;
/* R_386_32 can be resolved at run-time. */
if (r_type == R_386_32
&& (sec->flags & SEC_READONLY) == 0)
eh->func_pointer_refcount += 1;
}
} }
size_reloc = FALSE; size_reloc = FALSE;
@ -2076,6 +2096,14 @@ elf_i386_gc_sweep_hook (bfd *abfd,
{ {
if (h->plt.refcount > 0) if (h->plt.refcount > 0)
h->plt.refcount -= 1; h->plt.refcount -= 1;
if (r_type == R_386_32
&& (sec->flags & SEC_READONLY) == 0)
{
struct elf_i386_link_hash_entry *eh
= (struct elf_i386_link_hash_entry *) h;
if (eh->func_pointer_refcount > 0)
eh->func_pointer_refcount -= 1;
}
} }
break; break;
@ -2298,6 +2326,11 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd); plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
/* Clear the reference count of function pointer relocations if
symbol isn't a normal function. */
if (h->type != STT_FUNC)
eh->func_pointer_refcount = 0;
/* We can't use the GOT PLT if pointer equality is needed since /* We can't use the GOT PLT if pointer equality is needed since
finish_dynamic_symbol won't clear symbol value and the dynamic finish_dynamic_symbol won't clear symbol value and the dynamic
linker won't update the GOT slot. We will get into an infinite linker won't update the GOT slot. We will get into an infinite
@ -2323,11 +2356,18 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs,
plt_entry_size, plt_entry_size,
plt_entry_size, 4); plt_entry_size, 4);
/* Don't create the PLT entry if there are only function pointer
relocations which can be resolved at run-time. */
else if (htab->elf.dynamic_sections_created else if (htab->elf.dynamic_sections_created
&& (h->plt.refcount > 0 || eh->plt_got.refcount > 0)) && (h->plt.refcount > eh->func_pointer_refcount
|| eh->plt_got.refcount > 0))
{ {
bfd_boolean use_plt_got; bfd_boolean use_plt_got;
/* Clear the reference count of function pointer relocations
if PLT is used. */
eh->func_pointer_refcount = 0;
if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed) if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
{ {
/* Don't use the regular PLT for DF_BIND_NOW. */ /* Don't use the regular PLT for DF_BIND_NOW. */
@ -2570,9 +2610,10 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
{ {
/* For the non-shared case, discard space for relocs against /* For the non-shared case, discard space for relocs against
symbols which turn out to need copy relocs or are not symbols which turn out to need copy relocs or are not
dynamic. */ dynamic. Keep dynamic relocations for run-time function
pointer initialization. */
if (!h->non_got_ref if ((!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic && ((h->def_dynamic
&& !h->def_regular) && !h->def_regular)
|| (htab->elf.dynamic_sections_created || (htab->elf.dynamic_sections_created
@ -2595,6 +2636,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
} }
eh->dyn_relocs = NULL; eh->dyn_relocs = NULL;
eh->func_pointer_refcount = 0;
keep: ; keep: ;
} }
@ -3687,6 +3729,7 @@ elf_i386_relocate_section (bfd *output_bfd,
} }
} }
eh = (struct elf_i386_link_hash_entry *) h;
switch (r_type) switch (r_type)
{ {
case R_386_GOT32: case R_386_GOT32:
@ -3855,7 +3898,6 @@ elf_i386_relocate_section (bfd *output_bfd,
if (h == NULL) if (h == NULL)
break; break;
eh = (struct elf_i386_link_hash_entry *) h;
if ((h->plt.offset == (bfd_vma) -1 if ((h->plt.offset == (bfd_vma) -1
&& eh->plt_got.offset == (bfd_vma) -1) && eh->plt_got.offset == (bfd_vma) -1)
|| htab->elf.splt == NULL) || htab->elf.splt == NULL)
@ -3894,6 +3936,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls) || is_vxworks_tls)
break; break;
/* Copy dynamic function pointer relocations. */
if ((bfd_link_pic (info) if ((bfd_link_pic (info)
&& (h == NULL && (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@ -3904,7 +3947,7 @@ elf_i386_relocate_section (bfd *output_bfd,
&& !bfd_link_pic (info) && !bfd_link_pic (info)
&& h != NULL && h != NULL
&& h->dynindx != -1 && h->dynindx != -1
&& !h->non_got_ref && (!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic && ((h->def_dynamic
&& !h->def_regular) && !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefweak

View File

@ -767,6 +767,10 @@ struct elf_x86_64_link_hash_entry
/* TRUE if symbol has at least one BND relocation. */ /* TRUE if symbol has at least one BND relocation. */
unsigned int has_bnd_reloc : 1; unsigned int has_bnd_reloc : 1;
/* Reference count of C/C++ function pointer relocations in read-write
section which can be resolved at run-time. */
bfd_signed_vma func_pointer_refcount;
/* Information about the GOT PLT entry. Filled when there are both /* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */ GOT and PLT relocations against the same function. */
union gotplt_union plt_got; union gotplt_union plt_got;
@ -906,6 +910,7 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
eh->tls_type = GOT_UNKNOWN; eh->tls_type = GOT_UNKNOWN;
eh->needs_copy = 0; eh->needs_copy = 0;
eh->has_bnd_reloc = 0; eh->has_bnd_reloc = 0;
eh->func_pointer_refcount = 0;
eh->plt_bnd.offset = (bfd_vma) -1; eh->plt_bnd.offset = (bfd_vma) -1;
eh->plt_got.offset = (bfd_vma) -1; eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1; eh->tlsdesc_got = (bfd_vma) -1;
@ -976,6 +981,7 @@ elf_x86_64_get_local_sym_hash (struct elf_x86_64_link_hash_table *htab,
ret->elf.indx = sec->id; ret->elf.indx = sec->id;
ret->elf.dynstr_index = htab->r_sym (rel->r_info); ret->elf.dynstr_index = htab->r_sym (rel->r_info);
ret->elf.dynindx = -1; ret->elf.dynindx = -1;
ret->func_pointer_refcount = 0;
ret->plt_got.offset = (bfd_vma) -1; ret->plt_got.offset = (bfd_vma) -1;
*slot = ret; *slot = ret;
} }
@ -1173,7 +1179,15 @@ elf_x86_64_copy_indirect_symbol (struct bfd_link_info *info,
dir->pointer_equality_needed |= ind->pointer_equality_needed; dir->pointer_equality_needed |= ind->pointer_equality_needed;
} }
else else
_bfd_elf_link_hash_copy_indirect (info, dir, ind); {
if (eind->func_pointer_refcount > 0)
{
edir->func_pointer_refcount += eind->func_pointer_refcount;
eind->func_pointer_refcount = 0;
}
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
} }
static bfd_boolean static bfd_boolean
@ -1950,7 +1964,22 @@ pointer:
if (r_type != R_X86_64_PC32 if (r_type != R_X86_64_PC32
&& r_type != R_X86_64_PC32_BND && r_type != R_X86_64_PC32_BND
&& r_type != R_X86_64_PC64) && r_type != R_X86_64_PC64)
h->pointer_equality_needed = 1; {
h->pointer_equality_needed = 1;
/* At run-time, R_X86_64_64 can be resolved for both
x86-64 and x32. But R_X86_64_32 and R_X86_64_32S
can only be resolved for x32. */
if ((sec->flags & SEC_READONLY) == 0
&& (r_type == R_X86_64_64
|| (!ABI_64_P (abfd)
&& (r_type == R_X86_64_32
|| r_type == R_X86_64_32S))))
{
struct elf_x86_64_link_hash_entry *eh
= (struct elf_x86_64_link_hash_entry *) h;
eh->func_pointer_refcount += 1;
}
}
} }
size_reloc = FALSE; size_reloc = FALSE;
@ -2177,6 +2206,7 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
unsigned long r_symndx; unsigned long r_symndx;
unsigned int r_type; unsigned int r_type;
struct elf_link_hash_entry *h = NULL; struct elf_link_hash_entry *h = NULL;
bfd_boolean pointer_reloc;
r_symndx = htab->r_sym (rel->r_info); r_symndx = htab->r_sym (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info) if (r_symndx >= symtab_hdr->sh_info)
@ -2228,6 +2258,7 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
rel, relend, h, r_symndx)) rel, relend, h, r_symndx))
return FALSE; return FALSE;
pointer_reloc = FALSE;
switch (r_type) switch (r_type)
{ {
case R_X86_64_TLSLD: case R_X86_64_TLSLD:
@ -2261,11 +2292,15 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
} }
break; break;
case R_X86_64_32:
case R_X86_64_32S:
pointer_reloc = !ABI_64_P (abfd);
goto pointer;
case R_X86_64_64:
pointer_reloc = TRUE;
case R_X86_64_8: case R_X86_64_8:
case R_X86_64_16: case R_X86_64_16:
case R_X86_64_32:
case R_X86_64_64:
case R_X86_64_32S:
case R_X86_64_PC8: case R_X86_64_PC8:
case R_X86_64_PC16: case R_X86_64_PC16:
case R_X86_64_PC32: case R_X86_64_PC32:
@ -2273,6 +2308,7 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_PC64: case R_X86_64_PC64:
case R_X86_64_SIZE32: case R_X86_64_SIZE32:
case R_X86_64_SIZE64: case R_X86_64_SIZE64:
pointer:
if (bfd_link_pic (info) if (bfd_link_pic (info)
&& (h == NULL || h->type != STT_GNU_IFUNC)) && (h == NULL || h->type != STT_GNU_IFUNC))
break; break;
@ -2285,6 +2321,13 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
{ {
if (h->plt.refcount > 0) if (h->plt.refcount > 0)
h->plt.refcount -= 1; h->plt.refcount -= 1;
if (pointer_reloc && (sec->flags & SEC_READONLY) == 0)
{
struct elf_x86_64_link_hash_entry *eh
= (struct elf_x86_64_link_hash_entry *) h;
if (eh->func_pointer_refcount > 0)
eh->func_pointer_refcount -= 1;
}
} }
break; break;
@ -2516,6 +2559,11 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
eh->plt_got.refcount = 1; eh->plt_got.refcount = 1;
} }
/* Clear the reference count of function pointer relocations if
symbol isn't a normal function. */
if (h->type != STT_FUNC)
eh->func_pointer_refcount = 0;
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
here if it is defined and referenced in a non-shared object. */ here if it is defined and referenced in a non-shared object. */
if (h->type == STT_GNU_IFUNC if (h->type == STT_GNU_IFUNC
@ -2542,11 +2590,18 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
else else
return FALSE; return FALSE;
} }
/* Don't create the PLT entry if there are only function pointer
relocations which can be resolved at run-time. */
else if (htab->elf.dynamic_sections_created else if (htab->elf.dynamic_sections_created
&& (h->plt.refcount > 0 || eh->plt_got.refcount > 0)) && (h->plt.refcount > eh->func_pointer_refcount
|| eh->plt_got.refcount > 0))
{ {
bfd_boolean use_plt_got; bfd_boolean use_plt_got;
/* Clear the reference count of function pointer relocations
if PLT is used. */
eh->func_pointer_refcount = 0;
if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed) if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
{ {
/* Don't use the regular PLT for DF_BIND_NOW. */ /* Don't use the regular PLT for DF_BIND_NOW. */
@ -2791,9 +2846,10 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
{ {
/* For the non-shared case, discard space for relocs against /* For the non-shared case, discard space for relocs against
symbols which turn out to need copy relocs or are not symbols which turn out to need copy relocs or are not
dynamic. */ dynamic. Keep dynamic relocations for run-time function
pointer initialization. */
if (!h->non_got_ref if ((!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic && ((h->def_dynamic
&& !h->def_regular) && !h->def_regular)
|| (htab->elf.dynamic_sections_created || (htab->elf.dynamic_sections_created
@ -2814,6 +2870,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
} }
eh->dyn_relocs = NULL; eh->dyn_relocs = NULL;
eh->func_pointer_refcount = 0;
keep: ; keep: ;
} }
@ -4346,7 +4403,8 @@ direct:
/* Don't copy a pc-relative relocation into the output file /* Don't copy a pc-relative relocation into the output file
if the symbol needs copy reloc or the symbol is undefined if the symbol needs copy reloc or the symbol is undefined
when building executable. */ when building executable. Copy dynamic function pointer
relocations. */
if ((bfd_link_pic (info) if ((bfd_link_pic (info)
&& !(bfd_link_executable (info) && !(bfd_link_executable (info)
&& h != NULL && h != NULL
@ -4365,7 +4423,7 @@ direct:
&& !bfd_link_pic (info) && !bfd_link_pic (info)
&& h != NULL && h != NULL
&& h->dynindx != -1 && h->dynindx != -1
&& !h->non_got_ref && (!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic && ((h->def_dynamic
&& !h->def_regular) && !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefweak

View File

@ -1,3 +1,23 @@
2015-09-01 H.J. Lu <hongjiu.lu@intel.com>
PR ld/18900
* ld-i386/i386.exp: Run tests for PR ld/18900.
* ld-x86-64/x86-64.exp: Likewise.
* ld-i386/pr18900.out: New file.
* ld-i386/pr18900a.c: Likewise.
* ld-i386/pr18900a.c: Likewise.
* ld-i386/pr18900a.rd: Likewise.
* ld-i386/pr18900b.c: Likewise.
* ld-i386/pr18900b.rd: Likewise.
* ld-i386/pr18900c.c: Likewise.
* ld-x86-64/pr18900.out: Likewise.
* ld-x86-64/pr18900a.c: Likewise.
* ld-x86-64/pr18900a.rd: Likewise.
* ld-x86-64/pr18900b.c: Likewise.
* ld-x86-64/pr18900b.rd: Likewise.
* ld-x86-64/pr18900c.c: Likewise.
* ld-x86-64/mpx3.dd: Updated.
2015-08-27 Alan Modra <amodra@gmail.com> 2015-08-27 Alan Modra <amodra@gmail.com>
* ld-powerpc/relocsort.s, * ld-powerpc/relocsort.d: New test. * ld-powerpc/relocsort.s, * ld-powerpc/relocsort.d: New test.

View File

@ -466,6 +466,30 @@ if { [isnative]
{{readelf {-Wr} pr17827.rd}} \ {{readelf {-Wr} pr17827.rd}} \
"pr17827" \ "pr17827" \
] \ ] \
[list \
"Build pr18900.so" \
"-shared" \
"-fPIC" \
{ pr18900a.c } \
"" \
"pr18900.so" \
] \
[list \
"Build pr18900a" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
{{readelf {-Wrd} pr18900a.rd}} \
"pr18900a" \
] \
[list \
"Build pr18900b" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
{{readelf {-Wrd} pr18900b.rd}} \
"pr18900b" \
] \
] ]
run_ld_link_exec_tests [] [list \ run_ld_link_exec_tests [] [list \
@ -520,6 +544,14 @@ if { [isnative]
"pr17689ver" \ "pr17689ver" \
"pr17689.out" \ "pr17689.out" \
] \ ] \
[list \
"Run pr18900" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
"pr18900" \
"pr18900.out" \
] \
] ]
} }

View File

@ -0,0 +1,4 @@
OK
OK
OK
OK

View File

@ -0,0 +1,14 @@
#include <stdio.h>
void
foo (void)
{
printf ("OK\n");
}
void *
bar (void)
{
foo ();
return &foo;
}

View File

@ -0,0 +1,4 @@
#failif
#...
.*\(TEXTREL\).*
#...

View File

@ -0,0 +1,22 @@
extern void abort (void);
extern void foo (void);
extern void *bar (void);
typedef void (*func_p) (void);
extern const func_p p1;
func_p p2 = &foo;
func_p p3 = &foo;
int
main ()
{
void *p = bar ();
p1 ();
p2 ();
p3 ();
if (p != p1)
abort ();
return 0;
}

View File

@ -0,0 +1,4 @@
#failif
#...
[0-9a-f ]+R_386_JUMP_SLOT[0-9a-f ]+foo
#...

View File

@ -0,0 +1,5 @@
extern void foo (void);
typedef void (*func_p) (void);
func_p p1 = &foo;

View File

@ -3,33 +3,26 @@
Disassembly of section .plt: Disassembly of section .plt:
0+400290 <.plt>: 0+[a-f0-9]+ <.plt>:
[ ]*[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 600400 <_GLOBAL_OFFSET_TABLE_\+0x8> [ ]*[a-f0-9]+: ff ([0-9a-f]{2} ){5} pushq 0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x8>
[ ]*[a-f0-9]+: f2 ff 25 6b 01 20 00 bnd jmpq \*0x20016b\(%rip\) # 600408 <_GLOBAL_OFFSET_TABLE_\+0x10> [ ]*[a-f0-9]+: f2 ff ([0-9a-f]{2} ){5} bnd jmpq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x10>
[ ]*[a-f0-9]+: 0f 1f 00 nopl \(%rax\) [ ]*[a-f0-9]+: 0f 1f 00 nopl \(%rax\)
[ ]*[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 [ ]*[a-f0-9]+: 68 00 00 00 00 pushq \$0x0
[ ]*[a-f0-9]+: f2 e9 e5 ff ff ff bnd jmpq 400290 <call1@plt-0x30> [ ]*[a-f0-9]+: f2 e9 ([0-9a-f]{2} ){4} bnd jmpq [a-f0-9]+ <call1@plt-0x20>
[ ]*[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\)
[ ]*[a-f0-9]+: 68 01 00 00 00 pushq \$0x1
[ ]*[a-f0-9]+: f2 e9 d5 ff ff ff bnd jmpq 400290 <call1@plt-0x30>
[ ]*[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) [ ]*[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\)
Disassembly of section .plt.bnd: Disassembly of section .plt.bnd:
0+4002c0 <call1@plt>: 0+[a-f0-9]+ <call1@plt>:
[ ]*[a-f0-9]+: f2 ff 25 49 01 20 00 bnd jmpq \*0x200149\(%rip\) # 600410 <_GLOBAL_OFFSET_TABLE_\+0x18> [ ]*[a-f0-9]+: f2 ff ([0-9a-f]{2} ){5} bnd jmpq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x18>
[ ]*[a-f0-9]+: 90 nop
0+4002c8 <call2@plt>:
[ ]*[a-f0-9]+: f2 ff 25 49 01 20 00 bnd jmpq \*0x200149\(%rip\) # 600418 <_GLOBAL_OFFSET_TABLE_\+0x20>
[ ]*[a-f0-9]+: 90 nop [ ]*[a-f0-9]+: 90 nop
Disassembly of section .text: Disassembly of section .text:
0+4002d0 <_start>: 0+[a-f0-9]+ <_start>:
[ ]*[a-f0-9]+: bf c0 02 40 00 mov \$0x4002c0,%edi [ ]*[a-f0-9]+: bf ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%edi
[ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi [ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi
[ ]*[a-f0-9]+: 48 8b 3d 41 01 20 00 mov 0x200141\(%rip\),%rdi # 600420 <func> [ ]*[a-f0-9]+: 48 8b ([0-9a-f]{2} ){5} mov 0x[a-f0-9]+\(%rip\),%rdi # [a-f0-9]+ <func>
[ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi [ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi
[ ]*[a-f0-9]+: c3 retq [ ]*[a-f0-9]+: c3 retq
#pass #pass

View File

@ -0,0 +1,4 @@
OK
OK
OK
OK

View File

@ -0,0 +1,14 @@
#include <stdio.h>
void
foo (void)
{
printf ("OK\n");
}
void *
bar (void)
{
foo ();
return &foo;
}

View File

@ -0,0 +1,4 @@
#failif
#...
.*\(TEXTREL\).*
#...

View File

@ -0,0 +1,22 @@
extern void abort (void);
extern void foo (void);
extern void *bar (void);
typedef void (*func_p) (void);
extern const func_p p1;
func_p p2 = &foo;
func_p p3 = &foo;
int
main ()
{
void *p = bar ();
p1 ();
p2 ();
p3 ();
if (p != p1)
abort ();
return 0;
}

View File

@ -0,0 +1,4 @@
#failif
#...
[0-9a-f ]+R_X86_64_JUMP_SLOT[0-9a-f ]+foo \+ 0
#...

View File

@ -0,0 +1,5 @@
extern void foo (void);
typedef void (*func_p) (void);
func_p p1 = &foo;

View File

@ -476,6 +476,30 @@ if { [isnative] && [which $CC] != 0 } {
{{readelf {-Wr} pr17827.rd}} \ {{readelf {-Wr} pr17827.rd}} \
"pr17827" \ "pr17827" \
] \ ] \
[list \
"Build pr18900.so" \
"-shared" \
"-fPIC" \
{ pr18900a.c } \
"" \
"pr18900.so" \
] \
[list \
"Build pr18900a" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
{{readelf {-Wrd} pr18900a.rd}} \
"pr18900a" \
] \
[list \
"Build pr18900b" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
{{readelf {-Wrd} pr18900b.rd}} \
"pr18900b" \
] \
] ]
run_ld_link_exec_tests [] [list \ run_ld_link_exec_tests [] [list \
@ -522,6 +546,14 @@ if { [isnative] && [which $CC] != 0 } {
"pr17689now" \ "pr17689now" \
"pr17689.out" \ "pr17689.out" \
] \ ] \
[list \
"Run pr18900" \
"tmpdir/pr18900.so" \
"" \
{ pr18900b.c pr18900c.c } \
"pr18900" \
"pr18900.out" \
] \
] ]
if { [istarget "x86_64-*-linux*"] \ if { [istarget "x86_64-*-linux*"] \