daily update
[deliverable/binutils-gdb.git] / gas / symbols.c
index 36407238aaccd0a22391a9876daf409b242c7da1..5a55fcaf9ff38471eb8de1cee671457c95733b9b 100644 (file)
 
 /* #define DEBUG_SYMS / * to debug symbol list maintenance.  */
 
-#include <ctype.h>
-
 #include "as.h"
 
+#include "safe-ctype.h"
 #include "obstack.h"           /* For "symbols.h" */
 #include "subsegs.h"
 
@@ -61,6 +60,7 @@ symbolS abs_symbol;
 
 struct obstack notes;
 
+static char *save_symbol_name PARAMS ((const char *));
 static void fb_label_init PARAMS ((void));
 static long dollar_label_instance PARAMS ((long));
 static long fb_label_instance PARAMS ((long));
@@ -123,11 +123,10 @@ save_symbol_name (name)
 
   if (! symbols_case_sensitive)
     {
-      unsigned char *s;
+      char *s;
 
-      for (s = (unsigned char *) ret; *s != '\0'; s++)
-       if (islower (*s))
-         *s = toupper (*s);
+      for (s = ret; *s != '\0'; s++)
+       *s = TOUPPER (*s);
     }
 
   return ret;
@@ -206,10 +205,10 @@ static unsigned long local_symbol_conversion_count;
 /* Create a local symbol and insert it into the local hash table.  */
 
 static struct local_symbol *
-local_symbol_make (name, section, offset, frag)
+local_symbol_make (name, section, value, frag)
      const char *name;
      segT section;
-     valueT offset;
+     valueT value;
      fragS *frag;
 {
   char *name_copy;
@@ -224,7 +223,7 @@ local_symbol_make (name, section, offset, frag)
   ret->lsy_name = name_copy;
   ret->lsy_section = section;
   local_symbol_set_frag (ret, frag);
-  ret->lsy_offset = offset;
+  ret->lsy_value = value;
 
   hash_jam (local_hash, name_copy, (PTR) ret);
 
@@ -246,7 +245,7 @@ local_symbol_convert (locsym)
 
   ++local_symbol_conversion_count;
 
-  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset,
+  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value,
                    local_symbol_get_frag (locsym));
 
   if (local_symbol_resolved_p (locsym))
@@ -357,15 +356,15 @@ colon (sym_name)          /* Just seen "x:" - rattle symbols & frags.  */
          if (locsym->lsy_section != undefined_section
              && (local_symbol_get_frag (locsym) != frag_now
                  || locsym->lsy_section != now_seg
-                 || locsym->lsy_offset != frag_now_fix ()))
+                 || locsym->lsy_value != frag_now_fix ()))
            {
-             as_bad (_("Symbol %s already defined."), sym_name);
+             as_bad (_("symbol `%s' is already defined"), sym_name);
              return symbolP;
            }
 
          locsym->lsy_section = now_seg;
          local_symbol_set_frag (locsym, frag_now);
-         locsym->lsy_offset = frag_now_fix ();
+         locsym->lsy_value = frag_now_fix ();
 #endif
        }
       else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
@@ -444,7 +443,7 @@ colon (sym_name)            /* Just seen "x:" - rattle symbols & frags.  */
                            S_GET_OTHER (symbolP),
                            S_GET_DESC (symbolP));
 #endif
-                 as_bad (_("Symbol \"%s\" is already defined as \"%s\"/%s%ld."),
+                 as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"),
                            sym_name,
                            segment_name (S_GET_SEGMENT (symbolP)),
                            od_buf,
@@ -458,7 +457,7 @@ colon (sym_name)            /* Just seen "x:" - rattle symbols & frags.  */
          if (!(frag_now == symbolP->sy_frag
                && S_GET_VALUE (symbolP) == frag_now_fix ()
                && S_GET_SEGMENT (symbolP) == now_seg))
-           as_bad (_("Symbol %s already defined."), sym_name);
+           as_bad (_("symbol `%s' is already defined"), sym_name);
        }
 
     }
@@ -521,14 +520,14 @@ symbol_table_insert (symbolP)
       error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
                               (PTR) symbolP);
       if (error_string != NULL)
