ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected
LIU Hao <[email protected]> Mon, 27 Jul 2026 23:38:42 +0800
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
Hello, Below is a patch that is required for LD to work with `--gc-sections` with recent mingw-w64, tested on x86_64-w64-mingw32 and i686-w64-mingw32. I don't have access to binutils Git so please commit it for me. Also please consider backporting. From 9a98b90d43739f5979a999acda3beb21b17442b2 Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Mon, 27 Jul 2026 23:11:54 +0800 Subject: [PATCH] ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected Earlier today I pushed some patches to mingw-w64 to make `_tls_used` only linked on demand, by referencing it indirectly through tentative definitions. However, since the startup code no longer has strong references to `_tls_used`, if LD is passed `--gc-sections`, it garbage-collects `_tls_used`, resulting 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 <[email protected]> --- ld/emultempl/pe.em | 10 ++++++++++ ld/emultempl/pep.em | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 07ef2ca5953..475e0349ff8 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. */ +#if defined (TARGET_IS_i386pe) + lang_add_gc_name ("__tls_used"); + lang_add_gc_name ("__load_config_used"); +#else + lang_add_gc_name ("_tls_used"); + lang_add_gc_name ("_load_config_used"); +#endif + #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 14be8435685..1ab5c4d88f7 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1624,6 +1624,11 @@ 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. */ + lang_add_gc_name ("_tls_used"); + lang_add_gc_name ("_load_config_used"); + #ifdef DLL_SUPPORT pep_process_import_defs (link_info.output_bfd, &link_info); -- 2.55.0
2004-ld-Prevent-_tls_used-and-_load_config_used-from-bein.patch
(text/plain, 2.1 KB)
From 9a98b90d43739f5979a999acda3beb21b17442b2 Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Mon, 27 Jul 2026 23:11:54 +0800 Subject: [PATCH] ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected Earlier today I pushed some patches to mingw-w64 to make `_tls_used` only linked on demand, by referencing it indirectly through tentative definitions. However, since the startup code no longer has strong references to `_tls_used`, if LD is passed `--gc-sections`, it garbage-collects `_tls_used`, resulting 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 <[email protected]> --- ld/emultempl/pe.em | 10 ++++++++++ ld/emultempl/pep.em | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 07ef2ca5953..475e0349ff8 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. */ +#if defined (TARGET_IS_i386pe) + lang_add_gc_name ("__tls_used"); + lang_add_gc_name ("__load_config_used"); +#else + lang_add_gc_name ("_tls_used"); + lang_add_gc_name ("_load_config_used"); +#endif + #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 14be8435685..1ab5c4d88f7 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1624,6 +1624,11 @@ 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. */ + lang_add_gc_name ("_tls_used"); + lang_add_gc_name ("_load_config_used"); + #ifdef DLL_SUPPORT pep_process_import_defs (link_info.output_bfd, &link_info); -- 2.55.0
OpenPGP_signature.asc
(application/pgp-signature, 840 B)
-----BEGIN PGP SIGNATURE----- wsF5BAABCAAjFiEEYmSQWY4DEzq4FUs4hfveZl3ogBsFAmpne4MFAwAAAAAACgkQhfveZl3ogBv9 4hAAp4kTnhdt99MtpufAt0SgazsEPfP3khnT1mN0bPCVNpR2wG/0DxRIsCOzwryhUR6WdMJnS9Yh BJjVYHe54E5Hl9q369wn50K17EdDs2jtEsL2X403pJogHnJ2tVikGV/Do4D87MnECFxJGBUq+RD2 w8tXPbkoyQ/N9Ue6x6oUCwxIQOyvQwEPzq3A3XbgaAcr3LvTKMyl9KBgfaKNHLZ33NDhRwPmHu/2 rtElLRq8or0ia/N05956JYLiIfBUTHJyTaiNkz7opBuisVMyoSBoC27loSkDNKnbIVnib2uea1QO R3DlpEw6s9J+kE/+coRxqPlbYMKl3mEjz7J4WICyYGvmLHoRJN5qYLtmYhrh60iSr+APR/5ocL+I SxyJcZPPPkU96NPz24mYlZnV+FiWHxMtQ22Iah67D/uY4xIyMzrPr4ZSdYJTnfrCBqV9+BK2Zdg3 yCLK87ocd6MErj7lox2jybyTFVStRqzRRnuiBKYArbpNMBuDGRXDzhLX8c0I8HtqT8+YKJKIeBs2 OcsYak67H/edRF4lzv4UB6NpWEAEpYIFFcXbYP2H3DZX3CFQC2sHl5VEuwJShaWaHpOiYte+BK3a FjaVfAXxD7Gt8vX0tJGqIOI4mZlsKukiqyUVydKIScajUiKzuunBlnpbE4rb2Ymf4e6GNd0crLer oCk= =jw6P -----END PGP SIGNATURE-----