Fix excessive memory allocation attempts and possible integer overfloaws when attempt...
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index b970146cfb324b56db6f67c6cf50b66eb8ee5eed..6a5159d4b0ce30c9d347fc58d93236d95f665510 100644 (file)
@@ -820,24 +820,6 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] =
   DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
 };
 
-/* Architecture-specific backend data for x86-64.  */
-
-struct elf_x86_64_backend_data
-{
-  /* Target system.  */
-  enum
-    {
-      is_normal,
-      is_nacl
-    } os;
-};
-
-#define get_elf_x86_64_arch_data(bed) \
-  ((const struct elf_x86_64_backend_data *) (bed)->arch_data)
-
-#define get_elf_x86_64_backend_data(abfd) \
-  get_elf_x86_64_arch_data (get_elf_backend_data (abfd))
-
 /* These are the standard parameters.  */
 static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
   {
@@ -967,7 +949,7 @@ static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt =
     sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
   };
 
-static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
+static const struct elf_x86_backend_data elf_x86_64_arch_bed =
   {
     is_normal                            /* os */
   };
@@ -4360,273 +4342,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)
-       {
-         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 (htab->plt.has_plt0)
        {
-         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)
+      if (htab->tlsdesc_plt)
        {
-         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;
+         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,
@@ -4711,7 +4511,7 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
   if (relsize <= 0)
     return -1;
 
-  if (get_elf_x86_64_backend_data (abfd)->os == is_normal)
+  if (get_elf_x86_backend_data (abfd)->target_os == is_normal)
     {
       lazy_plt = &elf_x86_64_lazy_plt;
       non_lazy_plt = &elf_x86_64_non_lazy_plt;
@@ -5059,8 +4859,11 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
          != (int) R_X86_64_GNU_VTENTRY))
     abort ();
 
-  init_table.is_vxworks = FALSE;
-  if (get_elf_x86_64_backend_data (info->output_bfd)->os == is_normal)
+  /* This is unused for x86-64.  */
+  init_table.plt0_pad_byte = 0x90;
+
+  if (get_elf_x86_backend_data (info->output_bfd)->target_os
+      == is_normal)
     {
       if (info->bndplt)
        {
@@ -5083,7 +4886,6 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
          init_table.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
          init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
        }
-      init_table.normal_target = TRUE;
     }
   else
     {
@@ -5091,7 +4893,6 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
       init_table.non_lazy_plt = NULL;
       init_table.lazy_ibt_plt = NULL;
       init_table.non_lazy_ibt_plt = NULL;
-      init_table.normal_target = FALSE;
     }
 
   if (ABI_64_P (info->output_bfd))
@@ -5358,7 +5159,7 @@ static const bfd_byte elf_x86_64_nacl_eh_frame_plt[] =
      || PLT_FDE_LENGTH != 36                            \
      || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8  \
      || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12)
-# error "Need elf_x86_64_backend_data parameters for eh_frame_plt offsets!"
+# error "Need elf_x86_backend_data parameters for eh_frame_plt offsets!"
 #endif
     PLT_CIE_LENGTH, 0, 0, 0,   /* CIE length */
     0, 0, 0, 0,                        /* CIE ID */
@@ -5412,7 +5213,7 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt =
     sizeof (elf_x86_64_nacl_eh_frame_plt)    /* eh_frame_plt_size */
   };
 
-static const struct elf_x86_64_backend_data elf_x86_64_nacl_arch_bed =
+static const struct elf_x86_backend_data elf_x86_64_nacl_arch_bed =
   {
     is_nacl                                  /* os */
   };
This page took 0.027524 seconds and 4 git commands to generate.