-       as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
+       as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
                  S_GET_NAME (symbolP), error_string);
       return;
     }
 
   if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
     {
-      as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
+      as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
                S_GET_NAME (symbolP), error_string);
     }                          /* on error  */
 }
@@ -629,9 +628,7 @@ symbol_find_base (name, strip_underscore)
 
       while ((c = *orig++) != '\0')
        {
-         if (islower (c))
-           c = toupper (c);
-         *copy++ = c;
+         *copy++ = TOUPPER (c);
        }
       *copy = '\0';
     }
@@ -843,15 +840,15 @@ resolve_symbol_value (symp)
     {
       struct local_symbol *locsym = (struct local_symbol *) symp;
 
+      final_val = locsym->lsy_value;
       if (local_symbol_resolved_p (locsym))
-       return locsym->lsy_offset / bfd_octets_per_byte (stdoutput);
+       return final_val;
 
-      final_val = (local_symbol_get_frag (locsym)->fr_address
-                  + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput);
+      final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE;
 
       if (finalize_syms)
        {
-         locsym->lsy_offset = final_val;
+         locsym->lsy_value = final_val;
          local_symbol_mark_resolved (locsym);
        }
 
@@ -873,7 +870,7 @@ resolve_symbol_value (symp)
   if (symp->sy_resolving)
     {
       if (finalize_syms)
-       as_bad (_("Symbol definition loop encountered at %s"),
+       as_bad (_("symbol definition loop encountered at `%s'"),
                S_GET_NAME (symp));
       final_val = 0;
       resolved = 1;
@@ -913,13 +910,16 @@ resolve_symbol_value (symp)
        case O_symbol:
        case O_symbol_rva:
          left = resolve_symbol_value (add_symbol);
-       do_symbol:
+         seg_left = S_GET_SEGMENT (add_symbol);
+         if (finalize_syms)
+           symp->sy_value.X_op_symbol = NULL;
 
+       do_symbol:
          if (symp->sy_mri_common)
            {
              /* This is a symbol inside an MRI common section.  The
-                 relocation routines are going to handle it specially.
-                 Don't change the value.  */
+                relocation routines are going to handle it specially.
+                Don't change the value.  */
              resolved = symbol_resolved_p (add_symbol);
              break;
            }
@@ -932,30 +932,51 @@ resolve_symbol_value (symp)
              copy_symbol_attributes (symp, add_symbol);
            }
 
-         /* If we have equated this symbol to an undefined symbol, we
-             keep X_op set to O_symbol, and we don't change
-             X_add_number.  This permits the routine which writes out
-             relocation to detect this case, and convert the
-             relocation to be against the symbol to which this symbol
-             is equated.  */
+         /* If we have equated this symbol to an undefined or common
+            symbol, keep X_op set to O_symbol, and don't change
+            X_add_number.  This permits the routine which writes out
+            relocation to detect this case, and convert the
+            relocation to be against the symbol to which this symbol
+            is equated.  */
          if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
            {
              if (finalize_syms)
                {
-                 S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
                  symp->sy_value.X_op = O_symbol;
                  symp->sy_value.X_add_symbol = add_symbol;
                  symp->sy_value.X_add_number = final_val;
+                 /* Use X_op_symbol as a flag.  */
+                 symp->sy_value.X_op_symbol = add_symbol;
+                 final_seg = seg_left;
                }
              final_val = 0;
              resolved = symbol_resolved_p (add_symbol);
+             symp->sy_resolving = 0;
+             goto exit_dont_set_value;
+           }
+         else if (finalize_syms && final_seg == expr_section
+                  && seg_left != expr_section)
+           {
+             /* If the symbol is an expression symbol, do similarly
+                as for undefined and common syms above.  Handles
+                "sym +/- expr" where "expr" cannot be evaluated
+                immediately, and we want relocations to be against
+                "sym", eg. because it is weak.  */
+             symp->sy_value.X_op = O_symbol;
+             symp->sy_value.X_add_symbol = add_symbol;
+             symp->sy_value.X_add_number = final_val;
+             symp->sy_value.X_op_symbol = add_symbol;
+             final_seg = seg_left;
+             final_val += symp->sy_frag->fr_address + left;
+             resolved = symbol_resolved_p (add_symbol);
+             symp->sy_resolving = 0;
              goto exit_dont_set_value;
            }
          else
            {
              final_val += symp->sy_frag->fr_address + left;
              if (final_seg == expr_section || final_seg == undefined_section)
-               final_seg = S_GET_SEGMENT (add_symbol);
+               final_seg = seg_left;
            }
 
          resolved = symbol_resolved_p (add_symbol);
@@ -965,6 +986,7 @@ resolve_symbol_value (symp)
        case O_bit_not:
        case O_logical_not:
          left = resolve_symbol_value (add_symbol);
+         seg_left = S_GET_SEGMENT (add_symbol);
 
          if (op == O_uminus)
            left = -left;
@@ -975,7 +997,7 @@ resolve_symbol_value (symp)
 
          final_val += left + symp->sy_frag->fr_address;
          if (final_seg == expr_section || final_seg == undefined_section)
-           final_seg = absolute_section;
+           final_seg = seg_left;
 
          resolved = symbol_resolved_p (add_symbol);
          break;
@@ -1006,43 +1028,54 @@ resolve_symbol_value (symp)
 
          /* Simplify addition or subtraction of a constant by folding the
             constant into X_add_number.  */
-         if (op == O_add || op == O_subtract)
+         if (op == O_add)
            {
              if (seg_right == absolute_section)
                {
-                 if (op == O_add)
-                   final_val += right;
-                 else
-                   final_val -= right;
-                 op = O_symbol;
-                 op_symbol = NULL;
+                 final_val += right;
                  goto do_symbol;
                }
-             else if (seg_left == absolute_section && op == O_add)
+             else if (seg_left == absolute_section)
                {
-                 op = O_symbol;
                  final_val += left;
                  add_symbol = op_symbol;
                  left = right;
-                 op_symbol = NULL;
+                 seg_left = seg_right;
                  goto do_symbol;
                }
            }
+         else if (op == O_subtract)
+           {
+             if (seg_right == absolute_section)
+               {
+                 final_val -= right;
+                 goto do_symbol;
+               }
+           }
+
+         /* Equality and non-equality tests are permitted on anything.
+            Subtraction, and other comparison operators are permitted if
+            both operands are in the same section.  Otherwise, both
+            operands must be absolute.  We already handled the case of
+            addition or subtraction of a constant above.  This will
+            probably need to be changed for an object file format which
+            supports arbitrary expressions, such as IEEE-695.
 
-         /* Subtraction is permitted if both operands are in the same
-            section.  Otherwise, both operands must be absolute.  We
-            already handled the case of addition or subtraction of a
-            constant above.  This will probably need to be changed
-            for an object file format which supports arbitrary
-            expressions, such as IEEE-695.  */
-         /* Don't emit messages unless we're finalizing the symbol value,
+            Don't emit messages unless we're finalizing the symbol value,
             otherwise we may get the same message multiple times.  */
-         if ((seg_left != absolute_section
-              || seg_right != absolute_section)
-             && (op != O_subtract
-                 || seg_left != seg_right
-                 || seg_left == undefined_section)
-             && finalize_syms)
+         if ((op == O_eq || op == O_ne)
+             || ((op == O_subtract
+                  || op == O_lt || op == O_le || op == O_ge || op == O_gt)
+                 && seg_left == seg_right
+                 && (seg_left != undefined_section
+                     || add_symbol == op_symbol))
+             || (seg_left == absolute_section
+                 && seg_right == absolute_section))
+           {
+             if (final_seg == expr_section || final_seg == undefined_section)
+               final_seg = absolute_section;
+           }
+         else if (finalize_syms)
            {
              char *file;
              unsigned int line;
@@ -1051,11 +1084,11 @@ resolve_symbol_value (symp)
                {
                  if (seg_left == undefined_section)
                    as_bad_where (file, line,
-                                 _("undefined symbol %s in operation"),
+                                 _("undefined symbol `%s' in operation"),
                                  S_GET_NAME (symp->sy_value.X_add_symbol));
                  if (seg_right == undefined_section)
                    as_bad_where (file, line,
-                                 _("undefined symbol %s in operation"),
+                                 _("undefined symbol `%s' in operation"),
                                  S_GET_NAME (symp->sy_value.X_op_symbol));
                  if (seg_left != undefined_section
                      && seg_right != undefined_section)
@@ -1065,25 +1098,28 @@ resolve_symbol_value (symp)
              else
                {
                  if (seg_left == undefined_section)
-                   as_bad (_("undefined symbol %s in operation setting %s"),
+                   as_bad (_("undefined symbol `%s' in operation setting `%s'"),
                            S_GET_NAME (symp->sy_value.X_add_symbol),
                            S_GET_NAME (symp));
                  if (seg_right == undefined_section)
-                   as_bad (_("undefined symbol %s in operation setting %s"),
+                   as_bad (_("undefined symbol `%s' in operation setting `%s'"),
                            S_GET_NAME (symp->sy_value.X_op_symbol),
                            S_GET_NAME (symp));
                  if (seg_left != undefined_section
                      && seg_right != undefined_section)
-                   as_bad (_("invalid section for operation setting %s"),
+                   as_bad (_("invalid section for operation setting `%s'"),
                            S_GET_NAME (symp));
                }
+             /* Prevent the error propagating.  */
+             if (final_seg == expr_section || final_seg == undefined_section)
+               final_seg = absolute_section;
            }
 
          /* Check for division by zero.  */
          if ((op == O_divide || op == O_modulus) && right == 0)
            {
              /* If seg_right is not absolute_section, then we've
-                 already issued a warning about using a bad symbol.  */
+                already issued a warning about using a bad symbol.  */
              if (seg_right == absolute_section && finalize_syms)
                {
                  char *file;
@@ -1092,7 +1128,7 @@ resolve_symbol_value (symp)
                  if (expr_symbol_where (symp, &file, &line))
                    as_bad_where (file, line, _("division by zero"));
                  else
-                   as_bad (_("division by zero when setting %s"),
+                   as_bad (_("division by zero when setting `%s'"),
                            S_GET_NAME (symp));
                }
 
@@ -1112,8 +1148,15 @@ resolve_symbol_value (symp)
            case O_bit_and:             left &= right; break;
            case O_add:                 left += right; break;
            case O_subtract:            left -= right; break;
-           case O_eq:  left = left == right ? ~ (offsetT) 0 : 0; break;
-           case O_ne:  left = left != right ? ~ (offsetT) 0 : 0; break;
+           case O_eq:
+           case O_ne:
+             left = (left == right && seg_left == seg_right
+                     && (seg_left != undefined_section
+                         || add_symbol == op_symbol)
+                     ? ~ (offsetT) 0 : 0);
+             if (symp->sy_value.X_op == O_ne)
+               left = ~left;
+             break;
            case O_lt:  left = left <  right ? ~ (offsetT) 0 : 0; break;
            case O_le:  left = left <= right ? ~ (offsetT) 0 : 0; break;
            case O_ge:  left = left >= right ? ~ (offsetT) 0 : 0; break;
@@ -1125,7 +1168,15 @@ resolve_symbol_value (symp)
 
          final_val += symp->sy_frag->fr_address + left;
          if (final_seg == expr_section || final_seg == undefined_section)
-           final_seg = absolute_section;
+           {
+             if (seg_left == undefined_section
+                 || seg_right == undefined_section)
+               final_seg = undefined_section;
+             else if (seg_left == absolute_section)
+               final_seg = seg_right;
+             else
+               final_seg = seg_left;
+           }
          resolved = (symbol_resolved_p (add_symbol)
                      && symbol_resolved_p (op_symbol));
          break;
@@ -1145,18 +1196,18 @@ resolve_symbol_value (symp)
     }
 
   if (finalize_syms)
-    {
-      S_SET_VALUE (symp, final_val);
+    S_SET_VALUE (symp, final_val);
 
+exit_dont_set_value:
+  /* Always set the segment, even if not finalizing the value.
+     The segment is used to determine whether a symbol is defined.  */
 #if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
-      /* The old a.out backend does not handle S_SET_SEGMENT correctly
-         for a stab symbol, so we use this bad hack.  */
-      if (final_seg != S_GET_SEGMENT (symp))
+  /* The old a.out backend does not handle S_SET_SEGMENT correctly
+     for a stab symbol, so we use this bad hack.  */
+  if (final_seg != S_GET_SEGMENT (symp))
 #endif
-       S_SET_SEGMENT (symp, final_seg);
-    }
+    S_SET_SEGMENT (symp, final_seg);
 
-exit_dont_set_value:
   /* Don't worry if we can't resolve an expr_section symbol.  */
   if (finalize_syms)
     {
@@ -1164,7 +1215,7 @@ exit_dont_set_value:
        symp->sy_resolved = 1;
       else if (S_GET_SEGMENT (symp) != expr_section)
        {
-         as_bad (_("can't resolve value for symbol \"%s\""),
+         as_bad (_("can't resolve value for symbol `%s'"),
                  S_GET_NAME (symp));
          symp->sy_resolved = 1;
        }
@@ -1545,7 +1596,7 @@ decode_local_label_name (s)
   if (s[index] != 'L')
     return s;
 
-  for (label_number = 0, p = s + index + 1; isdigit ((unsigned char) *p); ++p)
+  for (label_number = 0, p = s + index + 1; ISDIGIT (*p); ++p)
     label_number = (10 * label_number) + *p - '0';
 
   if (*p == DOLLAR_LABEL_CHAR)
@@ -1555,7 +1606,7 @@ decode_local_label_name (s)
   else
     return s;
 
-  for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
+  for (instance_number = 0, p++; ISDIGIT (*p); ++p)
     instance_number = (10 * instance_number) + *p - '0';
 
   message_format = _("\"%d\" (instance number %d of a %s label)");
@@ -1573,10 +1624,10 @@ S_GET_VALUE (s)
 {
 #ifdef BFD_ASSEMBLER
   if (LOCAL_SYMBOL_CHECK (s))
-    return ((struct local_symbol *) s)->lsy_offset;
+    return resolve_symbol_value (s);
 #endif
 
-  if (!s->sy_resolved && s->sy_value.X_op != O_constant)
+  if (!s->sy_resolved)
     {
       valueT val = resolve_symbol_value (s);
       if (!finalize_syms)
@@ -1595,7 +1646,7 @@ S_GET_VALUE (s)
       if (! s->sy_resolved
          || s->sy_value.X_op != O_symbol
          || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
-       as_bad (_("Attempt to get value of unresolved symbol %s"),
+       as_bad (_("attempt to get value of unresolved symbol `%s'"),
                S_GET_NAME (s));
       recur = NULL;
     }
@@ -1612,7 +1663,7 @@ S_SET_VALUE (s, val)
 #ifdef BFD_ASSEMBLER
   if (LOCAL_SYMBOL_CHECK (s))
     {
-      ((struct local_symbol *) s)->lsy_offset = val;
+      ((struct local_symbol *) s)->lsy_value = val;
       return;
     }
 #endif
@@ -1823,6 +1874,17 @@ S_SET_EXTERNAL (s)
       /* Let .weak override .global.  */
       return;
     }
+  if (s->bsym->flags & BSF_SECTION_SYM)
+    {
+      char * file;
+      unsigned int line;
+      
+      /* Do not reassign section symbols.  */
+      as_where (& file, & line);
+      as_warn_where (file, line,
+                    _("section symbols are already global"));
+      return;
+    }
   s->bsym->flags |= BSF_GLOBAL;
   s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
 }
@@ -2133,6 +2195,24 @@ symbol_equated_p (s)
   return s->sy_value.X_op == O_symbol;
 }
 
+/* Return whether a symbol is equated to another symbol, and should be
+   treated specially when writing out relocs.  */
+
+int
+symbol_equated_reloc_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  /* X_op_symbol, normally not used for O_symbol, is set by
+     resolve_symbol_value to flag expression syms that have been
+     equated.  */
+  return (s->sy_value.X_op == O_symbol
+         && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
+             || ! S_IS_DEFINED (s)
+             || S_IS_COMMON (s)));
+}
+
 /* Return whether a symbol has a constant value.  */
 
 int
@@ -2329,7 +2409,7 @@ print_symbol_value_1 (file, sym)
 #ifdef BFD_ASSEMBLER
       if (LOCAL_SYMBOL_CHECK (sym))
        fprintf (file, "constant %lx",
-                (long) ((struct local_symbol *) sym)->lsy_offset);
+                (long) ((struct local_symbol *) sym)->lsy_value);
       else
 #endif
        print_expr_1 (file, &sym->sy_value);
This page took 0.041343 seconds and 4 git commands to generate.