2001-03-20 Michael Chastain <chastain@redhat.com>
[deliverable/binutils-gdb.git] / bfd / linker.c
index b47817d14aaab38275de86aca27b3f78b22f871d..fcfeb83412d4ee123fec1c8c0820c31b10213404 100644 (file)
@@ -1,5 +1,6 @@
 /* linker.c -- BFD linker routines
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -59,7 +60,7 @@ SECTION
        a.out (in <<aoutx.h>>) and ECOFF (in <<ecoff.c>>).  The a.out
        routines are used as examples throughout this section.
 
-@menu  
+@menu
 @* Creating a Linker Hash Table::
 @* Adding Symbols to the Hash Table::
 @* Performing the Final Link::
@@ -74,7 +75,7 @@ SUBSECTION
 @cindex target vector (_bfd_link_hash_table_create)
        The linker routines must create a hash table, which must be
        derived from <<struct bfd_link_hash_table>> described in
-       <<bfdlink.c>>.  @xref{Hash Tables} for information on how to
+       <<bfdlink.c>>.  @xref{Hash Tables}, for information on how to
        create a derived hash table.  This entry point is called using
        the target vector of the linker output file.
 
@@ -395,8 +396,7 @@ SUBSUBSECTION
        is used to further controls which local symbols are included
        in the output file.  If the value is <<discard_l>>, then all
        local symbols which begin with a certain prefix are discarded;
-       this prefix is described by the <<lprefix>> and
-       <<lprefix_len>> fields of the <<bfd_link_info>> structure.
+       this is controlled by the <<bfd_is_local_label_name>> entry point.
 
        The a.out backend handles symbols by calling
        <<aout_link_write_symbols>> on each input BFD and then
@@ -601,7 +601,7 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
    struct bfd_link_hash_entry * with no explicit cast required on the
    call.  */
 
-void 
+void
 bfd_link_hash_traverse (table, func, info)
      struct bfd_link_hash_table *table;
      boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR));
@@ -694,7 +694,7 @@ static boolean
 generic_link_read_symbols (abfd)
      bfd *abfd;
 {
-  if (abfd->outsymbols == (asymbol **) NULL)
+  if (bfd_get_outsymbols (abfd) == (asymbol **) NULL)
     {
       long symsize;
       long symcount;
@@ -702,13 +702,13 @@ generic_link_read_symbols (abfd)
       symsize = bfd_get_symtab_upper_bound (abfd);
       if (symsize < 0)
        return false;
-      abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize);
-      if (abfd->outsymbols == NULL && symsize != 0)
+      bfd_get_outsymbols (abfd) = (asymbol **) bfd_alloc (abfd, symsize);
+      if (bfd_get_outsymbols (abfd) == NULL && symsize != 0)
        return false;
-      symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols);
+      symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd));
       if (symcount < 0)
        return false;
-      abfd->symcount = symcount;
+      bfd_get_symcount (abfd) = symcount;
     }
 
   return true;
@@ -1320,14 +1320,14 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
                  if (bfd_is_com_section (bfd_get_section (p)))
                    p->flags |= BSF_OLD_COMMON;
                }
-
-             /* Store a back pointer from the symbol to the hash
-                table entry for the benefit of relaxation code until
-                it gets rewritten to not use asymbol structures.
-                Setting this is also used to check whether these
-                symbols were set up by the generic linker.  */
-             p->udata.p = (PTR) h;
            }
+
+         /* Store a back pointer from the symbol to the hash
+            table entry for the benefit of relaxation code until
+            it gets rewritten to not use asymbol structures.
+            Setting this is also used to check whether these
+            symbols were set up by the generic linker.  */
+         p->udata.p = (PTR) h;
        }
     }
 
