* rs6000-core.c (read_hdr): Fix typo in recent C++ compatibility
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index ab4f53dbe426366325666535cf2c362f924ba2d7..9de1a6c7aff4d7aaa095e4e6a2c71f9dd630bce9 100644 (file)
@@ -1,6 +1,6 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -704,8 +704,8 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
      subclass.  */
   if (entry == NULL)
     {
-      entry = bfd_hash_allocate (table,
-                                sizeof (struct elf_i386_link_hash_entry));
+      entry = (struct bfd_hash_entry *)
+          bfd_hash_allocate (table, sizeof (struct elf_i386_link_hash_entry));
       if (entry == NULL)
        return entry;
     }
@@ -802,7 +802,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
   struct elf_i386_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_i386_link_hash_table);
 
-  ret = bfd_malloc (amt);
+  ret = (struct elf_i386_link_hash_table *) bfd_malloc (amt);
   if (ret == NULL)
     return NULL;
 
@@ -1149,7 +1149,8 @@ elf_i386_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;
@@ -1163,7 +1164,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
     case R_386_TLS_IE_32:
     case R_386_TLS_IE:
     case R_386_TLS_GOTIE:
-      if (!info->shared)
+      if (info->executable)
        {
          if (h == NULL)
            to_type = R_386_TLS_LE_32;
@@ -1179,7 +1180,7 @@ elf_i386_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))
@@ -1205,7 +1206,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
       break;
 
     case R_386_TLS_LDM:
-      if (!info->shared)
+      if (info->executable)
        to_type = R_386_TLS_LE_32;
       break;
 
