*** empty log message ***
[deliverable/binutils-gdb.git] / gas / symbols.c
index 6d8147ce84ab48a13d189513b64bb288d73486f9..7362afbbaf4c347faa7cded247a940d91322b77a 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
+   1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -66,6 +66,7 @@ static long dollar_label_instance PARAMS ((long));
 static long fb_label_instance PARAMS ((long));
 
 static void print_binary PARAMS ((FILE *, const char *, expressionS *));
+static void report_op_error PARAMS ((symbolS *, symbolS *, symbolS *));
 
 /* Return a pointer to a new symbol.  Die if we can't make a new
    symbol.  Fill in the symbol's values.  Add symbol to end of symbol
@@ -181,8 +182,6 @@ symbol_create (name, segment, valu, frag)
 /* Local symbol support.  If we can get away with it, we keep only a
    small amount of information for local symbols.  */
 
-static struct local_symbol *local_symbol_make PARAMS ((const char *, segT,
-                                                      valueT, fragS *));
 static symbolS *local_symbol_convert PARAMS ((struct local_symbol *));
 
 /* Used for statistics.  */
@@ -204,7 +203,7 @@ static unsigned long local_symbol_conversion_count;
 
 /* Create a local symbol and insert it into the local hash table.  */
 
-static struct local_symbol *
+struct local_symbol *
 local_symbol_make (name, section, value, frag)
      const char *name;
      segT section;
@@ -313,6 +312,13 @@ colon (sym_name)           /* Just seen "x:" - rattle symbols & frags.  */
 
       extern const int md_short_jump_size;
       extern const int md_long_jump_size;
+
+      if (now_seg == absolute_section)
+       {
+         as_bad (_("cannot define symbol `%s' in absolute section"), sym_name);
+         return NULL;
+       }
+
       possible_bytes = (md_short_jump_size
                        + new_broken_words * md_long_jump_size);
 
@@ -483,7 +489,7 @@ colon (sym_name)            /* Just seen "x:" - rattle symbols & frags.  */
   if (mri_common_symbol != NULL)
     {
       /* This symbol is actually being defined within an MRI common
-         section.  This requires special handling.  */
+        section.  This requires special handling.  */
       if (LOCAL_SYMBOL_CHECK (symbolP))
        symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
       symbolP->sy_value.X_op = O_symbol;
@@ -582,6 +588,27 @@ symbol_make (name)
   return (symbolP);
 }
 
+symbolS *
+symbol_temp_new (seg, ofs, frag)
+     segT seg;
+     valueT ofs;
+     fragS *frag;
+{
+  return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag);
+}
+
+symbolS *
+symbol_temp_new_now ()
+{
+  return symbol_temp_new (now_seg, frag_now_fix (), frag_now);
+}
+
+symbolS *
+symbol_temp_make ()
+{
+  return symbol_make (FAKE_LABEL_NAME);
+}
+
 /* Implement symbol table lookup.
    In: A symbol's name as a string: '\0' can't be part of a symbol name.
    Out:        NULL if the name was not in the symbol table, else the address
@@ -830,6 +857,63 @@ verify_symbol_chain_2 (sym)
   verify_symbol_chain (p, n);
 }
 
+static void
+report_op_error (symp, left, right)
+     symbolS *symp;
+     symbolS *left, *right;
+{
+  char *file;
+  unsigned int line;
+  segT seg_left = S_GET_SEGMENT (left);
+  segT seg_right = right ? S_GET_SEGMENT (right) : 0;
+
+  if (expr_symbol_where (symp, &file, &line))
+    {
+      if (seg_left == undefined_section)
+       as_bad_where (file, line,
+                     _("undefined symbol `%s' in operation"),
+                     S_GET_NAME (left));
+      if (seg_right == undefined_section)
+       as_bad_where (file, line,
+                     _("undefined symbol `%s' in operation"),
+                     S_GET_NAME (right));
+      if (seg_left != undefined_section
+         && seg_right != undefined_section)
+       {
+         if (right)
+           as_bad_where (file, line,
+                         _("invalid sections for operation on `%s' and `%s'"),
+                         S_GET_NAME (left), S_GET_NAME (right));
+         else
+           as_bad_where (file, line,
+                         _("invalid section for operation on `%s'"),
+                         S_GET_NAME (left));
+       }
+
+    }
+  else
+    {
+      if (seg_left == undefined_section)
+       as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+               S_GET_NAME (left), S_GET_NAME (symp));
+      if (seg_right == undefined_section)
+       as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+               S_GET_NAME (right), S_GET_NAME (symp));
+      if (seg_left != undefined_section
+         && 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));
+         else
+           as_bad_where (file, line,
+                         _("invalid section for operation on `%s' setting `%s'"),
+                         S_GET_NAME (left), S_GET_NAME (symp));
+       }
+    }
+}
+
 /* Resolve the value of a symbol.  This is called during the final
    pass over the symbol table to resolve any symbols with complex
    values.  */