@@ -1361,7 +1361,7 @@ enum link_row
 
 enum link_action
 {
-  FAIL,                /* Abort. */
+  FAIL,                /* Abort.  */
   UND,         /* Mark symbol undefined.  */
   WEAK,                /* Mark symbol weak undefined.  */
   DEF,         /* Mark symbol defined.  */
@@ -1395,7 +1395,7 @@ static const enum link_action link_action[8][8] =
   /* UNDEFW_ROW        */  {WEAK,  NOACT, NOACT, REF,   REF,   NOACT, REFC,  WARNC },
   /* DEF_ROW   */  {DEF,   DEF,   DEF,   MDEF,  DEF,   CDEF,  MDEF,  CYCLE },
   /* DEFW_ROW  */  {DEFW,  DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT, CYCLE },
-  /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  CREF,  BIG,   CREF,  WARNC },
+  /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  CREF,  BIG,   REFC,  WARNC },
   /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  IND,   CIND,  MIND,  CYCLE },
   /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, MWARN },
   /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
@@ -1464,7 +1464,7 @@ hash_entry_bfd (h)
      or destructor names as collect2 does.
    HASHP, if not NULL, is a place to store the created hash table
      entry; if *HASHP is not NULL, the caller has already looked up
-     the hash table entry, and stored it in *HASHP. */
+     the hash table entry, and stored it in *HASHP.  */
 
 boolean
 _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
@@ -1521,11 +1521,13 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
        }
     }
 
-  if (info->notice_hash != (struct bfd_hash_table *) NULL
-      && (bfd_hash_lookup (info->notice_hash, name, false, false)
-         != (struct bfd_hash_entry *) NULL))
+  if (info->notice_all
+      || (info->notice_hash != (struct bfd_hash_table *) NULL
+         && (bfd_hash_lookup (info->notice_hash, name, false, false)
+             != (struct bfd_hash_entry *) NULL)))
     {
-      if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+      if (! (*info->callbacks->notice) (info, h->root.string, abfd, section,
+                                       value))
        return false;
     }
 
@@ -1565,7 +1567,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
             previously common.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
-                (info, name,
+                (info, h->root.string,
                  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_defined, (bfd_vma) 0)))
            return false;
@@ -1628,7 +1630,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
                        if (! ((*info->callbacks->constructor)
                               (info,
                                c == 'I' ? true : false,
-                               name, abfd, section, value)))
+                               h->root.string, abfd, section, value)))
                          return false;
                      }
                  }
@@ -1699,7 +1701,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
             two sizes.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
-                (info, name,
+                (info, h->root.string,
                  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_common, value)))
            return false;
@@ -1732,7 +1734,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            else
              obfd = NULL;
            if (! ((*info->callbacks->multiple_common)
-                  (info, name, obfd, h->type, (bfd_vma) 0,
+                  (info, h->root.string, obfd, h->type, (bfd_vma) 0,
                    abfd, bfd_link_hash_common, value)))
              return false;
          }
@@ -1747,8 +1749,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
        case MDEF:
          /* Handle a multiple definition.  */
          {
-           asection *msec;
-           bfd_vma mval;
+           asection *msec = NULL;
+           bfd_vma mval = 0;
 
            switch (h->type)
              {
@@ -1773,8 +1775,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
              break;
 
            if (! ((*info->callbacks->multiple_definition)
-                  (info, name, msec->owner, msec, mval, abfd, section,
-                   value)))
+                  (info, h->root.string, msec->owner, msec, mval, abfd,
+                   section, value)))
              return false;
          }
          break;
