gdb: objc-lang: check symbol name before accessing memory
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index 581d544013651e857523592ce0e90515f159d89d..3a24ccae578f2cb9f609f787d6b434c7a5a3ff93 100644 (file)
@@ -1,6 +1,6 @@
 /* X86-64 specific support for 64-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010  Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -451,13 +451,13 @@ struct elf64_x86_64_obj_tdata
 #define is_x86_64_elf(bfd)                             \
   (bfd_get_flavour (bfd) == bfd_target_elf_flavour     \
    && elf_tdata (bfd) != NULL                          \
-   && elf_object_id (bfd) == X86_64_ELF_TDATA)
+   && elf_object_id (bfd) == X86_64_ELF_DATA)
 
 static bfd_boolean
 elf64_x86_64_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf64_x86_64_obj_tdata),
-                                 X86_64_ELF_TDATA);
+                                 X86_64_ELF_DATA);
 }
 
 /* x86-64 ELF linker hash table.  */
@@ -470,16 +470,8 @@ struct elf64_x86_64_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
-  /* The offset into splt of the PLT entry for the TLS descriptor
-     resolver.  Special values are 0, if not necessary (or not found
-     to be necessary yet), and -1 if needed but not determined
-     yet.  */
-  bfd_vma tlsdesc_plt;
-  /* The offset into sgot of the GOT entry used by the PLT entry
-     above.  */
-  bfd_vma tlsdesc_got;
-
-  union {
+  union
+  {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ld_got;
@@ -487,21 +479,31 @@ struct elf64_x86_64_link_hash_table
   /* The amount of space used by the jump slots in the GOT.  */
   bfd_vma sgotplt_jump_table_size;
 
-  /* Small local sym to section mapping cache.  */
-  struct sym_sec_cache sym_sec;
+  /* Small local sym cache.  */
+  struct sym_cache sym_cache;
 
   /* _TLS_MODULE_BASE_ symbol.  */
   struct bfd_link_hash_entry *tls_module_base;
 
   /* Used by local STT_GNU_IFUNC symbols.  */
   htab_t loc_hash_table;
-  void *loc_hash_memory;
+  void * loc_hash_memory;
+
+  /* The offset into splt of the PLT entry for the TLS descriptor
+     resolver.  Special values are 0, if not necessary (or not found
+     to be necessary yet), and -1 if needed but not determined
+     yet.  */
+  bfd_vma tlsdesc_plt;
+  /* The offset into sgot of the GOT entry used by the PLT entry
+     above.  */
+  bfd_vma tlsdesc_got;
 };
 
 /* Get the x86-64 ELF linker hash table from a link_info structure.  */
 
 #define elf64_x86_64_hash_table(p) \
-  ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+  == X86_64_ELF_DATA ? ((struct elf64_x86_64_link_hash_table *) ((p)->hash)) : NULL)
 
 #define elf64_x86_64_compute_jump_table_size(htab) \
   ((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE)
@@ -517,8 +519,9 @@ elf64_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
      subclass.  */
   if (entry == NULL)
     {
-      entry = bfd_hash_allocate (table,
-                                sizeof (struct elf64_x86_64_link_hash_entry));
+      entry = (struct bfd_hash_entry *)
+          bfd_hash_allocate (table,
+                             sizeof (struct elf64_x86_64_link_hash_entry));
       if (entry == NULL)
        return entry;
     }
@@ -621,7 +624,8 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
 
   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
                                      elf64_x86_64_link_hash_newfunc,
-                                     sizeof (struct elf64_x86_64_link_hash_entry)))
+                                     sizeof (struct elf64_x86_64_link_hash_entry),
+                                     X86_64_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -629,7 +633,7 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
 
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
-  ret->sym_sec.abfd = NULL;
+  ret->sym_cache.abfd = NULL;
   ret->tlsdesc_plt = 0;
   ret->tlsdesc_got = 0;
   ret->tls_ld_got.refcount = 0;
@@ -678,6 +682,9 @@ elf64_x86_64_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
     return FALSE;
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
   if (!info->shared)
     htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
