Re: ld: Prevent `_tls_used` and `_load_config_used` from being garbage-collected

Jan Beulich <[email protected]> Mon, 27 Jul 2026 17:55:57 +0200
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
On 27.07.2026 17:38, LIU Hao wrote:
> From: LIU Hao <[email protected]>
> 
> 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`.

But it does so not knowing what environment the executable targets. Aiui
both names aren't exactly "reserved" in the PE world, they're more like
reserved in combination with certain C or other runtime libraries, I
suppose. In an EFI application, for example, they may exist but have an
entirely different purpose.

Then again I realize that bfd/peXXigen.c already makes a similar
assumption.

> --- 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

The #ifdef here likely wants replacing by appropriate use of
bfd_get_symbol_leading_char(). To play safe towards future uses, the
same code could then also be used in pep.em.

Jan