2009-06-18 Dave Korn <dave.korn.cygwin@gmail.com>
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 9b6e3ed86c974504d1f96846d3fdb0c69322fe6e..70bca46953e97adf1c95949fa373932d71c8ccac 100644 (file)
@@ -101,58 +101,57 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   asection *s;
   struct elf_link_hash_entry *h;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  int ptralign;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* This function may be called more than once.  */
   s = bfd_get_section_by_name (abfd, ".got");
   if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
     return TRUE;
 
-  switch (bed->s->arch_size)
-    {
-    case 32:
-      ptralign = 2;
-      break;
-
-    case 64:
-      ptralign = 3;
-      break;
-
-    default:
-      bfd_set_error (bfd_error_bad_value);
-      return FALSE;
-    }
-
   flags = bed->dynamic_sec_flags;
 
+  s = bfd_make_section_with_flags (abfd,
+                                  (bed->rela_plts_and_copies_p
+                                   ? ".rela.got" : ".rel.got"),
+                                  (bed->dynamic_sec_flags
+                                   | SEC_READONLY));
+  if (s == NULL
+      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+    return FALSE;
+  htab->srelgot = s;
+
   s = bfd_make_section_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, ptralign))
+      || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
+  htab->sgot = s;
 
   if (bed->want_got_plt)
     {
       s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s, ptralign))
+         || !bfd_set_section_alignment (abfd, s,
+                                        bed->s->log_file_align))
        return FALSE;
+      htab->sgotplt = s;
     }
 
+  /* The first bit of the global offset table is the header.  */
+  s->size += bed->got_header_size;
+
   if (bed->want_got_sym)
     {
       /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
         (or .got.plt) section.  We don't do this in the linker script
         because we don't want to define the symbol if we are not creating
         a global offset table.  */
-      h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
+      h = _bfd_elf_define_linkage_sym (abfd, info, s,
+                                      "_GLOBAL_OFFSET_TABLE_");
       elf_hash_table (info)->hgot = h;
       if (h == NULL)
        return FALSE;
     }
 
-  /* The first bit of the global offset table is the header.  */
-  s->size += bed->got_header_size;
-
   return TRUE;
 }
 \f
@@ -303,6 +302,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_entry *h;
   asection *s;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
      .rel[a].bss sections.  */
@@ -323,6 +323,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
+  htab->splt = s;
 
   /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
      .plt section.  */
@@ -342,6 +343,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
+  htab->srelplt = s;
 
   if (! _bfd_elf_create_got_section (abfd, info))
     return FALSE;
@@ -1798,80 +1800,6 @@ nondefault:
   return TRUE;
 }
 \f
-static struct bfd_elf_version_tree *
-find_version_for_sym (struct bfd_elf_version_tree *verdefs,
-                     const char *sym_name,
-                     bfd_boolean *hide)
-{
-  struct bfd_elf_version_tree *t;
-  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
-
-  local_ver = NULL;
-  global_ver = NULL;
-  exist_ver = NULL;
-  for (t = verdefs; t != NULL; t = t->next)
-    {
-      if (t->globals.list != NULL)
-       {
-         struct bfd_elf_version_expr *d = NULL;
-
-         while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
-           {
-             global_ver = t;
-             if (d->symver)
-               exist_ver = t;
-             d->script = 1;
-             /* If the match is a wildcard pattern, keep looking for
-                a more explicit, perhaps even local, match.  */
-             if (d->literal)
-               break;
-           }
-
-         if (d != NULL)
-           break;
-       }
-
-      if (t->locals.list != NULL)
-       {
-         struct bfd_elf_version_expr *d = NULL;
-
-         while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
-           {
-             local_ver = t;
-             /* If the match is a wildcard pattern, keep looking for
-                a more explicit, perhaps even global, match.  */
-             if (d->literal)
-               {
-                 /* An exact match overrides a global wildcard.  */
-                 global_ver = NULL;
-                 break;
-               }
-           }
-
-         if (d != NULL)
-           break;
-       }
-    }
-
-  if (global_ver != NULL)
-    {
-      /* If we already have a versioned symbol that matches the
-        node for this symbol, then we don't want to create a
-        duplicate from the unversioned symbol.  Instead hide the
-        unversioned symbol.  */
-      *hide = exist_ver == global_ver;
-      return global_ver;
-    }
-
-  if (local_ver != NULL)
-    {
-      *hide = TRUE;
-      return local_ver;
-    }
-
-  return NULL;
-}
-
 /* This routine is used to export all defined symbols into the dynamic
    symbol table.  It is called via elf_link_hash_traverse.  */
 