@@ -937,7 +944,8 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
                             unsigned int *r_type, int tls_type,
                             const Elf_Internal_Rela *rel,
                             const Elf_Internal_Rela *relend,
-                            struct elf_link_hash_entry *h)
+                            struct elf_link_hash_entry *h,
+                            unsigned long r_symndx)
 {
   unsigned int from_type = *r_type;
   unsigned int to_type = from_type;
@@ -949,7 +957,7 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
     case R_X86_64_GOTPC32_TLSDESC:
     case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
-      if (!info->shared)
+      if (info->executable)
        {
          if (h == NULL)
            to_type = R_X86_64_TPOFF32;
@@ -964,7 +972,7 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
        {
          unsigned int new_to_type = to_type;
 
-         if (!info->shared
+         if (info->executable
              && h != NULL
              && h->dynindx == -1
              && tls_type == GOT_TLS_IE)
@@ -988,7 +996,7 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
       break;
 
     case R_X86_64_TLSLD:
-      if (!info->shared)
+      if (info->executable)
        to_type = R_X86_64_TPOFF32;
       break;
 
@@ -1007,15 +1015,34 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
                                              from_type, rel, relend))
     {
       reloc_howto_type *from, *to;
+      const char *name;
 
       from = elf64_x86_64_rtype_to_howto (abfd, from_type);
       to = elf64_x86_64_rtype_to_howto (abfd, to_type);
 
+      if (h)
+       name = h->root.root.string;
+      else
+       {
+         struct elf64_x86_64_link_hash_table *htab;
+
+         htab = elf64_x86_64_hash_table (info);
+         if (htab == NULL)
+           name = "*unknown*";
+         else
+           {
+             Elf_Internal_Sym *isym;
+
+             isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                           abfd, r_symndx);
+             name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+           }
+       }
+
       (*_bfd_error_handler)
        (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
           "in section `%A' failed"),
-        abfd, sec, from->name, to->name,
-        h ? h->root.root.string : "a local symbol",
+        abfd, sec, from->name, to->name, name,
         (unsigned long) rel->r_offset);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -1040,7 +1067,6 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
-  Elf_Internal_Sym *isymbuf;
 
   if (info->relocatable)
     return TRUE;
@@ -1048,8 +1074,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
   BFD_ASSERT (is_x86_64_elf (abfd));
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   symtab_hdr = &elf_symtab_hdr (abfd);
-  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   sym_hashes = elf_sym_hashes (abfd);
 
   sreloc = NULL;
@@ -1060,6 +1088,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *isym;
+      const char *name;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       r_type = ELF64_R_TYPE (rel->r_info);
@@ -1074,28 +1104,19 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         Elf_Internal_Sym *isym;
-
-         /* Read this BFD's local symbols.  */
-         if (isymbuf == NULL)
-           {
-             if (isymbuf == NULL)
-               isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
-                                               symtab_hdr->sh_info, 0,
-                                               NULL, NULL, NULL);
-             if (isymbuf == NULL)
-                 return FALSE;
-           }
+         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                       abfd, r_symndx);
+         if (isym == NULL)
+           return FALSE;
 
          /* Check relocation against local STT_GNU_IFUNC symbol.  */
-         isym = isymbuf + r_symndx;
          if (ELF64_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              h = elf64_x86_64_get_local_sym_hash (htab, abfd, rel,
                                                   TRUE);
              if (h == NULL)
-               goto error_return;
-             
+               return FALSE;
+
              /* Fake a STT_GNU_IFUNC symbol.  */
              h->type = STT_GNU_IFUNC;
              h->def_regular = 1;
@@ -1108,6 +1129,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        }
       else
        {
+         isym = NULL;
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
@@ -1134,7 +1156,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            case R_X86_64_GOTPCREL:
            case R_X86_64_GOTPCREL64:
              if (!_bfd_elf_create_ifunc_sections (abfd, info))
-               goto error_return;
+               return FALSE;
              break;
            }
 
