]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 30308 again
authorAlan Modra <amodra@gmail.com>
Tue, 12 May 2026 00:27:16 +0000 (09:57 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 20 May 2026 09:16:14 +0000 (18:46 +0930)
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.

gas/config/tc-i386-intel.c
gas/config/tc-i386.c

index 09248e8f8f90c52f62293f59772857bc496c7f00..77b61d426bc9ca18587c1133d4249001bf3cca30 100644 (file)
@@ -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 ();
index d3287513a7581d99a98dbef5fadd759667ceceec..988b024f0b883399697f163f08c5951ae8b9788d 100644 (file)
@@ -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