@@ -1898,7 +1826,7 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
       bfd_boolean hide;
 
       if (eif->verdefs == NULL
-         || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+         || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
              && !hide))
        {
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
@@ -2160,7 +2088,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
     {
       bfd_boolean hide;
 
-      h->verinfo.vertree = find_version_for_sym (sinfo->verdefs,
+      h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
                                                 h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
        (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -3425,6 +3353,7 @@ _bfd_elf_relocs_compatible (const bfd_target *input,
 static bfd_boolean
 elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
+  Elf_Internal_Ehdr *ehdr;
   Elf_Internal_Shdr *hdr;
   bfd_size_type symcount;
   bfd_size_type extsymcount;
@@ -3480,6 +3409,17 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
+  ehdr = elf_elfheader (abfd);
+  if (info->warn_alternate_em
+      && bed->elf_machine_code != ehdr->e_machine
+      && ((bed->elf_machine_alt1 != 0
+          && ehdr->e_machine == bed->elf_machine_alt1)
+         || (bed->elf_machine_alt2 != 0
+             && ehdr->e_machine == bed->elf_machine_alt2)))
+    info->callbacks->einfo
+      (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
+       ehdr->e_machine, abfd, bed->elf_machine_code);
+
   /* As a GNU extension, any input sections which are named
      .gnu.warning.SYMBOL are treated as warning symbols for the given
      symbol.  This differs from .gnu.warning sections, which generate
@@ -4350,6 +4290,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              h->type = ELF_ST_TYPE (isym->st_info);
            }
 
+         /* STT_GNU_IFUNC symbol must go through PLT.  */
+         if (h->type == STT_GNU_IFUNC)
+           h->needs_plt = 1;
+
          /* Merge st_other field.  */
          elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
@@ -6724,8 +6668,12 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
                                bfd_boolean force_local)
 {
-  h->plt = elf_hash_table (info)->init_plt_offset;
-  h->needs_plt = 0;
+  /* STT_GNU_IFUNC symbol must go through PLT.  */
+  if (h->type != STT_GNU_IFUNC)
+    {
+      h->plt = elf_hash_table (info)->init_plt_offset;
+      h->needs_plt = 0;
+    }
   if (force_local)
     {
       h->forced_local = 1;
@@ -8251,7 +8199,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo,
 
 /* Add a symbol to the output symbol table.  */
 
-static bfd_boolean
+static int
 elf_link_output_sym (struct elf_final_link_info *finfo,
                     const char *name,
                     Elf_Internal_Sym *elfsym,
@@ -8260,7 +8208,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
 {
   bfd_byte *dest;
   Elf_External_Sym_Shndx *destshndx;
-  bfd_boolean (*output_symbol_hook)
+  int (*output_symbol_hook)
     (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
      struct elf_link_hash_entry *);
   const struct elf_backend_data *bed;
@@ -8269,8 +8217,9 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
   output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
   if (output_symbol_hook != NULL)
     {
-      if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
-       return FALSE;
+      int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h);
+      if (ret != 1)
+       return ret;
     }
 
   if (name == NULL || *name == '\0')
@@ -8282,13 +8231,13 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
       elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
                                                            name, TRUE, FALSE);
       if (elfsym->st_name == (unsigned long) -1)
-       return FALSE;
+       return 0;
     }
 
   if (finfo->symbuf_count >= finfo->symbuf_size)
     {
       if (! elf_link_flush_output_syms (finfo, bed))
-       return FALSE;
+       return 0;
     }
 
   dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
@@ -8302,7 +8251,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
          amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
          destshndx = bfd_realloc (destshndx, amt * 2);
          if (destshndx == NULL)
-           return FALSE;
+           return 0;
          finfo->symshndxbuf = destshndx;
          memset ((char *) destshndx + amt, 0, amt);
          finfo->shndxbuf_size *= 2;
@@ -8314,7 +8263,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
   finfo->symbuf_count += 1;
   bfd_get_symcount (finfo->output_bfd) += 1;
 
-  return TRUE;
+  return 1;
 }
 
 /* Return TRUE if the dynamic symbol SYM in ABFD is supported.  */
@@ -8500,6 +8449,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   Elf_Internal_Sym sym;
   asection *input_sec;
   const struct elf_backend_data *bed;
+  long indx;
+  int ret;
 
   if (h->root.type == bfd_link_hash_warning)
     {
@@ -8701,14 +8652,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   /* Give the processor backend a chance to tweak the symbol value,
      and also to finish up anything that needs to be done for this
      symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
-     forced local syms when non-shared is due to a historical quirk.  */
-  if ((h->dynindx != -1
-       || h->forced_local)
-      && ((finfo->info->shared
-          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-              || h->root.type != bfd_link_hash_undefweak))
-         || !h->forced_local)
-      && elf_hash_table (finfo->info)->dynamic_sections_created)
+     forced local syms when non-shared is due to a historical quirk.
+     STT_GNU_IFUNC symbol must go through PLT.  */
+  if ((h->type == STT_GNU_IFUNC
+       && h->ref_regular
+       && !finfo->info->relocatable)
+      || ((h->dynindx != -1
+          || h->forced_local)
+         && ((finfo->info->shared
+              && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || h->root.type != bfd_link_hash_undefweak))
+             || !h->forced_local)
+         && elf_hash_table (finfo->info)->dynamic_sections_created))
     {
       if (! ((*bed->elf_backend_finish_dynamic_symbol)
             (finfo->output_bfd, finfo->info, h, &sym)))
@@ -8842,13 +8797,17 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
     return TRUE;
 
-  h->indx = bfd_get_symcount (finfo->output_bfd);
-
-  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
+  indx = bfd_get_symcount (finfo->output_bfd);
+  ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h);
+  if (ret == 0)
     {
       eoinfo->failed = TRUE;
       return FALSE;
     }
+  else if (ret == 1)
+    h->indx = indx;
+  else if (h->indx == -2)
+    abort();
 
   return TRUE;
 }
@@ -9016,6 +8975,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
       asection *isec;
       const char *name;
       Elf_Internal_Sym osym;
+      long indx;
+      int ret;
 
       *pindex = -1;
 
@@ -9103,8 +9064,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
              && bfd_is_local_label_name (input_bfd, name)))
        continue;
 
