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

Jan Beulich via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d1b63466b9ebbe0fcf00409ff473cbc97b365a66

commit d1b63466b9ebbe0fcf00409ff473cbc97b365a66
Author: Jan Beulich <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.