include/ChangeLog
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index 462e0e854f476ee5e5c4681c999f88850572b9a9..b42e1a2b6b0eff70c3285b85cdeaba34bc5491e5 100644 (file)
@@ -1,6 +1,7 @@
 /* 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, 2010, 2011
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -28,6 +29,7 @@
 #include "bfd_stdint.h"
 #include "objalloc.h"
 #include "hashtab.h"
+#include "dwarf2.h"
 
 /* 386 uses REL relocations instead of RELA.  */
 #define USE_REL        1
@@ -323,7 +325,7 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
     case BFD_RELOC_386_IRELATIVE:
       TRACE ("BFD_RELOC_386_IRELATIVE");
-      return &elf_howto_table[R_386_IRELATIVE];
+      return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
 
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
@@ -419,7 +421,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
       elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20);
 
       /* pr_pid */
-      elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+      elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
 
       /* pr_reg */
       offset = 28;
@@ -437,7 +439,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
          elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
 
          /* pr_pid */
-         elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+         elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
 
          /* pr_reg */
          offset = 72;
@@ -475,6 +477,8 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
          return FALSE;
 
        case 124:               /* Linux/i386 elf_prpsinfo.  */
+         elf_tdata (abfd)->core_pid
+           = bfd_get_32 (abfd, note->descdata + 12);
          elf_tdata (abfd)->core_program
            = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
          elf_tdata (abfd)->core_command
@@ -571,6 +575,45 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
   0, 0, 0, 0   /* replaced with offset to start of .plt.  */
 };
 
+/* .eh_frame covering the .plt section.  */
+
+static const bfd_byte elf_i386_eh_frame_plt[] =
+{
+#define PLT_CIE_LENGTH         20
+#define PLT_FDE_LENGTH         36
+#define PLT_FDE_START_OFFSET   4 + PLT_CIE_LENGTH + 8
+#define PLT_FDE_LEN_OFFSET     4 + PLT_CIE_LENGTH + 12
+  PLT_CIE_LENGTH, 0, 0, 0,     /* CIE length */
+  0, 0, 0, 0,                  /* CIE ID */
+  1,                           /* CIE version */
+  'z', 'R', 0,                 /* Augmentation string */
+  1,                           /* Code alignment factor */
+  0x7c,                                /* Data alignment factor */
+  8,                           /* Return address column */
+  1,                           /* Augmentation size */
+  DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
+  DW_CFA_def_cfa, 4, 4,                /* DW_CFA_def_cfa: r4 (esp) ofs 4 */
+  DW_CFA_offset + 8, 1,                /* DW_CFA_offset: r8 (eip) at cfa-4 */
+  DW_CFA_nop, DW_CFA_nop,
+
+  PLT_FDE_LENGTH, 0, 0, 0,     /* FDE length */
+  PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
+  0, 0, 0, 0,                  /* R_386_PC32 .plt goes here */
+  0, 0, 0, 0,                  /* .plt size goes here */
+  0,                           /* Augmentation size */
+  DW_CFA_def_cfa_offset, 8,    /* DW_CFA_def_cfa_offset: 8 */
+  DW_CFA_advance_loc + 6,      /* DW_CFA_advance_loc: 6 to __PLT__+6 */
+  DW_CFA_def_cfa_offset, 12,   /* DW_CFA_def_cfa_offset: 12 */
+  DW_CFA_advance_loc + 10,     /* DW_CFA_advance_loc: 10 to __PLT__+16 */
+  DW_CFA_def_cfa_expression,   /* DW_CFA_def_cfa_expression */
+  11,                          /* Block length */
+  DW_OP_breg4, 4,              /* DW_OP_breg4 (esp): 4 */
+  DW_OP_breg8, 0,              /* DW_OP_breg8 (eip): 0 */
+  DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge,
+  DW_OP_lit2, DW_OP_shl, DW_OP_plus,
+  DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
+};
+
 /* On VxWorks, the .rel.plt.unloaded section has absolute relocations
    for the PLTResolve stub and then for each PLT entry.  */
 #define PLTRESOLVE_RELOCS_SHLIB 0
@@ -634,13 +677,13 @@ struct elf_i386_obj_tdata
 #define is_i386_elf(bfd)                               \
   (bfd_get_flavour (bfd) == bfd_target_elf_flavour     \
    && elf_tdata (bfd) != NULL                          \
-   && elf_object_id (bfd) == I386_ELF_TDATA)
+   && elf_object_id (bfd) == I386_ELF_DATA)
 
 static bfd_boolean
 elf_i386_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf_i386_obj_tdata),
