2005-02-17 Paul Brook <paul@codesourcery.com>
[deliverable/binutils-gdb.git] / gas / config / obj-coff.c
index 0239b76f88e613acf5354e30cde2fb0088d4bb80..bb97280e86496d2407708ec9c33d27801879a3b4 100644 (file)
 #include "obstack.h"
 #include "subsegs.h"
 
+#ifdef TE_PE
+#include "coff/pe.h"
+#endif
+
 /* I think this is probably always correct.  */
 #ifndef KEEP_RELOC_INFO
 #define KEEP_RELOC_INFO
 /* This is used to hold the symbol built by a sequence of pseudo-ops
    from .def and .endef.  */
 static symbolS *def_symbol_in_progress;
+#ifdef TE_PE
+/* PE weak alternate symbols begin with this string.  */
+static const char weak_altprefix[] = ".weak.";
+#endif /* TE_PE */
 
 typedef struct
   {
@@ -60,7 +68,9 @@ static void tag_insert PARAMS ((const char *, symbolS *));
 static symbolS *tag_find PARAMS ((char *));
 static symbolS *tag_find_or_make PARAMS ((char *));
 static void obj_coff_bss PARAMS ((int));
+#ifdef BFD_ASSEMBLER
 static void obj_coff_weak PARAMS ((int));
+#endif
 const char *s_get_name PARAMS ((symbolS * s));
 static void obj_coff_ln PARAMS ((int));
 static void obj_coff_def PARAMS ((int));
@@ -102,17 +112,6 @@ stack_init (chunk_size, element_size)
   return st;
 }
 
-#if 0
-/* Not currently used.  */
-static void
-stack_delete (st)
-     stack *st;
-{
-  free (st->data);
-  free (st);
-}
-#endif
-
 static char *
 stack_push (st, element)
      stack *st;
@@ -325,8 +324,7 @@ c_symbol_merge (debug, normal)
 }
 
 void
-c_dot_file_symbol (filename)
-     const char *filename;
+c_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED)
 {
   symbolS *symbolP;
 
@@ -1094,14 +1092,84 @@ obj_coff_val (ignore)
   demand_empty_rest_of_line ();
 }
 
+#ifdef TE_PE
+
+/* Return nonzero if name begins with weak alternate symbol prefix.  */
+
+static int
+weak_is_altname (const char * name)
+{
+  return ! strncmp (name, weak_altprefix, sizeof (weak_altprefix) - 1);
+}
+
+/* Return the name of the alternate symbol
+   name corresponding to a weak symbol's name.  */
+
+static const char *
+weak_name2altname (const char * name)
+{
+  char *alt_name;
+
+  alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name));
+  strcpy (alt_name, weak_altprefix);
+  return strcat (alt_name, name);
+}
+
+/* Return the name of the weak symbol corresponding to an 
+   alterate symbol.  */
+
+static const char *
+weak_altname2name (const char * name)
+{
+  char * weak_name;
+  char * dot;
+
+  assert (weak_is_altname (name));
+
+  weak_name = xstrdup (name + 6);
+  if ((dot = strchr (weak_name, '.')))
+    *dot = 0;
+  return weak_name;
+}
+
+/* Make a weak symbol name unique by
+   appending the name of an external symbol.  */
+
+static const char *
+weak_uniquify (const char * name)
+{
+  char *ret;
+  const char * unique = "";
+
+#ifdef USE_UNIQUE
+  if (an_external_name != NULL)
+    unique = an_external_name;
+#endif
+  assert (weak_is_altname (name));
+
+  if (strchr (name + sizeof (weak_altprefix), '.'))
+    return name;
+
+  ret = xmalloc (strlen (name) + strlen (unique) + 2);
+  strcpy (ret, name);
+  strcat (ret, ".");
+  strcat (ret, unique);
+  return ret;
+}
+
+#endif  /* TE_PE */
+
 /* Handle .weak.  This is a GNU extension in formats other than PE. */
+
 static void
-obj_coff_weak (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   int c;
   symbolS *symbolP;
+#ifdef TE_PE
+  symbolS *alternateP;
+#endif
 
   do
     {
@@ -1113,6 +1181,7 @@ obj_coff_weak (ignore)
          ignore_rest_of_line ();
          return;
        }
+      c = 0;
       symbolP = symbol_find_or_make (name);
       *input_line_pointer = c;
       SKIP_WHITESPACE ();
@@ -1123,42 +1192,20 @@ obj_coff_weak (ignore)
 
 #ifdef TE_PE
       /* See _Microsoft Portable Executable and Common Object
-       * File Format Specification_, section 5.5.3.
-       * Note that weak symbols without aux records are a GNU
-       * extension.
-       */
+         File Format Specification_, section 5.5.3.
+         Create a symbol representing the alternate value.
+         coff_frob_symbol will set the value of this symbol from
+         the value of the weak symbol itself.  */
       S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
+      S_SET_NUMBER_AUXILIARY (symbolP, 1);
+      SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_LIBRARY);
 
