From 9577f60b5a19ce93536f49cba3af4be39e39c327 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sat, 14 Oct 2017 11:29:58 -0700 Subject: [PATCH] x86: Add _bfd_x86_elf_finish_dynamic_sections Extract the common parts of elf_i386_finish_dynamic_sections and elf_x86_64_finish_dynamic_sections into a separate function in elfxx-x86.c. * elf32-i386.c (elf_i386_finish_dynamic_sections): Call _bfd_x86_elf_finish_dynamic_sections. * elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise. * elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New function. * elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New prototype. --- bfd/ChangeLog | 10 ++ bfd/elf32-i386.c | 308 +++++++++++------------------------------- bfd/elf64-x86-64.c | 324 ++++++++++----------------------------------- bfd/elfxx-x86.c | 218 ++++++++++++++++++++++++++++++ bfd/elfxx-x86.h | 3 + 5 files changed, 376 insertions(+), 487 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5f3fb8c14c..474572f4df 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2017-10-14 H.J. Lu + + * elf32-i386.c (elf_i386_finish_dynamic_sections): Call + _bfd_x86_elf_finish_dynamic_sections. + * elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise. + * elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New + function. + * elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New + prototype. + 2017-10-14 H.J. Lu PR ld/21384 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index cf2e43fc5e..166ca9d00f 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -4012,262 +4012,102 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct elf_x86_link_hash_table *htab; - bfd *dynobj; - asection *sdyn; - const struct elf_i386_backend_data *abed; - htab = elf_x86_hash_table (info, I386_ELF_DATA); + htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info); if (htab == NULL) return FALSE; - dynobj = htab->elf.dynobj; - sdyn = bfd_get_linker_section (dynobj, ".dynamic"); - abed = get_elf_i386_backend_data (output_bfd); + if (!htab->elf.dynamic_sections_created) + return TRUE; - if (htab->elf.dynamic_sections_created) + if (htab->elf.splt && htab->elf.splt->size > 0) { - Elf32_External_Dyn *dyncon, *dynconend; + /* UnixWare sets the entsize of .plt to 4, although that doesn't + really seem like the right value. */ + elf_section_data (htab->elf.splt->output_section) + ->this_hdr.sh_entsize = 4; - if (sdyn == NULL || htab->elf.sgot == NULL) - abort (); - - dyncon = (Elf32_External_Dyn *) sdyn->contents; - dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); - for (; dyncon < dynconend; dyncon++) + if (htab->plt.has_plt0) { - Elf_Internal_Dyn dyn; - asection *s; - - bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); - - switch (dyn.d_tag) + /* Fill in the special first entry in the procedure linkage + table. */ + const struct elf_i386_backend_data *abed + = get_elf_i386_backend_data (output_bfd); + + memcpy (htab->elf.splt->contents, htab->plt.plt0_entry, + htab->lazy_plt->plt0_entry_size); + memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size, + abed->plt0_pad_byte, + htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size); + if (!bfd_link_pic (info)) { - default: - if (htab->is_vxworks - && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) - break; - continue; - - case DT_PLTGOT: - s = htab->elf.sgotplt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - break; - - case DT_JMPREL: - s = htab->elf.srelplt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - break; - - case DT_PLTRELSZ: - s = htab->elf.srelplt; - dyn.d_un.d_val = s->size; - break; - } - - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); - } - - if (htab->elf.splt && htab->elf.splt->size > 0) - { - /* UnixWare sets the entsize of .plt to 4, although that doesn't - really seem like the right value. */ - elf_section_data (htab->elf.splt->output_section) - ->this_hdr.sh_entsize = 4; + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 4), + htab->elf.splt->contents + + htab->lazy_plt->plt0_got1_offset); + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 8), + htab->elf.splt->contents + + htab->lazy_plt->plt0_got2_offset); - if (htab->plt.has_plt0) - { - /* Fill in the special first entry in the procedure linkage - table. */ - memcpy (htab->elf.splt->contents, htab->plt.plt0_entry, - htab->lazy_plt->plt0_entry_size); - memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size, - abed->plt0_pad_byte, - htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size); - if (!bfd_link_pic (info)) + if (htab->is_vxworks) { - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 4), - htab->elf.splt->contents - + htab->lazy_plt->plt0_got1_offset); - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 8), - htab->elf.splt->contents - + htab->lazy_plt->plt0_got2_offset); + Elf_Internal_Rela rel; + int num_plts = (htab->elf.splt->size + / htab->plt.plt_entry_size) - 1; + unsigned char *p; + asection *srelplt2 = htab->srelplt2; + + /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + + 4. On IA32 we use REL relocations so the + addend goes in the PLT directly. */ + rel.r_offset = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + + htab->lazy_plt->plt0_got1_offset); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, + srelplt2->contents); + /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + + 8. */ + rel.r_offset = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + + htab->lazy_plt->plt0_got2_offset); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, + srelplt2->contents + + sizeof (Elf32_External_Rel)); + /* Correct the .rel.plt.unloaded relocations. */ + p = srelplt2->contents; + if (bfd_link_pic (info)) + p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel); + else + p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel); - if (htab->is_vxworks) + for (; num_plts; num_plts--) { - Elf_Internal_Rela rel; - int num_plts = (htab->elf.splt->size - / htab->plt.plt_entry_size) - 1; - unsigned char *p; - asection *srelplt2 = htab->srelplt2; - - /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ - + 4. On IA32 we use REL relocations so the - addend goes in the PLT directly. */ - rel.r_offset = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset - + htab->lazy_plt->plt0_got1_offset); - rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, - srelplt2->contents); - /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ - + 8. */ - rel.r_offset = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset - + htab->lazy_plt->plt0_got2_offset); + bfd_elf32_swap_reloc_in (output_bfd, p, &rel); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, - srelplt2->contents + - sizeof (Elf32_External_Rel)); - /* Correct the .rel.plt.unloaded relocations. */ - p = srelplt2->contents; - if (bfd_link_pic (info)) - p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel); - else - p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel); + bfd_elf32_swap_reloc_out (output_bfd, &rel, p); + p += sizeof (Elf32_External_Rel); - for (; num_plts; num_plts--) - { - bfd_elf32_swap_reloc_in (output_bfd, p, &rel); - rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, p); - p += sizeof (Elf32_External_Rel); - - bfd_elf32_swap_reloc_in (output_bfd, p, &rel); - rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, p); - p += sizeof (Elf32_External_Rel); - } + bfd_elf32_swap_reloc_in (output_bfd, p, &rel); + rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, p); + p += sizeof (Elf32_External_Rel); } } } } - - if (htab->plt_got != NULL && htab->plt_got->size > 0) - elf_section_data (htab->plt_got->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - - if (htab->plt_second != NULL && htab->plt_second->size > 0) - elf_section_data (htab->plt_second->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - } - - /* Fill in the first three entries in the global offset table. */ - if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0) - { - if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) - { - _bfd_error_handler - (_("discarded output section: `%A'"), htab->elf.sgotplt); - return FALSE; - } - - bfd_put_32 (output_bfd, - (sdyn == NULL ? 0 - : sdyn->output_section->vma + sdyn->output_offset), - htab->elf.sgotplt->contents); - bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4); - bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8); - - elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4; - } - - /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL - && htab->plt_eh_frame->contents != NULL) - { - if (htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 - && htab->elf.splt->output_section != NULL - && htab->plt_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->elf.splt->output_section->vma; - bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma - + htab->plt_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_eh_frame->sec_info_type - == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_eh_frame, - htab->plt_eh_frame->contents)) - return FALSE; - } - } - - /* Adjust .eh_frame for .plt.got section. */ - if (htab->plt_got_eh_frame != NULL - && htab->plt_got_eh_frame->contents != NULL) - { - if (htab->plt_got != NULL - && htab->plt_got->size != 0 - && (htab->plt_got->flags & SEC_EXCLUDE) == 0 - && htab->plt_got->output_section != NULL - && htab->plt_got_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->plt_got->output_section->vma; - bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma - + htab->plt_got_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_got_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_got_eh_frame, - htab->plt_got_eh_frame->contents)) - return FALSE; - } } - /* Adjust .eh_frame for the second PLT section. */ - if (htab->plt_second_eh_frame != NULL - && htab->plt_second_eh_frame->contents != NULL) - { - if (htab->plt_second != NULL - && htab->plt_second->size != 0 - && (htab->plt_second->flags & SEC_EXCLUDE) == 0 - && htab->plt_second->output_section != NULL - && htab->plt_second_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->plt_second->output_section->vma; - bfd_vma eh_frame_start - = (htab->plt_second_eh_frame->output_section->vma - + htab->plt_second_eh_frame->output_offset - + PLT_FDE_START_OFFSET); - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_second_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_second_eh_frame->sec_info_type - == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_second_eh_frame, - htab->plt_second_eh_frame->contents)) - return FALSE; - } - } - - if (htab->elf.sgot && htab->elf.sgot->size > 0) - elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; - /* Fill PLT entries for undefined weak symbols in PIE. */ if (bfd_link_pie (info)) bfd_hash_traverse (&info->hash->table, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index b970146cfb..047e78a341 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -4360,273 +4360,91 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct elf_x86_link_hash_table *htab; - bfd *dynobj; - asection *sdyn; - htab = elf_x86_hash_table (info, X86_64_ELF_DATA); + htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info); if (htab == NULL) return FALSE; - dynobj = htab->elf.dynobj; - sdyn = bfd_get_linker_section (dynobj, ".dynamic"); - - if (htab->elf.dynamic_sections_created) - { - bfd_byte *dyncon, *dynconend; - const struct elf_backend_data *bed; - bfd_size_type sizeof_dyn; - - if (sdyn == NULL || htab->elf.sgot == NULL) - abort (); - - bed = get_elf_backend_data (dynobj); - sizeof_dyn = bed->s->sizeof_dyn; - dyncon = sdyn->contents; - dynconend = sdyn->contents + sdyn->size; - for (; dyncon < dynconend; dyncon += sizeof_dyn) - { - Elf_Internal_Dyn dyn; - asection *s; - - (*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn); - - switch (dyn.d_tag) - { - default: - continue; - - case DT_PLTGOT: - s = htab->elf.sgotplt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - break; - - case DT_JMPREL: - dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma; - break; - - case DT_PLTRELSZ: - s = htab->elf.srelplt->output_section; - dyn.d_un.d_val = s->size; - break; - - case DT_TLSDESC_PLT: - s = htab->elf.splt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->tlsdesc_plt; - break; - - case DT_TLSDESC_GOT: - s = htab->elf.sgot; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->tlsdesc_got; - break; - } - - (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); - } - - if (htab->elf.splt && htab->elf.splt->size > 0) - { - elf_section_data (htab->elf.splt->output_section) - ->this_hdr.sh_entsize = htab->plt.plt_entry_size; - - if (htab->plt.has_plt0) - { - /* Fill in the special first entry in the procedure linkage - table. */ - memcpy (htab->elf.splt->contents, - htab->lazy_plt->plt0_entry, - htab->lazy_plt->plt0_entry_size); - /* Add offset for pushq GOT+8(%rip), since the instruction - uses 6 bytes subtract this value. */ - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 8 - - htab->elf.splt->output_section->vma - - htab->elf.splt->output_offset - - 6), - (htab->elf.splt->contents - + htab->lazy_plt->plt0_got1_offset)); - /* Add offset for the PC-relative instruction accessing - GOT+16, subtracting the offset to the end of that - instruction. */ - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 16 - - htab->elf.splt->output_section->vma - - htab->elf.splt->output_offset - - htab->lazy_plt->plt0_got2_insn_end), - (htab->elf.splt->contents - + htab->lazy_plt->plt0_got2_offset)); - - if (htab->tlsdesc_plt) - { - bfd_put_64 (output_bfd, (bfd_vma) 0, - htab->elf.sgot->contents + htab->tlsdesc_got); - - memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, - htab->lazy_plt->plt0_entry, - htab->lazy_plt->plt0_entry_size); - - /* Add offset for pushq GOT+8(%rip), since the - instruction uses 6 bytes subtract this value. */ - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 8 - - htab->elf.splt->output_section->vma - - htab->elf.splt->output_offset - - htab->tlsdesc_plt - - 6), - (htab->elf.splt->contents - + htab->tlsdesc_plt - + htab->lazy_plt->plt0_got1_offset)); - /* Add offset for the PC-relative instruction accessing - GOT+TDG, where TDG stands for htab->tlsdesc_got, - subtracting the offset to the end of that - instruction. */ - bfd_put_32 (output_bfd, - (htab->elf.sgot->output_section->vma - + htab->elf.sgot->output_offset - + htab->tlsdesc_got - - htab->elf.splt->output_section->vma - - htab->elf.splt->output_offset - - htab->tlsdesc_plt - - htab->lazy_plt->plt0_got2_insn_end), - (htab->elf.splt->contents - + htab->tlsdesc_plt - + htab->lazy_plt->plt0_got2_offset)); - } - } - } - - if (htab->plt_got != NULL && htab->plt_got->size > 0) - elf_section_data (htab->plt_got->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - - if (htab->plt_second != NULL && htab->plt_second->size > 0) - elf_section_data (htab->plt_second->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - } - - /* GOT is always created in setup_gnu_properties. But it may not be - needed. */ - if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0) - { - if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) - { - _bfd_error_handler - (_("discarded output section: `%A'"), htab->elf.sgotplt); - return FALSE; - } - - /* Set the first entry in the global offset table to the address of - the dynamic section. */ - if (sdyn == NULL) - bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents); - else - bfd_put_64 (output_bfd, - sdyn->output_section->vma + sdyn->output_offset, - htab->elf.sgotplt->contents); - /* Write GOT[1] and GOT[2], needed for the dynamic linker. */ - bfd_put_64 (output_bfd, (bfd_vma) 0, - htab->elf.sgotplt->contents + GOT_ENTRY_SIZE); - bfd_put_64 (output_bfd, (bfd_vma) 0, - htab->elf.sgotplt->contents + GOT_ENTRY_SIZE*2); - - elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize - = GOT_ENTRY_SIZE; - } + if (! htab->elf.dynamic_sections_created) + return TRUE; - /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL - && htab->plt_eh_frame->contents != NULL) + if (htab->elf.splt && htab->elf.splt->size > 0) { - if (htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 - && htab->elf.splt->output_section != NULL - && htab->plt_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->elf.splt->output_section->vma; - bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma - + htab->plt_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_eh_frame, - htab->plt_eh_frame->contents)) - return FALSE; - } - } + elf_section_data (htab->elf.splt->output_section) + ->this_hdr.sh_entsize = htab->plt.plt_entry_size; - /* Adjust .eh_frame for .plt.got section. */ - if (htab->plt_got_eh_frame != NULL - && htab->plt_got_eh_frame->contents != NULL) - { - if (htab->plt_got != NULL - && htab->plt_got->size != 0 - && (htab->plt_got->flags & SEC_EXCLUDE) == 0 - && htab->plt_got->output_section != NULL - && htab->plt_got_eh_frame->output_section != NULL) + if (htab->plt.has_plt0) { - bfd_vma plt_start = htab->plt_got->output_section->vma; - bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma - + htab->plt_got_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_got_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_got_eh_frame, - htab->plt_got_eh_frame->contents)) - return FALSE; + /* Fill in the special first entry in the procedure linkage + table. */ + memcpy (htab->elf.splt->contents, + htab->lazy_plt->plt0_entry, + htab->lazy_plt->plt0_entry_size); + /* Add offset for pushq GOT+8(%rip), since the instruction + uses 6 bytes subtract this value. */ + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 8 + - htab->elf.splt->output_section->vma + - htab->elf.splt->output_offset + - 6), + (htab->elf.splt->contents + + htab->lazy_plt->plt0_got1_offset)); + /* Add offset for the PC-relative instruction accessing + GOT+16, subtracting the offset to the end of that + instruction. */ + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 16 + - htab->elf.splt->output_section->vma + - htab->elf.splt->output_offset + - htab->lazy_plt->plt0_got2_insn_end), + (htab->elf.splt->contents + + htab->lazy_plt->plt0_got2_offset)); } - } - /* Adjust .eh_frame for the second PLT section. */ - if (htab->plt_second_eh_frame != NULL - && htab->plt_second_eh_frame->contents != NULL) - { - if (htab->plt_second != NULL - && htab->plt_second->size != 0 - && (htab->plt_second->flags & SEC_EXCLUDE) == 0 - && htab->plt_second->output_section != NULL - && htab->plt_second_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->plt_second->output_section->vma; - bfd_vma eh_frame_start - = (htab->plt_second_eh_frame->output_section->vma - + htab->plt_second_eh_frame->output_offset - + PLT_FDE_START_OFFSET); - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_second_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_second_eh_frame->sec_info_type - == SEC_INFO_TYPE_EH_FRAME) + if (htab->tlsdesc_plt) { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_second_eh_frame, - htab->plt_second_eh_frame->contents)) - return FALSE; + bfd_put_64 (output_bfd, (bfd_vma) 0, + htab->elf.sgot->contents + htab->tlsdesc_got); + + memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, + htab->lazy_plt->plt0_entry, + htab->lazy_plt->plt0_entry_size); + + /* Add offset for pushq GOT+8(%rip), since the + instruction uses 6 bytes subtract this value. */ + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 8 + - htab->elf.splt->output_section->vma + - htab->elf.splt->output_offset + - htab->tlsdesc_plt + - 6), + (htab->elf.splt->contents + + htab->tlsdesc_plt + + htab->lazy_plt->plt0_got1_offset)); + /* Add offset for the PC-relative instruction accessing + GOT+TDG, where TDG stands for htab->tlsdesc_got, + subtracting the offset to the end of that + instruction. */ + bfd_put_32 (output_bfd, + (htab->elf.sgot->output_section->vma + + htab->elf.sgot->output_offset + + htab->tlsdesc_got + - htab->elf.splt->output_section->vma + - htab->elf.splt->output_offset + - htab->tlsdesc_plt + - htab->lazy_plt->plt0_got2_insn_end), + (htab->elf.splt->contents + + htab->tlsdesc_plt + + htab->lazy_plt->plt0_got2_offset)); } } - if (htab->elf.sgot && htab->elf.sgot->size > 0) - elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize - = GOT_ENTRY_SIZE; - /* Fill PLT entries for undefined weak symbols in PIE. */ if (bfd_link_pie (info)) bfd_hash_traverse (&info->hash->table, diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index dd139caf41..1aad33f12d 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -1294,6 +1294,224 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, return TRUE; } +/* Finish up the x86 dynamic sections. */ + +struct elf_x86_link_hash_table * +_bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + struct elf_x86_link_hash_table *htab; + const struct elf_backend_data *bed; + bfd *dynobj; + asection *sdyn; + bfd_byte *dyncon, *dynconend; + bfd_size_type sizeof_dyn; + + bed = get_elf_backend_data (output_bfd); + htab = elf_x86_hash_table (info, bed->target_id); + if (htab == NULL) + return htab; + + dynobj = htab->elf.dynobj; + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); + + /* GOT is always created in setup_gnu_properties. But it may not be + needed. .got.plt section may be needed for static IFUNC. */ + if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0) + { + bfd_vma dynamic_addr; + + if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) + { + _bfd_error_handler + (_("discarded output section: `%A'"), htab->elf.sgotplt); + return NULL; + } + + elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize + = htab->got_entry_size; + + dynamic_addr = (sdyn == NULL + ? (bfd_vma) 0 + : sdyn->output_section->vma + sdyn->output_offset); + + /* Set the first entry in the global offset table to the address + of the dynamic section. Write GOT[1] and GOT[2], needed for + the dynamic linker. */ + if (htab->got_entry_size == 8) + { + bfd_put_64 (output_bfd, dynamic_addr, + htab->elf.sgotplt->contents); + bfd_put_64 (output_bfd, (bfd_vma) 0, + htab->elf.sgotplt->contents + 8); + bfd_put_64 (output_bfd, (bfd_vma) 0, + htab->elf.sgotplt->contents + 8*2); + } + else + { + bfd_put_32 (output_bfd, dynamic_addr, + htab->elf.sgotplt->contents); + bfd_put_32 (output_bfd, 0, + htab->elf.sgotplt->contents + 4); + bfd_put_32 (output_bfd, 0, + htab->elf.sgotplt->contents + 4*2); + } + } + + if (!htab->elf.dynamic_sections_created) + return htab; + + if (sdyn == NULL || htab->elf.sgot == NULL) + abort (); + + sizeof_dyn = bed->s->sizeof_dyn; + dyncon = sdyn->contents; + dynconend = sdyn->contents + sdyn->size; + for (; dyncon < dynconend; dyncon += sizeof_dyn) + { + Elf_Internal_Dyn dyn; + asection *s; + + (*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn); + + switch (dyn.d_tag) + { + default: + if (htab->is_vxworks + && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) + break; + continue; + + case DT_PLTGOT: + s = htab->elf.sgotplt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + break; + + case DT_JMPREL: + dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma; + break; + + case DT_PLTRELSZ: + s = htab->elf.srelplt->output_section; + dyn.d_un.d_val = s->size; + break; + + case DT_TLSDESC_PLT: + s = htab->elf.splt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset + + htab->tlsdesc_plt; + break; + + case DT_TLSDESC_GOT: + s = htab->elf.sgot; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset + + htab->tlsdesc_got; + break; + } + + (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); + } + + if (htab->plt_got != NULL && htab->plt_got->size > 0) + elf_section_data (htab->plt_got->output_section) + ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; + + if (htab->plt_second != NULL && htab->plt_second->size > 0) + elf_section_data (htab->plt_second->output_section) + ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; + + /* Adjust .eh_frame for .plt section. */ + if (htab->plt_eh_frame != NULL + && htab->plt_eh_frame->contents != NULL) + { + if (htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 + && htab->elf.splt->output_section != NULL + && htab->plt_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->elf.splt->output_section->vma; + bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma + + htab->plt_eh_frame->output_offset + + PLT_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + + if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_eh_frame, + htab->plt_eh_frame->contents)) + return NULL; + } + } + + /* Adjust .eh_frame for .plt.got section. */ + if (htab->plt_got_eh_frame != NULL + && htab->plt_got_eh_frame->contents != NULL) + { + if (htab->plt_got != NULL + && htab->plt_got->size != 0 + && (htab->plt_got->flags & SEC_EXCLUDE) == 0 + && htab->plt_got->output_section != NULL + && htab->plt_got_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->plt_got->output_section->vma; + bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma + + htab->plt_got_eh_frame->output_offset + + PLT_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_got_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_got_eh_frame, + htab->plt_got_eh_frame->contents)) + return NULL; + } + } + + /* Adjust .eh_frame for the second PLT section. */ + if (htab->plt_second_eh_frame != NULL + && htab->plt_second_eh_frame->contents != NULL) + { + if (htab->plt_second != NULL + && htab->plt_second->size != 0 + && (htab->plt_second->flags & SEC_EXCLUDE) == 0 + && htab->plt_second->output_section != NULL + && htab->plt_second_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->plt_second->output_section->vma; + bfd_vma eh_frame_start + = (htab->plt_second_eh_frame->output_section->vma + + htab->plt_second_eh_frame->output_offset + + PLT_FDE_START_OFFSET); + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_second_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + if (htab->plt_second_eh_frame->sec_info_type + == SEC_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_second_eh_frame, + htab->plt_second_eh_frame->contents)) + return NULL; + } + } + + if (htab->elf.sgot && htab->elf.sgot->size > 0) + elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize + = htab->got_entry_size; + + return htab; +} + + bfd_boolean _bfd_x86_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info) diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 542439c568..a6a8455ba9 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -601,6 +601,9 @@ extern bfd_boolean _bfd_x86_elf_link_check_relocs extern bfd_boolean _bfd_x86_elf_size_dynamic_sections (bfd *, struct bfd_link_info *); +extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections + (bfd *, struct bfd_link_info *); + extern bfd_boolean _bfd_x86_elf_always_size_sections (bfd *, struct bfd_link_info *); -- 2.34.1