@@ -1783,7 +1785,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          /* Create an indirect symbol from an existing common symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
-                (info, name,
+                (info, h->root.string,
                  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_indirect, (bfd_vma) 0)))
            return false;
@@ -1831,8 +1833,9 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          /* Issue a warning and cycle.  */
          if (h->u.i.warning != NULL)
            {
-             if (! (*info->callbacks->warning) (info, h->u.i.warning, name,
-                                                abfd, (asection *) NULL,
+             if (! (*info->callbacks->warning) (info, h->u.i.warning,
+                                                h->root.string, abfd,
+                                                (asection *) NULL,
                                                 (bfd_vma) 0))
                return false;
              /* Only issue a warning once.  */
@@ -1855,7 +1858,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
        case WARN:
          /* Issue a warning.  */
-         if (! (*info->callbacks->warning) (info, string, name,
+         if (! (*info->callbacks->warning) (info, string, h->root.string,
                                             hash_entry_bfd (h),
                                             (asection *) NULL, (bfd_vma) 0))
            return false;
@@ -1869,7 +1872,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
             ensure this.  */
          if (h->next != NULL || info->hash->undefs_tail == h)
            {
-             if (! (*info->callbacks->warning) (info, string, name,
+             if (! (*info->callbacks->warning) (info, string, h->root.string,
                                                 hash_entry_bfd (h),
                                                 (asection *) NULL,
                                                 (bfd_vma) 0))
@@ -1933,10 +1936,16 @@ _bfd_generic_final_link (abfd, info)
   size_t outsymalloc;
   struct generic_write_global_symbol_info wginfo;
 
-  abfd->outsymbols = (asymbol **) NULL;
-  abfd->symcount = 0;
+  bfd_get_outsymbols (abfd) = (asymbol **) NULL;
+  bfd_get_symcount (abfd) = 0;
   outsymalloc = 0;
 
+  /* Mark all sections which will be included in the output file.  */
+  for (o = abfd->sections; o != NULL; o = o->next)
+    for (p = o->link_order_head; p != NULL; p = p->next)
+      if (p->type == bfd_indirect_link_order)
+       p->u.indirect.section->linker_mark = true;
+
   /* Build the output symbol table.  */
   for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
     if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
@@ -1950,6 +1959,12 @@ _bfd_generic_final_link (abfd, info)
                                   _bfd_generic_link_write_global_symbol,
                                   (PTR) &wginfo);
 
+  /* Make sure we have a trailing NULL pointer on OUTSYMBOLS.  We
+     shouldn't really need one, since we have SYMCOUNT, but some old
+     code still expects one.  */
+  if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
+    return false;
+
   if (info->relocateable)
     {
       /* Allocate space for the output relocs for each section.  */
@@ -2051,7 +2066,7 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
      size_t *psymalloc;
      asymbol *sym;
 {
-  if (output_bfd->symcount >= *psymalloc)
+  if (bfd_get_symcount (output_bfd) >= *psymalloc)
     {
       asymbol **newsyms;
 
@@ -2059,15 +2074,16 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
        *psymalloc = 124;
       else
        *psymalloc *= 2;
-      newsyms = (asymbol **) bfd_realloc (output_bfd->outsymbols,
+      newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd),
                                          *psymalloc * sizeof (asymbol *));
       if (newsyms == (asymbol **) NULL)
        return false;
-      output_bfd->outsymbols = newsyms;
+      bfd_get_outsymbols (output_bfd) = newsyms;
     }
 
-  output_bfd->outsymbols[output_bfd->symcount] = sym;
-  ++output_bfd->symcount;
+  bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym;
+  if (sym != NULL)
+    ++ bfd_get_symcount (output_bfd);
 
   return true;
 }
@@ -2221,10 +2237,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
 
       /* This switch is straight from the old code in
         write_file_locals in ldsym.c.  */
-      if (info->strip == strip_some
-         && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
-                              false, false)
-             == (struct bfd_hash_entry *) NULL))
+      if (info->strip == strip_all
+         || (info->strip == strip_some
+             && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
+                                  false, false)
+                 == (struct bfd_hash_entry *) NULL)))
        output = false;
       else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
        {
@@ -2263,10 +2280,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                  output = false;
                  break;
                case discard_l:
-                 if (bfd_asymbol_name (sym)[0] == info->lprefix[0]
-                     && (info->lprefix_len == 1
-                         || strncmp (bfd_asymbol_name (sym), info->lprefix,
-                                     info->lprefix_len) == 0))
+                 if (bfd_is_local_label (input_bfd, sym))
                    output = false;
                  else
                    output = true;
@@ -2287,6 +2301,15 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
       else
        abort ();
 
+      /* If this symbol is in a section which is not being included
+        in the output file, then we don't want to output the symbol.
+
+        Gross.  .bss and similar sections won't have the linker_mark
+        field set.  */
+      if ((sym->section->flags & SEC_HAS_CONTENTS) != 0
+         && sym->section->linker_mark == false)
+       output = false;
+
       if (output)
        {
          if (! generic_add_output_symbol (output_bfd, psymalloc, sym))
@@ -2429,7 +2452,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
   r = (arelent *) bfd_alloc (abfd, sizeof (arelent));
   if (r == (arelent *) NULL)
     return false;
-      
+
   r->address = link_order->offset;
   r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
   if (r->howto == 0)
@@ -2501,7 +2524,9 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
          break;
        }
       ok = bfd_set_section_contents (abfd, sec, (PTR) buf,
-                                    (file_ptr) link_order->offset, size);
+                                    (file_ptr)
+                                     (link_order->offset *
+                                      bfd_octets_per_byte (abfd)), size);
       free (buf);
       if (! ok)
        return false;
@@ -2525,7 +2550,7 @@ bfd_new_link_order (abfd, section)
   struct bfd_link_order *new;
 
   new = ((struct bfd_link_order *)
-        bfd_alloc_by_size_t (abfd, sizeof (struct bfd_link_order)));
+        bfd_alloc (abfd, sizeof (struct bfd_link_order)));
   if (!new)
     return NULL;
 
@@ -2569,18 +2594,19 @@ _bfd_default_link_order (abfd, info, sec, link_order)
     case bfd_data_link_order:
       return bfd_set_section_contents (abfd, sec,
                                       (PTR) link_order->u.data.contents,
-                                      (file_ptr) link_order->offset,
+                                      (file_ptr)
+                                       (link_order->offset *
+                                        bfd_octets_per_byte (abfd)),
                                       link_order->size);
     }
 }
 
 /* Default routine to handle a bfd_fill_link_order.  */
 
