]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 34036 looping in symbol_equated_p chains
authorAlan Modra <amodra@gmail.com>
Fri, 3 Apr 2026 22:17:04 +0000 (08:47 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 3 Apr 2026 22:22:57 +0000 (08:52 +1030)
This patch adds a new function for safely traversing a chain of equated
symbols to find the defining symbol.

PR 34036
* symbols.c (symbol_equated_to): New function.
* symbols.h (symbol_equated_to): Declare.
* expr.c (resolve_register): Use symbol_equated_to.
* config/tc-i386.c (parse_register): Likewise.
* config/tc-v850.c (reg_name_search): Likewise.

gas/config/tc-i386.c
gas/config/tc-v850.c
gas/expr.c
gas/symbols.c
gas/symbols.h

index edc44a37345af48ace57e4944c8f2e0d4de5b0a2..8d517146cfa5fd3331f5aeaac01a370239d673d5 100644 (file)
@@ -17062,19 +17062,13 @@ parse_register (const char *reg_string, char **end_op)
       char *save = input_line_pointer;
       char *buf = xstrdup (reg_string), *name;
       symbolS *symbolP;
+      offsetT off;
 
       input_line_pointer = buf;
       get_symbol_name (&name);
       symbolP = symbol_find (name);
-      while (symbolP && symbol_equated_p (symbolP))
-       {
-         const expressionS *e = symbol_get_value_expression(symbolP);
-
-         if (e->X_add_number)
-           break;
-         symbolP = e->X_add_symbol;
-       }
-      if (symbolP && S_GET_SEGMENT (symbolP) == reg_section)
+      symbolP = symbol_equated_to (symbolP, &off);
+      if (symbolP && off == 0 && S_GET_SEGMENT (symbolP) == reg_section)
        {
          const expressionS *e = symbol_get_value_expression (symbolP);
 
index 75df8a1ecd1fc03407e03c5ef9753c45627a2d53..4373bd3cd2a24c12d287eb34b057fc4d00a21b12 100644 (file)
@@ -943,8 +943,13 @@ reg_name_search (const struct reg_name *regs,
       /* If the symbol is an alias for another name then use that.
         If the symbol is an alias for a number, then return the number.  */
       if (symbol_equated_p (symbolP))
-       name
-         = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol);
+       {
+         offsetT off;
+         symbolP = symbol_equated_to (symbolP, &off);
+         if (symbolP == NULL || off != 0)
+           return -1;
+         name = S_GET_NAME (symbolP);
+       }
       else if (accept_numbers)
        {
          int reg = S_GET_VALUE (symbolP);
index 5b6828d391a7df2b2fab288a5173d3bdf2db3cca..7108d7332c4e178c387da0f7119f8480410d94bc 100644 (file)
@@ -2473,22 +2473,19 @@ resolve_expression (expressionS *expressionP)
 void resolve_register (expressionS *expP)
 {
   symbolS *sym;
-  offsetT acc = 0;
-  const expressionS *e = expP;
+  offsetT acc;
+  const expressionS *e;
 
   if (expP->X_op != O_symbol)
     return;
 
-  do
-    {
-      if (!md_register_arithmetic && e->X_add_number)
-       break;
-      sym = e->X_add_symbol;
-      acc += e->X_add_number;
-      e = symbol_get_value_expression (sym);
-    }
-  while (symbol_equated_p (sym));
+  sym = symbol_equated_to (expP->X_add_symbol, &acc);
+  acc += expP->X_add_number;
+  if (sym == NULL
+      || (!md_register_arithmetic && acc != 0))
+    return;
 
+  e = symbol_get_value_expression (sym);
   if (e->X_op == O_register)
     {
       expr_copy (expP, e);
index 5844439fd34a375696890f6717c1d5578a544499..a0f8fcebeb8acd12e9d3eb963b251bfe7c653bd3 100644 (file)
@@ -3020,6 +3020,34 @@ symbol_equated_reloc_p (const symbolS *s)
              || S_IS_COMMON (s)));
 }
 
+/* Return the final symbol in a chain of equated symbols, and the offset
+   from that symbol.  If the chain has a loop, return NULL.
+   For a non-equated SYM, return SYM.  */
+
+symbolS *
+symbol_equated_to (symbolS *sym, offsetT *off)
+{
+  valueT add = 0;
+  symbolS *ret = sym;
+  while (ret && symbol_equated_p (ret))
+    {
+      const expressionS *e = symbol_get_value_expression (ret);
+      add += e->X_add_number;
+      ret->flags.resolving = 1;
+      ret = e->X_add_symbol;
+      if (ret->flags.resolving)
+       ret = NULL;
+    }
+  while (sym && sym->flags.resolving)
+    {
+      const expressionS *e = symbol_get_value_expression (sym);
+      sym->flags.resolving = 0;
+      sym = e->X_add_symbol;
+    }
+  *off = add;
+  return ret;
+}
+
 /* Return whether a symbol has a constant value.  */
 
 int
index 382af5dfd24b1ccb734b4ae80409a9f8a5c82cd1..6357237b7df62943a1c114832b68eb031c6672d8 100644 (file)
@@ -221,6 +221,7 @@ extern int symbol_resolving_p (const symbolS *);
 extern int symbol_section_p (const symbolS *);
 extern int symbol_equated_p (const symbolS *);
 extern int symbol_equated_reloc_p (const symbolS *);
+extern symbolS *symbol_equated_to (symbolS *, offsetT *);
 extern int symbol_constant_p (const symbolS *);
 extern int symbol_shadow_p (const symbolS *);
 extern symbolS *symbol_symbolS (symbolS *);