2006-12-13 Paul Brook <paul@codesourcery.com>
[binutils-gdb.git] / gas / symbols.c
index 8e3d492c71bafea13414622f4f4ff4a1521c2961..41fabc5df0a5987aee1fadbcf2a35fc8c3fec055 100644 (file)
@@ -1,6 +1,6 @@
 /* symbols.c -symbol table-
    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -144,8 +144,7 @@ symbol_create (const char *name, /* It is copied, the caller can destroy/modify.
 
   symbolP->bsym = bfd_make_empty_symbol (stdoutput);
   if (symbolP->bsym == NULL)
-    as_perror ("%s", "bfd_make_empty_symbol");
-  symbolP->bsym->udata.p = (PTR) symbolP;
+    as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
   S_SET_NAME (symbolP, preserved_copy_of_name);
 
   S_SET_SEGMENT (symbolP, segment);
@@ -336,10 +335,7 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
               || S_IS_COMMON (symbolP)
               || S_IS_VOLATILE (symbolP))
        {
-         if (S_IS_VOLATILE (symbolP)
-             /* This could be avoided when the symbol wasn't used so far, but
-                the comment in struc-symbol.h says this flag isn't reliable.  */
-             && (1 || !symbol_used_p (symbolP)))
+         if (S_IS_VOLATILE (symbolP))
            {
              symbolP = symbol_clone (symbolP, 1);
              S_SET_VALUE (symbolP, 0);
@@ -573,12 +569,11 @@ symbol_clone (symbolS *orgsymP, int replace)
   *newsymP = *orgsymP;
   bsymnew = bfd_make_empty_symbol (bfd_asymbol_bfd (bsymorg));
   if (bsymnew == NULL)
-    as_perror ("%s", "bfd_make_empty_symbol");
+    as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
   newsymP->bsym = bsymnew;
   bsymnew->name = bsymorg->name;
   bsymnew->flags =  bsymorg->flags;
   bsymnew->section =  bsymorg->section;
-  bsymnew->udata.p = (PTR) newsymP;
   bfd_copy_private_symbol_data (bfd_asymbol_bfd (bsymorg), bsymorg,
                                bfd_asymbol_bfd (bsymnew), bsymnew);
 
@@ -603,11 +598,13 @@ symbol_clone (symbolS *orgsymP, int replace)
        symbol_lastP = newsymP;
       else if (orgsymP->sy_next)
        orgsymP->sy_next->sy_previous = newsymP;
-      orgsymP->sy_next = NULL;
+      orgsymP->sy_previous = orgsymP->sy_next = orgsymP;
       debug_verify_symchain (symbol_rootP, symbol_lastP);
 
       symbol_table_insert (newsymP);
     }
+  else
+    newsymP->sy_previous = newsymP->sy_next = newsymP;
 
   return newsymP;
 }
@@ -928,13 +925,11 @@ report_op_error (symbolS *symp, symbolS *left, symbolS *right)
          && seg_right != undefined_section)
        {
          if (right)
-           as_bad_where (file, line,
-                         _("invalid sections for operation on `%s' and `%s' setting `%s'"),
-                         S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
+           as_bad (_("invalid sections for operation on `%s' and `%s' setting `%s'"),
+                   S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
          else
-           as_bad_where (file, line,
-                         _("invalid section for operation on `%s' setting `%s'"),
-                         S_GET_NAME (left), S_GET_NAME (symp));
+           as_bad (_("invalid section for operation on `%s' setting `%s'"),
+                   S_GET_NAME (left), S_GET_NAME (symp));
        }
     }
 }
@@ -1085,8 +1080,9 @@ resolve_symbol_value (symbolS *symp)
              symp->sy_resolving = 0;
              goto exit_dont_set_value;
            }
-         else if (finalize_syms && final_seg == expr_section
-                  && seg_left != expr_section)
+         else if (finalize_syms
+                  && ((final_seg == expr_section && seg_left != expr_section)
+                      || symbol_shadow_p (symp)))
            {
              /* If the symbol is an expression symbol, do similarly
                 as for undefined and common syms above.  Handles
@@ -1355,8 +1351,10 @@ resolve_local_symbol_values (void)
    sub-expressions used.  */
 
 int
-snapshot_symbol (symbolS *symbolP, valueT *valueP, segT *segP, fragS **fragPP)
+snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
 {
+  symbolS *symbolP = *symbolPP;
+
   if (LOCAL_SYMBOL_CHECK (symbolP))
     {
       struct local_symbol *locsym = (struct local_symbol *) symbolP;
@@ -1385,10 +1383,7 @@ snapshot_symbol (symbolS *symbolP, valueT *valueP, segT *segP, fragS **fragPP)
            {
            case O_constant:
            case O_register:
-             /* This check wouldn't be needed if pseudo_set() didn't set
-                symbols equated to bare symbols to undefined_section.  */
-             if (symbolP->bsym->section != undefined_section
-                 || symbolP->sy_value.X_op != O_symbol)
+             if (!symbol_equated_p (symbolP))
                break;
              /* Fall thru.  */
            case O_symbol:
@@ -1400,6 +1395,10 @@ snapshot_symbol (symbolS *symbolP, valueT *valueP, segT *segP, fragS **fragPP)
            }
        }
 
+      /* Never change a defined symbol.  */
+      if (symbolP->bsym->section == undefined_section
+         || symbolP->bsym->section == expr_section)
+       *symbolPP = symbolP;
       *valueP = expr.X_add_number;
       *segP = symbolP->bsym->section;
       *fragPP = symbolP->sy_frag;
@@ -2496,6 +2495,17 @@ symbol_constant_p (symbolS *s)
   return s->sy_value.X_op == O_constant;
 }
 
+/* Return whether a symbol was cloned and thus removed from the global
+   symbol list.  */
+
+int
+symbol_shadow_p (symbolS *s)
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return s->sy_next == s;
+}
+
 /* Return the BFD symbol for a symbol.  */
 
 asymbol *