@@ -1145,7 +1167,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            {
              /* It is referenced by a non-shared object. */
              h->ref_regular = 1;
+             h->needs_plt = 1;
+
              /* STT_GNU_IFUNC symbol must go through PLT.  */
              h->plt.refcount += 1;
 
@@ -1156,15 +1179,18 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
              switch (r_type)
                {
                default:
+                 if (h->root.root.string)
+                   name = h->root.root.string;
+                 else
+                   name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+                                            NULL);
                  (*_bfd_error_handler)
                    (_("%B: relocation %s against STT_GNU_IFUNC "
                       "symbol `%s' isn't handled by %s"), abfd,
                     x86_64_elf_howto_table[r_type].name,
-                    (h->root.root.string
-                     ? h->root.root.string : "a local symbol"),
-                    __FUNCTION__);
+                    name, __FUNCTION__);
                  bfd_set_error (bfd_error_bad_value);
-                 goto error_return;
+                 return FALSE;
 
                case R_X86_64_64:
                  h->non_got_ref = 1;
@@ -1178,7 +1204,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                        (abfd, info, sec, sreloc,
                         &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs);
                      if (sreloc == NULL)
-                       goto error_return;
+                       return FALSE;
                    }
                  break;
 
@@ -1201,7 +1227,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  if (htab->elf.sgot == NULL
                      && !_bfd_elf_create_got_section (htab->elf.dynobj,
                                                       info))
-                   goto error_return;
+                   return FALSE;
                  break;
                }
 
@@ -1212,8 +1238,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL,
                                         symtab_hdr, sym_hashes,
                                         &r_type, GOT_UNKNOWN,
-                                        rel, rel_end, h))
-       goto error_return;
+                                        rel, rel_end, h, r_symndx))
+       return FALSE;
 
       switch (r_type)
        {
@@ -1222,20 +1248,24 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
          goto create_got;
 
        case R_X86_64_TPOFF32:
-         if (info->shared)
+         if (!info->executable)
            {
+             if (h)
+               name = h->root.root.string;
+             else
+               name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+                                        NULL);
              (*_bfd_error_handler)
                (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
                 abfd,
-                x86_64_elf_howto_table[r_type].name,
-                (h) ? h->root.root.string : "a local symbol");
+                x86_64_elf_howto_table[r_type].name, name);
              bfd_set_error (bfd_error_bad_value);
-             goto error_return;
+             return FALSE;
            }
          break;
 
        case R_X86_64_GOTTPOFF:
-         if (info->shared)
+         if (!info->executable)
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
 
@@ -1290,7 +1320,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    local_got_refcounts = ((bfd_signed_vma *)
                                           bfd_zalloc (abfd, size));
                    if (local_got_refcounts == NULL)
-                     goto error_return;
+                     return FALSE;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
                    elf64_x86_64_local_tlsdesc_gotent (abfd)
                      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
@@ -1315,10 +1345,15 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  tls_type |= old_tls_type;
                else
                  {
+                   if (h)
+                     name = h->root.root.string;
+                   else
+                     name = bfd_elf_sym_name (abfd, symtab_hdr,
+                                              isym, NULL);
                    (*_bfd_error_handler)
                      (_("%B: '%s' accessed both as normal and thread local symbol"),
-                      abfd, h ? h->root.root.string : "<local>");
-                   goto error_return;
+                      abfd, name);
+                   return FALSE;
                  }
              }
 
@@ -1342,7 +1377,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                htab->elf.dynobj = abfd;
              if (!_bfd_elf_create_got_section (htab->elf.dynobj,
                                                info))
-               goto error_return;
+               return FALSE;
            }
          break;
 
@@ -1385,13 +1420,15 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
              && (sec->flags & SEC_ALLOC) != 0
              && (sec->flags & SEC_READONLY) != 0)
            {
+             if (h)
+               name = h->root.root.string;
+             else
+               name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
              (*_bfd_error_handler)
                (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
-                abfd,
-                x86_64_elf_howto_table[r_type].name,
-                (h) ? h->root.root.string : "a local symbol");
+                abfd, x86_64_elf_howto_table[r_type].name, name);
              bfd_set_error (bfd_error_bad_value);
