[binutils-gdb] PR 30308 again

Alan Modra via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cc28c46227cd483c22690ff7be003e48b5283573

commit cc28c46227cd483c22690ff7be003e48b5283573
Author: Alan Modra <[email protected]>
Date:   Tue May 12 09:57:16 2026 +0930

    PR 30308 again
    
    Commit 22f8905d9f38 reintroduced pr30308.  This fix resolves equates
    safely in the presence of symbol loops by using symbol_equated_to.
    Symbols aren't prematurely modified, by copying their value
    expressions before i386_intel_simplify does its work.  I figure that
    it is safer to do this for all symbols rather than just the particular
    case of equates, so the in_equate parameter can disappear.

Diff:
---
 gas/config/tc-i386-intel.c | 86 +++++++++++++++++++++-------------------------
 gas/config/tc-i386.c       |  4 +--
 2 files changed, 41 insertions(+), 49 deletions(-)

diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index 09248e8f8f9..77b61d426bc 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -381,49 +381,41 @@ i386_intel_simplify_register (expressionS *e)
 }
 
 static symbolS *
-i386_intel_simplify_symbol (symbolS *sym, bool in_equate)
+i386_intel_simplify_symbol (symbolS *sym)
 {
-  if (symbol_resolving_p (sym))
-    return sym;
+  symbolS *orig = sym;
+  offsetT off;
+  sym = symbol_equated_to (sym, &off);
+  if (sym == NULL || off != 0)
+    return orig;
 
   segT seg = S_GET_SEGMENT (sym);
-  if (seg != expr_section && seg != reg_section && !symbol_equated_p(sym))
+  if (seg == undefined_section
+      || (seg != expr_section && seg != reg_section && sym == orig))
     return sym;
 
-  for (;;)
-    {
-      /* While we're after equates, symbol_equated_p() isn't suitable here.  */
-      if (symbol_on_chain(sym, symbol_rootP, symbol_lastP))
-	{
-	  in_equate = true;
-	  sym = symbol_clone (sym, 0);
-	}
-      else if (in_equate)
-	{
-	  expressionS *e = symbol_get_value_expression (sym);
-
-	  if (e->X_op == O_symbol && !e->X_add_number)
-	    {
-	      sym = e->X_add_symbol;
-	      continue;
-	    }
-	  sym = make_expr_symbol (e);
-	}
-
-      break;
-    }
-
-  symbol_mark_resolving (sym);
-  int ret = i386_intel_simplify (symbol_get_value_expression (sym), in_equate);
-  if (ret == 2)
-    S_SET_SEGMENT (sym, absolute_section);
-  symbol_clear_resolving (sym);
-
-  return ret ? sym : NULL;
+  /* i386_intel_simplify modifies its arg.  We don't want to make
+     premature changes to symbols here, particularly for a symbol
+     equate.  Changing a symbol may affect future uses of that
+     symbol.  So copy the symbol value and make a new symbol after
+     i386_intel_simplify has done its work.  Don't use structure
+     assignment to copy the value as that doesn't guarantee writing
+     any padding bytes, and we want to use memcmp below rather than
+     comparing every field.  */
+  expressionS *e = symbol_get_value_expression (sym);
+  expressionS exp;
+  memcpy (&exp, e, sizeof exp);
+  int ret = i386_intel_simplify (&exp);
+  if (ret == 0)
+    return NULL;
+
+  if (memcmp (&exp, e, sizeof exp) != 0)
+    sym = make_expr_symbol (&exp);
+  return sym;
 }
 
 static int
-i386_intel_simplify (expressionS *e, bool in_equate)
+i386_intel_simplify (expressionS *e)
 {
   const reg_entry *the_reg = (this_operand >= 0
 			      ? i.op[this_operand].regs : NULL);
@@ -440,7 +432,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
     case O_index:
       if (e->X_add_symbol)
 	{
-	  newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_add_symbol);
 	  if (!newsym
 	      || !i386_intel_check(the_reg, intel_state.base,
 				   intel_state.index))
@@ -449,7 +441,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	}
       if (!intel_state.in_offset)
 	++intel_state.in_bracket;
