2004-01-12 Michael Chastain <mec.gnu@mindspring.com>
[deliverable/binutils-gdb.git] / bfd / elflink.h
index e53911df855bf140609408e1ac795a9a0102176a..c37d7398d0113af7c59984a651e4219b7e04532d 100644 (file)
@@ -437,7 +437,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       /* You can't use -r against a dynamic object.  Also, there's no
         hope of using a dynamic object which does not exactly match
         the format of the output file.  */
-      if (info->relocatable || info->hash->creator != abfd->xvec)
+      if (info->relocatable
+         || !is_elf_hash_table (hash_table)
+         || hash_table->root.creator != abfd->xvec)
        {
          bfd_set_error (bfd_error_invalid_operation);
          goto error_return;
@@ -475,7 +477,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                 fix is to keep track of what warnings we are supposed
                 to emit, and then handle them all at the end of the
                 link.  */
-             if (dynamic && abfd->xvec == info->hash->creator)
+             if (dynamic)
                {
                  struct elf_link_hash_entry *h;
 
@@ -531,15 +533,15 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
         format.  FIXME: If there are no input BFD's of the same
         format as the output, we can't make a shared library.  */
       if (info->shared
-         && is_elf_hash_table (info)
-         && ! hash_table->dynamic_sections_created
-         && abfd->xvec == info->hash->creator)
+         && is_elf_hash_table (hash_table)
+         && hash_table->root.creator == abfd->xvec
+         && ! hash_table->dynamic_sections_created)
        {
          if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
            goto error_return;
        }
     }
