This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR gas/827


http://sources.redhat.com/bugzilla/show_bug.cgi?id=827 shows a couple of
interesting failures with assignment of simple expressions to syms.

Lack of a reloc with
 .set y, 1
 .set y, y+_undef
 .long y
is due to y initially being set to an absolute symbol, then not having
the section changed with the second assignment.  Other parts of gas
treat absolute symbols specially.  Fixed by resetting the symbol section
and frag back to that for a newly created symbol.

I cured the symbol definition loop in
 .set x, _undef
 .set x, x+1
 .long x
by allowing x=x+1 to adjust X_add_number even for undefined symbols.  I
think this should be reasonably safe, but it does allow
 .set undef, undef+1
which has the curious result of an undefined symbol with a non-zero
value.   Hmm, I probably ought to disallow that.

While poking at pseudo_set, I noticed that assignment to section symbols
is only prevented when assigning some other symbol to the section
symbol.  This seemed odd to me, so I modified the code to give an error
on any assignment to section symbols.  Another oddity is special casing
sym1 = sym2 + const for const == 0.  When const != 0, the old code
created an expression symbol, and I can't see the reason for that.  Ian,
do you know why this was done?

	PR gas/827
	* symbols.c (symbol_X_add_number): New function.
	* symbols.h (symbol_X_add_number): Declare.
	* read.c (pseudo_set): Always check for assignment to section syms.
	Handle assignment of sym=sym+/-const specially.  Don't special
	case exp.X_add_number non-zero.  Set segment and frag of expression
	syms as for newly created syms.

Index: gas/symbols.c
===================================================================
RCS file: /cvs/src/src/gas/symbols.c,v
retrieving revision 1.56
diff -u -p -r1.56 symbols.c
--- gas/symbols.c	2 Mar 2005 00:11:30 -0000	1.56
+++ gas/symbols.c	6 Apr 2005 06:00:38 -0000
@@ -2022,6 +2022,19 @@ symbol_set_value_expression (symbolS *s,
   s->sy_value = *exp;
 }
 
+/* Return a pointer to the X_add_number component of a symbol.  */
+
+valueT *
+symbol_X_add_number (symbolS *s)
+{
+#ifdef BFD_ASSEMBLER
+  if (LOCAL_SYMBOL_CHECK (s))
+    return &((struct local_symbol *) s)->lsy_value;
+#endif
+
+  return &s->sy_value.X_add_number;
+}
+
 /* Set the value of SYM to the current position in the current segment.  */
 
 void
Index: gas/symbols.h
===================================================================
RCS file: /cvs/src/src/gas/symbols.h,v
retrieving revision 1.16
diff -u -p -r1.16 symbols.h
--- gas/symbols.h	8 Nov 2004 08:12:44 -0000	1.16
+++ gas/symbols.h	6 Apr 2005 06:00:38 -0000
@@ -1,6 +1,6 @@
 /* symbols.h -
    Copyright 1987, 1990, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
-   2002, 2003, 2004 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -175,6 +175,7 @@ extern symbolS *symbol_next (symbolS *);
 
 extern expressionS *symbol_get_value_expression (symbolS *);
 extern void symbol_set_value_expression (symbolS *, const expressionS *);
+extern valueT *symbol_X_add_number (symbolS *);
 extern void symbol_set_value_now (symbolS *);
 extern void symbol_set_frag (symbolS *, fragS *);
 extern fragS *symbol_get_frag (symbolS *);
Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.94
diff -u -p -r1.94 read.c
--- gas/read.c	1 Mar 2005 02:00:14 -0000	1.94
+++ gas/read.c	6 Apr 2005 07:59:48 -0000
@@ -3188,6 +3188,7 @@ void
 pseudo_set (symbolS *symbolP)
 {
   expressionS exp;
+  segT seg;
 #if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
   int ext;
 #endif /* OBJ_AOUT or OBJ_BOUT */
@@ -3220,6 +3221,12 @@ pseudo_set (symbolS *symbolP)
 			  - S_GET_VALUE (exp.X_op_symbol));
     }
 
+  if (symbol_section_p (symbolP))
+    {
+      as_bad ("attempt to set value of section symbol");
+      return;
+    }
+
   switch (exp.X_op)
     {
     case O_illegal:
@@ -3247,33 +3254,34 @@ pseudo_set (symbolS *symbolP)
       break;
 
     case O_symbol:
-      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
-	  || exp.X_add_number != 0)
-	symbol_set_value_expression (symbolP, &exp);
-      else if (symbol_section_p (symbolP))
-	as_bad ("attempt to set value of section symbol");
-      else
+      if (symbolP == exp.X_add_symbol)
+	{
+	  *symbol_X_add_number (symbolP) += exp.X_add_number;
+	  break;
+	}
+      else if ((seg = S_GET_SEGMENT (exp.X_add_symbol)) != undefined_section)
 	{
 	  symbolS *s = exp.X_add_symbol;
 
-	  S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
+	  S_SET_SEGMENT (symbolP, seg);
 #if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
 	  if (ext)
 	    S_SET_EXTERNAL (symbolP);
 	  else
 	    S_CLEAR_EXTERNAL (symbolP);
 #endif /* OBJ_AOUT or OBJ_BOUT */
-	  S_SET_VALUE (symbolP,
-		       exp.X_add_number + S_GET_VALUE (s));
+	  S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s));
 	  symbol_set_frag (symbolP, symbol_get_frag (s));
 	  copy_symbol_attributes (symbolP, s);
+	  break;
 	}
-      break;
+      /* Fall thru */
 
     default:
-      /* The value is some complex expression.
-	 FIXME: Should we set the segment to anything?  */
+      /* The value is some complex expression.  */
       symbol_set_value_expression (symbolP, &exp);
+      S_SET_SEGMENT (symbolP, undefined_section);
+      symbol_set_frag (symbolP, &zero_address_frag);
       break;
     }
 }

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]