[PATCH 7/8] x86/Intel: don't modify equates' expressions
Jan Beulich
jbeulich@suse.com
Fri Mar 27 14:14:05 GMT 2026
Equates involving registers were mis-treated when parsing insn operand
expressions: When "pulling out" the register(s), they would have got
converted to O_constant. While other (local) parsing code was able to cope
with this, the generic part of the assembler was misled. A visible bad
effect would be that local absolute symbols would appear in the symbol
table, when really that should be register symbols (which wouldn't be put
in the symbol table at all).
Clone symbols / expressions as necessary before modifying them.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -167,7 +167,7 @@ static int i386_finalize_displacement (s
const char *);
static int i386_att_operand (char *);
static int i386_intel_operand (char *, int);
-static int i386_intel_simplify (expressionS *);
+static int i386_intel_simplify (expressionS *, bool);
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);
@@ -13526,7 +13526,7 @@ x86_cons (expressionS *exp, int size)
intel_syntax = -intel_syntax;
if (intel_syntax)
- i386_intel_simplify (exp);
+ i386_intel_simplify (exp, false);
/* If not 64bit, massage value, to account for wraparound when !BFD64. */
if (size <= 4 && expr_mode == expr_operator_present
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -378,30 +378,56 @@ i386_intel_simplify_register (expression
return 2;
}
-static int
-i386_intel_simplify_symbol (symbolS *sym)
+static symbolS *
+i386_intel_simplify_symbol (symbolS *sym, bool in_equate)
{
if (symbol_resolving_p (sym))
- return 1;
+ return sym;
- symbol_mark_resolving (sym);
- int ret = i386_intel_simplify (symbol_get_value_expression (sym));
- if (ret == 2)
+ segT seg = S_GET_SEGMENT (sym);
+ if (seg != expr_section && seg != reg_section && !symbol_equated_p(sym))
+ return sym;
+
+ for (;;)
{
- S_SET_SEGMENT (sym, absolute_section);
- ret = 1;
+ /* 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;
+
+ return ret ? sym : NULL;
}
static int
-i386_intel_simplify (expressionS *e)
+i386_intel_simplify (expressionS *e, bool in_equate)
{
const reg_entry *the_reg = (this_operand >= 0
? i.op[this_operand].regs : NULL);
const reg_entry *base = intel_state.base;
const reg_entry *state_index = intel_state.index;
+ symbolS *newsym;
int ret;
if (!intel_syntax)
@@ -412,18 +438,21 @@ i386_intel_simplify (expressionS *e)
case O_index:
if (e->X_add_symbol)
{
- if (!i386_intel_simplify_symbol (e->X_add_symbol)
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym
|| !i386_intel_check(the_reg, intel_state.base,
intel_state.index))
return 0;
+ e->X_add_symbol = newsym;
}
if (!intel_state.in_offset)
++intel_state.in_bracket;
- ret = i386_intel_simplify_symbol (e->X_op_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
if (!intel_state.in_offset)
--intel_state.in_bracket;
- if (!ret)
+ if (!newsym)
return 0;
+ e->X_op_symbol = newsym;
if (e->X_add_symbol)
e->X_op = O_add;
else
@@ -433,12 +462,13 @@ i386_intel_simplify (expressionS *e)
case O_offset:
intel_state.has_offset = 1;
++intel_state.in_offset;
- ret = i386_intel_simplify_symbol (e->X_add_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
--intel_state.in_offset;
- if (!ret || !i386_intel_check(the_reg, base, state_index))
+ if (!newsym || !i386_intel_check(the_reg, base, state_index))
return 0;
+ e->X_add_symbol = newsym;
i386_intel_fold (e, e->X_add_symbol);
- return ret;
+ return 1;
case O_byte_ptr:
case O_word_ptr:
@@ -461,8 +491,10 @@ i386_intel_simplify (expressionS *e)
as_bad (_("invalid use of register"));
return 0;
}
- if (!i386_intel_simplify_symbol (e->X_add_symbol))
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym)
return 0;
+ e->X_add_symbol = newsym;
i386_intel_fold (e, e->X_add_symbol);
break;
@@ -473,10 +505,12 @@ i386_intel_simplify (expressionS *e)
as_bad (_("invalid use of register"));
return 0;
}
- if (!i386_intel_simplify_symbol (e->X_op_symbol)
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ if (!newsym
|| !i386_intel_check(the_reg, intel_state.base,
intel_state.index))
return 0;
+ e->X_op_symbol = newsym;
if (!intel_state.in_offset)
{
if (!intel_state.seg)
@@ -503,16 +537,26 @@ i386_intel_simplify (expressionS *e)
if (!intel_state.in_scale++)
intel_state.scale_factor = 1;
- ret = i386_intel_simplify_symbol (e->X_add_symbol);
- if (ret && !has_index && intel_state.index)
- scale = symbol_get_value_expression (e->X_op_symbol);
-
- if (ret)
- ret = i386_intel_simplify_symbol (e->X_op_symbol);
- if (ret && !scale && !has_index && intel_state.index)
- scale = symbol_get_value_expression (e->X_add_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (newsym)
+ {
+ e->X_add_symbol = newsym;
+
+ if (!has_index && intel_state.index)
+ scale = symbol_get_value_expression (e->X_op_symbol);
+
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ }
+
+ if (newsym)
+ {
+ e->X_op_symbol = newsym;
+
+ if (!scale && !has_index && intel_state.index)
+ scale = symbol_get_value_expression (e->X_add_symbol);
+ }
- if (ret && scale)
+ if (newsym && scale)
{
resolve_expression (scale);
if (scale->X_op != O_constant
@@ -522,7 +566,7 @@ i386_intel_simplify (expressionS *e)
}
--intel_state.in_scale;
- if (!ret)
+ if (!newsym)
return 0;
if (!intel_state.in_scale)
@@ -568,9 +612,13 @@ i386_intel_simplify (expressionS *e)
/* FALLTHROUGH */
default:
fallthrough:
- if (e->X_add_symbol
- && !i386_intel_simplify_symbol (e->X_add_symbol))
- return 0;
+ if (e->X_add_symbol)
+ {
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym)
+ return 0;
+ e->X_add_symbol = newsym;
+ }
if (!the_reg && this_operand >= 0
&& e->X_op == O_symbol && !e->X_add_number)
the_reg = i.op[this_operand].regs;
@@ -579,14 +627,19 @@ i386_intel_simplify (expressionS *e)
base = intel_state.base;
state_index = intel_state.index;
}
- if (!i386_intel_check (the_reg, base, state_index)
- || (e->X_op_symbol
- && !i386_intel_simplify_symbol (e->X_op_symbol))
- || !i386_intel_check (the_reg,
- (e->X_op != O_add
- ? base : intel_state.base),
- (e->X_op != O_add
- ? state_index : intel_state.index)))
+ if (!i386_intel_check (the_reg, base, state_index))
+ return 0;
+ if (e->X_op_symbol)
+ {
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ if (!newsym)
+ return 0;
+ e->X_op_symbol = newsym;
+ }
+ if (!i386_intel_check (the_reg,
+ e->X_op != O_add ? base : intel_state.base,
+ (e->X_op != O_add ? state_index
+ : intel_state.index)))
return 0;
break;
}
@@ -654,7 +707,7 @@ i386_intel_operand (char *operand_string
expr_mode = expr_operator_none;
memset (&exp, 0, sizeof(exp));
exp_seg = expression (&exp);
- ret = i386_intel_simplify (&exp);
+ ret = i386_intel_simplify (&exp, false);
intel_syntax = 1;
SKIP_WHITESPACE ();
--- /dev/null
+++ b/gas/testsuite/gas/i386/equ2.d
@@ -0,0 +1,10 @@
+#source: equ.s
+#objdump: -t
+#name: i386 equates (symtab check)
+
+.*: +file format .*
+
+SYMBOL TABLE:
+.* \.text .*
+!.* \*ABS\* .*
+#pass
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -726,6 +726,7 @@ if [gas_32_check] then {
run_dump_test "pcrel-elf"
run_dump_test "relax"
run_dump_test "gotpc"
+ run_dump_test "equ2"
run_dump_test "tlsd"
run_dump_test "tlspic"
run_dump_test "tlsnopic"
More information about the Binutils
mailing list