-             goto error_return;
+             return FALSE;
            }
          /* Fall through.  */
 
@@ -1467,7 +1504,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    (sec, htab->elf.dynobj, 3, abfd, /*rela?*/ TRUE);
 
                  if (sreloc == NULL)
-                   goto error_return;
+                   return FALSE;
                }
 
              /* If this is a global symbol, we count the number of
@@ -1478,16 +1515,20 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                }
              else
                {
-                 void **vpp;
                  /* Track dynamic relocs needed for local syms too.
                     We really need local syms available to do this
                     easily.  Oh well.  */
-
                  asection *s;
-                 s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
-                                                sec, r_symndx);
+                 void **vpp;
+
+                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                               abfd, r_symndx);
+                 if (isym == NULL)
+                   return FALSE;
+
+                 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
-                   goto error_return;
+                   s = sec;
 
                  /* Beware of type punned pointers vs strict aliasing
                     rules.  */
@@ -1503,7 +1544,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
-                   goto error_return;
+                   return FALSE;
                  p->next = *head;
                  *head = p;
                  p->sec = sec;
@@ -1521,7 +1562,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
             Reconstruct it for later use during GC.  */
        case R_X86_64_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-           goto error_return;
+           return FALSE;
          break;
 
          /* This relocation describes which C++ vtable entries are actually
@@ -1530,7 +1571,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
          BFD_ASSERT (h != NULL);
          if (h != NULL
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-           goto error_return;
+           return FALSE;
          break;
 
        default:
@@ -1538,25 +1579,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        }
     }
 
-   if (isymbuf != NULL
-       && (unsigned char *) isymbuf != symtab_hdr->contents)
-    {
-      if (!info->keep_memory)
-       free (isymbuf);
-      else
-       {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) isymbuf;
-       }
-    }
-
   return TRUE;
-
-error_return:
-   if (isymbuf != NULL
-       && (unsigned char *) isymbuf != symtab_hdr->contents)
-     free (isymbuf);
-   return FALSE;
 }
 
 /* Return the section that should be marked against GC for a given
@@ -1587,6 +1610,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
                            asection *sec,
                            const Elf_Internal_Rela *relocs)
 {
+  struct elf64_x86_64_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_signed_vma *local_got_refcounts;
@@ -1595,6 +1619,10 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
   if (info->relocatable)
     return TRUE;
 
+  htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_symtab_hdr (abfd);
@@ -1634,14 +1662,14 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL,
                                         symtab_hdr, sym_hashes,
                                         &r_type, GOT_UNKNOWN,
-                                        rel, relend, h))
+                                        rel, relend, h, r_symndx))
        return FALSE;
 
       switch (r_type)
        {
        case R_X86_64_TLSLD:
-         if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0)
-           elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1;
+         if (htab->tls_ld_got.refcount > 0)
+           htab->tls_ld_got.refcount -= 1;
          break;
 
        case R_X86_64_TLSGD:
@@ -1827,6 +1855,8 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
      same memory location for the variable.  */
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
      to copy the initial value out of the dynamic object and into the