-                                 I386_ELF_TDATA);
+                                 I386_ELF_DATA);
 }
 
 /* i386 ELF linker hash table.  */
@@ -652,20 +695,10 @@ struct elf_i386_link_hash_table
   /* Short-cuts to get to dynamic linker sections.  */
   asection *sdynbss;
   asection *srelbss;
+  asection *plt_eh_frame;
 
-  /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
-  asection *srelplt2;
-
-  /* True if the target system is VxWorks.  */
-  int is_vxworks;
-
-  /* Value used to fill the last word of the first plt entry.  */
-  bfd_byte plt0_pad_byte;
-
-  /* The index of the next unused R_386_TLS_DESC slot in .rel.plt.  */
-  bfd_vma next_tls_desc_index;
-
-  union {
+  union
+  {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ldm_got;
@@ -682,13 +715,26 @@ struct elf_i386_link_hash_table
 
   /* Used by local STT_GNU_IFUNC symbols.  */
   htab_t loc_hash_table;
-  void *loc_hash_memory;
+  void * loc_hash_memory;
+
+  /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
+  asection *srelplt2;
+
+  /* True if the target system is VxWorks.  */
+  int is_vxworks;
+
+  /* The index of the next unused R_386_TLS_DESC slot in .rel.plt.  */
+  bfd_vma next_tls_desc_index;
+
+  /* Value used to fill the last word of the first plt entry.  */
+  bfd_byte plt0_pad_byte;
 };
 
 /* Get the i386 ELF linker hash table from a link_info structure.  */
 
 #define elf_i386_hash_table(p) \
-  ((struct elf_i386_link_hash_table *) ((p)->hash))
+  (elf_hash_table_id  ((struct elf_link_hash_table *) ((p)->hash)) \
+  == I386_ELF_DATA ? ((struct elf_i386_link_hash_table *) ((p)->hash)) : NULL)
 
 #define elf_i386_compute_jump_table_size(htab) \
   ((htab)->next_tls_desc_index * 4)
@@ -704,8 +750,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;
     }
@@ -787,8 +833,6 @@ elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab,
       ret->elf.indx = sec->id;
       ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info);
       ret->elf.dynindx = -1;
-      ret->elf.plt.offset = (bfd_vma) -1;
-      ret->elf.got.offset = (bfd_vma) -1;
       *slot = ret;
     }
   return &ret->elf;
@@ -802,13 +846,14 @@ 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;
 
   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
                                      elf_i386_link_hash_newfunc,
-                                     sizeof (struct elf_i386_link_hash_entry)))
+                                     sizeof (struct elf_i386_link_hash_entry),
+                                     I386_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -816,6 +861,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
 
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->plt_eh_frame = NULL;
   ret->tls_ldm_got.refcount = 0;
   ret->next_tls_desc_index = 0;
   ret->sgotplt_jump_table_size = 0;
@@ -867,6 +913,9 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
     return FALSE;
 
   htab = elf_i386_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, ".rel.bss");
@@ -880,6 +929,25 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
                                               &htab->srelplt2))
     return FALSE;
 
+  if (!info->no_ld_generated_unwind_info
+      && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL
+      && htab->elf.splt != NULL)
+    {
+      flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
+      htab->plt_eh_frame
+       = bfd_make_section_with_flags (dynobj, ".eh_frame",
+                                      flags | SEC_READONLY);
+      if (htab->plt_eh_frame == NULL
+         || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2))
+       return FALSE;
+
+      htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
+      htab->plt_eh_frame->contents
+       = bfd_alloc (dynobj, htab->plt_eh_frame->size);
+      memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
+             sizeof (elf_i386_eh_frame_plt));
+    }
+
   return TRUE;
 }
 
@@ -1156,6 +1224,12 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
   unsigned int to_type = from_type;
   bfd_boolean check = TRUE;
 
+  /* Skip TLS transition for functions.  */
+  if (h != NULL
+      && (h->type == STT_FUNC
+         || h->type == STT_GNU_IFUNC))
+    return TRUE;
+
   switch (from_type)
     {
     case R_386_TLS_GD:
@@ -1234,12 +1308,19 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
        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);
