]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld/pe-dll: Don't auto-export symbols from .tls section
authorLIU Hao <lh_mouse@126.com>
Fri, 12 Dec 2025 14:00:15 +0000 (15:00 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 12 Dec 2025 14:00:15 +0000 (15:00 +0100)
The .tls section of an image contains template data that will be duplicated
for each new thread to be created. Accessing thread-local data involves an
image-specific global variable, _tls_used, for calculation. Therefore, it is
impossible to export thread-local variables from a DLL.

The only symbol that exists in the .tls input section is _tls_start, but it's
a CRT symbol and is never auto-exported. It's only necessary to check for
user symbols, which are always generated in the subsection .tls$ by default,
or in subsections like .tls$$<symbol> when -fdata-sections is specified.

Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80881
Signed-off-by: LIU Hao <lh_mouse@126.com>
ld/pe-dll.c

index 853425dc287b86669fda65526ed5d09b9c15d598..37b32dc69a7896e5f1a750229ced9b2fd1092132 100644 (file)
@@ -806,9 +806,17 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
            {
              /* We should export symbols which are either global or not
                 anything at all.  (.bss data is the latter)
-                We should not export undefined symbols.  */
+                We should not export undefined symbols.
+                Compilers may generate template data (initializers) for
+                thread-local variables in .tls$* sections, but they are only
+                used by the DLL loader.  Symbols in those sections are used
+                to access thread-local variables, but only via offsets to the
+                beginning of the .tls output section.  These offsets can't be
+                exported.  PE targets not using BSF_THREAD_LOCAL, we need to
+                go by section name for now.  */
              bool would_export
                = (symbols[j]->section != bfd_und_section_ptr
+                  && !startswith (symbols[j]->section->name, ".tls$")
                   && ((symbols[j]->flags & BSF_GLOBAL)
                       || (symbols[j]->flags == 0)));
              if (link_info.version_info && would_export)