@@ -995,6 +1079,17 @@ resolve_symbol_value (symp)
          left = resolve_symbol_value (add_symbol);
          seg_left = S_GET_SEGMENT (add_symbol);
 
+         /* By reducing these to the relevant dyadic operator, we get
+               !S -> S == 0    permitted on anything,
+               -S -> 0 - S     only permitted on absolute
+               ~S -> S ^ ~0    only permitted on absolute  */
+         if (op != O_logical_not && seg_left != absolute_section
+             && finalize_syms)
+           report_op_error (symp, add_symbol, NULL);
+
+         if (final_seg == expr_section || final_seg == undefined_section)
+           final_seg = absolute_section;
+
          if (op == O_uminus)
            left = -left;
          else if (op == O_logical_not)
@@ -1003,8 +1098,6 @@ resolve_symbol_value (symp)
            left = ~left;
 
          final_val += left + symp->sy_frag->fr_address;
-         if (final_seg == expr_section || final_seg == undefined_section)
-           final_seg = seg_left;
 
          resolved = symbol_resolved_p (add_symbol);
          break;
@@ -1070,57 +1163,19 @@ resolve_symbol_value (symp)
 
             Don't emit messages unless we're finalizing the symbol value,
             otherwise we may get the same message multiple times.  */
-         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;
+         if (finalize_syms
+             && !(seg_left == absolute_section
+                  && seg_right == absolute_section)
+             && !(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)))
+           report_op_error (symp, add_symbol, op_symbol);
 
-             if (expr_symbol_where (symp, &file, &line))
-               {
-                 if (seg_left == undefined_section)
-                   as_bad_where (file, line,
-                                 _("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"),
-                                 S_GET_NAME (symp->sy_value.X_op_symbol));
-                 if (seg_left != undefined_section
-                     && seg_right != undefined_section)
-                   as_bad_where (file, line,
-                                 _("invalid section for operation"));
-               }
-             else
-               {
-                 if (seg_left == undefined_section)
-                   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'"),
-                           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'"),
-                           S_GET_NAME (symp));
-               }
-             /* Prevent the error propagating.  */
-             if (final_seg == expr_section || final_seg == undefined_section)
-               final_seg = absolute_section;
-           }
+         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)
@@ -1645,8 +1700,8 @@ S_GET_VALUE (s)
       static symbolS *recur;
 
       /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
-         may call S_GET_VALUE.  We use a static symbol to avoid the
-         immediate recursion.  */
+        may call S_GET_VALUE.  We use a static symbol to avoid the
+        immediate recursion.  */
       if (recur == s)
        return (valueT) s->sy_value.X_add_number;
       recur = s;
@@ -1771,15 +1826,17 @@ S_IS_DEFINED (s)
    symbols or eliminated from expressions, because they may be
    overridden by the linker.  */
 int
-S_FORCE_RELOC (s)
+S_FORCE_RELOC (s, strict)
      symbolS *s;
+     int strict;
 {
   if (LOCAL_SYMBOL_CHECK (s))
     return ((struct local_symbol *) s)->lsy_section == undefined_section;
 
-  return ((s->bsym->flags & BSF_WEAK) != 0
-         || (EXTERN_FORCE_RELOC
-             && (s->bsym->flags & BSF_GLOBAL) != 0)
+  return ((strict
+          && ((s->bsym->flags & BSF_WEAK) != 0
+              || (EXTERN_FORCE_RELOC
+                  && (s->bsym->flags & BSF_GLOBAL) != 0)))
          || s->bsym->section == undefined_section
          || bfd_is_com_section (s->bsym->section));
 }
@@ -1943,6 +2000,25 @@ S_SET_WEAK (s)
   s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
 }
 
+void
+S_SET_THREAD_LOCAL (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  if (bfd_is_com_section (s->bsym->section)
+      && (s->bsym->flags & BSF_THREAD_LOCAL) != 0)
+    return;
+  s->bsym->flags |= BSF_THREAD_LOCAL;
+  if ((s->bsym->flags & BSF_FUNCTION) != 0)
+    as_bad (_("Accessing function `%s' as thread-local object"),
+           S_GET_NAME (s));
+  else if (! bfd_is_und_section (s->bsym->section)
+          && (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0)
+    as_bad (_("Accessing `%s' as thread-local object"),
+           S_GET_NAME (s));
+}
+
 void
 S_SET_NAME (s, name)
      symbolS *s;
@@ -2006,6 +2082,17 @@ symbol_set_value_expression (s, exp)
   s->sy_value = *exp;
 }
 
+/* Set the value of SYM to the current position in the current segment.  */
+
+void
+symbol_set_value_now (sym)
+     symbolS *sym;
+{
+  S_SET_SEGMENT (sym, now_seg);
+  S_SET_VALUE (sym, frag_now_fix ());
+  symbol_set_frag (sym, frag_now);
+}
+
 /* Set the frag of a symbol.  */
 
 void
This page took 0.02713 seconds and 4 git commands to generate.