@@ -1224,15 +1225,27 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
                                          from_type, rel, relend))
     {
       reloc_howto_type *from, *to;
+      const char *name;
 
       from = elf_i386_rtype_to_howto (abfd, from_type);
       to = elf_i386_rtype_to_howto (abfd, to_type);
 
+      if (h)
+       name = h->root.root.string;
+      else
+       {
+         Elf_Internal_Sym *isym;
+         struct elf_i386_link_hash_table *htab;
+         htab = elf_i386_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);
+       }
+
       (*_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;
@@ -1258,7 +1271,6 @@ elf_i386_check_relocs (bfd *abfd,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
-  Elf_Internal_Sym *isymbuf;
 
   if (info->relocatable)
     return TRUE;
@@ -1267,7 +1279,6 @@ elf_i386_check_relocs (bfd *abfd,
 
   htab = elf_i386_hash_table (info);
   symtab_hdr = &elf_symtab_hdr (abfd);
-  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   sym_hashes = elf_sym_hashes (abfd);
 
   sreloc = NULL;
@@ -1278,6 +1289,8 @@ elf_i386_check_relocs (bfd *abfd,
       unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *isym;
+      const char *name;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -1293,27 +1306,18 @@ elf_i386_check_relocs (bfd *abfd,
       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 (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              h = elf_i386_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;
@@ -1327,6 +1331,7 @@ elf_i386_check_relocs (bfd *abfd,
        }
       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)
@@ -1350,7 +1355,7 @@ elf_i386_check_relocs (bfd *abfd,
            case R_386_GOT32:
            case R_386_GOTOFF:
              if (!_bfd_elf_create_ifunc_sections (abfd, info))
-               goto error_return;
+               return FALSE;
              break;
            }
 
@@ -1361,6 +1366,7 @@ elf_i386_check_relocs (bfd *abfd,
            {
              /* 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;
@@ -1372,15 +1378,18 @@ elf_i386_check_relocs (bfd *abfd,
              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,
                     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_386_32:
                  h->non_got_ref = 1;
@@ -1394,7 +1403,7 @@ elf_i386_check_relocs (bfd *abfd,
                        (abfd, info, sec, sreloc,
                         &((struct elf_i386_link_hash_entry *) h)->dyn_relocs);
                      if (sreloc == NULL)
-                       goto error_return;
+                       return FALSE;
                    }
                  break;
 
@@ -1411,7 +1420,7 @@ elf_i386_check_relocs (bfd *abfd,
                  if (htab->elf.sgot == NULL
                      && !_bfd_elf_create_got_section (htab->elf.dynobj,
                                                       info))
-                   goto error_return;
+                   return FALSE;
                  break;
                }
 
@@ -1422,8 +1431,8 @@ elf_i386_check_relocs (bfd *abfd,
       if (! elf_i386_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)
        {
@@ -1451,7 +1460,7 @@ elf_i386_check_relocs (bfd *abfd,
        case R_386_TLS_IE_32:
        case R_386_TLS_IE:
        case R_386_TLS_GOTIE:
-         if (info->shared)
+         if (!info->executable)
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
 
@@ -1502,9 +1511,10 @@ elf_i386_check_relocs (bfd *abfd,
                    size = symtab_hdr->sh_info;
                    size *= (sizeof (bfd_signed_vma)
                             + sizeof (bfd_vma) + sizeof(char));
-                   local_got_refcounts = bfd_zalloc (abfd, size);
+                   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;
                    elf_i386_local_tlsdesc_gotent (abfd)
                      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
@@ -1530,12 +1540,16 @@ elf_i386_check_relocs (bfd *abfd,
                  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;
                  }
              }
 
@@ -1557,7 +1571,7 @@ elf_i386_check_relocs (bfd *abfd,
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
              if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
-               goto error_return;
+               return FALSE;
            }
          if (r_type != R_386_TLS_IE)
            break;
@@ -1565,7 +1579,7 @@ elf_i386_check_relocs (bfd *abfd,
 
        case R_386_TLS_LE_32:
        case R_386_TLS_LE:
-         if (!info->shared)
+         if (info->executable)
            break;
          info->flags |= DF_STATIC_TLS;
          /* Fall through */
@@ -1639,7 +1653,7 @@ elf_i386_check_relocs (bfd *abfd,
                    (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
 
                  if (sreloc == NULL)
-                   goto error_return;
+                   return FALSE;
                }
 
              /* If this is a global symbol, we count the number of
@@ -1674,9 +1688,10 @@ elf_i386_check_relocs (bfd *abfd,
              if (p == NULL || p->sec != sec)
                {
                  bfd_size_type amt = sizeof *p;
-                 p = bfd_alloc (htab->elf.dynobj, amt);
+                 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;
@@ -1694,7 +1709,7 @@ elf_i386_check_relocs (bfd *abfd,
             Reconstruct it for later use during GC.  */
        case R_386_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
@@ -1703,7 +1718,7 @@ elf_i386_check_relocs (bfd *abfd,
          BFD_ASSERT (h != NULL);
          if (h != NULL
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
-           goto error_return;
+           return FALSE;
          break;
 
        default:
@@ -1711,25 +1726,7 @@ elf_i386_check_relocs (bfd *abfd,
        }
     }
 
-   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
@@ -1808,7 +1805,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
       if (! elf_i386_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)
@@ -2121,7 +2118,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
      make it a R_386_TLS_LE_32 requiring no TLS entry.  */
   if (h->got.refcount > 0
-      && !info->shared
+      && info->executable
       && h->dynindx == -1
       && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE))
     h->got.offset = (bfd_vma) -1;
@@ -2564,7 +2561,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         section's contents are written out.  This should not happen,
         but this way if it does, we get a R_386_NONE reloc instead
         of garbage.  */
-      s->contents = bfd_zalloc (dynobj, s->size);
+      s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
        return FALSE;
     }
@@ -2896,7 +2893,8 @@ elf_i386_relocate_section (bfd *output_bfd,
                  break;
                }
            }
-         else if (ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+         else if (!info->relocatable
+                  && ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
            {
              /* Relocate against local STT_GNU_IFUNC symbol.  */
              h = elf_i386_get_local_sym_hash (htab, input_bfd,
@@ -2941,6 +2939,7 @@ elf_i386_relocate_section (bfd *output_bfd,
        {
          asection *plt, *gotplt, *base_got;
          bfd_vma plt_index;
+         const char *name;
 
          if ((input_section->flags & SEC_ALLOC) == 0
              || h->plt.offset == (bfd_vma) -1)
@@ -2964,13 +2963,16 @@ elf_i386_relocate_section (bfd *output_bfd,
          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,
                 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;
 
@@ -3366,7 +3368,7 @@ elf_i386_relocate_section (bfd *output_bfd,
          break;
 
        case R_386_TLS_IE:
-         if (info->shared)
+         if (!info->executable)
            {
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
@@ -3402,7 +3404,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         &r_type, tls_type, rel,
-                                        relend, h))
+                                        relend, h, r_symndx))
            return FALSE;
 
          if (r_type == R_386_TLS_LE_32)
@@ -3871,7 +3873,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         &r_type, GOT_UNKNOWN, rel,
-                                        relend, h))
+                                        relend, h, r_symndx))
            return FALSE;
 
          if (r_type != R_386_TLS_LDM)
@@ -3932,7 +3934,7 @@ elf_i386_relocate_section (bfd *output_bfd,
 
        case R_386_TLS_LE_32:
        case R_386_TLS_LE:
-         if (info->shared)
+         if (!info->executable)
            {
              Elf_Internal_Rela outrel;
              asection *sreloc;
This page took 0.029596 seconds and 4 git commands to generate.