-      if (c == '=')
-       {
-         symbolS *alternateP;
-         long characteristics = 2;
-         ++input_line_pointer;
-         if (*input_line_pointer == '=')
-           {
-             characteristics = 1;
-             ++input_line_pointer;
-           }
-
-         SKIP_WHITESPACE();
-         name = input_line_pointer;
-         c = get_symbol_end();
-         if (*name == 0)
-           {
-             as_warn (_("alternate name missing in .weak directive"));
-             ignore_rest_of_line ();
-             return;
-           }
-         alternateP = symbol_find_or_make (name);
-         *input_line_pointer = c;
+      alternateP = symbol_find_or_make (weak_name2altname (name));
+      S_SET_EXTERNAL (alternateP);
+      S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
 
-         S_SET_NUMBER_AUXILIARY (symbolP, 1);
-         SA_SET_SYM_TAGNDX (symbolP, alternateP);
-         SA_SET_SYM_FSIZE (symbolP, characteristics);
-       }
-#else  /* TE_PE */
-      S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT);
-#endif  /* TE_PE */
+      SA_SET_SYM_TAGNDX (symbolP, alternateP);
+#endif
 
       if (c == ',')
        {
@@ -1212,14 +1259,67 @@ coff_frob_symbol (symp, punt)
   if (!block_stack)
     block_stack = stack_init (512, sizeof (symbolS*));
 
-  if (S_IS_WEAK (symp))
-    {
 #ifdef TE_PE
-      S_SET_STORAGE_CLASS (symp, C_NT_WEAK);
-#else
-      S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
-#endif
+  if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
+      && ! S_IS_WEAK (symp)
+      && weak_is_altname (S_GET_NAME (symp)))
+    {
+      /* This is a weak alternate symbol.  All processing of
+        PECOFFweak symbols is done here, through the alternate.  */
+      symbolS *weakp = symbol_find (weak_altname2name (S_GET_NAME (symp)));
+
+      assert (weakp);
+      assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
+
+      if (symbol_equated_p (weakp))
+       {
+         /* The weak symbol has an alternate specified; symp is unneeded.  */
+         S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
+         SA_SET_SYM_TAGNDX (weakp,
+           symbol_get_value_expression (weakp)->X_add_symbol);
+
+         S_CLEAR_EXTERNAL (symp);
+         *punt = 1;
+         return;
+       }
+      else
+       {
+         /* The weak symbol has been assigned an alternate value.
+             Copy this value to symp, and set symp as weakp's alternate.  */
+         if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
+           {
+             S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
+             S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
+           }
+
+         if (S_IS_DEFINED (weakp))
+           {
+             /* This is a defined weak symbol.  Copy value information
+                from the weak symbol itself to the alternate symbol.  */
+             symbol_set_value_expression (symp,
+                                          symbol_get_value_expression (weakp));
+             symbol_set_frag (symp, symbol_get_frag (weakp));
+             S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
+           }
+         else
+           {
+             /* This is an undefined weak symbol.
+                Define the alternate symbol to zero.  */
+             S_SET_VALUE (symp, 0);
+             S_SET_SEGMENT (symp, absolute_section);
+           }
+
+         S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
+         S_SET_STORAGE_CLASS (symp, C_EXT);
+
+         S_SET_VALUE (weakp, 0);
+         S_SET_SEGMENT (weakp, undefined_section);
+       }
     }
+#else /* TE_PE */
+  if (S_IS_WEAK (symp))
+    S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
+#endif /* TE_PE */
 
   if (!S_IS_DEFINED (symp)
       && !S_IS_WEAK (symp)
@@ -1325,7 +1425,7 @@ coff_frob_symbol (symp, punt)
      order to call SA_SET_SYM_ENDNDX correctly.  */
   if (! symbol_used_in_reloc_p (symp)
       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
-         || (! S_IS_EXTERNAL (symp)
+         || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
              && ! symbol_get_tc (symp)->output
              && S_GET_STORAGE_CLASS (symp) != C_FILE)))
     *punt = 1;
@@ -1575,7 +1675,7 @@ coff_adjust_symtab ()
 {
   if (symbol_rootP == NULL
       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
-    c_dot_file_symbol ("fake");
+    c_dot_file_symbol ("fake", 0);
 }
 
 void
@@ -1720,10 +1820,6 @@ symbol_dump ()
 #include "libbfd.h"
 #include "libcoff.h"
 
-#ifdef TE_PE
-#include "coff/pe.h"
-#endif
-
 /* The NOP_OPCODE is for the alignment fill value.  Fill with nop so
    that we can stick sections together without causing trouble.  */
 #ifndef NOP_OPCODE
@@ -1876,7 +1972,6 @@ size_section (abfd, idx)
      bfd *abfd ATTRIBUTE_UNUSED;
      unsigned int idx;
 {
-
   unsigned int size = 0;
   fragS *frag = segment_info[idx].frchainP->frch_root;
 
@@ -2748,9 +2843,6 @@ obj_coff_line (ignore)
      start of the containing function.  */
   if (!strcmp (".bf", name))
     {
-#if 0 /* XXX Can we ever have line numbers going backwards?  */
-      if (this_base > line_base)
-#endif
        line_base = this_base;
 
 #ifndef NO_LISTING
@@ -3068,13 +3160,6 @@ yank_symbols ()
 
                  if (S_GET_NUMBER_AUXILIARY (symbolP) < 1)
                    S_SET_NUMBER_AUXILIARY (symbolP, 1);
-
-                 /* Clobber possible stale .dim information.  */
-#if 0
-                 /* Iffed out by steve - this fries the lnnoptr info too.  */
-                 bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
-                        sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
-#endif
                }
              if (S_GET_STORAGE_CLASS (symbolP) == C_FCN)
                {
@@ -3297,7 +3382,7 @@ crawl_symbols (h, abfd)
   /* Is there a .file symbol ? If not insert one at the beginning.  */
   if (symbol_rootP == NULL
       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
-    c_dot_file_symbol ("fake");
+    c_dot_file_symbol ("fake", 0);
 
   /* Build up static symbols for the sections, they are filled in later.  */
 
@@ -3667,19 +3752,10 @@ write_object_file ()
   }
 
   coff_header_append (abfd, &headers);
-#if 0
-  /* Recent changes to write need this, but where it should
-     go is up to Ken..  */
-  if (!bfd_close_all_done (abfd))
-    as_fatal (_("Can't close %s: %s"), out_file_name,
-             bfd_errmsg (bfd_get_error ()));
-#else
   {
     extern bfd *stdoutput;
     stdoutput = abfd;
   }
-#endif
-
 }
 
 /* Add a new segment.  This is called from subseg_new via the
@@ -3898,8 +3974,7 @@ c_line_new (symbol, paddr, line_number, frag)
 }
 
 void
-c_dot_file_symbol (filename)
-     char *filename;
+c_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED)
 {
   symbolS *symbolP;
 
@@ -4075,68 +4150,8 @@ static void
 obj_coff_lcomm (ignore)
      int ignore ATTRIBUTE_UNUSED;
 {
-  s_lcomm(0);
+  s_lcomm (0);
   return;
-#if 0
-  char *name;
-  char c;
-  int temp;
-  char *p;
-
-  symbolS *symbolP;
-
-  name = input_line_pointer;
-
-  c = get_symbol_end ();
-  p = input_line_pointer;
-  *p = c;
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer != ',')
-    {
-      as_bad (_("Expected comma after name"));
-      ignore_rest_of_line ();
-      return;
-    }
-  if (*input_line_pointer == '\n')
-    {
-      as_bad (_("Missing size expression"));
-      return;
-    }
-  input_line_pointer++;
-  if ((temp = get_absolute_expression ()) < 0)
-    {
-      as_warn (_("lcomm length (%d.) <0! Ignored."), temp);
-      ignore_rest_of_line ();
-      return;
-    }
-  *p = 0;
-
-  symbolP = symbol_find_or_make (name);
-
-  if (S_GET_SEGMENT (symbolP) == SEG_UNKNOWN &&
-      S_GET_VALUE (symbolP) == 0)
-    {
-      if (! need_pass_2)
-       {
-         char *p;
-         segT current_seg = now_seg;   /* Save current seg.  */
-         subsegT current_subseg = now_subseg;
-
-         subseg_set (SEG_E2, 1);
-         symbolP->sy_frag = frag_now;
-         p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP,
-                      (offsetT) temp, (char *) 0);
-         *p = 0;
-         subseg_set (current_seg, current_subseg); /* Restore current seg.  */
-         S_SET_SEGMENT (symbolP, SEG_E2);
-         S_SET_STORAGE_CLASS (symbolP, C_STAT);
-       }
-    }
-  else
-    as_bad (_("Symbol %s already defined"), name);
-
-  demand_empty_rest_of_line ();
-#endif
 }
 
 static void