@@ -1862,6 +1892,8 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
   info = (struct bfd_link_info *) inf;
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
@@ -1935,7 +1967,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
   if (h->got.refcount > 0
-      && !info->shared
+      && info->executable
       && h->dynindx == -1
       && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
     {
@@ -2152,6 +2184,9 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *ibfd;
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   if (dynobj == NULL)
     abort ();
@@ -2447,17 +2482,22 @@ elf64_x86_64_always_size_sections (bfd *output_bfd,
 
       if (tlsbase && tlsbase->type == STT_TLS)
        {
+         struct elf64_x86_64_link_hash_table *htab;
          struct bfd_link_hash_entry *bh = NULL;
          const struct elf_backend_data *bed
            = get_elf_backend_data (output_bfd);
 
+         htab = elf64_x86_64_hash_table (info);
+         if (htab == NULL)
+           return FALSE;
+
          if (!(_bfd_generic_link_add_one_symbol
                (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
                 tls_sec, 0, NULL, FALSE,
                 bed->collect, &bh)))
            return FALSE;
 
-         elf64_x86_64_hash_table (info)->tls_module_base = bh;
+         htab->tls_module_base = bh;
 
          tlsbase = (struct elf_link_hash_entry *)bh;
          tlsbase->def_regular = 1;
@@ -2477,17 +2517,21 @@ elf64_x86_64_always_size_sections (bfd *output_bfd,
 static void
 elf64_x86_64_set_tls_module_base (struct bfd_link_info *info)
 {
+  struct elf64_x86_64_link_hash_table *htab;
   struct bfd_link_hash_entry *base;
 
   if (!info->executable)
     return;
 
-  base = elf64_x86_64_hash_table (info)->tls_module_base;
+  htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return;
 
-  if (!base)
+  base = htab->tls_module_base;
+  if (base == NULL)
     return;
 
-  base->u.def.value = elf_hash_table (info)->tls_size;
+  base->u.def.value = htab->elf.tls_size;
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
@@ -2535,6 +2579,16 @@ is_32bit_relative_branch (bfd_byte *contents, bfd_vma offset)
              && (contents [offset - 1] & 0xf0) == 0x80));
 }
 
+static void
+elf64_x86_64_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
+{
+  bfd_byte *loc = s->contents;
+  loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
+  BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+             <= s->contents + s->size);
+  bfd_elf64_swap_reloca_out (abfd, rel, loc);
+}
+
 /* Relocate an x86_64 ELF section.  */
 
 static bfd_boolean
@@ -2555,6 +2609,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   BFD_ASSERT (is_x86_64_elf (input_bfd));
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
   symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
@@ -2605,7 +2661,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                                &sec, rel);
 
          /* Relocate against local STT_GNU_IFUNC symbol.  */
-         if (ELF64_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+         if (!info->relocatable
+             && ELF64_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
            {
              h = elf64_x86_64_get_local_sym_hash (htab, input_bfd,
                                                   rel, FALSE);
@@ -2619,7 +2676,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        }
       else
        {
-         bfd_boolean warned;
+         bfd_boolean warned ATTRIBUTE_UNUSED;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
@@ -2649,6 +2706,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        {
          asection *plt;
          bfd_vma plt_index;
+         const char *name;
 
          if ((input_section->flags & SEC_ALLOC) == 0
              || h->plt.offset == (bfd_vma) -1)
@@ -2662,13 +2720,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          switch (r_type)
            {
            default:
+             if (h->root.root.string)
+               name = h->root.root.string;
+             else
+               name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+                                        NULL);
              (*_bfd_error_handler)
                (_("%B: relocation %s against STT_GNU_IFUNC "
                   "symbol `%s' isn't handled by %s"), input_bfd,
                 x86_64_elf_howto_table[r_type].name,
-                (h->root.root.string
-                 ? h->root.root.string : "a local symbol"),
-                __FUNCTION__);
+                name, __FUNCTION__);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
 
@@ -2680,13 +2741,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            case R_X86_64_64: 
              if (rel->r_addend != 0)
                {
+                 if (h->root.root.string)
+                   name = h->root.root.string;
+                 else
+                   name = bfd_elf_sym_name (input_bfd, symtab_hdr,
+                                            sym, NULL);
                  (*_bfd_error_handler)
                    (_("%B: relocation %s against STT_GNU_IFUNC "
                       "symbol `%s' has non-zero addend: %d"),
                     input_bfd, x86_64_elf_howto_table[r_type].name,
-                    (h->root.root.string
-                     ? h->root.root.string : "a local symbol"),
-                    rel->r_addend);
+                    name, rel->r_addend);
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
@@ -2696,7 +2760,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              if (info->shared && h->non_got_ref)
                {
                  Elf_Internal_Rela outrel;
-                 bfd_byte *loc;
                  asection *sreloc;
 
                  /* Need a dynamic relocation to get the real function
@@ -2729,10 +2792,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                    }
 
                  sreloc = htab->elf.irelifunc;
-                 loc = sreloc->contents;
-                 loc += (sreloc->reloc_count++
-                         * sizeof (Elf64_External_Rela));
-                 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+                 elf64_x86_64_append_rela (output_bfd, sreloc, &outrel);
 
                  /* If this reloc is against an external symbol, we
                     do not want to fiddle with the addend.  Otherwise,
@@ -2915,7 +2975,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                    {
                      asection *s;
                      Elf_Internal_Rela outrel;
-                     bfd_byte *loc;
 
                      /* We need to generate a R_X86_64_RELATIVE reloc
                         for the dynamic linker.  */
@@ -2928,9 +2987,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                         + off);
                      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
                      outrel.r_addend = relocation;
-                     loc = s->contents;
-                     loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
-                     bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+                     elf64_x86_64_append_rela (output_bfd, s, &outrel);
                    }
 
                  local_got_offsets[r_symndx] |= 1;
@@ -3119,7 +3176,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                      || h->root.type == bfd_link_hash_undefined)))
            {
              Elf_Internal_Rela outrel;
-             bfd_byte *loc;
              bfd_boolean skip, relocate;
              asection *sreloc;
 
@@ -3203,9 +3259,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
              BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
 
-             loc = sreloc->contents;
-             loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
-             bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+             elf64_x86_64_append_rela (output_bfd, sreloc, &outrel);
 
              /* If this reloc is against an external symbol, we do
                 not want to fiddle with the addend.  Otherwise, we
@@ -3231,7 +3285,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                             input_section, contents,
                                             symtab_hdr, sym_hashes,
                                             &r_type, tls_type, rel,
-                                            relend, h))
+                                            relend, h, r_symndx))
            return FALSE;
 
          if (r_type == R_X86_64_TPOFF32)
@@ -3265,13 +3319,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                     leaq x@tlsdesc(%rip), %rax
 
                     Change it to:
-                    movl $x@tpoff, %rax
-                  */
+                    movl $x@tpoff, %rax.  */
 
-                 unsigned int val, type, type2;
+                 unsigned int val, type;
 
                  type = bfd_get_8 (input_bfd, contents + roff - 3);
-                 type2 = bfd_get_8 (input_bfd, contents + roff - 2);
                  val = bfd_get_8 (input_bfd, contents + roff - 1);
                  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
                             contents + roff - 3);
