import gdb-1999-06-21 snapshot
[external/binutils.git] / bfd / cofflink.c
index 58c6d94..cf56869 100644 (file)
@@ -1,5 +1,5 @@
 /* COFF specific linker code.
-   Copyright 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -244,6 +244,11 @@ coff_link_check_ar_symbols (abfd, info, pneeded)
       bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
 
       if ((sym.n_sclass == C_EXT
+          || sym.n_sclass == C_WEAKEXT
+          || (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK)
+#ifdef C_SYSTEM
+          || sym.n_sclass == C_SYSTEM
+#endif
           || (sym_is_global && (*sym_is_global) (abfd, &sym)))
          && (sym.n_scnum != 0 || sym.n_value != 0))
        {
@@ -334,6 +339,11 @@ coff_link_add_symbols (abfd, info)
       bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
 
       if (sym.n_sclass == C_EXT
+          || sym.n_sclass == C_WEAKEXT
+          || (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK)
+#ifdef C_SYSTEM
+         || sym.n_sclass == C_SYSTEM
+#endif
          || (sym_is_global && (*sym_is_global) (abfd, &sym)))
        {
          const char *name;
@@ -378,6 +388,10 @@ coff_link_add_symbols (abfd, info)
                value -= section->vma;
            }
 
+         if (sym.n_sclass == C_WEAKEXT
+             || (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK))
+           flags = BSF_WEAK;
+
          if (! (bfd_coff_link_add_one_symbol
                 (info, abfd, name, flags, section, value,
                  (const char *) NULL, copy, false,
@@ -397,7 +411,8 @@ coff_link_add_symbols (abfd, info)
                   && (*sym_hash)->type == T_NULL)
                  || sym.n_scnum != 0
                  || (sym.n_value != 0
-                     && (*sym_hash)->root.type != bfd_link_hash_defined))
+                     && (*sym_hash)->root.type != bfd_link_hash_defined
+                     && (*sym_hash)->root.type != bfd_link_hash_defweak))
                {
                  (*sym_hash)->class = sym.n_sclass;
                  if (sym.n_type != T_NULL)
@@ -405,7 +420,7 @@ coff_link_add_symbols (abfd, info)
                      if ((*sym_hash)->type != T_NULL
                          && (*sym_hash)->type != sym.n_type)
                        (*_bfd_error_handler)
-                         ("Warning: type of symbol `%s' changed from %d to %d in %s",
+                         (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
                           name, (*sym_hash)->type, sym.n_type,
                           bfd_get_filename (abfd));
                      (*sym_hash)->type = sym.n_type;
@@ -762,7 +777,7 @@ _bfd_coff_final_link (abfd, info)
                  == bfd_target_coff_flavour))
            {
              sub = p->u.indirect.section->owner;
-             if (! sub->output_has_begun)
+             if (! bfd_coff_link_output_has_begun (sub, & finfo))
                {
                  if (! _bfd_coff_link_input_bfd (&finfo, sub))
                    goto error_return;
@@ -783,6 +798,9 @@ _bfd_coff_final_link (abfd, info)
        }
     }
 
+  if (! bfd_coff_final_link_postscript (abfd, & finfo))
+    goto error_return;
+  
   /* Free up the buffers used by _bfd_coff_link_input_bfd.  */
 
   coff_debug_merge_hash_table_free (&finfo.debug_merge);
@@ -1298,8 +1316,9 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
            *secpp = bfd_com_section_ptr;
        }
 
