1
0
mirror of https://github.com/skeeto/w64devkit.git synced 2026-10-29 06:52:56 +03:00

ld: Don't reference _pei386_runtime_relocator in relocatable links

Since Binutils 2.41 (PR30343) the PE linker creates an early undefined
reference to _pei386_runtime_relocator whenever the LTO plugin is
loaded, which an LTO-enabled GCC does on every link. With -r that
reference leaks into the output as a stray undefined symbol, breaking
later -nostdlib links of the result. Skip it for relocatable output,
where the final link makes its own reference.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Christopher Wellons
2026-09-05 11:24:49 -04:00
parent 16ed33fa2d
commit 38865eb833
2 changed files with 49 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
Since Binutils 2.41 (PR30343, commit defb881754d), whenever the LTO
plugin is loaded the PE linker unconditionally creates an undefined
reference to _pei386_runtime_relocator before the plugin's "all symbols
read" phase. Because it cannot yet know whether LTO output will need
runtime pseudo-relocations, it makes the reference anyway, marking the
symbol as referenced from a regular object so that an LTO-compiled
definition survives. In a final link this is harmless: the reference
resolves to pseudo-reloc.o in libmingw32.a, which the CRT startup drags
in regardless.
In a relocatable link (-r) the reference has no definition to resolve
against and leaks into the output as a stray undefined symbol. Since GCC
passes the plugin to the linker for every link when built with LTO, this
affects even links with no LTO objects at all:
$ cc -r -s -u ___chkstk_ms -o chkstk.o -lgcc
$ nm chkstk.o
0000000000000000 T ___chkstk_ms
U _pei386_runtime_relocator
An object linked with -r is never a final image, so no pseudo-relocation
will run from it. If it is later used in a final link, that link makes
its own reference. The early reference also buys nothing for LTO in a
relocatable link: the linker's plugin interface already reports every
symbol as visible from outside for relocatable output, so none resolve
as IR-only and GCC keeps them all. So skip the early reference for
relocatable output.
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -1457,6 +1457,7 @@
{
#ifdef DLL_SUPPORT
if (link_info.lto_plugin_active
+ && !bfd_link_relocatable (&link_info)
&& link_info.pei386_auto_import)
make_runtime_ref ();
#endif
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -1465,6 +1465,7 @@
{
#ifdef DLL_SUPPORT
if (link_info.lto_plugin_active
+ && !bfd_link_relocatable (&link_info)
&& link_info.pei386_auto_import) /* -1=warn or 1=enable */
make_runtime_ref ();
#endif

View File

@@ -3,3 +3,4 @@ exclude-sysroot.patch
windmc-bom.patch
windmc-carry-severity-facility.patch
windmc-per-facility-ids.patch
pe-lto-no-relocator-ref-for-relocatable.patch