aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog61
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-ifunc.c176
-rw-r--r--bfd/elf32-i386.c262
-rw-r--r--bfd/elf64-x86-64.c257
-rw-r--r--bfd/elfnn-aarch64.c3
-rw-r--r--ld/ChangeLog91
-rw-r--r--ld/testsuite/ld-i386/i386.exp5
-rw-r--r--ld/testsuite/ld-i386/no-plt.exp118
-rw-r--r--ld/testsuite/ld-i386/pr13302.d4
-rw-r--r--ld/testsuite/ld-i386/pr20244-2a.d33
-rw-r--r--ld/testsuite/ld-i386/pr20244-2b.d3
-rw-r--r--ld/testsuite/ld-i386/pr20244-2c.d4
-rw-r--r--ld/testsuite/ld-i386/pr20253-1a.c8
-rw-r--r--ld/testsuite/ld-i386/pr20253-1b.S52
-rw-r--r--ld/testsuite/ld-i386/pr20253-1c.S35
-rw-r--r--ld/testsuite/ld-i386/pr20253-1d.S81
-rw-r--r--ld/testsuite/ld-i386/pr20253-2a.c8
-rw-r--r--ld/testsuite/ld-i386/pr20253-2b.S39
-rw-r--r--ld/testsuite/ld-i386/pr20253-2c.S24
-rw-r--r--ld/testsuite/ld-i386/pr20253-2d.S49
-rw-r--r--ld/testsuite/ld-i386/pr20253-3.d3
-rw-r--r--ld/testsuite/ld-i386/pr20253-3.s11
-rw-r--r--ld/testsuite/ld-i386/pr20253-4.s11
-rw-r--r--ld/testsuite/ld-i386/pr20253-4a.d8
-rw-r--r--ld/testsuite/ld-i386/pr20253-4b.d8
-rw-r--r--ld/testsuite/ld-i386/pr20253-4c.d9
-rw-r--r--ld/testsuite/ld-i386/pr20253-5.d7
-rw-r--r--ld/testsuite/ld-i386/pr20253-5.s10
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-13-i386.d4
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-13-x86-64.d4
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-15-i386.d4
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-15-x86-64.d4
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-18a-i386.d1
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-18a-x86-64.d1
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-18a.s2
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-18b-i386.d1
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-18b-x86-64.d1
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-21-i386.d26
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-21-x86-64.d26
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-22-i386.d26
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-22-x86-64.d26
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-23-x86.s10
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-23a-x86.d8
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-23b-x86.d8
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-23c-x86.d8
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-24-x86.s11
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-24a-x86.d8
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-24b-x86.d12
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-24c-x86.d12
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-25-x86.s12
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-25a-x86.d8
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-25b-x86.d12
-rw-r--r--ld/testsuite/ld-ifunc/ifunc-25c-x86.d12
-rw-r--r--ld/testsuite/ld-x86-64/no-plt.exp85
-rw-r--r--ld/testsuite/ld-x86-64/pr13082-5a.d4
-rw-r--r--ld/testsuite/ld-x86-64/pr13082-5b.d4
-rw-r--r--ld/testsuite/ld-x86-64/pr13082-6a.d4
-rw-r--r--ld/testsuite/ld-x86-64/pr13082-6b.d4
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1.s18
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1a.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1b.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1c.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1d.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1e.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1f.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1g.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1h.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1i.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1j.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1k.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-1l.d25
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-2a.c8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-2b.S46
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-2c.S29
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-2d.S61
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-3.d3
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-3.s11
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4.s11
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4a.d8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4b.d8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4c.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4d.d8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4e.d8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-4f.d9
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-5.s10
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-5a.d8
-rw-r--r--ld/testsuite/ld-x86-64/pr20253-5b.d8
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp21
89 files changed, 1876 insertions, 342 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 0e52b95..2173fc9 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,64 @@
+2016-06-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/20253
+ * elf-bfd.h (_bfd_elf_allocate_ifunc_dyn_relocs): Add an
+ bfd_boolean argument.
+ * elf-ifunc.c (_bfd_elf_create_ifunc_sections): Replace
+ "shared object" with "PIC object" in comments.
+ (_bfd_elf_allocate_ifunc_dyn_relocs): Updated. Replace
+ "shared object" with "PIC object" in comments. Avoid PLT if
+ requested. Generate dynamic relocations for non-GOT references.
+ Make room for the special first entry in PLT and allocate PLT
+ entry only for PLT and PC-relative references. Store dynamic
+ GOT relocations in .rel[a].iplt section for static executables.
+ If PLT isn't used, always use GOT for symbol value. Don't
+ allocate GOT entry if it isn't used.
+ * elf32-i386.c (elf_i386_check_relocs): Increment PLT reference
+ count only in the code section. Allocate dynamic pointer
+ relocation against STT_GNU_IFUNC symbol in the non-code section.
+ (elf_i386_adjust_dynamic_symbol): Increment PLT reference count
+ only for PC-relative references.
+ (elf_i386_allocate_dynrelocs): Pass TRUE to
+ _bfd_elf_allocate_ifunc_dyn_relocs.
+ (elf_i386_relocate_section): Allow R_386_GOT32/R_386_GOT32X
+ relocations against STT_GNU_IFUNC symbols without PLT. Generate
+ dynamic pointer relocation against STT_GNU_IFUNC symbol in
+ the non-code section and store it in the proper REL section.
+ Don't allow non-pointer relocation against STT_GNU_IFUNC symbol
+ without PLT.
+ (elf_i386_finish_dynamic_symbol): Generate dynamic
+ R_386_IRELATIVE and R_386_GLOB_DAT GOT relocations against
+ STT_GNU_IFUNC symbols without PLT.
+ (elf_i386_finish_dynamic_sections): Don't handle local
+ STT_GNU_IFUNC symbols here.
+ (elf_i386_output_arch_local_syms): Handle local STT_GNU_IFUNC
+ symbols here.
+ (elf_backend_output_arch_local_syms): New.
+ * elf32-x86-64.c (elf_i386_check_relocs): Increment PLT reference
+ count only in the code section. Allocate dynamic pointer
+ relocation against STT_GNU_IFUNC symbol in the non-code section.
+ (elf_x86_64_adjust_dynamic_symbol): Increment PLT reference
+ count only for PC-relative references.
+ (elf_x86_64_allocate_dynrelocs): Pass TRUE to
+ _bfd_elf_allocate_ifunc_dyn_relocs.
+ (elf_x86_64_relocate_section): Allow R_X86_64_GOTPCREL,
+ R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX and
+ R_X86_64_GOTPCREL64 relocations against STT_GNU_IFUNC symbols
+ without PLT. Generate dynamic pointer relocation against
+ STT_GNU_IFUNC symbol in the non-code section and store it in
+ the proper RELA section. Don't allow non-pointer relocation
+ against STT_GNU_IFUNC symbol without PLT.
+ (elf_x86_64_finish_dynamic_symbol): Generate dynamic
+ R_X86_64_IRELATIVE and R_X86_64_GLOB_DAT GOT relocations against
+ STT_GNU_IFUNC symbols without PLT.
+ (elf_x86_64_finish_dynamic_sections): Don't handle local
+ STT_GNU_IFUNC symbols here.
+ (elf_x86_64_output_arch_local_syms): Handle local STT_GNU_IFUNC
+ symbols here.
+ (elf_backend_output_arch_local_syms): New.
+ * elfnn-aarch64.c (elfNN_aarch64_allocate_ifunc_dynrelocs):
+ Pass FALSE to _bfd_elf_allocate_ifunc_dyn_relocs.
+
2016-06-17 Thomas Preud'homme <thomas.preudhomme@arm.com>
Tony Wang <tony.wang@arm.com>
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 6825530..163ef35 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2521,7 +2521,7 @@ extern bfd_boolean _bfd_elf_create_ifunc_sections
extern bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs
(struct bfd_link_info *, struct elf_link_hash_entry *,
struct elf_dyn_relocs **, bfd_boolean *, unsigned int,
- unsigned int, unsigned int);
+ unsigned int, unsigned int, bfd_boolean);
extern long _bfd_elf_ifunc_get_synthetic_symtab
(bfd *, long, asymbol **, long, asymbol **, asymbol **, asection *,
bfd_vma *(*) (bfd *, asymbol **, asection *, asection *));
diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c
index 1377fed..09cbf4a 100644
--- a/bfd/elf-ifunc.c
+++ b/bfd/elf-ifunc.c
@@ -55,7 +55,7 @@ _bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
if (bfd_link_pic (info))
{
- /* We need to create .rel[a].ifunc for shared objects. */
+ /* We need to create .rel[a].ifunc for PIC objects. */
const char *rel_sec = (bed->rela_plts_and_copies_p
? ".rela.ifunc" : ".rel.ifunc");
@@ -113,7 +113,8 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
bfd_boolean *readonly_dynrelocs_against_ifunc_p,
unsigned int plt_entry_size,
unsigned int plt_header_size,
- unsigned int got_entry_size)
+ unsigned int got_entry_size,
+ bfd_boolean avoid_plt)
{
asection *plt, *gotplt, *relplt;
struct elf_dyn_relocs *p;
@@ -121,13 +122,17 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
const struct elf_backend_data *bed;
struct elf_link_hash_table *htab;
bfd_boolean readonly_dynrelocs_against_ifunc;
-
- /* When a shared library references a STT_GNU_IFUNC symbol defined
- in executable, the address of the resolved function may be used.
- But in non-shared executable, the address of its .plt slot may
- be used. Pointer equality may not work correctly. PIE should
- be used if pointer equality is required here. */
- if (!bfd_link_pic (info)
+ /* If AVOID_PLT is TRUE, don't use PLT if possible. */
+ bfd_boolean use_plt = !avoid_plt || h->plt.refcount > 0;
+ bfd_boolean need_dynreloc = !use_plt || bfd_link_pic (info);
+
+ /* When a PIC object references a STT_GNU_IFUNC symbol defined
+ in executable or it isn't referenced via PLT, the address of
+ the resolved function may be used. But in non-PIC executable,
+ the address of its .plt slot may be used. Pointer equality may
+ not work correctly. PIE or non-PLT reference should be used if
+ pointer equality is required here. */
+ if (!need_dynreloc
&& (h->dynindx != -1
|| info->export_dynamic)
&& h->pointer_equality_needed)
@@ -144,16 +149,30 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
htab = elf_hash_table (info);
- /* When building shared library, we need to handle the case where it is
- marked with regular reference, but not non-GOT reference since the
- non-GOT reference bit may not be set here. */
- if (bfd_link_pic (info) && !h->non_got_ref && h->ref_regular)
- for (p = *head; p != NULL; p = p->next)
- if (p->count)
- {
- h->non_got_ref = 1;
- goto keep;
- }
+ /* When the symbol is marked with regular reference, if PLT isn't used
+ or we are building a PIC object, we must keep dynamic relocation
+ if there is non-GOT reference and use PLT if there is PC-relative
+ reference. */
+ if (need_dynreloc && h->ref_regular)
+ {
+ bfd_boolean keep = FALSE;
+ for (p = *head; p != NULL; p = p->next)
+ if (p->count)
+ {
+ h->non_got_ref = 1;
+ /* Need dynamic relocations for non-GOT reference. */
+ keep = TRUE;
+ if (p->pc_count)
+ {
+ /* Must use PLT for PC-relative reference. */
+ use_plt = TRUE;
+ need_dynreloc = bfd_link_pic (info);
+ break;
+ }
+ }
+ if (keep)
+ goto keep;
+ }
/* Support garbage collection against STT_GNU_IFUNC symbols. */
if (h->plt.refcount <= 0 && h->got.refcount <= 0)
@@ -165,7 +184,7 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
}
/* Return and discard space for dynamic relocations against it if
- it is never referenced in a non-shared object. */
+ it is never referenced. */
if (!h->ref_regular)
{
if (h->plt.refcount > 0
@@ -192,9 +211,9 @@ keep:
gotplt = htab->sgotplt;
relplt = htab->srelplt;
- /* If this is the first .plt entry, make room for the special
- first entry. */
- if (plt->size == 0)
+ /* If this is the first .plt entry and PLT is used, make room for
+ the special first entry. */
+ if (plt->size == 0 && use_plt)
plt->size += plt_header_size;
}
else
@@ -204,26 +223,31 @@ keep:
relplt = htab->irelplt;
}
- /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
- the original value for R_*_IRELATIVE. */
- h->plt.offset = plt->size;
+ if (use_plt)
+ {
+ /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
+ the original value for R_*_IRELATIVE. */
+ h->plt.offset = plt->size;
- /* Make room for this entry in the .plt/.iplt section. */
- plt->size += plt_entry_size;
+ /* Make room for this entry in the .plt/.iplt section. */
+ plt->size += plt_entry_size;
- /* We also need to make an entry in the .got.plt/.got.iplt section,
- which will be placed in the .got section by the linker script. */
- gotplt->size += got_entry_size;
+ /* We also need to make an entry in the .got.plt/.got.iplt section,
+ which will be placed in the .got section by the linker script. */
+ gotplt->size += got_entry_size;
+ }
/* We also need to make an entry in the .rel[a].plt/.rel[a].iplt
- section. */
- relplt->size += sizeof_reloc;
- relplt->reloc_count++;
+ section for GOTPLT relocation if PLT is used. */
+ if (use_plt)
+ {
+ relplt->size += sizeof_reloc;
+ relplt->reloc_count++;
+ }
/* We need dynamic relocation for STT_GNU_IFUNC symbol only when
- there is a non-GOT reference in a shared object. */
- if (!bfd_link_pic (info)
- || !h->non_got_ref)
+ there is a non-GOT reference in a PIC object or PLT isn't used. */
+ if (!need_dynreloc || !h->non_got_ref)
*head = NULL;
readonly_dynrelocs_against_ifunc = FALSE;
@@ -245,7 +269,20 @@ keep:
p = p->next;
}
while (p != NULL);
- htab->irelifunc->size += count * sizeof_reloc;
+
+ /* Dynamic relocations are stored in
+ 1. .rel[a].ifunc section in PIC object.
+ 2. .rel[a].got section in dynamic executable.
+ 3. .rel[a].iplt section in static executable. */
+ if (bfd_link_pic (info))
+ htab->irelifunc->size += count * sizeof_reloc;
+ else if (htab->splt != NULL)
+ htab->srelgot->size += count * sizeof_reloc;
+ else
+ {
+ relplt->size += count * sizeof_reloc;
+ relplt->reloc_count += count;
+ }
}
if (readonly_dynrelocs_against_ifunc_p)
@@ -254,34 +291,65 @@ keep:
/* For STT_GNU_IFUNC symbol, .got.plt has the real function address
and .got has the PLT entry adddress. We will load the GOT entry
with the PLT entry in finish_dynamic_symbol if it is used. For
- branch, it uses .got.plt. For symbol value,
- 1. Use .got.plt in a shared object if it is forced local or not
+ branch, it uses .got.plt. For symbol value, if PLT is used,
+ 1. Use .got.plt in a PIC object if it is forced local or not
dynamic.
- 2. Use .got.plt in a non-shared object if pointer equality isn't
+ 2. Use .got.plt in a non-PIC object if pointer equality isn't
needed.
3. Use .got.plt in PIE.
4. Use .got.plt if .got isn't used.
5. Otherwise use .got so that it can be shared among different
objects at run-time.
- We only need to relocate .got entry in shared object. */
- if (h->got.refcount <= 0
- || (bfd_link_pic (info)
- && (h->dynindx == -1
- || h->forced_local))
- || (!bfd_link_pic (info)
- && !h->pointer_equality_needed)
- || bfd_link_pie (info)
- || htab->sgot == NULL)
+ If PLT isn't used, always use .got for symbol value.
+ We only need to relocate .got entry in PIC object or in dynamic
+ executable without PLT. */
+ if (use_plt
+ && (h->got.refcount <= 0
+ || (bfd_link_pic (info)
+ && (h->dynindx == -1
+ || h->forced_local))
+ || (!bfd_link_pic (info)
+ && !h->pointer_equality_needed)
+ || bfd_link_pie (info)
+ || htab->sgot == NULL))
{
/* Use .got.plt. */
h->got.offset = (bfd_vma) -1;
}
else
{
- h->got.offset = htab->sgot->size;
- htab->sgot->size += got_entry_size;
- if (bfd_link_pic (info))
- htab->srelgot->size += sizeof_reloc;
+ if (!use_plt)
+ {
+ /* PLT isn't used. */
+ h->plt.offset = (bfd_vma) -1;
+ }
+ if (h->got.refcount <= 0)
+ {
+ /* GOT isn't need when there are only relocations for static
+ pointers. */
+ h->got.offset = (bfd_vma) -1;
+ }
+ else
+ {
+ h->got.offset = htab->sgot->size;
+ htab->sgot->size += got_entry_size;
+ /* Need to relocate the GOT entry in a PIC object or PLT isn't
+ used. Otherwise, the GOT entry will be filled with the PLT
+ entry and dynamic GOT relocation isn't needed. */
+ if (need_dynreloc)
+ {
+ /* For non-static executable, dynamic GOT relocation is in
+ .rel[a].got section, but for static executable, it is
+ in .rel[a].iplt section. */
+ if (htab->splt != NULL)
+ htab->srelgot->size += sizeof_reloc;
+ else
+ {
+ relplt->size += sizeof_reloc;
+ relplt->reloc_count++;
+ }
+ }
+ }
}
return TRUE;
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 2b7de33..4179572 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2164,9 +2164,13 @@ do_relocation:
adjust_dynamic_symbol. */
h->non_got_ref = 1;
- /* We may need a .plt entry if the function this reloc
- refers to is in a shared lib. */
- h->plt.refcount += 1;
+ /* We may need a .plt entry if the symbol is a function
+ defined in a shared lib or is a STT_GNU_IFUNC function
+ referenced from the code or read-only section. */
+ if (!h->def_regular
+ || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+ h->plt.refcount += 1;
+
if (r_type == R_386_PC32)
{
/* Since something like ".long foo - ." may be used
@@ -2207,7 +2211,10 @@ do_size:
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 manage to avoid copy relocs for the
- symbol. */
+ symbol.
+
+ Generate dynamic pointer relocation against STT_GNU_IFUNC
+ symbol in the non-code section. */
if ((bfd_link_pic (info)
&& (r_type != R_386_PC32
|| (h != NULL
@@ -2215,6 +2222,10 @@ do_size:
|| SYMBOLIC_BIND (info, h))
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
+ || (h != NULL
+ && h->type == STT_GNU_IFUNC
+ && r_type == R_386_32
+ && (sec->flags & SEC_CODE) == 0)
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
@@ -2448,12 +2459,17 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
if (pc_count || count)
{
- h->needs_plt = 1;
h->non_got_ref = 1;
- if (h->plt.refcount <= 0)
- h->plt.refcount = 1;
- else
- h->plt.refcount += 1;
+ if (pc_count)
+ {
+ /* Increment PLT reference count only for PC-relative
+ references. */
+ h->needs_plt = 1;
+ if (h->plt.refcount <= 0)
+ h->plt.refcount = 1;
+ else
+ h->plt.refcount += 1;
+ }
}
}
@@ -2643,7 +2659,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs,
&htab->readonly_dynrelocs_against_ifunc,
plt_entry_size,
- plt_entry_size, 4);
+ plt_entry_size, 4, TRUE);
/* 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
@@ -3898,8 +3914,6 @@ elf_i386_relocate_section (bfd *output_bfd,
continue;
abort ();
}
- else if (h->plt.offset == (bfd_vma) -1)
- abort ();
/* STT_GNU_IFUNC symbol must go through PLT. */
if (htab->elf.splt != NULL)
@@ -3913,77 +3927,10 @@ elf_i386_relocate_section (bfd *output_bfd,
gotplt = htab->elf.igotplt;
}
- relocation = (plt->output_section->vma
- + plt->output_offset + h->plt.offset);
-
switch (r_type)
{
default:
- if (h->root.root.string)
- name = h->root.root.string;
- else
- name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
- NULL);
- (*_bfd_error_handler)
- (_("%B: relocation %s against STT_GNU_IFUNC "
- "symbol `%s' isn't handled by %s"), input_bfd,
- elf_howto_table[r_type].name,
- name, __FUNCTION__);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
-
- case R_386_32:
- /* Generate dynamic relcoation only when there is a
- non-GOT reference in a shared object. */
- if (bfd_link_pic (info) && h->non_got_ref)
- {
- Elf_Internal_Rela outrel;
- asection *sreloc;
- bfd_vma offset;
-
- /* Need a dynamic relocation to get the real function
- adddress. */
- offset = _bfd_elf_section_offset (output_bfd,
- info,
- input_section,
- rel->r_offset);
- if (offset == (bfd_vma) -1
- || offset == (bfd_vma) -2)
- abort ();
-
- outrel.r_offset = (input_section->output_section->vma
- + input_section->output_offset
- + offset);
-
- if (h->dynindx == -1
- || h->forced_local
- || bfd_link_executable (info))
- {
- /* This symbol is resolved locally. */
- outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
- bfd_put_32 (output_bfd,
- (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset),
- contents + offset);
- }
- else
- outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
-
- sreloc = htab->elf.irelifunc;
- elf_append_rel (output_bfd, sreloc, &outrel);
-
- /* If this reloc is against an external symbol, we
- do not want to fiddle with the addend. Otherwise,
- we need to include the symbol value so that it
- becomes an addend for the dynamic reloc. For an
- internal symbol, we have updated addend. */
- continue;
- }
- /* FALLTHROUGH */
- case R_386_PC32:
- case R_386_PLT32:
- goto do_relocation;
+ break;
case R_386_GOT32:
case R_386_GOT32X:
@@ -3999,6 +3946,9 @@ elf_i386_relocate_section (bfd *output_bfd,
even just remember the offset, as finish_dynamic_symbol
would use that as offset into .got. */
+ if (h->plt.offset == (bfd_vma) -1)
+ abort ();
+
if (htab->elf.splt != NULL)
{
plt_index = h->plt.offset / plt_entry_size - 1;
@@ -4059,6 +4009,99 @@ elf_i386_relocate_section (bfd *output_bfd,
}
goto do_relocation;
+ }
+
+ if (h->plt.offset == (bfd_vma) -1)
+ {
+ /* Handle static pointers of STT_GNU_IFUNC symbols. */
+ if (r_type == R_386_32
+ && (input_section->flags & SEC_CODE) == 0)
+ goto do_ifunc_pointer;
+ goto bad_ifunc_reloc;
+ }
+
+ relocation = (plt->output_section->vma
+ + plt->output_offset + h->plt.offset);
+
+ switch (r_type)
+ {
+ default:
+bad_ifunc_reloc:
+ if (h->root.root.string)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+ NULL);
+ (*_bfd_error_handler)
+ (_("%B: relocation %s against STT_GNU_IFUNC "
+ "symbol `%s' isn't supported"), input_bfd,
+ howto->name, name);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+
+ case R_386_32:
+ /* Generate dynamic relcoation only when there is a
+ non-GOT reference in a shared object. */
+ if ((bfd_link_pic (info) && h->non_got_ref)
+ || h->plt.offset == (bfd_vma) -1)
+ {
+ Elf_Internal_Rela outrel;
+ asection *sreloc;
+ bfd_vma offset;
+
+do_ifunc_pointer:
+ /* Need a dynamic relocation to get the real function
+ adddress. */
+ offset = _bfd_elf_section_offset (output_bfd,
+ info,
+ input_section,
+ rel->r_offset);
+ if (offset == (bfd_vma) -1
+ || offset == (bfd_vma) -2)
+ abort ();
+
+ outrel.r_offset = (input_section->output_section->vma
+ + input_section->output_offset
+ + offset);
+
+ if (h->dynindx == -1
+ || h->forced_local
+ || bfd_link_executable (info))
+ {
+ /* This symbol is resolved locally. */
+ outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+ bfd_put_32 (output_bfd,
+ (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset),
+ contents + offset);
+ }
+ else
+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+
+ /* Dynamic relocations are stored in
+ 1. .rel.ifunc section in PIC object.
+ 2. .rel.got section in dynamic executable.
+ 3. .rel.iplt section in static executable. */
+ if (bfd_link_pic (info))
+ sreloc = htab->elf.irelifunc;
+ else if (htab->elf.splt != NULL)
+ sreloc = htab->elf.srelgot;
+ else
+ sreloc = htab->elf.irelplt;
+ elf_append_rel (output_bfd, sreloc, &outrel);
+
+ /* If this reloc is against an external symbol, we
+ do not want to fiddle with the addend. Otherwise,
+ we need to include the symbol value so that it
+ becomes an addend for the dynamic reloc. For an
+ internal symbol, we have updated addend. */
+ continue;
+ }
+ /* FALLTHROUGH */
+ case R_386_PC32:
+ case R_386_PLT32:
+ goto do_relocation;
case R_386_GOTOFF:
relocation -= (gotplt->output_section->vma
@@ -5432,6 +5475,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
&& !local_undefweak)
{
Elf_Internal_Rela rel;
+ asection *relgot = htab->elf.srelgot;
/* This symbol has an entry in the global offset table. Set it
up. */
@@ -5451,7 +5495,28 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
if (h->def_regular
&& h->type == STT_GNU_IFUNC)
{
- if (bfd_link_pic (info))
+ if (h->plt.offset == (bfd_vma) -1)
+ {
+ /* STT_GNU_IFUNC is referenced without PLT. */
+ if (htab->elf.splt == NULL)
+ {
+ /* use .rel[a].iplt section to store .got relocations
+ in static executable. */
+ relgot = htab->elf.irelplt;
+ }
+ if (SYMBOL_REFERENCES_LOCAL (info, h))
+ {
+ bfd_put_32 (output_bfd,
+ (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset),
+ htab->elf.sgot->contents + h->got.offset);
+ rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+ }
+ else
+ goto do_glob_dat;
+ }
+ else if (bfd_link_pic (info))
{
/* Generate R_386_GLOB_DAT. */
goto do_glob_dat;
@@ -5489,7 +5554,7 @@ do_glob_dat:
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
}
- elf_append_rel (output_bfd, htab->elf.srelgot, &rel);
+ elf_append_rel (output_bfd, relgot, &rel);
}
if (h->needs_copy)
@@ -5826,11 +5891,6 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
if (htab->elf.sgot && htab->elf.sgot->size > 0)
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
- /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
- htab_traverse (htab->loc_hash_table,
- elf_i386_finish_local_dynamic_symbol,
- info);
-
/* Fill PLT entries for undefined weak symbols in PIE. */
if (bfd_link_pie (info))
bfd_hash_traverse (&info->hash->table,
@@ -5840,6 +5900,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
return TRUE;
}
+/* Fill PLT/GOT entries and allocate dynamic relocations for local
+ STT_GNU_IFUNC symbols, which aren't in the ELF linker hash table.
+ It has to be done before elf_link_sort_relocs is called so that
+ dynamic relocations are properly sorted. */
+
+static bfd_boolean
+elf_i386_output_arch_local_syms
+ (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
+ void *flaginfo ATTRIBUTE_UNUSED,
+ int (*func) (void *, const char *,
+ Elf_Internal_Sym *,
+ asection *,
+ struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
+{
+ struct elf_i386_link_hash_table *htab = elf_i386_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
+ /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
+ htab_traverse (htab->loc_hash_table,
+ elf_i386_finish_local_dynamic_symbol,
+ info);
+
+ return TRUE;
+}
+
/* Return an array of PLT entry symbol values. */
static bfd_vma *
@@ -5982,6 +6069,7 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
#define elf_backend_fake_sections elf_i386_fake_sections
#define elf_backend_finish_dynamic_sections elf_i386_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_i386_finish_dynamic_symbol
+#define elf_backend_output_arch_local_syms elf_i386_output_arch_local_syms
#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook
#define elf_backend_grok_prstatus elf_i386_grok_prstatus
#define elf_backend_grok_psinfo elf_i386_grok_psinfo
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 57a3c73..f920208 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2556,9 +2556,13 @@ pointer:
adjust_dynamic_symbol. */
h->non_got_ref = 1;
- /* We may need a .plt entry if the function this reloc
- refers to is in a shared lib. */
- h->plt.refcount += 1;
+ /* We may need a .plt entry if the symbol is a function
+ defined in a shared lib or is a STT_GNU_IFUNC function
+ referenced from the code or read-only section. */
+ if (!h->def_regular
+ || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+ h->plt.refcount += 1;
+
if (r_type == R_X86_64_PC32)
{
/* Since something like ".long foo - ." may be used
@@ -2605,7 +2609,10 @@ do_size:
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 manage to avoid copy relocs for the
- symbol. */
+ symbol.
+
+ Generate dynamic pointer relocation against STT_GNU_IFUNC
+ symbol in the non-code section. */
if ((bfd_link_pic (info)
&& (! IS_X86_64_PCREL_TYPE (r_type)
|| (h != NULL
@@ -2613,6 +2620,10 @@ do_size:
|| SYMBOLIC_BIND (info, h))
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
+ || (h != NULL
+ && h->type == STT_GNU_IFUNC
+ && r_type == htab->pointer_r_type
+ && (sec->flags & SEC_CODE) == 0)
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
@@ -2850,12 +2861,17 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
if (pc_count || count)
{
- h->needs_plt = 1;
h->non_got_ref = 1;
- if (h->plt.refcount <= 0)
- h->plt.refcount = 1;
- else
- h->plt.refcount += 1;
+ if (pc_count)
+ {
+ /* Increment PLT reference count only for PC-relative
+ references. */
+ h->needs_plt = 1;
+ if (h->plt.refcount <= 0)
+ h->plt.refcount = 1;
+ else
+ h->plt.refcount += 1;
+ }
}
}
@@ -3049,7 +3065,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
&htab->readonly_dynrelocs_against_ifunc,
plt_entry_size,
plt_entry_size,
- GOT_ENTRY_SIZE))
+ GOT_ENTRY_SIZE, TRUE))
{
asection *s = htab->plt_bnd;
if (h->plt.offset != (bfd_vma) -1 && s != NULL)
@@ -4233,8 +4249,84 @@ elf_x86_64_relocate_section (bfd *output_bfd,
continue;
abort ();
}
- else if (h->plt.offset == (bfd_vma) -1)
- abort ();
+
+ switch (r_type)
+ {
+ default:
+ break;
+
+ case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTPCRELX:
+ case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_GOTPCREL64:
+ base_got = htab->elf.sgot;
+ off = h->got.offset;
+
+ if (base_got == NULL)
+ abort ();
+
+ if (off == (bfd_vma) -1)
+ {
+ /* We can't use h->got.offset here to save state, or
+ even just remember the offset, as finish_dynamic_symbol
+ would use that as offset into .got. */
+
+ if (h->plt.offset == (bfd_vma) -1)
+ abort ();
+
+ if (htab->elf.splt != NULL)
+ {
+ plt_index = h->plt.offset / plt_entry_size - 1;
+ off = (plt_index + 3) * GOT_ENTRY_SIZE;
+ base_got = htab->elf.sgotplt;
+ }
+ else
+ {
+ plt_index = h->plt.offset / plt_entry_size;
+ off = plt_index * GOT_ENTRY_SIZE;
+ base_got = htab->elf.igotplt;
+ }
+
+ if (h->dynindx == -1
+ || h->forced_local
+ || info->symbolic)
+ {
+ /* This references the local defitionion. We must
+ initialize this entry in the global offset table.
+ Since the offset must always be a multiple of 8,
+ we use the least significant bit to record
+ whether we have initialized it already.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_64 (output_bfd, relocation,
+ base_got->contents + off);
+ /* Note that this is harmless for the GOTPLT64
+ case, as -1 | 1 still is -1. */
+ h->got.offset |= 1;
+ }
+ }
+ }
+
+ relocation = (base_got->output_section->vma
+ + base_got->output_offset + off);
+
+ goto do_relocation;
+ }
+
+ if (h->plt.offset == (bfd_vma) -1)
+ {
+ /* Handle static pointers of STT_GNU_IFUNC symbols. */
+ if (r_type == htab->pointer_r_type
+ && (input_section->flags & SEC_CODE) == 0)
+ goto do_ifunc_pointer;
+ goto bad_ifunc_reloc;
+ }
/* STT_GNU_IFUNC symbol must go through PLT. */
if (htab->elf.splt != NULL)
@@ -4262,6 +4354,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
switch (r_type)
{
default:
+bad_ifunc_reloc:
if (h->root.root.string)
name = h->root.root.string;
else
@@ -4269,8 +4362,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
NULL);
(*_bfd_error_handler)
(_("%B: relocation %s against STT_GNU_IFUNC "
- "symbol `%s' isn't handled by %s"), input_bfd,
- howto->name, name, __FUNCTION__);
+ "symbol `%s' isn't supported"), input_bfd,
+ howto->name, name);
bfd_set_error (bfd_error_bad_value);
return FALSE;
@@ -4284,6 +4377,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
goto do_relocation;
/* FALLTHROUGH */
case R_X86_64_64:
+do_ifunc_pointer:
if (rel->r_addend != 0)
{
if (h->root.root.string)
@@ -4300,8 +4394,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
}
/* Generate dynamic relcoation only when there is a
- non-GOT reference in a shared object. */
- if (bfd_link_pic (info) && h->non_got_ref)
+ non-GOT reference in a shared object or there is no
+ PLT. */
+ if ((bfd_link_pic (info) && h->non_got_ref)
+ || h->plt.offset == (bfd_vma) -1)
{
Elf_Internal_Rela outrel;
asection *sreloc;
@@ -4335,7 +4431,16 @@ elf_x86_64_relocate_section (bfd *output_bfd,
outrel.r_addend = 0;
}
- sreloc = htab->elf.irelifunc;
+ /* Dynamic relocations are stored in
+ 1. .rela.ifunc section in PIC object.
+ 2. .rela.got section in dynamic executable.
+ 3. .rela.iplt section in static executable. */
+ if (bfd_link_pic (info))
+ sreloc = htab->elf.irelifunc;
+ else if (htab->elf.splt != NULL)
+ sreloc = htab->elf.srelgot;
+ else
+ sreloc = htab->elf.irelplt;
elf_append_rela (output_bfd, sreloc, &outrel);
/* If this reloc is against an external symbol, we
@@ -4352,66 +4457,6 @@ elf_x86_64_relocate_section (bfd *output_bfd,
case R_X86_64_PLT32:
case R_X86_64_PLT32_BND:
goto do_relocation;
-
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_GOTPCREL64:
- base_got = htab->elf.sgot;
- off = h->got.offset;
-
- if (base_got == NULL)
- abort ();
-
- if (off == (bfd_vma) -1)
- {
- /* We can't use h->got.offset here to save state, or
- even just remember the offset, as finish_dynamic_symbol
- would use that as offset into .got. */
-
- if (htab->elf.splt != NULL)
- {
- plt_index = h->plt.offset / plt_entry_size - 1;
- off = (plt_index + 3) * GOT_ENTRY_SIZE;
- base_got = htab->elf.sgotplt;
- }
- else
- {
- plt_index = h->plt.offset / plt_entry_size;
- off = plt_index * GOT_ENTRY_SIZE;
- base_got = htab->elf.igotplt;
- }
-
- if (h->dynindx == -1
- || h->forced_local
- || info->symbolic)
- {
- /* This references the local defitionion. We must
- initialize this entry in the global offset table.
- Since the offset must always be a multiple of 8,
- we use the least significant bit to record
- whether we have initialized it already.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_64 (output_bfd, relocation,
- base_got->contents + off);
- /* Note that this is harmless for the GOTPLT64
- case, as -1 | 1 still is -1. */
- h->got.offset |= 1;
- }
- }
- }
-
- relocation = (base_got->output_section->vma
- + base_got->output_offset + off);
-
- goto do_relocation;
}
}
@@ -5870,6 +5915,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
&& !local_undefweak)
{
Elf_Internal_Rela rela;
+ asection *relgot = htab->elf.srelgot;
/* This symbol has an entry in the global offset table. Set it
up. */
@@ -5888,7 +5934,27 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
if (h->def_regular
&& h->type == STT_GNU_IFUNC)
{
- if (bfd_link_pic (info))
+ if (h->plt.offset == (bfd_vma) -1)
+ {
+ /* STT_GNU_IFUNC is referenced without PLT. */
+ if (htab->elf.splt == NULL)
+ {
+ /* use .rel[a].iplt section to store .got relocations
+ in static executable. */
+ relgot = htab->elf.irelplt;
+ }
+ if (SYMBOL_REFERENCES_LOCAL (info, h))
+ {
+ rela.r_info = htab->r_info (0,
+ R_X86_64_IRELATIVE);
+ rela.r_addend = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ }
+ else
+ goto do_glob_dat;
+ }
+ else if (bfd_link_pic (info))
{
/* Generate R_X86_64_GLOB_DAT. */
goto do_glob_dat;
@@ -5932,7 +5998,7 @@ do_glob_dat:
rela.r_addend = 0;
}
- elf_append_rela (output_bfd, htab->elf.srelgot, &rela);
+ elf_append_rela (output_bfd, relgot, &rela);
}
if (h->needs_copy)
@@ -6265,11 +6331,6 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
= GOT_ENTRY_SIZE;
- /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
- htab_traverse (htab->loc_hash_table,
- elf_x86_64_finish_local_dynamic_symbol,
- info);
-
/* Fill PLT entries for undefined weak symbols in PIE. */
if (bfd_link_pie (info))
bfd_hash_traverse (&info->hash->table,
@@ -6279,6 +6340,33 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
return TRUE;
}
+/* Fill PLT/GOT entries and allocate dynamic relocations for local
+ STT_GNU_IFUNC symbols, which aren't in the ELF linker hash table.
+ It has to be done before elf_link_sort_relocs is called so that
+ dynamic relocations are properly sorted. */
+
+static bfd_boolean
+elf_x86_64_output_arch_local_syms
+ (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
+ void *flaginfo ATTRIBUTE_UNUSED,
+ int (*func) (void *, const char *,
+ Elf_Internal_Sym *,
+ asection *,
+ struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
+{
+ struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
+ /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
+ htab_traverse (htab->loc_hash_table,
+ elf_x86_64_finish_local_dynamic_symbol,
+ info);
+
+ return TRUE;
+}
+
/* Return an array of PLT entry symbol values. */
static bfd_vma *
@@ -6641,6 +6729,7 @@ static const struct bfd_elf_special_section
#define elf_backend_create_dynamic_sections elf_x86_64_create_dynamic_sections
#define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol
+#define elf_backend_output_arch_local_syms elf_x86_64_output_arch_local_syms
#define elf_backend_gc_mark_hook elf_x86_64_gc_mark_hook
#define elf_backend_grok_prstatus elf_x86_64_grok_prstatus
#define elf_backend_grok_psinfo elf_x86_64_grok_psinfo
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 774364a..fa66b0f 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -8238,7 +8238,8 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
NULL,
htab->plt_entry_size,
htab->plt_header_size,
- GOT_ENTRY_SIZE);
+ GOT_ENTRY_SIZE,
+ FALSE);
return TRUE;
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index cd5f4e3..09de0c7 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,94 @@
+2016-06-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/20253
+ * testsuite/ld-i386/i386.exp: Run PR ld/20253 tests.
+ * testsuite/ld-i386/no-plt.exp: Likewise.
+ * testsuite/ld-x86-64/no-plt.exp: Likewise.
+ * testsuite/ld-i386/pr13302.d: Remove .rel.plt section.
+ * testsuite/ld-ifunc/ifunc-13-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-13-x86-64.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-15-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-15-x86-64.d: Likewise.
+ * testsuite/ld-x86-64/pr13082-5a.d: Likewise.
+ * testsuite/ld-x86-64/pr13082-5b.d: Likewise.
+ * testsuite/ld-x86-64/pr13082-6a.d: Likewise.
+ * testsuite/ld-x86-64/pr13082-6b.d: Likewise.
+ * testsuite/ld-i386/pr20244-2a.d: Remove .plt section.
+ * testsuite/ld-ifunc/ifunc-21-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-21-x86-64.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-22-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-22-x86-64.d: Likewise.
+ * testsuite/ld-i386/pr20244-2b.d: Updated.
+ * testsuite/ld-i386/pr20244-2c.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18a-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18a-x86-64.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18b-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18b-x86-64.d: Likewise.
+ * testsuite/ld-i386/pr20253-1a.c: New file.
+ * testsuite/ld-i386/pr20253-1b.S: Likewise.
+ * testsuite/ld-i386/pr20253-1c.S: Likewise.
+ * testsuite/ld-i386/pr20253-1d.S: Likewise.
+ * testsuite/ld-i386/pr20253-2a.c: Likewise.
+ * testsuite/ld-i386/pr20253-2b.S: Likewise.
+ * testsuite/ld-i386/pr20253-2c.S: Likewise.
+ * testsuite/ld-i386/pr20253-2d.S: Likewise.
+ * testsuite/ld-i386/pr20253-3.d: Likewise.
+ * testsuite/ld-i386/pr20253-3.s: Likewise.
+ * testsuite/ld-i386/pr20253-4.s: Likewise.
+ * testsuite/ld-i386/pr20253-4a.d: Likewise.
+ * testsuite/ld-i386/pr20253-4b.d: Likewise.
+ * testsuite/ld-i386/pr20253-4c.d: Likewise.
+ * testsuite/ld-i386/pr20253-5.d: Likewise.
+ * testsuite/ld-i386/pr20253-5.s: Likewise.
+ * testsuite/ld-ifunc/ifunc-23-x86.s: Likewise.
+ * testsuite/ld-ifunc/ifunc-23a-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-23b-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-23c-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-24-x86.s: Likewise.
+ * testsuite/ld-ifunc/ifunc-24a-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-24b-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-24c-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-25-x86.s: Likewise.
+ * testsuite/ld-ifunc/ifunc-25a-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-25b-x86.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-25c-x86.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1.s: Likewise.
+ * testsuite/ld-x86-64/pr20253-1a.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1b.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1c.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1d.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1e.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1f.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1g.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1h.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1i.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1j.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1k.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-1l.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-2a.c: Likewise.
+ * testsuite/ld-x86-64/pr20253-2b.S: Likewise.
+ * testsuite/ld-x86-64/pr20253-2c.S: Likewise.
+ * testsuite/ld-x86-64/pr20253-2d.S: Likewise.
+ * testsuite/ld-x86-64/pr20253-3.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-3.s: Likewise.
+ * testsuite/ld-x86-64/pr20253-4.s: Likewise.
+ * testsuite/ld-x86-64/pr20253-4a.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-4b.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-4c.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-4d.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-4e.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-4f.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-5.s: Likewise.
+ * testsuite/ld-x86-64/pr20253-5a.d: Likewise.
+ * testsuite/ld-x86-64/pr20253-5b.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18a-i386.d: Remove extra IRELATIVE
+ relocation.
+ * testsuite/ld-ifunc/ifunc-18a-x86-64.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18b-i386.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18b-x86-64.d: Likewise.
+ * testsuite/ld-ifunc/ifunc-18a.s: Fix a typo.
+ * testsuite/ld-x86-64/x86-64.exp: Run pr20253-1 tests.
+
2016-06-17 Thomas Preud'homme <thomas.preudhomme@arm.com>
Tony Wang <tony.wang@arm.com>
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 98f0b1c..9efe406 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -408,6 +408,11 @@ run_dump_test "pr20244-2a"
run_dump_test "pr20244-2b"
run_dump_test "pr20244-2c"
run_dump_test "pr20244-2d"
+run_dump_test "pr20253-3"
+run_dump_test "pr20253-4a"
+run_dump_test "pr20253-4b"
+run_dump_test "pr20253-4c"
+run_dump_test "pr20253-5"
if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/no-plt.exp b/ld/testsuite/ld-i386/no-plt.exp
index c4af0a9..377253c 100644
--- a/ld/testsuite/ld-i386/no-plt.exp
+++ b/ld/testsuite/ld-i386/no-plt.exp
@@ -265,6 +265,27 @@ if { [check_ifunc_available] } {
"-fPIC -O2 -g" \
{ pr20244-3a.c pr20244-3b.S pr20244-3c.S pr20244-3d.S } \
] \
+ [list \
+ "Build pr20253-1a.o pr20253-1b.o pr20253-1c.o pr20253-1d.o" \
+ "" \
+ "-fPIE -O2 -g" \
+ { pr20253-1a.c pr20253-1b.S pr20253-1c.S pr20253-1d.S } \
+ ] \
+ [list \
+ "Build libpr20253-1a.so" \
+ "-shared tmpdir/pr20253-1b.o \
+ tmpdir/pr20253-1c.o tmpdir/pr20253-1d.o" \
+ "" \
+ { dummy.s } \
+ {} \
+ "libpr20253-1a.so" \
+ ] \
+ [list \
+ "Build pr20253-2a.o pr20253-2b.o pr20253-2c.o pr20253-2d.o" \
+ "" \
+ "-fPIE -O2 -g" \
+ { pr20253-2a.c pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ ] \
]
run_ld_link_exec_tests [] [list \
@@ -286,5 +307,102 @@ if { [check_ifunc_available] } {
"pr20244-3b" \
"pass.out" \
] \
+ [list \
+ "Run pr20253-1a" \
+ "tmpdir/pr20253-1a.o tmpdir/pr20253-1b.o \
+ tmpdir/pr20253-1c.o tmpdir/pr20253-1d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-1a" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-1b" \
+ "--static tmpdir/pr20253-1a.o tmpdir/pr20253-1b.o \
+ tmpdir/pr20253-1c.o tmpdir/pr20253-1d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-1b" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-1c" \
+ "-pie tmpdir/pr20253-1a.o tmpdir/pr20253-1b.o \
+ tmpdir/pr20253-1c.o tmpdir/pr20253-1d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-1c" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-1d" \
+ "tmpdir/pr20253-1a.o tmpdir/libpr20253-1a.so" \
+ "" \
+ { dummy.s } \
+ "pr20253-1d" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-1e" \
+ "-pie tmpdir/pr20253-1a.o tmpdir/libpr20253-1a.so" \
+ "" \
+ { dummy.s } \
+ "pr20253-1e" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-1f" \
+ "tmpdir/pr20253-1a.o" \
+ "" \
+ { pr20253-1b.S pr20253-1c.S pr20253-1d.S } \
+ "pr20253-1f" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
+ [list \
+ "Run pr20253-1g" \
+ "--static tmpdir/pr20253-1a.o" \
+ "" \
+ { pr20253-1b.S pr20253-1c.S pr20253-1d.S } \
+ "pr20253-1g" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
+ [list \
+ "Run pr20253-2a" \
+ "tmpdir/pr20253-2a.o tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-2a" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2b" \
+ "--static tmpdir/pr20253-2a.o tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-2b" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2c" \
+ "tmpdir/pr20253-2a.o" \
+ "" \
+ { pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ "pr20253-2c" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
+ [list \
+ "Run pr20253-2d" \
+ "--static tmpdir/pr20253-2a.o" \
+ "" \
+ { pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ "pr20253-2d" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
]
}
diff --git a/ld/testsuite/ld-i386/pr13302.d b/ld/testsuite/ld-i386/pr13302.d
index 35c09ae..9ab4fa5 100644
--- a/ld/testsuite/ld-i386/pr13302.d
+++ b/ld/testsuite/ld-i386/pr13302.d
@@ -6,7 +6,3 @@
Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Symbol's Name
[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
-
-Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset Info Type Sym. Value Symbol's Name
-[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
diff --git a/ld/testsuite/ld-i386/pr20244-2a.d b/ld/testsuite/ld-i386/pr20244-2a.d
index a04902f..ec3948e 100644
--- a/ld/testsuite/ld-i386/pr20244-2a.d
+++ b/ld/testsuite/ld-i386/pr20244-2a.d
@@ -8,36 +8,25 @@
SYMBOL TABLE:
#...
-0+80480b1 l i .text 00000000 bar
+0+8048085 l i .text 00000000 bar
#...
-0+80480b2 g F .text 00000000 _start
+0+8048086 g F .text 00000000 _start
#...
-0+80480b0 g i .text 00000000 foo
+0+8048084 g i .text 00000000 foo
#...
-
-Disassembly of section .plt:
-
-0+8048090 <.plt>:
- +[a-f0-9]+: ff 25 e0 90 04 08 jmp \*0x80490e0
- +[a-f0-9]+: 68 00 00 00 00 push \$0x0
- +[a-f0-9]+: e9 00 00 00 00 jmp 80480a0 <foo-0x10>
- +[a-f0-9]+: ff 25 e4 90 04 08 jmp \*0x80490e4
- +[a-f0-9]+: 68 00 00 00 00 push \$0x0
- +[a-f0-9]+: e9 00 00 00 00 jmp 80480b0 <foo>
-
Disassembly of section .text:
-0+80480b0 <foo>:
+0+8048084 <foo>:
+[a-f0-9]+: c3 ret
-0+80480b1 <bar>:
+0+8048085 <bar>:
+[a-f0-9]+: c3 ret
-0+80480b2 <_start>:
- +[a-f0-9]+: ff 15 e0 90 04 08 call \*0x80490e0
- +[a-f0-9]+: ff 25 e4 90 04 08 jmp \*0x80490e4
- +[a-f0-9]+: c7 05 e4 90 04 08 00 00 00 00 movl \$0x0,0x80490e4
- +[a-f0-9]+: 83 3d e0 90 04 08 00 cmpl \$0x0,0x80490e0
- +[a-f0-9]+: b9 10 00 00 00 mov \$0x10,%ecx
+0+8048086 <_start>:
+ +[a-f0-9]+: ff 15 a8 90 04 08 call \*0x80490a8
+ +[a-f0-9]+: ff 25 ac 90 04 08 jmp \*0x80490ac
+ +[a-f0-9]+: c7 05 ac 90 04 08 00 00 00 00 movl \$0x0,0x80490ac
+ +[a-f0-9]+: 83 3d a8 90 04 08 00 cmpl \$0x0,0x80490a8
+ +[a-f0-9]+: b9 fc ff ff ff mov \$0xfffffffc,%ecx
#pass
diff --git a/ld/testsuite/ld-i386/pr20244-2b.d b/ld/testsuite/ld-i386/pr20244-2b.d
index fc0fa17..f23a406 100644
--- a/ld/testsuite/ld-i386/pr20244-2b.d
+++ b/ld/testsuite/ld-i386/pr20244-2b.d
@@ -7,5 +7,4 @@
.*: +file format .*
Contents of section .got.plt:
- 80490d4 00000000 00000000 00000000 b0800408 ................
- 80490e4 b1800408 ....
+ 80490b0 00000000 00000000 00000000 ............
diff --git a/ld/testsuite/ld-i386/pr20244-2c.d b/ld/testsuite/ld-i386/pr20244-2c.d
index 54eee9f..acca560 100644
--- a/ld/testsuite/ld-i386/pr20244-2c.d
+++ b/ld/testsuite/ld-i386/pr20244-2c.d
@@ -6,5 +6,5 @@
Relocation section '.rel.plt' at offset 0x74 contains 2 entries:
Offset Info Type Sym. Value Symbol's Name
-0+80490e4 0000002a R_386_IRELATIVE
-0+80490e0 0000002a R_386_IRELATIVE
+0+80490ac 0000002a R_386_IRELATIVE
+0+80490a8 0000002a R_386_IRELATIVE
diff --git a/ld/testsuite/ld-i386/pr20253-1a.c b/ld/testsuite/ld-i386/pr20253-1a.c
new file mode 100644
index 0000000..370275a
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-1a.c
@@ -0,0 +1,8 @@
+extern void check (void);
+
+int
+main ()
+{
+ check ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr20253-1b.S b/ld/testsuite/ld-i386/pr20253-1b.S
new file mode 100644
index 0000000..93c6d26
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-1b.S
@@ -0,0 +1,52 @@
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+ .string "PASS"
+ .text
+ .globl check
+ .type check, @function
+check:
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $8, %esp
+ call *get_func1@GOT(%ebx)
+#ifdef CHECK_PLT
+ cmpl $func1, %eax
+#else
+ cmpl func1@GOT(%ebx), %eax
+#endif
+ jne .L3
+ movl func1_p@GOT(%ebx), %edx
+ cmpl %eax, (%edx)
+ jne .L3
+ call *func1@GOT(%ebx)
+ cmpl $1, %eax
+ jne .L3
+ call *call_func1@GOT(%ebx)
+ cmpl $1, %eax
+ jne .L3
+ call *get_func2@GOT(%ebx)
+ movl func2_p@GOT(%ebx), %edx
+ cmpl %eax, (%edx)
+ jne .L3
+ call *call_func2@GOT(%ebx)
+ cmpl $2, %eax
+ jne .L3
+ leal .LC0@GOTOFF(%ebx), %eax
+ subl $12, %esp
+ pushl %eax
+ call *puts@GOT(%ebx)
+ addl $24, %esp
+ popl %ebx
+ ret
+.L3:
+ call *abort@GOT(%ebx)
+ .size check, .-check
+ .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
diff --git a/ld/testsuite/ld-i386/pr20253-1c.S b/ld/testsuite/ld-i386/pr20253-1c.S
new file mode 100644
index 0000000..8a17e7c
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-1c.S
@@ -0,0 +1,35 @@
+ .text
+ .globl get_func1
+ .type get_func1, @function
+get_func1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl func1@GOT(%eax), %eax
+ ret
+ .size get_func1, .-get_func1
+ .globl call_func1
+ .type call_func1, @function
+call_func1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ jmp *func1@GOT(%eax)
+ .size call_func1, .-call_func1
+ .globl func1_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+ .align 4
+ .type func1_p, @object
+ .size func1_p, 4
+func1_p:
+ .long func1
+ .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:
+ movl (%esp), %eax
+ ret
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20253-1d.S b/ld/testsuite/ld-i386/pr20253-1d.S
new file mode 100644
index 0000000..2d6a1de
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-1d.S
@@ -0,0 +1,81 @@
+ .text
+ .type implementation1, @function
+implementation1:
+ movl $1, %eax
+ ret
+ .size implementation1, .-implementation1
+ .type implementation2, @function
+implementation2:
+ movl $2, %eax
+ ret
+ .size implementation2, .-implementation2
+ .type resolver2, @function
+resolver2:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ leal implementation2@GOTOFF(%eax), %eax
+ ret
+ .size resolver2, .-resolver2
+ .type func2, @gnu_indirect_function
+ .set func2,resolver2
+ .type resolver1, @function
+resolver1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ leal implementation1@GOTOFF(%eax), %eax
+ ret
+ .size resolver1, .-resolver1
+ .globl func1
+ .type func1, @gnu_indirect_function
+ .set func1,resolver1
+ .globl get_func2
+ .type get_func2, @function
+get_func2:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl func2@GOT(%eax), %eax
+ ret
+ .size get_func2, .-get_func2
+ .globl call_func2
+ .type call_func2, @function
+call_func2:
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $8, %esp
+ call *get_func2@GOT(%ebx)
+ cmpl func2@GOT(%ebx), %eax
+ jne .L10
+ addl $8, %esp
+ movl %ebx, %eax
+ popl %ebx
+ jmp *func2@GOT(%eax)
+.L10:
+ call *abort@GOT(%ebx)
+ .size call_func2, .-call_func2
+ .globl func2_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+ .align 4
+ .type func2_p, @object
+ .size func2_p, 4
+func2_p:
+ .long func2
+ .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:
+ movl (%esp), %eax
+ ret
+ .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
diff --git a/ld/testsuite/ld-i386/pr20253-2a.c b/ld/testsuite/ld-i386/pr20253-2a.c
new file mode 100644
index 0000000..370275a
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-2a.c
@@ -0,0 +1,8 @@
+extern void check (void);
+
+int
+main ()
+{
+ check ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr20253-2b.S b/ld/testsuite/ld-i386/pr20253-2b.S
new file mode 100644
index 0000000..46ab4f4
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-2b.S
@@ -0,0 +1,39 @@
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+ .string "PASS"
+ .text
+ .globl check
+ .type check, @function
+check:
+ subl $12, %esp
+ call *get_func1@GOT
+#ifdef CHECK_PLT
+ movl $func1, %edx
+#else
+ movl func1@GOT, %edx
+#endif
+ cmpl %edx, %eax
+ jne .L3
+ cmpl %edx, func1_p
+ jne .L3
+ call *func1@GOT
+ cmpl $1, %eax
+ jne .L3
+ call *call_func1@GOT
+ cmpl $1, %eax
+ jne .L3
+ call *get_func2@GOT
+ cmpl %eax, func2_p
+ jne .L3
+ call *call_func2@GOT
+ cmpl $2, %eax
+ jne .L3
+ subl $12, %esp
+ pushl $.LC0
+ call *puts@GOT
+ addl $28, %esp
+ ret
+.L3:
+ call *abort@GOT
+ .size check, .-check
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20253-2c.S b/ld/testsuite/ld-i386/pr20253-2c.S
new file mode 100644
index 0000000..7e724b4
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-2c.S
@@ -0,0 +1,24 @@
+ .text
+ .globl get_func1
+ .type get_func1, @function
+get_func1:
+ movl func1@GOT, %eax
+ ret
+ .size get_func1, .-get_func1
+ .globl call_func1
+ .type call_func1, @function
+call_func1:
+ jmp *func1@GOT
+ .size call_func1, .-call_func1
+ .globl func1_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+ .align 4
+ .type func1_p, @object
+ .size func1_p, 4
+func1_p:
+ .long func1
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20253-2d.S b/ld/testsuite/ld-i386/pr20253-2d.S
new file mode 100644
index 0000000..5c1f9ae
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-2d.S
@@ -0,0 +1,49 @@
+ .text
+ .type implementation1, @function
+implementation1:
+ movl $1, %eax
+ ret
+ .size implementation1, .-implementation1
+ .type implementation2, @function
+implementation2:
+ movl $2, %eax
+ ret
+ .size implementation2, .-implementation2
+ .type resolver2, @function
+resolver2:
+ movl $implementation2, %eax
+ ret
+ .size resolver2, .-resolver2
+ .type func2, @gnu_indirect_function
+ .set func2,resolver2
+ .type resolver1, @function
+resolver1:
+ movl $implementation1, %eax
+ ret
+ .size resolver1, .-resolver1
+ .globl func1
+ .type func1, @gnu_indirect_function
+ .set func1,resolver1
+ .globl get_func2
+ .type get_func2, @function
+get_func2:
+ movl func2@GOT, %eax
+ ret
+ .size get_func2, .-get_func2
+ .globl call_func2
+ .type call_func2, @function
+call_func2:
+ jmp *func2@GOT
+ .size call_func2, .-call_func2
+ .globl func2_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+ .align 4
+ .type func2_p, @object
+ .size func2_p, 4
+func2_p:
+ .long func2
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20253-3.d b/ld/testsuite/ld-i386/pr20253-3.d
new file mode 100644
index 0000000..7ce0b58
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-3.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -melf_i386
+#error: relocation R_386_PC32 against STT_GNU_IFUNC symbol `foo' isn't supported
diff --git a/ld/testsuite/ld-i386/pr20253-3.s b/ld/testsuite/ld-i386/pr20253-3.s
new file mode 100644
index 0000000..8cd25fb
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-3.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ ret
+ .globl __start
+__start:
+ .data
+ .long foo - .
diff --git a/ld/testsuite/ld-i386/pr20253-4.s b/ld/testsuite/ld-i386/pr20253-4.s
new file mode 100644
index 0000000..88f0f1b
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-4.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ movl __start@GOT(%eax), %eax
+ .globl __start
+__start:
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-i386/pr20253-4a.d b/ld/testsuite/ld-i386/pr20253-4a.d
new file mode 100644
index 0000000..cd10080
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-4a.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --32 -mrelax-relocations=yes
+#ld: -melf_i386
+#readelf: -r --wide
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
diff --git a/ld/testsuite/ld-i386/pr20253-4b.d b/ld/testsuite/ld-i386/pr20253-4b.d
new file mode 100644
index 0000000..3b45f8f
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-4b.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --32 -mrelax-relocations=yes
+#ld: -pie -melf_i386
+#readelf: -r --wide
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
diff --git a/ld/testsuite/ld-i386/pr20253-4c.d b/ld/testsuite/ld-i386/pr20253-4c.d
new file mode 100644
index 0000000..6fa68aa
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-4c.d
@@ -0,0 +1,9 @@
+#source: pr20253-4.s
+#as: --32 -mrelax-relocations=yes
+#ld: -shared -melf_i386
+#readelf: -r --wide
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +[0-9a-f]+ +__start
+[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
diff --git a/ld/testsuite/ld-i386/pr20253-5.d b/ld/testsuite/ld-i386/pr20253-5.d
new file mode 100644
index 0000000..0936d98
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-5.d
@@ -0,0 +1,7 @@
+#as: --32
+#ld: -melf_i386
+#readelf: -r --wide
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
diff --git a/ld/testsuite/ld-i386/pr20253-5.s b/ld/testsuite/ld-i386/pr20253-5.s
new file mode 100644
index 0000000..0cc1803
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20253-5.s
@@ -0,0 +1,10 @@
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ call *func1@GOT(%eax)
+ cmp $func1,%eax
+ .globl func1
+ .type func1, @gnu_indirect_function
+func1:
+ ret
diff --git a/ld/testsuite/ld-ifunc/ifunc-13-i386.d b/ld/testsuite/ld-ifunc/ifunc-13-i386.d
index 677fa92..8dd3fed 100644
--- a/ld/testsuite/ld-ifunc/ifunc-13-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-13-i386.d
@@ -8,7 +8,3 @@
Relocation section '.rel.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_32[ ]+ifunc\(\)[ ]+ifunc
-
-Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries:
-[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc
diff --git a/ld/testsuite/ld-ifunc/ifunc-13-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-13-x86-64.d
index b01c735..1a1d061 100644
--- a/ld/testsuite/ld-ifunc/ifunc-13-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-13-x86-64.d
@@ -8,7 +8,3 @@
Relocation section '.rela.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_64[ ]+ifunc\(\)[ ]+ifunc \+ 0
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
-[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0
diff --git a/ld/testsuite/ld-ifunc/ifunc-15-i386.d b/ld/testsuite/ld-ifunc/ifunc-15-i386.d
index c37dd51..0d44ba1 100644
--- a/ld/testsuite/ld-ifunc/ifunc-15-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-15-i386.d
@@ -7,7 +7,3 @@
Relocation section '.rel.got' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_GLOB_DAT[ ]+ifunc\(\)[ ]+ifunc
-
-Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries:
-[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc
diff --git a/ld/testsuite/ld-ifunc/ifunc-15-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-15-x86-64.d
index a4a5cb1..8a28ec9 100644
--- a/ld/testsuite/ld-ifunc/ifunc-15-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-15-x86-64.d
@@ -7,7 +7,3 @@
Relocation section '.rela.got' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_GLOB_DAT[ ]+ifunc\(\)[ ]+ifunc \+ 0
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
-[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0
diff --git a/ld/testsuite/ld-ifunc/ifunc-18a-i386.d b/ld/testsuite/ld-ifunc/ifunc-18a-i386.d
index 10490b1..7c392fb 100644
--- a/ld/testsuite/ld-ifunc/ifunc-18a-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-18a-i386.d
@@ -12,4 +12,3 @@ Relocation section '.rel.ifunc' at .*
Relocation section '.rel.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-18a-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-18a-x86-64.d
index 0d600eb..e9d6031 100644
--- a/ld/testsuite/ld-ifunc/ifunc-18a-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-18a-x86-64.d
@@ -12,4 +12,3 @@ Relocation section '.rela.ifunc' at .*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-18a.s b/ld/testsuite/ld-ifunc/ifunc-18a.s
index c29c121..f68c151 100644
--- a/ld/testsuite/ld-ifunc/ifunc-18a.s
+++ b/ld/testsuite/ld-ifunc/ifunc-18a.s
@@ -1,5 +1,5 @@
.section .data.rel,"aw",@progbits
- .globl foo_ptrt
+ .globl foo_ptr
.type foo_ptr, @object
foo_ptr:
.dc.a foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-18b-i386.d b/ld/testsuite/ld-ifunc/ifunc-18b-i386.d
index a5eda94..4b63c57 100644
--- a/ld/testsuite/ld-ifunc/ifunc-18b-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-18b-i386.d
@@ -12,4 +12,3 @@ Relocation section '.rel.ifunc' at .*
Relocation section '.rel.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-18b-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-18b-x86-64.d
index 8dfebfb..b4ff6c3 100644
--- a/ld/testsuite/ld-ifunc/ifunc-18b-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-18b-x86-64.d
@@ -12,4 +12,3 @@ Relocation section '.rela.ifunc' at .*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-21-i386.d b/ld/testsuite/ld-ifunc/ifunc-21-i386.d
index e609dbe..d61ccd0 100644
--- a/ld/testsuite/ld-ifunc/ifunc-21-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-21-i386.d
@@ -5,18 +5,20 @@
.*: +file format .*
-#...
-0+8048090 <__start>:
-[ ]*[a-f0-9]+: ff 93 0c 00 00 00 call \*0xc\(%ebx\)
-[ ]*[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\)
-[ ]*[a-f0-9]+: 03 83 0c 00 00 00 add 0xc\(%ebx\),%eax
-[ ]*[a-f0-9]+: 8b 83 0c 00 00 00 mov 0xc\(%ebx\),%eax
-[ ]*[a-f0-9]+: 85 83 0c 00 00 00 test %eax,0xc\(%ebx\)
-[ ]*[a-f0-9]+: c7 c0 b5 80 04 08 mov \$0x80480b5,%eax
-0+80480b4 <foo>:
-[ ]*[a-f0-9]+: c3 ret
+Disassembly of section .text:
-0+80480b5 <bar>:
-[ ]*[a-f0-9]+: c3 ret
+0+804807c <__start>:
+ +[a-f0-9]+: ff 93 fc ff ff ff call \*-0x4\(%ebx\)
+ +[a-f0-9]+: ff a3 fc ff ff ff jmp \*-0x4\(%ebx\)
+ +[a-f0-9]+: 03 83 fc ff ff ff add -0x4\(%ebx\),%eax
+ +[a-f0-9]+: 8b 83 fc ff ff ff mov -0x4\(%ebx\),%eax
+ +[a-f0-9]+: 85 83 fc ff ff ff test %eax,-0x4\(%ebx\)
+ +[a-f0-9]+: c7 c0 a1 80 04 08 mov \$0x80480a1,%eax
+
+0+80480a0 <foo>:
+ +[a-f0-9]+: c3 ret
+
+0+80480a1 <bar>:
+ +[a-f0-9]+: c3 ret
#pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-21-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-21-x86-64.d
index e28734e..4e3582d 100644
--- a/ld/testsuite/ld-ifunc/ifunc-21-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-21-x86-64.d
@@ -5,18 +5,20 @@
.*: +file format .*
-#...
-0+4000e0 <__start>:
-[ ]*[a-f0-9]+: ff 15 42 00 20 00 callq \*0x200042\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: ff 25 3c 00 20 00 jmpq \*0x20003c\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 03 05 35 00 20 00 add 0x200035\(%rip\),%rax # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 8b 05 2e 00 20 00 mov 0x20002e\(%rip\),%rax # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 85 05 27 00 20 00 test %rax,0x200027\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 c7 c0 09 01 40 00 mov \$0x400109,%rax
-0+400108 <foo>:
-[ ]*[a-f0-9]+: c3 retq
+Disassembly of section .text:
-0+400109 <bar>:
-[ ]*[a-f0-9]+: c3 retq
+0+4000c8 <__start>:
+ +[a-f0-9]+: ff 15 2a 00 20 00 callq \*0x20002a\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: ff 25 24 00 20 00 jmpq \*0x200024\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 03 05 1d 00 20 00 add 0x20001d\(%rip\),%rax # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 8b 05 16 00 20 00 mov 0x200016\(%rip\),%rax # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 85 05 0f 00 20 00 test %rax,0x20000f\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 c7 c0 f1 00 40 00 mov \$0x4000f1,%rax
+
+0+4000f0 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+4000f1 <bar>:
+ +[a-f0-9]+: c3 retq
#pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-22-i386.d b/ld/testsuite/ld-ifunc/ifunc-22-i386.d
index e609dbe..d61ccd0 100644
--- a/ld/testsuite/ld-ifunc/ifunc-22-i386.d
+++ b/ld/testsuite/ld-ifunc/ifunc-22-i386.d
@@ -5,18 +5,20 @@
.*: +file format .*
-#...
-0+8048090 <__start>:
-[ ]*[a-f0-9]+: ff 93 0c 00 00 00 call \*0xc\(%ebx\)
-[ ]*[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\)
-[ ]*[a-f0-9]+: 03 83 0c 00 00 00 add 0xc\(%ebx\),%eax
-[ ]*[a-f0-9]+: 8b 83 0c 00 00 00 mov 0xc\(%ebx\),%eax
-[ ]*[a-f0-9]+: 85 83 0c 00 00 00 test %eax,0xc\(%ebx\)
-[ ]*[a-f0-9]+: c7 c0 b5 80 04 08 mov \$0x80480b5,%eax
-0+80480b4 <foo>:
-[ ]*[a-f0-9]+: c3 ret
+Disassembly of section .text:
-0+80480b5 <bar>:
-[ ]*[a-f0-9]+: c3 ret
+0+804807c <__start>:
+ +[a-f0-9]+: ff 93 fc ff ff ff call \*-0x4\(%ebx\)
+ +[a-f0-9]+: ff a3 fc ff ff ff jmp \*-0x4\(%ebx\)
+ +[a-f0-9]+: 03 83 fc ff ff ff add -0x4\(%ebx\),%eax
+ +[a-f0-9]+: 8b 83 fc ff ff ff mov -0x4\(%ebx\),%eax
+ +[a-f0-9]+: 85 83 fc ff ff ff test %eax,-0x4\(%ebx\)
+ +[a-f0-9]+: c7 c0 a1 80 04 08 mov \$0x80480a1,%eax
+
+0+80480a0 <foo>:
+ +[a-f0-9]+: c3 ret
+
+0+80480a1 <bar>:
+ +[a-f0-9]+: c3 ret
#pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-22-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-22-x86-64.d
index e28734e..4e3582d 100644
--- a/ld/testsuite/ld-ifunc/ifunc-22-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-22-x86-64.d
@@ -5,18 +5,20 @@
.*: +file format .*
-#...
-0+4000e0 <__start>:
-[ ]*[a-f0-9]+: ff 15 42 00 20 00 callq \*0x200042\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: ff 25 3c 00 20 00 jmpq \*0x20003c\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 03 05 35 00 20 00 add 0x200035\(%rip\),%rax # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 8b 05 2e 00 20 00 mov 0x20002e\(%rip\),%rax # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 85 05 27 00 20 00 test %rax,0x200027\(%rip\) # 600128 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 48 c7 c0 09 01 40 00 mov \$0x400109,%rax
-0+400108 <foo>:
-[ ]*[a-f0-9]+: c3 retq
+Disassembly of section .text:
-0+400109 <bar>:
-[ ]*[a-f0-9]+: c3 retq
+0+4000c8 <__start>:
+ +[a-f0-9]+: ff 15 2a 00 20 00 callq \*0x20002a\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: ff 25 24 00 20 00 jmpq \*0x200024\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 03 05 1d 00 20 00 add 0x20001d\(%rip\),%rax # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 8b 05 16 00 20 00 mov 0x200016\(%rip\),%rax # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 85 05 0f 00 20 00 test %rax,0x20000f\(%rip\) # 6000f8 <bar\+0x200007>
+ +[a-f0-9]+: 48 c7 c0 f1 00 40 00 mov \$0x4000f1,%rax
+
+0+4000f0 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+4000f1 <bar>:
+ +[a-f0-9]+: c3 retq
#pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-23-x86.s b/ld/testsuite/ld-ifunc/ifunc-23-x86.s
new file mode 100644
index 0000000..69c2279
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-23-x86.s
@@ -0,0 +1,10 @@
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ ret
+ .globl __start
+__start:
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-23a-x86.d b/ld/testsuite/ld-ifunc/ifunc-23a-x86.d
new file mode 100644
index 0000000..47ec5d1
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-23a-x86.d
@@ -0,0 +1,8 @@
+#source: ifunc-23-x86.s
+#ld:
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-23b-x86.d b/ld/testsuite/ld-ifunc/ifunc-23b-x86.d
new file mode 100644
index 0000000..dbe2ec1
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-23b-x86.d
@@ -0,0 +1,8 @@
+#source: ifunc-23-x86.s
+#ld: -pie
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-23c-x86.d b/ld/testsuite/ld-ifunc/ifunc-23c-x86.d
new file mode 100644
index 0000000..dc7e5c1
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-23c-x86.d
@@ -0,0 +1,8 @@
+#source: ifunc-23-x86.s
+#ld: -shared
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-24-x86.s b/ld/testsuite/ld-ifunc/ifunc-24-x86.s
new file mode 100644
index 0000000..967cdf6
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-24-x86.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ call foo@PLT
+ .globl __start
+__start:
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-24a-x86.d b/ld/testsuite/ld-ifunc/ifunc-24a-x86.d
new file mode 100644
index 0000000..78bd4e2
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-24a-x86.d
@@ -0,0 +1,8 @@
+#source: ifunc-24-x86.s
+#ld:
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-24b-x86.d b/ld/testsuite/ld-ifunc/ifunc-24b-x86.d
new file mode 100644
index 0000000..c73b019
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-24b-x86.d
@@ -0,0 +1,12 @@
+#source: ifunc-24-x86.s
+#ld: -pie
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-24c-x86.d b/ld/testsuite/ld-ifunc/ifunc-24c-x86.d
new file mode 100644
index 0000000..db16754
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-24c-x86.d
@@ -0,0 +1,12 @@
+#source: ifunc-24-x86.s
+#ld: -shared
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-25-x86.s b/ld/testsuite/ld-ifunc/ifunc-25-x86.s
new file mode 100644
index 0000000..0549cbf
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-25-x86.s
@@ -0,0 +1,12 @@
+ .text
+ .globl foo
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ call foo@PLT
+ .globl __start
+__start:
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-25a-x86.d b/ld/testsuite/ld-ifunc/ifunc-25a-x86.d
new file mode 100644
index 0000000..0f37f52
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-25a-x86.d
@@ -0,0 +1,8 @@
+#source: ifunc-25-x86.s
+#ld:
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-25b-x86.d b/ld/testsuite/ld-ifunc/ifunc-25b-x86.d
new file mode 100644
index 0000000..96b0ed5
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-25b-x86.d
@@ -0,0 +1,12 @@
+#source: ifunc-25-x86.s
+#ld: -pie
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)+_IRELATIVE[ ]*[0-9a-f]*
diff --git a/ld/testsuite/ld-ifunc/ifunc-25c-x86.d b/ld/testsuite/ld-ifunc/ifunc-25c-x86.d
new file mode 100644
index 0000000..f9c08dc
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/ifunc-25c-x86.d
@@ -0,0 +1,12 @@
+#source: ifunc-25-x86.s
+#ld: -shared
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel(a|).dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)_(32|64) +foo\(\) +foo( \+ 0|)
+
+Relocation section '.rel(a|).plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_(386|X86_64)_JUMP_SLOT +foo\(\) +foo( \+ 0|)
diff --git a/ld/testsuite/ld-x86-64/no-plt.exp b/ld/testsuite/ld-x86-64/no-plt.exp
index d57ccb5..bdf1843 100644
--- a/ld/testsuite/ld-x86-64/no-plt.exp
+++ b/ld/testsuite/ld-x86-64/no-plt.exp
@@ -199,3 +199,88 @@ run_ld_link_exec_tests [] [list \
"pass.out" \
] \
]
+
+# Run-time tests which require working IFUNC support.
+if { [check_ifunc_available] } {
+ run_cc_link_tests [list \
+ [list \
+ "Build pr20253-2a.o pr20253-2b.o pr20253-2c.o pr20253-2d.o" \
+ "" \
+ "-fPIE -O2 -g" \
+ { pr20253-2a.c pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ ] \
+ [list \
+ "Build libpr20253-2a.so" \
+ "-shared tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ {} \
+ "libpr20253-2a.so" \
+ ] \
+ ]
+
+ run_ld_link_exec_tests [] [list \
+ [list \
+ "Run pr20253-2a" \
+ "tmpdir/pr20253-2a.o tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-2a" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2b" \
+ "--static tmpdir/pr20253-2a.o tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-2b" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2c" \
+ "-pie tmpdir/pr20253-2a.o tmpdir/pr20253-2b.o \
+ tmpdir/pr20253-2c.o tmpdir/pr20253-2d.o" \
+ "" \
+ { dummy.s } \
+ "pr20253-2c" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2d" \
+ "tmpdir/pr20253-2a.o tmpdir/libpr20253-2a.so" \
+ "" \
+ { dummy.s } \
+ "pr20253-2d" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2e" \
+ "-pie tmpdir/pr20253-2a.o tmpdir/libpr20253-2a.so" \
+ "" \
+ { dummy.s } \
+ "pr20253-2e" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run pr20253-2f" \
+ "tmpdir/pr20253-2a.o" \
+ "" \
+ { pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ "pr20253-2f" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
+ [list \
+ "Run pr20253-2g" \
+ "--static tmpdir/pr20253-2a.o" \
+ "" \
+ { pr20253-2b.S pr20253-2c.S pr20253-2d.S } \
+ "pr20253-2g" \
+ "pass.out" \
+ "-DCHECK_PLT" \
+ ] \
+ ]
+}
diff --git a/ld/testsuite/ld-x86-64/pr13082-5a.d b/ld/testsuite/ld-x86-64/pr13082-5a.d
index 191c29e..d1b100d 100644
--- a/ld/testsuite/ld-x86-64/pr13082-5a.d
+++ b/ld/testsuite/ld-x86-64/pr13082-5a.d
@@ -7,7 +7,3 @@
Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ +R_X86_64_32 +ifunc\(\)+ +ifunc \+ 0
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset Info Type Sym. Value Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +ifunc\(\)+ +ifunc \+ 0
diff --git a/ld/testsuite/ld-x86-64/pr13082-5b.d b/ld/testsuite/ld-x86-64/pr13082-5b.d
index 1c5a5e7..01e403b 100644
--- a/ld/testsuite/ld-x86-64/pr13082-5b.d
+++ b/ld/testsuite/ld-x86-64/pr13082-5b.d
@@ -7,7 +7,3 @@
Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset Info Type Sym. Value Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr13082-6a.d b/ld/testsuite/ld-x86-64/pr13082-6a.d
index 9a1a655..5914f3d 100644
--- a/ld/testsuite/ld-x86-64/pr13082-6a.d
+++ b/ld/testsuite/ld-x86-64/pr13082-6a.d
@@ -7,7 +7,3 @@
Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset Info Type Sym. Value Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr13082-6b.d b/ld/testsuite/ld-x86-64/pr13082-6b.d
index 792c348..6ff23ff 100644
--- a/ld/testsuite/ld-x86-64/pr13082-6b.d
+++ b/ld/testsuite/ld-x86-64/pr13082-6b.d
@@ -7,7 +7,3 @@
Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
-
-Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset Info Type Sym. Value Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1.s b/ld/testsuite/ld-x86-64/pr20253-1.s
new file mode 100644
index 0000000..4b9b7a4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1.s
@@ -0,0 +1,18 @@
+ .text
+ .globl foo
+ .type foo, @gnu_indirect_function
+foo:
+ ret
+ .text
+ .type bar, @gnu_indirect_function
+bar:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ call *foo@GOTPCREL(%rip)
+ jmp *bar@GOTPCREL(%rip)
+ movq $0, bar@GOTPCREL(%rip)
+ cmpq $0, foo@GOTPCREL(%rip)
+ cmpq foo@GOTPCREL(%rip), %rcx
+ cmpq bar@GOTPCREL(%rip), %rcx
diff --git a/ld/testsuite/ld-x86-64/pr20253-1a.d b/ld/testsuite/ld-x86-64/pr20253-1a.d
new file mode 100644
index 0000000..94c7c1d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1a.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1b.d b/ld/testsuite/ld-x86-64/pr20253-1b.d
new file mode 100644
index 0000000..247e042
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1b.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -melf_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+4000e0 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+4000e1 <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+4000e2 <_start>:
+ +[a-f0-9]+: ff 15 28 00 20 00 callq \*0x200028\(%rip\) # 600110 <_start\+0x20002e>
+ +[a-f0-9]+: ff 25 2a 00 20 00 jmpq \*0x20002a\(%rip\) # 600118 <_start\+0x200036>
+ +[a-f0-9]+: 48 c7 05 1f 00 20 00 00 00 00 00 movq \$0x0,0x20001f\(%rip\) # 600118 <_start\+0x200036>
+ +[a-f0-9]+: 48 83 3d 0f 00 20 00 00 cmpq \$0x0,0x20000f\(%rip\) # 600110 <_start\+0x20002e>
+ +[a-f0-9]+: 48 3b 0d 08 00 20 00 cmp 0x200008\(%rip\),%rcx # 600110 <_start\+0x20002e>
+ +[a-f0-9]+: 48 3b 0d 09 00 20 00 cmp 0x200009\(%rip\),%rcx # 600118 <_start\+0x200036>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1c.d b/ld/testsuite/ld-x86-64/pr20253-1c.d
new file mode 100644
index 0000000..02c4542
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1c.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -pie -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1d.d b/ld/testsuite/ld-x86-64/pr20253-1d.d
new file mode 100644
index 0000000..35c04f8
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1d.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -pie -melf_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+1c8 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+1c9 <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+1ca <_start>:
+ +[a-f0-9]+: ff 15 28 01 20 00 callq \*0x200128\(%rip\) # 2002f8 <_DYNAMIC\+0x100>
+ +[a-f0-9]+: ff 25 2a 01 20 00 jmpq \*0x20012a\(%rip\) # 200300 <_DYNAMIC\+0x108>
+ +[a-f0-9]+: 48 c7 05 1f 01 20 00 00 00 00 00 movq \$0x0,0x20011f\(%rip\) # 200300 <_DYNAMIC\+0x108>
+ +[a-f0-9]+: 48 83 3d 0f 01 20 00 00 cmpq \$0x0,0x20010f\(%rip\) # 2002f8 <_DYNAMIC\+0x100>
+ +[a-f0-9]+: 48 3b 0d 08 01 20 00 cmp 0x200108\(%rip\),%rcx # 2002f8 <_DYNAMIC\+0x100>
+ +[a-f0-9]+: 48 3b 0d 09 01 20 00 cmp 0x200109\(%rip\),%rcx # 200300 <_DYNAMIC\+0x108>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1e.d b/ld/testsuite/ld-x86-64/pr20253-1e.d
new file mode 100644
index 0000000..722fdf7
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1e.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +foo\(\)+ +foo \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1f.d b/ld/testsuite/ld-x86-64/pr20253-1f.d
new file mode 100644
index 0000000..d84b60e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1f.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+1f8 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+1f9 <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+1fa <_start>:
+ +[a-f0-9]+: ff 15 08 01 20 00 callq \*0x200108\(%rip\) # 200308 <_DYNAMIC\+0xe0>
+ +[a-f0-9]+: ff 25 0a 01 20 00 jmpq \*0x20010a\(%rip\) # 200310 <_DYNAMIC\+0xe8>
+ +[a-f0-9]+: 48 c7 05 ff 00 20 00 00 00 00 00 movq \$0x0,0x2000ff\(%rip\) # 200310 <_DYNAMIC\+0xe8>
+ +[a-f0-9]+: 48 83 3d ef 00 20 00 00 cmpq \$0x0,0x2000ef\(%rip\) # 200308 <_DYNAMIC\+0xe0>
+ +[a-f0-9]+: 48 3b 0d e8 00 20 00 cmp 0x2000e8\(%rip\),%rcx # 200308 <_DYNAMIC\+0xe0>
+ +[a-f0-9]+: 48 3b 0d e9 00 20 00 cmp 0x2000e9\(%rip\),%rcx # 200310 <_DYNAMIC\+0xe8>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1g.d b/ld/testsuite/ld-x86-64/pr20253-1g.d
new file mode 100644
index 0000000..671a980
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1g.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1h.d b/ld/testsuite/ld-x86-64/pr20253-1h.d
new file mode 100644
index 0000000..77ff100
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1h.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -melf32_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+40008c <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+40008d <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+40008e <_start>:
+ +[a-f0-9]+: ff 15 28 00 20 00 callq \*0x200028\(%rip\) # 6000bc <_start\+0x20002e>
+ +[a-f0-9]+: ff 25 2a 00 20 00 jmpq \*0x20002a\(%rip\) # 6000c4 <_start\+0x200036>
+ +[a-f0-9]+: 48 c7 05 1f 00 20 00 00 00 00 00 movq \$0x0,0x20001f\(%rip\) # 6000c4 <_start\+0x200036>
+ +[a-f0-9]+: 48 83 3d 0f 00 20 00 00 cmpq \$0x0,0x20000f\(%rip\) # 6000bc <_start\+0x20002e>
+ +[a-f0-9]+: 48 3b 0d 08 00 20 00 cmp 0x200008\(%rip\),%rcx # 6000bc <_start\+0x20002e>
+ +[a-f0-9]+: 48 3b 0d 09 00 20 00 cmp 0x200009\(%rip\),%rcx # 6000c4 <_start\+0x200036>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1i.d b/ld/testsuite/ld-x86-64/pr20253-1i.d
new file mode 100644
index 0000000..bf42ed1
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1i.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -pie -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1j.d b/ld/testsuite/ld-x86-64/pr20253-1j.d
new file mode 100644
index 0000000..6f5d666
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1j.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -pie -melf32_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+120 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+121 <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+122 <_start>:
+ +[a-f0-9]+: ff 15 a8 00 20 00 callq \*0x2000a8\(%rip\) # 2001d0 <_DYNAMIC\+0x80>
+ +[a-f0-9]+: ff 25 aa 00 20 00 jmpq \*0x2000aa\(%rip\) # 2001d8 <_DYNAMIC\+0x88>
+ +[a-f0-9]+: 48 c7 05 9f 00 20 00 00 00 00 00 movq \$0x0,0x20009f\(%rip\) # 2001d8 <_DYNAMIC\+0x88>
+ +[a-f0-9]+: 48 83 3d 8f 00 20 00 00 cmpq \$0x0,0x20008f\(%rip\) # 2001d0 <_DYNAMIC\+0x80>
+ +[a-f0-9]+: 48 3b 0d 88 00 20 00 cmp 0x200088\(%rip\),%rcx # 2001d0 <_DYNAMIC\+0x80>
+ +[a-f0-9]+: 48 3b 0d 89 00 20 00 cmp 0x200089\(%rip\),%rcx # 2001d8 <_DYNAMIC\+0x88>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1k.d b/ld/testsuite/ld-x86-64/pr20253-1k.d
new file mode 100644
index 0000000..1d55770
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1k.d
@@ -0,0 +1,9 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -shared -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +foo\(\)+ +foo \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-1l.d b/ld/testsuite/ld-x86-64/pr20253-1l.d
new file mode 100644
index 0000000..0276558
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-1l.d
@@ -0,0 +1,25 @@
+#source: pr20253-1.s
+#as: --x32
+#ld: -shared -melf32_x86_64
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+158 <foo>:
+ +[a-f0-9]+: c3 retq
+
+0+159 <bar>:
+ +[a-f0-9]+: c3 retq
+
+0+15a <_start>:
+ +[a-f0-9]+: ff 15 98 00 20 00 callq \*0x200098\(%rip\) # 2001f8 <_DYNAMIC\+0x70>
+ +[a-f0-9]+: ff 25 9a 00 20 00 jmpq \*0x20009a\(%rip\) # 200200 <_DYNAMIC\+0x78>
+ +[a-f0-9]+: 48 c7 05 8f 00 20 00 00 00 00 00 movq \$0x0,0x20008f\(%rip\) # 200200 <_DYNAMIC\+0x78>
+ +[a-f0-9]+: 48 83 3d 7f 00 20 00 00 cmpq \$0x0,0x20007f\(%rip\) # 2001f8 <_DYNAMIC\+0x70>
+ +[a-f0-9]+: 48 3b 0d 78 00 20 00 cmp 0x200078\(%rip\),%rcx # 2001f8 <_DYNAMIC\+0x70>
+ +[a-f0-9]+: 48 3b 0d 79 00 20 00 cmp 0x200079\(%rip\),%rcx # 200200 <_DYNAMIC\+0x78>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-2a.c b/ld/testsuite/ld-x86-64/pr20253-2a.c
new file mode 100644
index 0000000..370275a
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-2a.c
@@ -0,0 +1,8 @@
+extern void check (void);
+
+int
+main ()
+{
+ check ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr20253-2b.S b/ld/testsuite/ld-x86-64/pr20253-2b.S
new file mode 100644
index 0000000..9bfab0c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-2b.S
@@ -0,0 +1,46 @@
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+ .string "PASS"
+ .text
+ .globl check
+ .type check, @function
+check:
+ subq $8, %rsp
+ call *get_func1@GOTPCREL(%rip)
+#ifdef CHECK_PLT
+ cmpl $func1, %eax
+#else
+ cmpq func1@GOTPCREL(%rip), %rax
+#endif
+ jne .L3
+ movq func1_p@GOTPCREL(%rip), %rdx
+#ifdef __LP64__
+ cmpq %rax, (%rdx)
+#else
+ cmpl %eax, (%rdx)
+#endif
+ jne .L3
+ call *func1@GOTPCREL(%rip)
+ cmpl $1, %eax
+ jne .L3
+ call *call_func1@GOTPCREL(%rip)
+ cmpl $1, %eax
+ jne .L3
+ call *get_func2@GOTPCREL(%rip)
+ movq func2_p@GOTPCREL(%rip), %rdx
+#ifdef __LP64__
+ cmpq %rax, (%rdx)
+#else
+ cmpl %eax, (%rdx)
+#endif
+ jne .L3
+ call *call_func2@GOTPCREL(%rip)
+ cmpl $2, %eax
+ jne .L3
+ leaq .LC0(%rip), %rdi
+ addq $8, %rsp
+ jmp *puts@GOTPCREL(%rip)
+.L3:
+ call *abort@GOTPCREL(%rip)
+ .size check, .-check
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr20253-2c.S b/ld/testsuite/ld-x86-64/pr20253-2c.S
new file mode 100644
index 0000000..5ec7e76
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-2c.S
@@ -0,0 +1,29 @@
+ .text
+ .globl get_func1
+ .type get_func1, @function
+get_func1:
+ movq func1@GOTPCREL(%rip), %rax
+ ret
+ .size get_func1, .-get_func1
+ .globl call_func1
+ .type call_func1, @function
+call_func1:
+ jmp *func1@GOTPCREL(%rip)
+ .size call_func1, .-call_func1
+ .globl func1_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+#ifdef __LP64__
+ .align 8
+ .size func1_p, 8
+#else
+ .align 4
+ .size func1_p, 4
+#endif
+ .type func1_p, @object
+func1_p:
+ .dc.a func1
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr20253-2d.S b/ld/testsuite/ld-x86-64/pr20253-2d.S
new file mode 100644
index 0000000..bc4c32e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-2d.S
@@ -0,0 +1,61 @@
+ .text
+ .type implementation1, @function
+implementation1:
+ movl $1, %eax
+ ret
+ .size implementation1, .-implementation1
+ .type implementation2, @function
+implementation2:
+ movl $2, %eax
+ ret
+ .size implementation2, .-implementation2
+ .type resolver2, @function
+resolver2:
+ leaq implementation2(%rip), %rax
+ ret
+ .size resolver2, .-resolver2
+ .type func2, @gnu_indirect_function
+ .set func2,resolver2
+ .type resolver1, @function
+resolver1:
+ leaq implementation1(%rip), %rax
+ ret
+ .size resolver1, .-resolver1
+ .globl func1
+ .type func1, @gnu_indirect_function
+ .set func1,resolver1
+ .globl get_func2
+ .type get_func2, @function
+get_func2:
+ movq func2@GOTPCREL(%rip), %rax
+ ret
+ .size get_func2, .-get_func2
+ .globl call_func2
+ .type call_func2, @function
+call_func2:
+ subq $8, %rsp
+ call *get_func2@GOTPCREL(%rip)
+ cmpq func2@GOTPCREL(%rip), %rax
+ jne .L10
+ addq $8, %rsp
+ jmp *func2@GOTPCREL(%rip)
+.L10:
+ call *abort@GOTPCREL(%rip)
+ .size call_func2, .-call_func2
+ .globl func2_p
+#ifdef CHECK_PLT
+ .section .rodata,"a",@progbits
+#else
+ .section .data.rel,"aw",@progbits
+#endif
+#ifdef __LP64__
+ .align 8
+ .size func2_p, 8
+#else
+ .align 4
+ .size func2_p, 4
+#endif
+ .type func2_p, @object
+func2_p:
+ .dc.a func2
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr20253-3.d b/ld/testsuite/ld-x86-64/pr20253-3.d
new file mode 100644
index 0000000..30db29c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-3.d
@@ -0,0 +1,3 @@
+#as: --64
+#ld: -melf_x86_64
+#error: relocation R_X86_64_PC32 against STT_GNU_IFUNC symbol `foo' isn't supported
diff --git a/ld/testsuite/ld-x86-64/pr20253-3.s b/ld/testsuite/ld-x86-64/pr20253-3.s
new file mode 100644
index 0000000..8cd25fb
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-3.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ ret
+ .globl __start
+__start:
+ .data
+ .long foo - .
diff --git a/ld/testsuite/ld-x86-64/pr20253-4.s b/ld/testsuite/ld-x86-64/pr20253-4.s
new file mode 100644
index 0000000..7dc9aa3
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo,%gnu_indirect_function
+foo:
+ ret
+ .globl _start
+_start:
+ movq __start@GOTPCREL(%rip), %rax
+ .globl __start
+__start:
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-x86-64/pr20253-4a.d b/ld/testsuite/ld-x86-64/pr20253-4a.d
new file mode 100644
index 0000000..041c164
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4a.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --64
+#ld: -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-4b.d b/ld/testsuite/ld-x86-64/pr20253-4b.d
new file mode 100644
index 0000000..6dc95b5
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4b.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --64
+#ld: -pie -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-4c.d b/ld/testsuite/ld-x86-64/pr20253-4c.d
new file mode 100644
index 0000000..26fa0df
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4c.d
@@ -0,0 +1,9 @@
+#source: pr20253-4.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +[0-9a-f]+ +__start \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-4d.d b/ld/testsuite/ld-x86-64/pr20253-4d.d
new file mode 100644
index 0000000..52dd877
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4d.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --x32
+#ld: -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-4e.d b/ld/testsuite/ld-x86-64/pr20253-4e.d
new file mode 100644
index 0000000..d9f2fa4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4e.d
@@ -0,0 +1,8 @@
+#source: pr20253-4.s
+#as: --x32
+#ld: -pie -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-4f.d b/ld/testsuite/ld-x86-64/pr20253-4f.d
new file mode 100644
index 0000000..fb3d6f8
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-4f.d
@@ -0,0 +1,9 @@
+#source: pr20253-4.s
+#as: --x32
+#ld: -shared -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +[0-9a-f]+ +__start \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-5.s b/ld/testsuite/ld-x86-64/pr20253-5.s
new file mode 100644
index 0000000..ade0e8b
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-5.s
@@ -0,0 +1,10 @@
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ call *func1@GOTPCREL(%rip)
+ cmp $func1,%eax
+ .globl func1
+ .type func1, @gnu_indirect_function
+func1:
+ ret
diff --git a/ld/testsuite/ld-x86-64/pr20253-5a.d b/ld/testsuite/ld-x86-64/pr20253-5a.d
new file mode 100644
index 0000000..1eceda4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-5a.d
@@ -0,0 +1,8 @@
+#source: pr20253-5.s
+#as: --64
+#ld: -melf_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/pr20253-5b.d b/ld/testsuite/ld-x86-64/pr20253-5b.d
new file mode 100644
index 0000000..c1cb335
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20253-5b.d
@@ -0,0 +1,8 @@
+#source: pr20253-5.s
+#as: --x32
+#ld: -melf32_x86_64
+#readelf: -r --wide
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 7fd953b..f6f89e2 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -503,6 +503,27 @@ run_dump_test "pr19609-7d"
run_dump_test "pr19939a"
run_dump_test "pr19939b"
run_dump_test "pr19719"
+run_dump_test "pr20253-1a"
+run_dump_test "pr20253-1b"
+run_dump_test "pr20253-1c"
+run_dump_test "pr20253-1d"
+run_dump_test "pr20253-1e"
+run_dump_test "pr20253-1f"
+run_dump_test "pr20253-1g"
+run_dump_test "pr20253-1h"
+run_dump_test "pr20253-1i"
+run_dump_test "pr20253-1j"
+run_dump_test "pr20253-1k"
+run_dump_test "pr20253-1l"
+run_dump_test "pr20253-3"
+run_dump_test "pr20253-4a"
+run_dump_test "pr20253-4b"
+run_dump_test "pr20253-4c"
+run_dump_test "pr20253-4d"
+run_dump_test "pr20253-4e"
+run_dump_test "pr20253-4f"
+run_dump_test "pr20253-5a"
+run_dump_test "pr20253-5b"
proc undefined_weak {cflags ldflags} {
set testname "Undefined weak symbol"