-      /* Extract the flag indicating if this symbol is used by a relocation */
-      if ((   finfo->info->strip   != strip_none
+      /* Extract the flag indicating if this symbol is used by a
+         relocation.  */
+      if ((finfo->info->strip != strip_none
           || finfo->info->discard != discard_none)
          && finfo->info->relocateable)
        dont_skip_symbol = *indexp;
@@ -1319,14 +1338,19 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       if (! skip)
        {
          if (isym.n_sclass == C_EXT
+             || isym.n_sclass == C_WEAKEXT
+             || (obj_pe (input_bfd) && isym.n_sclass == C_NT_WEAK)
+#ifdef C_SYSTEM
+             || isym.n_sclass == C_SYSTEM
+#endif
              || (sym_is_global && (*sym_is_global) (input_bfd, &isym)))
            {
              /* This is a global symbol.  Global symbols come at the
                 end of the symbol table, so skip them for now.
-                Function symbols, however, are an exception, and are
-                not moved to the end.  */
+                Locally defined function symbols, however, are an
+                exception, and are not moved to the end.  */
              global = true;
-             if (! ISFCN (isym.n_type))
+             if (! ISFCN (isym.n_type) || isym.n_scnum == 0)
                skip = true;
            }
          else
@@ -1339,11 +1363,23 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
        }
 
       /* If we stripping debugging symbols, and this is a debugging
-         symbol, then skip it.  */
+         symbol, then skip it.  FIXME: gas sets the section to N_ABS
+         for some types of debugging symbols; I don't know if this is
+         a bug or not.  In any case, we handle it here.  */
       if (! skip
          && finfo->info->strip == strip_debugger
          && ! dont_skip_symbol
-         && isym.n_scnum == N_DEBUG)
+         && (isym.n_scnum == N_DEBUG
+             || (isym.n_scnum == N_ABS
+                 && (isym.n_sclass == C_AUTO
+                     || isym.n_sclass == C_REG
+                     || isym.n_sclass == C_MOS
+                     || isym.n_sclass == C_MOE
+                     || isym.n_sclass == C_MOU
+                     || isym.n_sclass == C_ARG
+                     || isym.n_sclass == C_REGPARM
+                     || isym.n_sclass == C_FIELD
+                     || isym.n_sclass == C_EOS))))
        skip = true;
 
       /* If some symbols are stripped based on the name, work out the
@@ -1623,7 +1659,10 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
          /* If doing task linking, convert normal global function symbols to
             static functions. */
 
-         if (finfo->info->task_link && isym.n_sclass == C_EXT)
+         if (finfo->info->task_link
+             && (isym.n_sclass == C_EXT
+                 || isym.n_sclass == C_WEAKEXT
+                 || (obj_pe (input_bfd) && isym.n_sclass == C_NT_WEAK)))
            isym.n_sclass = C_STAT;
 
          /* Output the symbol.  */
@@ -2051,7 +2090,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              && o->reloc_count != 0)
            {
              ((*_bfd_error_handler)
-              ("%s: relocs in section `%s', but it has no contents",
+              (_("%s: relocs in section `%s', but it has no contents"),
                bfd_get_filename (input_bfd),
                bfd_get_section_name (input_bfd, o)));
              bfd_set_error (bfd_error_no_contents);
@@ -2312,12 +2351,15 @@ _bfd_coff_write_global_sym (h, data)
   if (isym.n_sclass == C_NULL)
     isym.n_sclass = C_EXT;
 
-  /* If doing task linking and this is the pass where we convert defined globals to
-     statics, then do that conversion now.  If the symbol is not being converted,
-     just ignore it and it will be output during a later pass. */
+  /* If doing task linking and this is the pass where we convert
+     defined globals to statics, then do that conversion now.  If the
+     symbol is not being converted, just ignore it and it will be
+     output during a later pass. */
   if (finfo->global_to_static)
     {
-      if (isym.n_sclass != C_EXT)
+      if (isym.n_sclass != C_EXT
+         && isym.n_sclass != C_WEAKEXT
+         && (! obj_pe (output_bfd) || isym.n_sclass != C_NT_WEAK))
        {
          return true;
        }
@@ -2373,6 +2415,7 @@ _bfd_coff_write_task_globals (h, data)
 {
   struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
   boolean rtnval = true;
+  boolean save_global_to_static;
 
   if (h->indx < 0)
     {
@@ -2380,9 +2423,12 @@ _bfd_coff_write_task_globals (h, data)
        {
        case bfd_link_hash_defined:
        case bfd_link_hash_defweak:
+         save_global_to_static = finfo->global_to_static;
          finfo->global_to_static = true;
          rtnval = _bfd_coff_write_global_sym (h, data);
-         finfo->global_to_static = false;
+         finfo->global_to_static = save_global_to_static;
+         break;
+       default:
          break;
        }
     }
@@ -2673,7 +2719,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
          break;
        case bfd_reloc_outofrange:
          (*_bfd_error_handler)
-           ("%s: bad reloc address 0x%lx in section `%s'",
+           (_("%s: bad reloc address 0x%lx in section `%s'"),
             bfd_get_filename (input_bfd),
             (unsigned long) rel->r_vaddr,
             bfd_get_section_name (input_bfd, input_section));