* Preliminary support for m88k-coff.
[binutils-gdb.git] / gas / symbols.c
index e39e50c92f941bf5db972f3c9525305268eb7d3f..535810f1f96f69388987c1d8f46e8079b8bbc487 100644 (file)
@@ -118,7 +118,6 @@ symbol_new (name, segment, value, frag)
   symbol_clear_list_pointers(symbolP);
 
   symbolP->sy_frag = frag;
-  symbolP->sy_forward = NULL;
 #ifndef BFD_ASSEMBLER
   symbolP->sy_number = ~0;
   symbolP->sy_name_offset = ~0;
@@ -566,6 +565,68 @@ verify_symbol_chain_2 (sym)
   verify_symbol_chain (p, n);
 }
 
+/* Resolve the value of a symbol.  This is called during the final
+   pass over the symbol table to resolve any symbols with complex
+   values.  */
+
+void
+resolve_symbol_value (symp)
+     symbolS *symp;
+{
+  if (symp->sy_resolved)
+    return;
+
+  if (symp->sy_resolving)
+    {
+      as_bad ("Symbol definition loop encountered at %s",
+             S_GET_NAME (symp));
+      S_SET_VALUE (symp, (valueT) 0);
+    }
+  else
+    {
+      symp->sy_resolving = 1;
+
+      if (symp->sy_value.X_seg == absolute_section)
+       S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
+      else if (symp->sy_value.X_seg == undefined_section)
+       {
+         resolve_symbol_value (symp->sy_value.X_add_symbol);
+
+#ifdef obj_frob_forward_symbol
+         /* Some object formats need to forward the segment.  */
+         obj_frob_forward_symbol (symp);
+#endif
+
+         S_SET_VALUE (symp,
+                      (symp->sy_value.X_add_number
+                       + symp->sy_frag->fr_address
+                       + S_GET_VALUE (symp->sy_value.X_add_symbol)));
+       }
+      else if (symp->sy_value.X_seg == diff_section)
+       {
+         resolve_symbol_value (symp->sy_value.X_add_symbol);
+         resolve_symbol_value (symp->sy_value.X_subtract_symbol);
+         if (S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+             != S_GET_SEGMENT (symp->sy_value.X_subtract_symbol))
+           as_bad ("%s is difference of symbols in different sections",
+                   S_GET_NAME (symp));
+         S_SET_VALUE (symp,
+                      (symp->sy_value.X_add_number
+                       + symp->sy_frag->fr_address
+                       + S_GET_VALUE (symp->sy_value.X_add_symbol)
+                       - S_GET_VALUE (symp->sy_value.X_subtract_symbol)));
+         S_SET_SEGMENT (symp, absolute_section);
+       }
+      else
+       {
+         /* More cases need to be added here.  */
+         abort ();
+       }
+    }
+
+  symp->sy_resolved = 1;
+}
+
 #ifdef LOCAL_LABELS_DOLLAR
 
 /* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
@@ -946,6 +1007,28 @@ decode_local_label_name (s)
   return (symbol_decode);
 }                              /* decode_local_label_name() */
 
+/* Get the value of a symbol.  */
+
+valueT
+S_GET_VALUE (s)
+     symbolS *s;
+{
+  if (s->sy_value.X_seg != absolute_section)
+    as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
+  return (valueT) s->sy_value.X_add_number;
+}
+
+/* Set the value of a symbol.  */
+
+void
+S_SET_VALUE (s, val)
+     symbolS *s;
+     valueT val;
+{
+  s->sy_value.X_seg = absolute_section;
+  s->sy_value.X_add_number = (offsetT) val;
+}
+
 #ifdef BFD_ASSEMBLER
 
 int
@@ -1016,13 +1099,6 @@ S_IS_STABD (s)
   return S_GET_NAME (s) == 0;
 }
 
-valueT
-S_GET_VALUE (s)
-     symbolS *s;
-{
-  return s->bsym->value;
-}
-
 CONST char *
 S_GET_NAME (s)
      symbolS *s;
@@ -1037,14 +1113,6 @@ S_GET_SEGMENT (s)
   return s->bsym->section;
 }
 
-void
-S_SET_VALUE (s, val)
-     symbolS *s;
-     valueT val;
-{
-  s->bsym->value = val;
-}
-
 void
 S_SET_SEGMENT (s, seg)
      symbolS *s;