-  else if (! is_elf_hash_table (info))
+  else if (!is_elf_hash_table (hash_table))
     goto error_return;
   else
     {
@@ -723,9 +725,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
       /* If this is the first dynamic object found in the link, create
         the special sections required for dynamic linking.  */
-      if (! hash_table->dynamic_sections_created)
-       if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
-         goto error_return;
+      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
+       goto error_return;
 
       if (add_needed)
        {
@@ -875,7 +876,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        {
          /* This should be impossible, since ELF requires that all
             global symbols follow all local symbols, and that sh_info
-            point to the first global symbol.  Unfortunatealy, Irix 5
+            point to the first global symbol.  Unfortunately, Irix 5
             screws this up.  */
          continue;
        }
@@ -968,7 +969,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       old_alignment = 0;
       old_bfd = NULL;
 
-      if (info->hash->creator->flavour == bfd_target_elf_flavour)
+      if (is_elf_hash_table (hash_table))
        {
          Elf_Internal_Versym iver;
          unsigned int vernum = 0;
@@ -1131,7 +1132,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          && definition
          && (flags & BSF_WEAK) != 0
          && ELF_ST_TYPE (isym->st_info) != STT_FUNC
-         && info->hash->creator->flavour == bfd_target_elf_flavour
+         && is_elf_hash_table (hash_table)
          && h->weakdef == NULL)
        {
          /* Keep a list of all weak defined non function symbols from
@@ -1167,14 +1168,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            h->root.u.c.p->alignment_power = old_alignment;
        }
 
-      if (info->hash->creator->flavour == bfd_target_elf_flavour)
+      if (is_elf_hash_table (hash_table))
        {
          int old_flags;
          bfd_boolean dynsym;
          int new_flag;
 
          /* Check the alignment when a common symbol is involved. This
-            can change when a common symbol is overriden by a normal
+            can change when a common symbol is overridden by a normal
             definition or a common symbol is ignored due to the old
             normal definition. We need to make sure the maximum
             alignment is maintained.  */
@@ -1380,9 +1381,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              bfd_size_type oldsize;
              bfd_size_type strindex;
 
-             if (! is_elf_hash_table (info))
-               goto error_free_vers;
-
              /* The symbol from a DT_NEEDED object is referenced from
                 the regular object to create a dynamic executable. We
                 have to make sure there is a DT_NEEDED entry for it.  */
@@ -1446,7 +1444,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          shortname[amt] = '\0';
 
          hi = (struct elf_link_hash_entry *)
-              bfd_link_hash_lookup (info->hash, shortname,
+              bfd_link_hash_lookup (&hash_table->root, shortname,
                                     FALSE, FALSE, FALSE);
          if (hi != NULL
              && hi->root.type == h->root.type
@@ -1573,7 +1571,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
      different format.  It probably can't be done.  */
   check_relocs = get_elf_backend_data (abfd)->check_relocs;
   if (! dynamic
-      && abfd->xvec == info->hash->creator
+      && is_elf_hash_table (hash_table)
+      && hash_table->root.creator == abfd->xvec
       && check_relocs != NULL)
     {
       asection *o;
@@ -1609,8 +1608,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
      of the .stab/.stabstr sections.  */
   if (! dynamic
       && ! info->traditional_format
-      && info->hash->creator->flavour == bfd_target_elf_flavour
-      && is_elf_hash_table (info)
+      && is_elf_hash_table (hash_table)
       && (info->strip != strip_all && info->strip != strip_debugger))
     {
       asection *stabstr;
@@ -1643,8 +1641,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (! info->relocatable && ! dynamic
-      && is_elf_hash_table (info))
+  if (! info->relocatable
+      && ! dynamic
+      && is_elf_hash_table (hash_table))
     {
       asection *s;
 
@@ -1664,7 +1663,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          }
     }
 
-  if (is_elf_hash_table (info))
+  if (is_elf_hash_table (hash_table))
     {
       /* Add this bfd to the loaded list.  */
       struct elf_link_loaded_list *n;
@@ -1702,7 +1701,7 @@ elf_add_dynamic_entry (struct bfd_link_info *info, bfd_vma tag, bfd_vma val)
   bfd_size_type newsize;
   bfd_byte *newcontents;
 
-  if (! is_elf_hash_table (info))
+  if (! is_elf_hash_table (info->hash))
     return FALSE;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -1832,7 +1831,7 @@ compute_bucket_count (struct bfd_link_info *info)
 
 # if 1
          /* Variant 1: optimize for short chains.  We add the squares
-            of all the chain lengths (which favous many small chain
+            of all the chain lengths (which favors many small chain
             over a few long chains).  */
          for (j = 0; j < i; ++j)
            max += counts[j] * counts[j];
@@ -1907,10 +1906,7 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
 
   soname_indx = (bfd_size_type) -1;
 
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
-    return TRUE;
-
-  if (! is_elf_hash_table (info))
+  if (!is_elf_hash_table (info->hash))
     return TRUE;
 
   if (info->execstack)
@@ -1981,7 +1977,7 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
       bfd_boolean all_defined;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || info->shared);
+      BFD_ASSERT (*sinterpptr != NULL || !info->executable);
 
       if (soname != NULL)
        {
@@ -2056,19 +2052,17 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
            return FALSE;
        }
 
-      /* Make all global versions with definiton.  */
+      /* Make all global versions with definition.  */
       for (t = verdefs; t != NULL; t = t->next)
        for (d = t->globals.list; d != NULL; d = d->next)
-         /* FIXME: Shouldn't this be !d->symver && d->wildcard == 0
-            instead?  */
-         if (!d->symver && strchr (d->pattern, '*') == NULL)
+         if (!d->symver && d->symbol)
            {
              const char *verstr, *name;
              size_t namelen, verlen, newlen;
              char *newname, *p;
              struct elf_link_hash_entry *newh;
 
-             name = d->pattern;
+             name = d->symbol;
              namelen = strlen (name);
              verstr = t->name;
              verlen = strlen (verstr);
@@ -2123,7 +2117,7 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
 
       if (!info->allow_undefined_version)
        {
-         /* Check if all global versions have a definiton.  */
+         /* Check if all global versions have a definition.  */
          all_defined = TRUE;
          for (t = verdefs; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
@@ -2806,8 +2800,6 @@ struct elf_final_link_info
   asection *hash_sec;
   /* symbol version section (.gnu.version).  */
   asection *symver_sec;
-  /* first SHF_TLS section (if any).  */
-  asection *first_tls_sec;
   /* Buffer large enough to hold contents of any section.  */
   bfd_byte *contents;
   /* Buffer large enough to hold external relocs of any section.  */
@@ -2841,7 +2833,8 @@ struct elf_final_link_info
 };
 
 static bfd_boolean elf_link_output_sym
-  (struct elf_final_link_info *, const char *, Elf_Internal_Sym *, asection *);
+  (struct elf_final_link_info *, const char *, Elf_Internal_Sym *, asection *,
+   struct elf_link_hash_entry *);
 static bfd_boolean elf_link_flush_output_syms
   (struct elf_final_link_info *);
 static bfd_boolean elf_link_output_extsym
@@ -3116,7 +3109,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   asection *reldyn = 0;
   bfd_size_type amt;
 
-  if (! is_elf_hash_table (info))
+  if (! is_elf_hash_table (info->hash))
     return FALSE;
 
   if (info->shared)
@@ -3162,14 +3155,6 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   finfo.symshndxbuf = NULL;
   finfo.symbuf_count = 0;
   finfo.shndxbuf_size = 0;
-  finfo.first_tls_sec = NULL;
-  for (o = abfd->sections; o != NULL; o = o->next)
-    if ((o->flags & SEC_THREAD_LOCAL) != 0
-       && (o->flags & SEC_LOAD) != 0)
-      {
-       finfo.first_tls_sec = o;
-       break;
-      }
 
   /* Count up the number of relocations we will output for each output
      section, so that we know the sizes of the reloc sections.  We
@@ -3423,7 +3408,8 @@ elf_bfd_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))
+      if (! elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
+                                NULL))
        goto error_return;
     }
 
@@ -3439,7 +3425,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   elfsym.st_other = 0;
   elfsym.st_shndx = SHN_ABS;
   if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
-                            &elfsym, bfd_abs_section_ptr))
+                            &elfsym, bfd_abs_section_ptr, NULL))
     goto error_return;
 #endif
 
@@ -3464,7 +3450,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
            elfsym.st_value = 0;
          else
            elfsym.st_value = o->vma;
-         if (! elf_link_output_sym (&finfo, NULL, &elfsym, o))
+         if (! elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
            goto error_return;
          if (i == SHN_LORESERVE - 1)
            i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
@@ -3527,38 +3513,30 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
     }
 
-  if (finfo.first_tls_sec)
+  if (elf_hash_table (info)->tls_sec)
     {
-      unsigned int align = 0;
-      bfd_vma base = finfo.first_tls_sec->vma, end = 0;
+      bfd_vma base, end = 0;
       asection *sec;
 
-      for (sec = finfo.first_tls_sec;
+      for (sec = elf_hash_table (info)->tls_sec;
           sec && (sec->flags & SEC_THREAD_LOCAL);
           sec = sec->next)
        {
          bfd_vma size = sec->_raw_size;
 
-         if (bfd_get_section_alignment (abfd, sec) > align)
-           align = bfd_get_section_alignment (abfd, sec);
-         if (sec->_raw_size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+         if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
            {
              struct bfd_link_order *o;
 
-             size = 0;
              for (o = sec->link_order_head; o != NULL; o = o->next)
                if (size < o->offset + o->size)
                  size = o->offset + o->size;
            }
          end = sec->vma + size;
        }
-      elf_hash_table (info)->tls_segment
-       = bfd_zalloc (abfd, sizeof (struct elf_link_tls_segment));
-      if (elf_hash_table (info)->tls_segment == NULL)
-       goto error_return;
-      elf_hash_table (info)->tls_segment->start = base;
-      elf_hash_table (info)->tls_segment->size = end - base;
-      elf_hash_table (info)->tls_segment->align = align;
+      base = elf_hash_table (info)->tls_sec->vma;
+      end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
+      elf_hash_table (info)->tls_size = end - base;
     }
 
   /* Since ELF permits relocations to be against local symbols, we
@@ -3726,7 +3704,8 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   if (bed->elf_backend_output_arch_syms)
     {
       typedef bfd_boolean (*out_sym_func)
-       (void *, const char *, Elf_Internal_Sym *, asection *);
+       (void *, const char *, Elf_Internal_Sym *, asection *,
+        struct elf_link_hash_entry *);
 
       if (! ((*bed->elf_backend_output_arch_syms)
             (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
@@ -4110,20 +4089,20 @@ static bfd_boolean
 elf_link_output_sym (struct elf_final_link_info *finfo,
                     const char *name,
                     Elf_Internal_Sym *elfsym,
-                    asection *input_sec)
+                    asection *input_sec,
+                    struct elf_link_hash_entry *h)
 {
   Elf_External_Sym *dest;
   Elf_External_Sym_Shndx *destshndx;
   bfd_boolean (*output_symbol_hook)
-    (bfd *, struct bfd_link_info *info, const char *,
-     Elf_Internal_Sym *, asection *);
+    (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
+     struct elf_link_hash_entry *);
 
   output_symbol_hook = get_elf_backend_data (finfo->output_bfd)->
     elf_backend_link_output_symbol_hook;
   if (output_symbol_hook != NULL)
     {
-      if (! ((*output_symbol_hook)
-            (finfo->output_bfd, finfo->info, name, elfsym, input_sec)))
+      if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
        return FALSE;
     }
 
@@ -4208,7 +4187,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
   bfd *abfd;
   struct elf_link_loaded_list *loaded;
 
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (!is_elf_hash_table (info->hash))
     return FALSE;
 
   switch (h->root.type)
@@ -4505,8 +4484,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
                  {
                    /* STT_TLS symbols are relative to PT_TLS segment
                       base.  */
-                   BFD_ASSERT (finfo->first_tls_sec != NULL);
-                   sym.st_value -= finfo->first_tls_sec->vma;
+                   BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+                   sym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
                  }
              }
          }
@@ -4664,7 +4643,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
 
   h->indx = bfd_get_symcount (finfo->output_bfd);
 
-  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec))
+  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
     {
       eoinfo->failed = TRUE;
       return FALSE;
@@ -4864,12 +4843,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
            {
              /* STT_TLS symbols are relative to PT_TLS segment base.  */
-             BFD_ASSERT (finfo->first_tls_sec != NULL);
-             osym.st_value -= finfo->first_tls_sec->vma;
+             BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+             osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
            }
        }
 
-      if (! elf_link_output_sym (finfo, name, &osym, isec))
+      if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
        return FALSE;
     }
 
@@ -5221,15 +5200,18 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                                {
                                  /* STT_TLS symbols are relative to PT_TLS
                                     segment base.  */
-                                 BFD_ASSERT (finfo->first_tls_sec != NULL);
-                                 sym.st_value -= finfo->first_tls_sec->vma;
+                                 BFD_ASSERT (elf_hash_table (finfo->info)
+                                             ->tls_sec != NULL);
+                                 sym.st_value -= (elf_hash_table (finfo->info)
+                                                  ->tls_sec->vma);
                                }
                            }
 
                          finfo->indices[r_symndx]
                            = bfd_get_symcount (output_bfd);
 
-                         if (! elf_link_output_sym (finfo, name, &sym, sec))
+                         if (! elf_link_output_sym (finfo, name, &sym, sec,
+                                                    NULL))
                            return FALSE;
                        }
 
