PR binutils/10654
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index 36672fe7904ac10e3e2c1956c018bcaf86af8c4d..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;
@@ -1276,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);
@@ -1291,8 +1306,6 @@ elf_i386_check_relocs (bfd *abfd,
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         Elf_Internal_Sym *isym;
-
          isym = bfd_sym_from_r_symndx (&htab->sym_cache,
                                        abfd, r_symndx);
          if (isym == NULL)
@@ -1318,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)
@@ -1352,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;
@@ -1363,13 +1378,16 @@ 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);
                  return FALSE;
 
@@ -1413,7 +1431,7 @@ 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)) 
+                                    rel, rel_end, h, r_symndx)) 
        return FALSE;
 
       switch (r_type)
@@ -1442,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 */
 
@@ -1493,7 +1511,8 @@ 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)
                      return FALSE;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
@@ -1521,11 +1540,15 @@ 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>");
+                      abfd, name);
                    return FALSE;
                  }
              }
@@ -1556,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 */
@@ -1665,7 +1688,8 @@ 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)
                    return FALSE;
                  p->next = *head;
@@ -1781,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)
@@ -2094,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;
@@ -2537,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;
     }
@@ -2869,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,
@@ -2914,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)
@@ -2937,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;
 
@@ -3339,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;
@@ -3375,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)
@@ -3844,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)
@@ -3905,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.028719 seconds and 4 git commands to generate.