aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index e4c3946..a850ce7 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -698,6 +698,11 @@ struct elf_x86_64_link_hash_table
/* The offset into sgot of the GOT entry used by the PLT entry
above. */
bfd_vma tlsdesc_got;
+
+ /* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt. */
+ bfd_vma next_jump_slot_index;
+ /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */
+ bfd_vma next_irelative_index;
};
/* Get the x86-64 ELF linker hash table from a link_info structure. */
@@ -839,6 +844,8 @@ elf_x86_64_link_hash_table_create (bfd *abfd)
ret->tls_ld_got.refcount = 0;
ret->sgotplt_jump_table_size = 0;
ret->tls_module_base = NULL;
+ ret->next_jump_slot_index = 0;
+ ret->next_irelative_index = 0;
if (ABI_64_P (abfd))
{
@@ -2667,10 +2674,18 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
incremented. However, when we reserve space for TLS descriptors,
it's not incremented, so in order to compute the space reserved
for them, it suffices to multiply the reloc count by the jump
- slot size. */
+ slot size.
+
+ PR ld/13302: We start next_irelative_index at the end of .rela.plt
+ so that R_X86_64_IRELATIVE entries come last. */
if (htab->elf.srelplt)
- htab->sgotplt_jump_table_size
- = elf_x86_64_compute_jump_table_size (htab);
+ {
+ htab->sgotplt_jump_table_size
+ = elf_x86_64_compute_jump_table_size (htab);
+ htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1;
+ }
+ else if (htab->elf.irelplt)
+ htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1;
if (htab->tlsdesc_plt)
{
@@ -4205,13 +4220,13 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
if (plt == htab->elf.splt)
{
- plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
- got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
+ got_offset = h->plt.offset / PLT_ENTRY_SIZE - 1;
+ got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
}
else
{
- plt_index = h->plt.offset / PLT_ENTRY_SIZE;
- got_offset = plt_index * GOT_ENTRY_SIZE;
+ got_offset = h->plt.offset / PLT_ENTRY_SIZE;
+ got_offset = got_offset * GOT_ENTRY_SIZE;
}
/* Fill in the entry in the procedure linkage table. */
@@ -4233,17 +4248,6 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
- 6),
plt->contents + h->plt.offset + 2);
- /* Don't fill PLT entry for static executables. */
- if (plt == htab->elf.splt)
- {
- /* Put relocation index. */
- bfd_put_32 (output_bfd, plt_index,
- plt->contents + h->plt.offset + 7);
- /* Put offset for jmp .PLT0. */
- bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
- plt->contents + h->plt.offset + 12);
- }
-
/* Fill in the entry in the global offset table, initially this
points to the pushq instruction in the PLT which is at offset 6. */
bfd_put_64 (output_bfd, (plt->output_section->vma
@@ -4267,11 +4271,25 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+ /* R_X86_64_IRELATIVE comes last. */
+ plt_index = htab->next_irelative_index--;
}
else
{
rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
rela.r_addend = 0;
+ plt_index = htab->next_jump_slot_index++;
+ }
+
+ /* Don't fill PLT entry for static executables. */
+ if (plt == htab->elf.splt)
+ {
+ /* Put relocation index. */
+ bfd_put_32 (output_bfd, plt_index,
+ plt->contents + h->plt.offset + 7);
+ /* Put offset for jmp .PLT0. */
+ bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
+ plt->contents + h->plt.offset + 12);
}
bed = get_elf_backend_data (output_bfd);