[4/8] gas: don't fail due to local register symbols

Message ID 617d6e4b-4055-4dec-aa23-2a7681d659ba@suse.com
State New
Headers
Series gas/x86: towards better Intel syntax expression evaluation |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply

Commit Message

Jan Beulich March 27, 2026, 2:12 p.m. UTC
  The diagnostic text as well as its origin are pretty clear: This is about
global symbols. This is further supported by S_IS_LOCAL() returning true
for symbols in reg_section. Add the missing check, adjusting the testcase
that was introduced back at the time (where the sole diagnostic originally
issued was therefore wrong, while other diagnostics were missing, but got
added thanks to work done elsewhere). Further drop the bogus trailing .equ
in another testcase, which were apparently put there to avoid tripping
this or some other undue check (albeit no error surfaced there already
before the change here).

While there also fully eliminate the redundant "sname": There's "name"
already, getting set up a little earlier.
---
For context: There's a pretty deep reaching issue in x86'es Intel syntax
parsing, fixing of which would expose the issue addressed here by breaking
(at least) the i386/equ.s testcase.

If it was the "global" in the diagnostic that was wrong, i.e. if we'd want
to error also on local register symbols, this check would need moving past
the subsequent check for symbols wanting removing: If in particular
S_IS_LOCAL() would cause the symbol to be dropped anyway, emitting the
diagnostic would be wrong (making it entirely impossible to use register
equates). Really this is also the connection to the Intel syntax issue
mentioned above: The parser bogusly fiddles with equates when they're
used, and once that's corrected the check here would trigger for any such
equate (as it did already when an equate isn't used anywhere).

This may actually be only a special case of a wider problem. Equates can
be about any expression. If registers are involved (no matter whether the
recorded section is reg_section or expr_section), surely such symbols
should not only not appear in the symbol table, but also not cause errors
out of resolve_symbol_value() (unless appearing in a relocation or being
global)?

There's also a listing issue lurking: Without the "nop", the diagnostics
aren't (re-)emitted as part of the listing. Plus of course the first three
shouldn't really be at the end in the first place.
  

Patch

--- a/gas/testsuite/gas/i386/equ.s
+++ b/gas/testsuite/gas/i386/equ.s
@@ -59,6 +59,3 @@  _start:
  .if s == x
  .err
  .endif
-
- .equ r, -3
- .equ s, -3
--- a/gas/testsuite/gas/i386/inval-equ-2.l
+++ b/gas/testsuite/gas/i386/inval-equ-2.l
@@ -18,10 +18,13 @@  GAS LISTING .*
 [ 	]*6[ 	]+\.globl  bar2
 [ 	]*7[ 	]+\.set    bar3,\(%eax\+1\)
 [ 	]*8[ 	]+\?\?\?\? A1...... 		mov bar3,%eax
+[ 	]*8[ 	]+..
+[ 	]*9[ 	]+\.globl  bar4
+[ 	]*10[ 	]+\.set    bar4,\(%eax\+1\)
+[ 	]*11[ 	]+\?\?\?\? 90       		nop
 .*  Error: invalid .* relocation against register
 .*  Error: invalid .* relocation against register
 .*  Error: invalid .* relocation against register
 .*  Error: can't make global register symbol `bar1'
 .*  Error: can't make global register symbol `bar2'
-.*  Error: can't make global register symbol `bar3'
-[ 	]*8[ 	]+..
+.*  Error: can't make global register symbol `bar4'
--- a/gas/testsuite/gas/i386/inval-equ-2.s
+++ b/gas/testsuite/gas/i386/inval-equ-2.s
@@ -6,3 +6,6 @@ 
 	.globl  bar2
 	.set    bar3,(%eax+1)
 	mov bar3,%eax
+	.globl  bar4
+	.set    bar4,(%eax+1)
+	nop
--- a/gas/write.c
+++ b/gas/write.c
@@ -2396,24 +2396,22 @@  write_object_file (void)
 	  if (symbol_equated_reloc_p (symp)
 	      || S_IS_WEAKREFR (symp))
 	    {
-	      const char *sname = S_GET_NAME (symp);
-
 	      if (S_IS_COMMON (symp)
-		  && !TC_FAKE_LABEL (sname)
+		  && !TC_FAKE_LABEL (name)
 		  && !S_IS_WEAKREFR (symp))
 		{
 		  expressionS *e = symbol_get_value_expression (symp);
 
 		  as_bad (_("`%s' can't be equated to common symbol `%s'"),
-			  sname, S_GET_NAME (e->X_add_symbol));
+			  name, S_GET_NAME (e->X_add_symbol));
 		}
-	      if (S_GET_SEGMENT (symp) == reg_section)
-		{
+
+	      if (S_GET_SEGMENT (symp) == reg_section
+		  && S_IS_EXTERNAL (symp)
 		  /* Report error only if we know the symbol name.  */
-		  if (S_GET_NAME (symp) != reg_section->name)
-		    as_bad (_("can't make global register symbol `%s'"),
-			    sname);
-		}
+		  && name != reg_section->name)
+		as_bad (_("can't make global register symbol `%s'"), name);
+
 	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);
 	      continue;
 	    }