+         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)
@@ -1278,6 +1359,9 @@ elf_i386_check_relocs (bfd *abfd,
   BFD_ASSERT (is_i386_elf (abfd));
 
   htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
 
@@ -1314,11 +1398,10 @@ elf_i386_check_relocs (bfd *abfd,
          /* Check relocation against local STT_GNU_IFUNC symbol.  */
          if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
-             h = elf_i386_get_local_sym_hash (htab, abfd, rel,
-                                                  TRUE);
+             h = elf_i386_get_local_sym_hash (htab, abfd, rel, TRUE);
              if (h == NULL)
                return FALSE;
-             
+
              /* Fake a STT_GNU_IFUNC symbol.  */
              h->type = STT_GNU_IFUNC;
              h->def_regular = 1;
@@ -1354,7 +1437,9 @@ elf_i386_check_relocs (bfd *abfd,
            case R_386_PLT32:
            case R_386_GOT32:
            case R_386_GOTOFF:
-             if (!_bfd_elf_create_ifunc_sections (abfd, info))
+             if (htab->elf.dynobj == NULL)
+               htab->elf.dynobj = abfd;
+             if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
                return FALSE;
              break;
            }
@@ -1367,7 +1452,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;
 
@@ -1511,7 +1596,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;
@@ -1668,7 +1754,6 @@ elf_i386_check_relocs (bfd *abfd,
                     easily.  Oh well.  */
                  void **vpp;
                  asection *s;
-                 Elf_Internal_Sym *isym;
 
                  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
                                                abfd, r_symndx);
@@ -1687,7 +1772,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;
@@ -1756,6 +1842,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
                        asection *sec,
                        const Elf_Internal_Rela *relocs)
 {
+  struct elf_i386_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_signed_vma *local_got_refcounts;
@@ -1764,6 +1851,10 @@ elf_i386_gc_sweep_hook (bfd *abfd,
   if (info->relocatable)
     return TRUE;
 
+  htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_symtab_hdr (abfd);
@@ -1780,16 +1871,36 @@ elf_i386_gc_sweep_hook (bfd *abfd,
       r_symndx = ELF32_R_SYM (rel->r_info);
       if (r_symndx >= symtab_hdr->sh_info)
        {
-         struct elf_i386_link_hash_entry *eh;
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
-         eh = (struct elf_i386_link_hash_entry *) h;
+       }
+      else
+       {
+         /* A local symbol.  */
+         Elf_Internal_Sym *isym;
+
+         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                       abfd, r_symndx);
+
+         /* Check relocation against local STT_GNU_IFUNC symbol.  */
+         if (isym != NULL
+             && ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+           {
+             h = elf_i386_get_local_sym_hash (htab, abfd, rel, FALSE);
+             if (h == NULL)
+               abort ();
+           }
+       }
+
+      if (h)
+       {
+         struct elf_i386_link_hash_entry *eh;
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
 
+         eh = (struct elf_i386_link_hash_entry *) h;
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
            if (p->sec == sec)
              {
@@ -1809,8 +1920,8 @@ elf_i386_gc_sweep_hook (bfd *abfd,
       switch (r_type)
        {
        case R_386_TLS_LDM:
-         if (elf_i386_hash_table (info)->tls_ldm_got.refcount > 0)
-           elf_i386_hash_table (info)->tls_ldm_got.refcount -= 1;
+         if (htab->tls_ldm_got.refcount > 0)
+           htab->tls_ldm_got.refcount -= 1;
          break;
 
        case R_386_TLS_GD:
@@ -1824,6 +1935,11 @@ elf_i386_gc_sweep_hook (bfd *abfd,
            {
              if (h->got.refcount > 0)
                h->got.refcount -= 1;
+             if (h->type == STT_GNU_IFUNC)
+               {
+                 if (h->plt.refcount > 0)
+                   h->plt.refcount -= 1;
+               }
            }
          else if (local_got_refcounts != NULL)
            {
@@ -1834,7 +1950,8 @@ elf_i386_gc_sweep_hook (bfd *abfd,
 
        case R_386_32:
        case R_386_PC32:
-         if (info->shared)
+         if (info->shared
+             && (h == NULL || h->type != STT_GNU_IFUNC))
            break;
          /* Fall through */
 
@@ -1846,6 +1963,16 @@ elf_i386_gc_sweep_hook (bfd *abfd,
            }
          break;
 
+       case R_386_GOTOFF:
+         if (h != NULL && h->type == STT_GNU_IFUNC)
+           {
+             if (h->got.refcount > 0)
+               h->got.refcount -= 1;
+             if (h->plt.refcount > 0)
+               h->plt.refcount -= 1;
+           }
+         break;
+
        default:
          break;
        }
@@ -1945,6 +2072,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
     }
 
   htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* If there aren't any dynamic relocs in read-only sections, then
      we can keep the dynamic relocs and avoid the copy reloc.  This
@@ -2015,15 +2144,12 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
   eh = (struct elf_i386_link_hash_entry *) h;
 
   info = (struct bfd_link_info *) inf;
   htab = elf_i386_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.  */
@@ -2313,8 +2439,9 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct elf_i386_link_hash_entry *eh;
   struct elf_dyn_relocs *p;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  /* Skip local IFUNC symbols. */
+  if (h->forced_local && h->type == STT_GNU_IFUNC)
+    return TRUE;
 
   eh = (struct elf_i386_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
@@ -2327,6 +2454,11 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
          info->flags |= DF_TEXTREL;
 
+         if (info->warn_shared_textrel && info->shared)
+           info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'.\n"),
+                                   p->sec->owner, h->root.root.string,
+                                   p->sec);
+
          /* Not an error, just cut short the traversal.  */
          return FALSE;
        }
@@ -2347,6 +2479,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *ibfd;
 
   htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
   dynobj = htab->elf.dynobj;
   if (dynobj == NULL)
     abort ();
@@ -2407,8 +2541,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                {
                  srel = elf_section_data (p->sec)->sreloc;
                  srel->size += p->count * sizeof (Elf32_External_Rel);
-                 if ((p->sec->output_section->flags & SEC_READONLY) != 0)
-                   info->flags |= DF_TEXTREL;
+                 if ((p->sec->output_section->flags & SEC_READONLY) != 0
+                     && (info->flags & DF_TEXTREL) == 0)
+                   {
+                     info->flags |= DF_TEXTREL;
+                     if (info->warn_shared_textrel && info->shared)
+                       info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'.\n"),
+                                               p->sec->owner, p->sec);
+                   }
                }
            }
        }
@@ -2492,6 +2632,30 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->elf.srelplt)
     htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
 
+  if (htab->elf.sgotplt)
+    {
+      struct elf_link_hash_entry *got;
+      got = elf_link_hash_lookup (elf_hash_table (info),
+                                 "_GLOBAL_OFFSET_TABLE_",
+                                 FALSE, FALSE, FALSE);
+
+      /* Don't allocate .got.plt section if there are no GOT nor PLT
+         entries and there is no refeence to _GLOBAL_OFFSET_TABLE_.  */
+      if ((got == NULL
+          || !got->ref_regular_nonweak)
+         && (htab->elf.sgotplt->size
+             == get_elf_backend_data (output_bfd)->got_header_size)
+         && (htab->elf.splt == NULL
+             || htab->elf.splt->size == 0)
+         && (htab->elf.sgot == NULL
+             || htab->elf.sgot->size == 0)
+         && (htab->elf.iplt == NULL
+             || htab->elf.iplt->size == 0)
+         && (htab->elf.igotplt == NULL
+             || htab->elf.igotplt->size == 0))
+       htab->elf.sgotplt->size = 0;
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -2559,11 +2723,18 @@ 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;
     }
 
+  if (htab->plt_eh_frame != NULL
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
+    bfd_put_32 (dynobj, htab->elf.splt->size,
+               htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+
   if (htab->elf.dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -2633,17 +2804,22 @@ elf_i386_always_size_sections (bfd *output_bfd,
 
       if (tlsbase && tlsbase->type == STT_TLS)
        {
+         struct elf_i386_link_hash_table *htab;
          struct bfd_link_hash_entry *bh = NULL;
          const struct elf_backend_data *bed
            = get_elf_backend_data (output_bfd);
 
+         htab = elf_i386_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;
 
-         elf_i386_hash_table (info)->tls_module_base = bh;
+         htab->tls_module_base = bh;
 
          tlsbase = (struct elf_link_hash_entry *)bh;
          tlsbase->def_regular = 1;
@@ -2663,7 +2839,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
                        Elf_Internal_Shdr *hdr,
                        asection *sec)
 {
-  register const char *name;
+  const char *name;
 
   name = bfd_get_section_name (abfd, sec);
 
@@ -2697,17 +2873,21 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
 static void
 elf_i386_set_tls_module_base (struct bfd_link_info *info)
 {
+  struct elf_i386_link_hash_table *htab;
   struct bfd_link_hash_entry *base;
 
   if (!info->executable)
     return;
 
-  base = elf_i386_hash_table (info)->tls_module_base;
+  htab = elf_i386_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
@@ -2730,11 +2910,16 @@ static bfd_vma
 elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
+  const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd);
+  bfd_vma static_tls_size;
 
   /* If tls_sec is NULL, we should have signalled an error already.  */
   if (htab->tls_sec == NULL)
     return 0;
-  return htab->tls_size + htab->tls_sec->vma - address;
+
+  /* Consider special static TLS alignment requirements.  */
+  static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment);
+  return static_tls_size + htab->tls_sec->vma - address;
 }
 
 /* Relocate an i386 ELF section.  */
@@ -2759,8 +2944,10 @@ elf_i386_relocate_section (bfd *output_bfd,
   bfd_boolean is_vxworks_tls;
 
   BFD_ASSERT (is_i386_elf (input_bfd));
-  
+
   htab = elf_i386_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);
@@ -2895,8 +3082,8 @@ elf_i386_relocate_section (bfd *output_bfd,
                   && 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,
-                                                  rel, FALSE);
+             h = elf_i386_get_local_sym_hash (htab, input_bfd, rel,
+                                              FALSE);
              if (h == NULL)
                abort ();
 
@@ -2907,7 +3094,7 @@ elf_i386_relocate_section (bfd *output_bfd,
        }
       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,
@@ -2916,15 +3103,8 @@ elf_i386_relocate_section (bfd *output_bfd,
        }
 
       if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, relend, howto, contents);
 
       if (info->relocatable)
        continue;
@@ -3026,7 +3206,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                     internal symbol, we have updated addend.  */
                  continue;
                }
-
+             /* FALLTHROUGH */
            case R_386_PC32:
            case R_386_PLT32:
              goto do_relocation;
@@ -3043,7 +3223,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  /* We can't use h->got.offset here to save state, or
                     even just remember the offset, as finish_dynamic_symbol
                     would use that as offset into .got.  */
-                 
+
                  if (htab->elf.splt != NULL)
                    {
                      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
@@ -3349,7 +3529,11 @@ elf_i386_relocate_section (bfd *output_bfd,
 
              sreloc = elf_section_data (input_section)->sreloc;
 
-             BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
+             if (sreloc == NULL || sreloc->contents == NULL)
+               {
+                 r = bfd_reloc_notsupported;
+                 goto check_relocation_error;
+               }
 
              loc = sreloc->contents;
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
@@ -3475,7 +3659,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                     xchg %ax,%ax  */
 
                  bfd_vma roff;
-                 
+
                  roff = rel->r_offset;
                  bfd_put_8 (output_bfd, 0x66, contents + roff);
                  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
@@ -3608,7 +3792,7 @@ elf_i386_relocate_section (bfd *output_bfd,
            {
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
-             int dr_type, indx;
+             int dr_type;
              asection *sreloc;
 
              if (htab->elf.srelgot == NULL)
@@ -3923,7 +4107,7 @@ elf_i386_relocate_section (bfd *output_bfd,
          break;
 
        case R_386_TLS_LDO_32:
-         if (info->shared || (input_section->flags & SEC_CODE) == 0)
+         if (!info->executable || (input_section->flags & SEC_CODE) == 0)
            relocation -= elf_i386_dtpoff_base (info);
          else
            /* When converting LDO to LE, we must negate.  */
@@ -3937,7 +4121,6 @@ elf_i386_relocate_section (bfd *output_bfd,
              Elf_Internal_Rela outrel;
              asection *sreloc;
              bfd_byte *loc;
-             int indx;
 
              outrel.r_offset = rel->r_offset
                                + input_section->output_section->vma
@@ -3995,6 +4178,7 @@ do_relocation:
                                    contents, rel->r_offset,
                                    relocation, 0);
 
+check_relocation_error:
       if (r != bfd_reloc_ok)
        {
          const char *name;
@@ -4045,24 +4229,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
 {
   struct elf_i386_link_hash_table *htab;
 
-  /* PR 10433: STT_GNU_IFUNC symbols must go through the PLT
-     only when they are referenced, not when they are defined.  */
-  if (h->type == STT_GNU_IFUNC
-      && h->def_regular
-      && ! h->ref_regular
-      && ! info->relocatable)
-    {
-      if (! ((h->dynindx != -1
-             || h->forced_local)
-            && ((info->shared
-                 && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                     || h->root.type != bfd_link_hash_undefweak))
-                || ! h->forced_local)
-            && elf_hash_table (info)->dynamic_sections_created))
-       return TRUE;
-    }
-
   htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -4097,7 +4266,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
          || plt == NULL
          || gotplt == NULL
          || relplt == NULL)
-       abort ();
+       return FALSE;
 
       /* Get the index in the procedure linkage table which
         corresponds to this symbol.  This is the index of this symbol
@@ -4107,7 +4276,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
         Get the offset into the .got table of the entry that
         corresponds to this function.  Each .got entry is 4 bytes.
         The first three are reserved.
-        
+
         For static executables, we don't reserve anything.  */
 
       if (plt == htab->elf.splt)
@@ -4266,13 +4435,15 @@ elf_i386_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_32 (output_bfd,
                          (plt->output_section->vma
                           + plt->output_offset + h->plt.offset),
@@ -4380,6 +4551,9 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
   asection *sdyn;
 
   htab = elf_i386_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
@@ -4540,6 +4714,13 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 
   if (htab->elf.sgotplt)
     {
+      if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
+       {
+         (*_bfd_error_handler)
+           (_("discarded output section: `%A'"), htab->elf.sgotplt);
+         return FALSE;
+       }
+
       /* Fill in the first three entries in the global offset table.  */
       if (htab->elf.sgotplt->size > 0)
        {
@@ -4554,6 +4735,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
       elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
     }
 
+  /* Adjust .eh_frame for .plt section.  */
+  if (htab->plt_eh_frame != NULL)
+    {
+      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
+         == ELF_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;
+       }
+    }
+
   if (htab->elf.sgot && htab->elf.sgot->size > 0)
     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
 
@@ -4592,7 +4800,7 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
    file.  */
 
 static bfd_boolean
-elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
+elf_i386_add_symbol_hook (bfd * abfd,
                          struct bfd_link_info * info ATTRIBUTE_UNUSED,
                          Elf_Internal_Sym * sym,
                          const char ** namep ATTRIBUTE_UNUSED,
@@ -4600,8 +4808,10 @@ elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
                          asection ** secp ATTRIBUTE_UNUSED,
                          bfd_vma * valp ATTRIBUTE_UNUSED)
 {
-  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
-    elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+  if ((abfd->flags & DYNAMIC) == 0
+      && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+         || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+    elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
 
   return TRUE;
 }
@@ -4609,6 +4819,7 @@ elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
 #define TARGET_LITTLE_SYM              bfd_elf32_i386_vec
 #define TARGET_LITTLE_NAME             "elf32-i386"
 #define ELF_ARCH                       bfd_arch_i386
+#define ELF_TARGET_ID                  I386_ELF_DATA
 #define ELF_MACHINE_CODE               EM_386
 #define ELF_MAXPAGESIZE                        0x1000
 
@@ -4618,6 +4829,7 @@ elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_plt_sym       0
 #define elf_backend_got_header_size    12
+#define elf_backend_plt_alignment      4
 
 /* Support RELA for objdump of prelink objects.  */
 #define elf_info_to_howto                    elf_i386_info_to_howto_rel
@@ -4690,6 +4902,34 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 
 #include "elf32-target.h"
 
+/* Solaris 2.  */
+
+#undef TARGET_LITTLE_SYM
+#define        TARGET_LITTLE_SYM               bfd_elf32_i386_sol2_vec
+#undef TARGET_LITTLE_NAME
+#define        TARGET_LITTLE_NAME              "elf32-i386-sol2"
+
+/* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
+   objects won't be recognized.  */
+#undef ELF_OSABI
+
+#undef elf32_bed
+#define        elf32_bed                       elf32_i386_sol2_bed
+
+/* The 32-bit static TLS arena size is rounded to the nearest 8-byte
+   boundary.  */
+#undef elf_backend_static_tls_alignment
+#define elf_backend_static_tls_alignment 8
+
+/* 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 "elf32-target.h"
+
 /* VxWorks support.  */
 
 #undef TARGET_LITTLE_SYM
@@ -4734,6 +4974,7 @@ elf_i386_vxworks_link_hash_table_create (bfd *abfd)
 #undef elf_backend_final_write_processing
 #define elf_backend_final_write_processing \
   elf_vxworks_final_write_processing
+#undef elf_backend_static_tls_alignment
 
 /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so
    define it.  */
This page took 0.037524 seconds and 4 git commands to generate.