-      /* If we get here, we are going to output this symbol.  */
-
       osym = *isym;
 
       /* Adjust the section index for the output file.  */
@@ -9113,8 +9072,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
       if (osym.st_shndx == SHN_BAD)
        return FALSE;
 
-      *pindex = bfd_get_symcount (output_bfd);
-
       /* ELF symbols in relocatable files are section relative, but
         in executable files they are virtual addresses.  Note that
         this code assumes that all ELF sections have an associated
@@ -9134,8 +9091,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
            }
        }
 
-      if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
+      indx = bfd_get_symcount (output_bfd);
+      ret = elf_link_output_sym (finfo, name, &osym, isec, NULL);
+      if (ret == 0)
        return FALSE;
+      else if (ret == 1)
+       *pindex = indx;
     }
 
   /* Relocate the contents of each section.  */
@@ -9184,6 +9145,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                  Elf_Internal_Sym sym = isymbuf[symndx];
                  asection *sec = finfo->sections[symndx]->output_section;
                  const char *name;
+                 long indx;
+                 int ret;
 
                  name = bfd_elf_string_from_elf_section (input_bfd,
                                                          symtab_hdr->sh_link,
@@ -9198,9 +9161,14 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
 
                  sym.st_value += o->output_offset;
 
-                 finfo->indices[symndx] = bfd_get_symcount (output_bfd);
-                 if (! elf_link_output_sym (finfo, name, &sym, o, NULL))
+                 indx = bfd_get_symcount (output_bfd);
+                 ret = elf_link_output_sym (finfo, name, &sym, o, NULL);
+                 if (ret == 0)
                    return FALSE;
+                 else if (ret == 1)
+                   finfo->indices[symndx] = indx;
+                 else
+                   abort ();
                }
              elf_section_data (osec)->this_hdr.sh_info
                = finfo->indices[symndx];
@@ -9591,6 +9559,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                          unsigned long shlink;
                          const char *name;
                          asection *osec;
+                         long indx;
 
                          if (finfo->info->strip == strip_all)
                            {
@@ -9630,12 +9599,15 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                                }
                            }
 
-                         finfo->indices[r_symndx]
-                           = bfd_get_symcount (output_bfd);
-
-                         if (! elf_link_output_sym (finfo, name, &sym, sec,
-                                                    NULL))
+                         indx = bfd_get_symcount (output_bfd);
+                         ret = elf_link_output_sym (finfo, name, &sym, sec,
+                                                    NULL);
+                         if (ret == 0)
                            return FALSE;
+                         else if (ret == 1)
+                           finfo->indices[r_symndx] = indx;
+                         else
+                           abort ();
                        }
 
                      r_symndx = finfo->indices[r_symndx];
@@ -10387,8 +10359,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       elfsym.st_info = 0;
       elfsym.st_other = 0;
       elfsym.st_shndx = SHN_UNDEF;
-      if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
-                                NULL))
+      if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
+                              NULL) != 1)
        goto error_return;
     }
 
@@ -10413,7 +10385,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              elfsym.st_shndx = i;
              if (!info->relocatable)
                elfsym.st_value = o->vma;
-             if (!elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
+             if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1)
                goto error_return;
            }
        }
@@ -10589,7 +10561,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      table, do it now.  */
   if (bed->elf_backend_output_arch_local_syms)
     {
-      typedef bfd_boolean (*out_sym_func)
+      typedef int (*out_sym_func)
        (void *, const char *, Elf_Internal_Sym *, asection *,
         struct elf_link_hash_entry *);
 
@@ -10700,7 +10672,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      table, do it now.  */
   if (bed->elf_backend_output_arch_syms)
     {
-      typedef bfd_boolean (*out_sym_func)
+      typedef int (*out_sym_func)
        (void *, const char *, Elf_Internal_Sym *, asection *,
         struct elf_link_hash_entry *);
 
@@ -12365,7 +12337,7 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
 
   /* This is the first section with this name.  Record it.  */
   if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
-    info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
+    info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
 }
 
 bfd_boolean
This page took 0.054805 seconds and 4 git commands to generate.