@@ -4352,11 +4367,7 @@ fixup_segment (segP, this_segment_type)
                add_number -= S_GET_VALUE (sub_symbolP);
 
 #ifdef DIFF_EXPR_OK
-             else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type
-#if 0 /* Okay for 68k, at least...  */
-                      && !pcrel
-#endif
-                      )
+             else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type)
                {
                  /* Make it pc-relative.  */
                  add_number += (md_pcrel_from (fixP)
@@ -4654,7 +4665,6 @@ const pseudo_typeS coff_pseudo_table[] =
   /* We accept the .bss directive for backward compatibility with
      earlier versions of gas.  */
   {"bss", obj_coff_bss, 0},
-  {"weak", obj_coff_weak, 0},
   {"ident", obj_coff_ident, 0},
 #ifndef BFD_ASSEMBLER
   {"use", obj_coff_section, 0},
@@ -4662,6 +4672,7 @@ const pseudo_typeS coff_pseudo_table[] =
   {"data", obj_coff_data, 0},
   {"lcomm", obj_coff_lcomm, 0},
 #else
+  {"weak", obj_coff_weak, 0},
   {"optim", s_ignore, 0},      /* For sun386i cc (?) */
 #endif
   {"version", s_ignore, 0},
This page took 0.028262 seconds and 4 git commands to generate.