diff options
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 54 |
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); |