gdb: objc-lang: check symbol name before accessing memory
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index 779ad0f80f4dc618747785ee71dc1751d1dc5389..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, 2009
-   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;
@@ -495,13 +487,23 @@ struct elf64_x86_64_link_hash_table
 
   /* 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)
@@ -622,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;
@@ -679,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");
@@ -1018,12 +1024,19 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
        name = h->root.root.string;
       else
        {
-         Elf_Internal_Sym *isym;
          struct elf64_x86_64_link_hash_table *htab;
+
          htab = elf64_x86_64_hash_table (info);
-         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
-                                       abfd, r_symndx);
-         name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+         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)
@@ -1061,6 +1074,9 @@ 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);
   sym_hashes = elf_sym_hashes (abfd);
 
@@ -1100,7 +1116,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                                                   TRUE);
              if (h == NULL)
                return FALSE;
-             
+
              /* Fake a STT_GNU_IFUNC symbol.  */
              h->type = STT_GNU_IFUNC;
              h->def_regular = 1;
@@ -1152,7 +1168,7 @@ 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;
 
@@ -1504,7 +1520,6 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                     easily.  Oh well.  */
                  asection *s;
                  void **vpp;
-                 Elf_Internal_Sym *isym;
 
                  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
                                                abfd, r_symndx);
@@ -1595,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;
@@ -1603,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);
@@ -1648,8 +1668,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       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:
@@ -1835,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
@@ -1870,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.  */
@@ -2160,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 ();
@@ -2455,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;
@@ -2485,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
@@ -2573,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);
@@ -2638,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,
@@ -3281,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);
@@ -3516,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
@@ -3548,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;
@@ -3703,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)
     {
@@ -3742,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.
@@ -3982,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");
 
@@ -4211,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;
@@ -4226,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;
@@ -4466,6 +4497,29 @@ static const struct bfd_elf_special_section
 
 #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
This page took 0.028379 seconds and 4 git commands to generate.