]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
MinGW: Fix native TLS bug with -fdata-sections
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 8 Dec 2025 16:47:56 +0000 (17:47 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 8 Dec 2025 16:50:45 +0000 (17:50 +0100)
The problem comes from a quirk of the GNU PE-COFF linker, which wants
to make sure that .tls$ZZZ is laid out last among the TLS sections,
but first globs all .tls$* sections together.  The solution matches
Clang's output.

gcc/
PR target/80881
* config/mingw/winnt.cc (mingw_pe_unique_section): Put two dollar
signs for TLS sections after the prefix.
(mingw_pe_asm_named_section): Deal with all TLS sections uniformly.

gcc/testsuite/
* gcc.dg/tls/data-sections-1.c: New test.

gcc/config/mingw/winnt.cc
gcc/testsuite/gcc.dg/tls/data-sections-1.c [new file with mode: 0644]

index b51fd8e9cc6a2e8edb9162bfe6fc6e2668e6a8a3..fe2fb4cb267f8c54f5f0e5bc09a9ac5d4107c737 100644 (file)
@@ -446,8 +446,11 @@ mingw_pe_unique_section (tree decl, int reloc)
     prefix = ".text$";
   else if (decl_readonly_section (decl, reloc))
     prefix = ".rdata$";
+  /* Note that we need two dollar signs for TLS sections
+     because they need to be ASCII-sorted before .tls$ZZZ
+     to be properly laid out by the GNU linker.  */
   else if (DECL_THREAD_LOCAL_P (decl))
-    prefix = ".tls$";
+    prefix = ".tls$$";
   else
     prefix = ".data$";
   len = strlen (name) + strlen (prefix);
@@ -522,9 +525,6 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags,
     *f++ = 'e';
 #endif
 
-  if (strcmp (name, ".tls$") == 0)
-    *f++ = 'd';
-
   if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
     /* readonly data */
     {
@@ -533,6 +533,8 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags,
     }
   else
     {
+      if (startswith (name, ".tls$"))
+        *f++ = 'd';
       if (flags & SECTION_CODE)
         *f++ = 'x';
       if (flags & SECTION_WRITE)
diff --git a/gcc/testsuite/gcc.dg/tls/data-sections-1.c b/gcc/testsuite/gcc.dg/tls/data-sections-1.c
new file mode 100644 (file)
index 0000000..c829256
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_runtime } */
+/* { dg-options "-fdata-sections" } */
+/* { dg-add-options tls } */
+
+__thread int i = 1;
+
+int main (void)
+{
+  if (i != 1)
+    __builtin_abort ();
+
+  return 0;
+}