-      newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+      newsym = i386_intel_simplify_symbol (e->X_op_symbol);
       if (!intel_state.in_offset)
 	--intel_state.in_bracket;
       if (!newsym)
@@ -476,7 +468,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
     case O_offset:
       intel_state.has_offset = 1;
       ++intel_state.in_offset;
-      newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+      newsym = i386_intel_simplify_symbol (e->X_add_symbol);
       --intel_state.in_offset;
       if (!newsym || !i386_intel_check(the_reg, base, state_index))
 	return 0;
@@ -505,7 +497,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	  as_bad (_("invalid use of register"));
 	  return 0;
 	}
-      newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+      newsym = i386_intel_simplify_symbol (e->X_add_symbol);
       if (!newsym)
 	return 0;
       e->X_add_symbol = newsym;
@@ -519,7 +511,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	  as_bad (_("invalid use of register"));
 	  return 0;
 	}
-      newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+      newsym = i386_intel_simplify_symbol (e->X_op_symbol);
       if (!newsym
 	  || !i386_intel_check(the_reg, intel_state.base,
 			       intel_state.index))
@@ -548,7 +540,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	  expressionS *left = NULL, *right = NULL;
 	  segT leftseg = NULL, rightseg = NULL;
 
-	  newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_add_symbol);
 	  if (newsym)
 	    {
 	      e->X_add_symbol = newsym;
@@ -563,7 +555,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 		}
 	    }
 
-	  newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_op_symbol);
 	  if (newsym)
 	    {
 	      e->X_op_symbol = newsym;
@@ -609,7 +601,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	  if (!intel_state.in_scale++)
 	    intel_state.scale_factor = 1;
 
-	  newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_add_symbol);
 	  if (newsym)
 	    {
 	      e->X_add_symbol = newsym;
@@ -620,7 +612,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 		  other = symbol_get_value_expression (e->X_add_symbol);
 		}
 
-	      newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+	      newsym = i386_intel_simplify_symbol (e->X_op_symbol);
 	    }
 
 	  if (newsym)
@@ -705,7 +697,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
     fallthrough:
       if (e->X_add_symbol)
 	{
-	  newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_add_symbol);
 	  if (!newsym)
 	    return 0;
 	  e->X_add_symbol = newsym;
@@ -722,7 +714,7 @@ i386_intel_simplify (expressionS *e, bool in_equate)
 	return 0;
       if (e->X_op_symbol)
 	{
-	  newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+	  newsym = i386_intel_simplify_symbol (e->X_op_symbol);
 	  if (!newsym)
 	    return 0;
 	  e->X_op_symbol = newsym;
@@ -798,7 +790,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
   expr_mode = expr_operator_none;
   memset (&exp, 0, sizeof(exp));
   exp_seg = expression (&exp);
-  ret = i386_intel_simplify (&exp, false);
+  ret = i386_intel_simplify (&exp);
   intel_syntax = 1;
 
   SKIP_WHITESPACE ();
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index d3287513a75..988b024f0b8 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -167,7 +167,7 @@ static int i386_finalize_displacement (segT, expressionS *, i386_operand_type,
 				       const char *);
 static int i386_att_operand (char *);
 static int i386_intel_operand (char *, int);
-static int i386_intel_simplify (expressionS *, bool);
+static int i386_intel_simplify (expressionS *);
 static int i386_intel_parse_name (const char *, expressionS *, enum expr_mode);
 static const reg_entry *parse_register (const char *, char **);
 static const char *parse_insn (const char *, char *, enum parse_mode);
@@ -13527,7 +13527,7 @@ x86_cons (expressionS *exp, int size)
   intel_syntax = -intel_syntax;
 
   if (intel_syntax)
-    i386_intel_simplify (exp, false);
+    i386_intel_simplify (exp);
 
   /* If not 64bit, massage value, to account for wraparound when !BFD64.  */
   if (size <= 4 && expr_mode == expr_operator_present
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.