[binutils-gdb] gas: don't lose addend in snapshot_symbol() when hitting a local symbol

Jan Beulich jbeulich@sourceware.org
Mon Apr 20 06:40:04 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d1b63466b9ebbe0fcf00409ff473cbc97b365a66

commit d1b63466b9ebbe0fcf00409ff473cbc97b365a66
Author: Jan Beulich <jbeulich@suse.com>
Date:   Mon Apr 20 08:37:47 2026 +0200

    gas: don't lose addend in snapshot_symbol() when hitting a local symbol
    
    Unlike the one in PR gas/20941, input doesn't need to be entirely bogus
    for a local symbol to appear here: Local symbols can be created for
    various reasons. If we find one, we have to take exp.X_add_number into
    account. Plus, like for "normal" symbols, we should not add in the
    symbol's value if the result (in resolve_expression()) is still going to
    be O_symbol: The returned value then is relative to the returned symbol.

Diff:
---
 gas/symbols.c                    | 20 ++++++++++++++++----
 gas/testsuite/gas/elf/elf.exp    |  2 ++
 gas/testsuite/gas/elf/equ-rept.l |  3 +++
 gas/testsuite/gas/elf/equ-rept.s |  7 +++++++
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/gas/symbols.c b/gas/symbols.c
index ef02f1dcc60..3fc0a97927c 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -1871,20 +1871,32 @@ snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
 	}
 
       *symbolPP = symbolP;
+      *valueP = exp.X_add_number;
 
-      /* A bogus input file can result in resolve_expression()
-	 generating a local symbol, so we have to check again.  */
+      /* We may have picked up a local symbol above: Check again.  */
       if (symbolP->flags.local_symbol)
 	{
 	  struct local_symbol *locsym = (struct local_symbol *) symbolP;
 
-	  *valueP = locsym->value;
+	  if (locsym->section == expr_section
+	      || locsym->section == absolute_section
+	      || locsym->section == reg_section)
+	    {
+	      switch (exp.X_op)
+		{
+		case O_constant:
+		case O_register:
+		  *valueP += locsym->value;
+		  break;
+		default:
+		  break;
+		}
+	    }
 	  *segP = locsym->section;
 	  *fragPP = locsym->frag;
 	}
       else
 	{
-	  *valueP = exp.X_add_number;
 	  *segP = symbolP->bsym->section;
 	  *fragPP = symbolP->frag;
 	}
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index b8c12711942..cf983057bf6 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -364,6 +364,8 @@ if { [is_elf_format] } then {
 
     run_list_test "line2" -I${srcdir}/$subdir
 
+    run_list_test "equ-rept"
+
     run_dump_test "pr25917"
     run_dump_test "bss"
     # Some targets treat .bss similar to .lcomm.
diff --git a/gas/testsuite/gas/elf/equ-rept.l b/gas/testsuite/gas/elf/equ-rept.l
new file mode 100644
index 00000000000..90cc3de01de
--- /dev/null
+++ b/gas/testsuite/gas/elf/equ-rept.l
@@ -0,0 +1,3 @@
+# The line should appear exactly twice.
+>output<
+>output<
diff --git a/gas/testsuite/gas/elf/equ-rept.s b/gas/testsuite/gas/elf/equ-rept.s
new file mode 100644
index 00000000000..fee6e98f4db
--- /dev/null
+++ b/gas/testsuite/gas/elf/equ-rept.s
@@ -0,0 +1,7 @@
+	.equiv n, (.L1+2) + null - .L2
+	.equiv null, 0
+.L1: .L2:
+
+	.rept n
+	.print ">output<"
+	.endr


More information about the Binutils-cvs mailing list