@@ -5692,7 +5674,7 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *idxptr)
   return TRUE;
 }
 
-/* Propogate collected vtable information.  This is called through
+/* Propagate collected vtable information.  This is called through
    elf_link_hash_traverse.  */
 
 static bfd_boolean
@@ -5815,9 +5797,14 @@ elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
      struct elf_link_hash_entry *h, Elf_Internal_Sym *);
 
   if (!get_elf_backend_data (abfd)->can_gc_sections
-      || info->relocatable || info->emitrelocations
+      || info->relocatable
+      || info->emitrelocations
+      || !is_elf_hash_table (info->hash)
       || elf_hash_table (info)->dynamic_sections_created)
-    return TRUE;
+    {
+      (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
+      return TRUE;
+    }
 
   /* Apply transitive closure to the vtable entry usage info.  */
   elf_link_hash_traverse (elf_hash_table (info),
@@ -5858,7 +5845,7 @@ elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 \f
-/* Called from check_relocs to record the existance of a VTINHERIT reloc.  */
+/* Called from check_relocs to record the existence of a VTINHERIT reloc.  */
 
 bfd_boolean
 elf_gc_record_vtinherit (bfd *abfd,
@@ -5914,7 +5901,7 @@ elf_gc_record_vtinherit (bfd *abfd,
   return TRUE;
 }
 
-/* Called from check_relocs to record the existance of a VTENTRY reloc.  */
+/* Called from check_relocs to record the existence of a VTENTRY reloc.  */
 
 bfd_boolean
 elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
@@ -5991,6 +5978,9 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_vma gotoff;
 
+  if (! is_elf_hash_table (info->hash))
+    return FALSE;
+
   /* The GOT offset is relative to the .got section, but the GOT header is
      put into the .got.plt section, if the backend uses it.  */
   if (bed->want_got_plt)
@@ -6197,8 +6187,7 @@ elf_bfd_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   bfd_boolean ret = FALSE;
 
   if (info->traditional_format
-      || info->hash->creator->flavour != bfd_target_elf_flavour
-      || ! is_elf_hash_table (info))
+      || !is_elf_hash_table (info->hash))
     return FALSE;
 
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
This page took 0.031642 seconds and 4 git commands to generate.