aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2025-12-08 17:47:56 +0100
committerEric Botcazou <ebotcazou@adacore.com>2025-12-08 17:50:45 +0100
commit3777a0b41f9fdcbb5fde4bdfce06031805cebc33 (patch)
tree856e6337b8b7089e521a9323c61d870de02cfc1f
parent76fc22a292ad652338be21b7ff4a767ddb3d7015 (diff)
downloadgcc-3777a0b41f9fdcbb5fde4bdfce06031805cebc33.zip
gcc-3777a0b41f9fdcbb5fde4bdfce06031805cebc33.tar.gz
gcc-3777a0b41f9fdcbb5fde4bdfce06031805cebc33.tar.bz2
MinGW: Fix native TLS bug with -fdata-sections
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.
-rw-r--r--gcc/config/mingw/winnt.cc10
-rw-r--r--gcc/testsuite/gcc.dg/tls/data-sections-1.c14
2 files changed, 20 insertions, 4 deletions
diff --git a/gcc/config/mingw/winnt.cc b/gcc/config/mingw/winnt.cc
index b51fd8e..fe2fb4c 100644
--- a/gcc/config/mingw/winnt.cc
+++ b/gcc/config/mingw/winnt.cc
@@ -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
index 0000000..c829256
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tls/data-sections-1.c
@@ -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;
+}