]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected
authorLIU Hao <lh_mouse@126.com>
Fri, 31 Jul 2026 11:52:14 +0000 (13:52 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 31 Jul 2026 11:52:14 +0000 (13:52 +0200)
In mingw-w64 there's an ongoing effort to make the TLS directory of an image
optional and only linked on demand. The approach is to have the entrypoint
function reference TLS initialization callbacks through function pointers as
tentative definitions, and the object files where TLS initialization callbacks
are defined should ensure `_tls_used` is linked, by referencing its address in
file-scope static pointers.

The issue here is that data sections of those object files are not referenced
otherwise. During linking, if LD is passed `--gc-sections`, it garbage-collects
such sections along with `_tls_used`, leaving a symbol of value zero, which
results in a broken executable:

   $ objdump -p bin/test_thread_id_cpp.exe | grep -F .tls
   Entry 9 ffffffffc0000000 00000028 Thread Storage Directory [.tls]

This patch prevents `_tls_used` from being garbage-collected, and likewise for
`_load_config_used`.

Signed-off-by: LIU Hao <lh_mouse@126.com>
ld/emultempl/pe.em
ld/emultempl/pep.em

index 07ef2ca595314b58902462ab942ad63a19481075..1d02a86be96d6de643c188d69f317bf5366cb40c 100644 (file)
@@ -1573,6 +1573,16 @@ gld${EMULATION_NAME}_after_open (void)
 
   pe_output_file_set_long_section_names (link_info.output_bfd);
 
+  /* The RVAs of these symbols will be written into the PE header, so they
+     must not be collected.  */
+  char *sym = xstrdup ("__tls_used");
+  sym[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
+  lang_add_gc_name (sym + !sym[0]);
+
+  sym = xstrdup ("__load_config_used");
+  sym[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
+  lang_add_gc_name (sym + !sym[0]);
+
 #ifdef DLL_SUPPORT
   pe_process_import_defs (link_info.output_bfd, &link_info);
 
index 25ce3963b3639e61a6ceb145201f54cca101725c..3ba29401821d3b5e240d971e31f216b16c11087d 100644 (file)
@@ -1582,6 +1582,16 @@ gld${EMULATION_NAME}_after_open (void)
 
   pep_output_file_set_long_section_names (link_info.output_bfd);
 
+  /* The RVAs of these symbols will be written into the PE header, so they
+     must not be collected.  */
+  char *sym = xstrdup ("__tls_used");
+  sym[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
+  lang_add_gc_name (sym + !sym[0]);
+
+  sym = xstrdup ("__load_config_used");
+  sym[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
+  lang_add_gc_name (sym + !sym[0]);
+
 #ifdef DLL_SUPPORT
   pep_process_import_defs (link_info.output_bfd, &link_info);