@@ -3376,7 +3428,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          else
            {
              Elf_Internal_Rela outrel;
-             bfd_byte *loc;
              int dr_type, indx;
              asection *sreloc;
 
@@ -3395,16 +3446,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                     + offplt
                                     + htab->sgotplt_jump_table_size);
                  sreloc = htab->elf.srelplt;
-                 loc = sreloc->contents;
-                 loc += sreloc->reloc_count++
-                   * sizeof (Elf64_External_Rela);
-                 BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
-                             <= sreloc->contents + sreloc->size);
                  if (indx == 0)
                    outrel.r_addend = relocation - elf64_x86_64_dtpoff_base (info);
                  else
                    outrel.r_addend = 0;
-                 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+                 elf64_x86_64_append_rela (output_bfd, sreloc, &outrel);
                }
 
              sreloc = htab->elf.srelgot;
@@ -3426,11 +3472,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                outrel.r_addend = relocation - elf64_x86_64_dtpoff_base (info);
              outrel.r_info = ELF64_R_INFO (indx, dr_type);
 
-             loc = sreloc->contents;
-             loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
-             BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
-                         <= sreloc->contents + sreloc->size);
-             bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+             elf64_x86_64_append_rela (output_bfd, sreloc, &outrel);
 
              if (GOT_TLS_GD_P (tls_type))
                {
@@ -3448,11 +3490,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                      outrel.r_info = ELF64_R_INFO (indx,
                                                    R_X86_64_DTPOFF64);
                      outrel.r_offset += GOT_ENTRY_SIZE;
-                     sreloc->reloc_count++;
-                     loc += sizeof (Elf64_External_Rela);
-                     BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
-                                 <= sreloc->contents + sreloc->size);
-                     bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+                     elf64_x86_64_append_rela (output_bfd, sreloc,
+                                               &outrel);
                    }
                }
 
