This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH 1/2] x86: Add _bfd_x86_elf_finish_dynamic_sections
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Sat, 14 Oct 2017 11:28:29 -0700
- Subject: Re: [PATCH 1/2] x86: Add _bfd_x86_elf_finish_dynamic_sections
- Authentication-results: sourceware.org; auth=none
- References: <20170914152329.GA26174@gmail.com>
On Thu, Sep 14, 2017 at 8:23 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> 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/elf32-i386.c | 308 ++++++++++++--------------------------------------
> bfd/elf64-x86-64.c | 324 ++++++++++++-----------------------------------------
> bfd/elfxx-x86.c | 218 +++++++++++++++++++++++++++++++++++
> bfd/elfxx-x86.h | 3 +
> 4 files changed, 366 insertions(+), 487 deletions(-)
>
> diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
> index 4337ab0ea0..2daa163cbf 100644
> --- a/bfd/elf32-i386.c
> +++ b/bfd/elf32-i386.c
> @@ -4101,262 +4101,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 4371a1625c..fd58bd7139 100644
> --- a/bfd/elf64-x86-64.c
> +++ b/bfd/elf64-x86-64.c
> @@ -4451,273 +4451,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 c41dbeff76..a0fe9d19ff 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 17aa10cd56..3d6366f16b 100644
> --- a/bfd/elfxx-x86.h
> +++ b/bfd/elfxx-x86.h
> @@ -454,6 +454,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.13.5
>
I am checking it in.
--
H.J.