This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/2] x86: Add _bfd_x86_elf_finish_dynamic_sections


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]