@@ -3513,14 +3552,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                     leaq x@tlsdesc(%rip), %rax
 
                     Change it to:
-                    movq x@gottpoff(%rip), %rax # before xchg %ax,%ax
-                  */
-
-                 unsigned int val, type, type2;
-
-                 type = bfd_get_8 (input_bfd, contents + roff - 3);
-                 type2 = bfd_get_8 (input_bfd, contents + roff - 2);
-                 val = bfd_get_8 (input_bfd, contents + roff - 1);
+                    movq x@gottpoff(%rip), %rax # before xchg %ax,%ax.  */
 
                  /* Now modify the instruction as appropriate. To
                     turn a leaq into a movq in the form we use it, it
@@ -3545,12 +3577,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                     call *(%rax)
 
                     Change it to:
-                    xchg %ax,%ax.  */
-
-                 unsigned int val, type;
+                    xchg %ax, %ax.  */
 
-                 type = bfd_get_8 (input_bfd, contents + roff);
-                 val = bfd_get_8 (input_bfd, contents + roff + 1);
                  bfd_put_8 (output_bfd, 0x66, contents + roff);
                  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
                  continue;
@@ -3565,7 +3593,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                             input_section, contents,
                                             symtab_hdr, sym_hashes,
                                             &r_type, GOT_UNKNOWN,
-                                            rel, relend, h))
+                                            rel, relend, h, r_symndx))
            return FALSE;
 
          if (r_type != R_X86_64_TLSLD)
@@ -3592,7 +3620,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          else
            {
              Elf_Internal_Rela outrel;
-             bfd_byte *loc;
 
              if (htab->elf.srelgot == NULL)
                abort ();
@@ -3606,9 +3633,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                          htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
              outrel.r_info = ELF64_R_INFO (0, R_X86_64_DTPMOD64);
              outrel.r_addend = 0;
-             loc = htab->elf.srelgot->contents;
-             loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
-             bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+             elf64_x86_64_append_rela (output_bfd, htab->elf.srelgot,
+                                       &outrel);
              htab->tls_ld_got.offset |= 1;
            }
          relocation = htab->elf.sgot->output_section->vma
@@ -3617,14 +3643,14 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          break;
 
        case R_X86_64_DTPOFF32:
-         if (info->shared || (input_section->flags & SEC_CODE) == 0)
+         if (!info->executable|| (input_section->flags & SEC_CODE) == 0)
            relocation -= elf64_x86_64_dtpoff_base (info);
          else
            relocation = elf64_x86_64_tpoff (info, relocation);
          break;
 
        case R_X86_64_TPOFF32:
-         BFD_ASSERT (! info->shared);
+         BFD_ASSERT (info->executable);
          relocation = elf64_x86_64_tpoff (info, relocation);
          break;
 
@@ -3702,6 +3728,8 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
   struct elf64_x86_64_link_hash_table *htab;
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -3741,7 +3769,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
         corresponds to this symbol.  This is the index of this symbol
         in all the symbols for which we are making plt entries.  The
         first entry in the procedure linkage table is reserved.
-        
+
         Get the offset into the .got table of the entry that
         corresponds to this function.  Each .got entry is GOT_ENTRY_SIZE
         bytes. The first three are reserved for the dynamic linker.
