PR 33917 Internal error in S_SET_SEGMENT

Alan Modra amodra@gmail.com
Sat Feb 21 01:24:23 GMT 2026


Commit d4d05d13eba6 attempted to fix a similar error to that uncovered
by the testcase in pr33917, but did so in a way that was wrong.
Modifying an undefined_section symbol that is an equate breaks prior
use of that symbol, as shown in the rewrite of the
section-symbol-redef test.

Another oddity found when poking at pr33917 is that gas allows
 x=0
 .sect x
 x=u
while
 .sect x
 x=u
fails with "Error: symbol `x' is already defined".

Fix all of this by rewriting section_symbol to properly check for the
only case where we want to redefine an existing symbol, a truly
undefined symbol, and always use section_symbol in obj-elf rather than
trying to handle undefined symbols there too.

	PR 33917
	* config/obj-elf.c (change_section): Always call section_symbol
	to set up sym.
	* subsegs.c (section_symbol): Rewrite.
	* testsuite/gas/elf/section-symbol-redef.d
	* testsuite/gas/elf/section-symbol-redef.s: Rewrite.
	* testsuite/gas/elf/section-symbol-redef-2.d,
	* testsuite/gas/elf/section-symbol-redef-2.s: New test.
	* testsuite/gas/elf/elf.exp: Run new test.

diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 3c617bc36a3..e09be292cd1 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -774,8 +774,6 @@ change_section (const char *name,
 
   if (old_sec == NULL)
     {
-      symbolS *secsym;
-
       if (type == SHT_NULL)
 	type = bfd_elf_get_default_section_type (flags);
       elf_section_type (sec) = type;
@@ -800,18 +798,7 @@ change_section (const char *name,
       elf_group_name (sec) = match_p->group_name;
 
       /* Add a symbol for this section to the symbol table.  */
-      secsym = symbol_find (name);
-      if (secsym != NULL)
-	{
-	  /* We could be repurposing an undefined symbol here: make sure we
-	     reset sy_value to look like other section symbols in order to avoid
-	     trying to incorrectly resolve this section symbol later on.  */
-	  static const expressionS exp = { .X_op = O_constant };
-	  symbol_set_value_expression (secsym, &exp);
-	  symbol_set_bfdsym (secsym, sec->symbol);
-	}
-      else
-	symbol_table_insert (section_symbol (sec));
+      symbol_table_insert (section_symbol (sec));
     }
   else
     {
diff --git a/gas/subsegs.c b/gas/subsegs.c
index 2f830327dc6..199fd869f21 100644
--- a/gas/subsegs.c
+++ b/gas/subsegs.c
@@ -247,27 +247,23 @@ section_symbol (segT sec)
 #define EMIT_SECTION_SYMBOLS 1
 #endif
 
-  if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
+  /* A reference to the section (ie. an undefined symbol)
+     should now become defined, but any other symbol that happens to
+     have the same name as the section should not be modified.  Make
+     sure an undefined_section symbol isn't equated to some other
+     undefined symbol.  */
+  s = symbol_find (sec->symbol->name);
+  if (s == NULL
+      || S_GET_SEGMENT (s) != undefined_section
+      || !symbol_constant_p (s))
     {
-      /* Here we know it won't be going into the symbol table.  */
-      s = symbol_create (sec->symbol->name, sec, &zero_address_frag, 0);
-    }
-  else
-    {
-      segT seg;
-      s = symbol_find (sec->symbol->name);
-      /* We have to make sure it is the right symbol when we
-	 have multiple sections with the same section name.  */
-      if (s == NULL
-	  || ((seg = S_GET_SEGMENT (s)) != sec
-	      && seg != undefined_section))
+      if (!EMIT_SECTION_SYMBOLS || symbol_table_frozen)
+	s = symbol_create (sec->symbol->name, sec, &zero_address_frag, 0);
+      else
 	s = symbol_new (sec->symbol->name, sec, &zero_address_frag, 0);
-      else if (seg == undefined_section)
-	{
-	  S_SET_SEGMENT (s, sec);
-	  symbol_set_frag (s, &zero_address_frag);
-	}
     }
+  else
+    S_SET_SEGMENT (s, sec);
 
   S_CLEAR_EXTERNAL (s);
 
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index b4b4272ab9f..07acb4ad514 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -408,5 +408,6 @@ if { [is_elf_format] } then {
 
     run_dump_test "bignums" $dump_opts
     run_dump_test "section-symbol-redef"
+    run_dump_test "section-symbol-redef-2"
     run_dump_test "pr27228"
 }
diff --git a/gas/testsuite/gas/elf/section-symbol-redef-2.d b/gas/testsuite/gas/elf/section-symbol-redef-2.d
new file mode 100644
index 00000000000..10141c51d4d
--- /dev/null
+++ b/gas/testsuite/gas/elf/section-symbol-redef-2.d
@@ -0,0 +1,2 @@
+#error: 4: Error: symbol `x' is already defined
+#xfail: bfin-*-*
diff --git a/gas/testsuite/gas/elf/section-symbol-redef-2.s b/gas/testsuite/gas/elf/section-symbol-redef-2.s
new file mode 100644
index 00000000000..56c25bb3672
--- /dev/null
+++ b/gas/testsuite/gas/elf/section-symbol-redef-2.s
@@ -0,0 +1,6 @@
+#pr33917
+ x=0
+ .sect x
+ x=u
+ .reloc 0,BFD_RELOC_NONE,0
+ y=x
diff --git a/gas/testsuite/gas/elf/section-symbol-redef.d b/gas/testsuite/gas/elf/section-symbol-redef.d
index 149e8f9de64..1daa20bd175 100644
--- a/gas/testsuite/gas/elf/section-symbol-redef.d
+++ b/gas/testsuite/gas/elf/section-symbol-redef.d
@@ -1,5 +1,8 @@
-#readelf: -x myseg
+#objdump: -r
 #xfail: bfin-*-* h8300-*
 
-Hex dump of section .*:
-  0x0+ 2a\s+\*
+#...
+0+ .* u
+#...
+0+ .* x
+#pass
diff --git a/gas/testsuite/gas/elf/section-symbol-redef.s b/gas/testsuite/gas/elf/section-symbol-redef.s
index 87e65699b48..55b34ea37d6 100644
--- a/gas/testsuite/gas/elf/section-symbol-redef.s
+++ b/gas/testsuite/gas/elf/section-symbol-redef.s
@@ -1,3 +1,4 @@
-  myseg=not_defined_here
-  .section myseg
-  .byte 42
+ x=u
+ .dc.a x
+ .section x
+ .dc.a x

-- 
Alan Modra


More information about the Binutils mailing list