From: Alan Modra Date: Fri, 3 Apr 2026 22:17:04 +0000 (+1030) Subject: PR 34036 looping in symbol_equated_p chains X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea2b9ecdc80fade6db5046224b821390cfac06b5;p=thirdparty%2Fbinutils-gdb.git PR 34036 looping in symbol_equated_p chains 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. --- diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index edc44a37345..8d517146cfa 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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); diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index 75df8a1ecd1..4373bd3cd2a 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -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); diff --git a/gas/expr.c b/gas/expr.c index 5b6828d391a..7108d7332c4 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -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); diff --git a/gas/symbols.c b/gas/symbols.c index 5844439fd34..a0f8fcebeb8 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -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 diff --git a/gas/symbols.h b/gas/symbols.h index 382af5dfd24..6357237b7df 100644 --- a/gas/symbols.h +++ b/gas/symbols.h @@ -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 *);