@@ -3842,7 +3870,6 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
-      bfd_byte *loc;
 
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
@@ -3868,13 +3895,15 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
            }
          else
            {
+             asection *plt;
+
              if (!h->pointer_equality_needed)
                abort ();
 
              /* For non-shared object, we can't use .got.plt, which
                 contains the real function addres if we need pointer
                 equality.  We load the GOT entry with the PLT entry.  */
-             asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
+             plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
              bfd_put_64 (output_bfd, (plt->output_section->vma
                                       + plt->output_offset
                                       + h->plt.offset),
@@ -3903,15 +3932,12 @@ do_glob_dat:
          rela.r_addend = 0;
        }
 
-      loc = htab->elf.srelgot->contents;
-      loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
-      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+      elf64_x86_64_append_rela (output_bfd, htab->elf.srelgot, &rela);
     }
 
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
-      bfd_byte *loc;
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
@@ -3926,9 +3952,7 @@ do_glob_dat:
                       + h->root.u.def.section->output_offset);
       rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY);
       rela.r_addend = 0;
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
-      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+      elf64_x86_64_append_rela (output_bfd, htab->srelbss, &rela);
     }
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
@@ -3985,6 +4009,9 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
   asection *sdyn;
 
   htab = elf64_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
@@ -4214,10 +4241,11 @@ elf64_x86_64_add_symbol_hook (bfd *abfd,
        }
       *secp = lcomm;
       *valp = sym->st_size;
-      break;
+      return TRUE;
     }
 
-  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+  if ((abfd->flags & DYNAMIC) == 0
+      && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
     elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
 
   return TRUE;
@@ -4229,11 +4257,11 @@ elf64_x86_64_add_symbol_hook (bfd *abfd,
 
 static bfd_boolean
 elf64_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
-                                          asection *sec, int *index)
+                                          asection *sec, int *index_return)
 {
   if (sec == &_bfd_elf_large_com_section)
     {
-      *index = SHN_X86_64_LCOMMON;
+      *index_return = SHN_X86_64_LCOMMON;
       return TRUE;
     }
   return FALSE;
@@ -4468,3 +4496,76 @@ static const struct bfd_elf_special_section
 #define elf64_bed elf64_x86_64_fbsd_bed
 
 #include "elf64-target.h"
+
+/* Solaris 2 support.  */
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM                  bfd_elf64_x86_64_sol2_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME                 "elf64-x86-64-sol2"
+
+/* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
+   objects won't be recognized.  */
+#undef ELF_OSABI
+
+#undef  elf64_bed
+#define elf64_bed                          elf64_x86_64_sol2_bed
+
+/* The Solaris 2 ABI requires a plt symbol on all platforms.
+
+   Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output
+   File, p.63.  */
+#undef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym           1
+
+#include "elf64-target.h"
+
+/* Intel L1OM support.  */
+
+static bfd_boolean
+elf64_l1om_elf_object_p (bfd *abfd)
+{
+  /* Set the right machine number for an L1OM elf64 file.  */
+  bfd_default_set_arch_mach (abfd, bfd_arch_l1om, bfd_mach_l1om);
+  return TRUE;
+}
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM                  bfd_elf64_l1om_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME                 "elf64-l1om"
+#undef ELF_ARCH
+#define ELF_ARCH                           bfd_arch_l1om
+
+#undef ELF_MACHINE_CODE
+#define ELF_MACHINE_CODE                   EM_L1OM
+
+#undef ELF_OSABI
+
+#undef  elf64_bed
+#define elf64_bed elf64_l1om_bed
+
+#undef elf_backend_object_p
+#define elf_backend_object_p               elf64_l1om_elf_object_p
+
+#undef  elf_backend_post_process_headers
+
+#include "elf64-target.h"
+
+/* FreeBSD L1OM support.  */
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM                  bfd_elf64_l1om_freebsd_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME                 "elf64-l1om-freebsd"
+
+#undef ELF_OSABI
+#define        ELF_OSABI                           ELFOSABI_FREEBSD
+
+#undef  elf64_bed
+#define elf64_bed elf64_l1om_fbsd_bed
+
+#undef  elf_backend_post_process_headers
+#define elf_backend_post_process_headers  _bfd_elf_set_osabi
+
+#include "elf64-target.h"
This page took 0.039311 seconds and 4 git commands to generate.