From: LIU Hao Date: Fri, 31 Jul 2026 11:52:14 +0000 (+0200) Subject: ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ee7506d8ffbec39df2262f08a348346914d71efd;p=thirdparty%2Fbinutils-gdb.git ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected 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 --- diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 07ef2ca5953..1d02a86be96 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -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); diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 25ce3963b36..3ba29401821 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -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);