-/*ARGSUSED*/
 static boolean
 default_fill_link_order (abfd, info, sec, link_order)
      bfd *abfd;
-     struct bfd_link_info *info;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
      asection *sec;
      struct bfd_link_order *link_order;
 {
@@ -2603,7 +2629,9 @@ default_fill_link_order (abfd, info, sec, link_order)
   for (i = 1; i < size; i += 2)
     space[i] = fill;
   result = bfd_set_section_contents (abfd, sec, space,
-                                    (file_ptr) link_order->offset,
+                                    (file_ptr)
+                                     (link_order->offset *
+                                      bfd_octets_per_byte (abfd)),
                                     link_order->size);
   free (space);
   return result;
@@ -2646,7 +2674,11 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
         because somebody is attempting to link together different
         types of object files.  Handling this case correctly is
         difficult, and sometimes impossible.  */
-      abort ();
+      (*_bfd_error_handler)
+       (_("Attempt to do relocateable link with %s input and %s output"),
+        bfd_get_target (input_bfd), bfd_get_target (output_bfd));
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
     }
 
   if (! generic_linker)
@@ -2699,7 +2731,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
              if (h != NULL)
                set_symbol_from_hash (sym, h);
            }
-       }         
+       }
     }
 
   /* Get and relocate the section contents.  */
@@ -2716,7 +2748,10 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
   /* Output the section contents.  */
   if (! bfd_set_section_contents (output_bfd, output_section,
                                  (PTR) new_contents,
-                                 link_order->offset, link_order->size))
+                                 (file_ptr)
+                                  (link_order->offset *
+                                   bfd_octets_per_byte (output_bfd)),
+                                  link_order->size))
     goto error_return;
 
   if (contents != NULL)
@@ -2767,12 +2802,10 @@ DESCRIPTION
 
 */
 
-
-
 boolean
 _bfd_generic_link_split_section (abfd, sec)
-     bfd *abfd;
-     asection *sec;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
 {
   return false;
 }
This page took 0.032361 seconds and 4 git commands to generate.