]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: don't lose addend in snapshot_symbol() when hitting a local symbol
authorJan Beulich <jbeulich@suse.com>
Mon, 20 Apr 2026 06:37:47 +0000 (08:37 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 20 Apr 2026 06:37:47 +0000 (08:37 +0200)
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.

gas/symbols.c
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/equ-rept.l [new file with mode: 0644]
gas/testsuite/gas/elf/equ-rept.s [new file with mode: 0644]

index ef02f1dcc60ac958a3370c08fafcc27b731ee458..3fc0a97927c3e9799ae54efb074faddfbd009dba 100644 (file)
@@ -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;
        }
index b8c12711942e31e8510877d37ccff5d8dae29db7..cf983057bf6b75f0cce3c013d1bd6564f2b5d901 100644 (file)
@@ -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 (file)
index 0000000..90cc3de
--- /dev/null
@@ -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 (file)
index 0000000..fee6e98
--- /dev/null
@@ -0,0 +1,7 @@
+       .equiv n, (.L1+2) + null - .L2
+       .equiv null, 0
+.L1: .L2:
+
+       .rept n
+       .print ">output<"
+       .endr