Active references seem ignored by ld, for MinGW delay-loaded import libraries

Pete Batard pete@akeo.ie
Tue Jul 16 16:42:32 GMT 2024


Hi,

# Description

This whole issue is better illustrated (and replicated) with the MinGW 
sample code provided at [1] and, since it pertains to delay loading of 
Windows DLL with MinGW, we first reported it to the MinGW mailing list 
[2], before people there suggested that it ultimately looks like a 
binutils bug, and would be better submitted to this list.

The gist of the issue is that, because of the longstanding issue of 
sideloading vulnerabilities with Windows DLLs, Windows applications 
compiled with MinGW may want to delay-load vulnerable DLLs by using 
dlltool with the '--output-delaylib' option, in order to create an 
import library, that takes care of the delay-loading, and can be linked 
with the final executable, per the method described at [3].

This appears works fine with some DLLs, but for quite a few others, such 
as wininet.dll, this results in an application crash whenever a 
delay-loaded function call is invoked, on account that the thunk, that 
is meant to perform the actual loading, contains a NULL dereference. 
Currently, we are assuming that this is due to ld.bfd erroneously 
thinking that the code is not referenced at all, and not including it.

This seems further evidenced by the fact that, in our test sample, if we 
force an explicit reference to __imp__InternetCrackUrlA@16 (which is one 
of the internal calls that is exposed by the import library) then the 
problem goes away.

So it does seem to us like, in some circumstances, ld is dismissing what 
should be an active reference, as an unused one.


# Steps to replicate

Note that the issue only manifests itself when using the 32-bit version 
of MinGW and not the 64-bit version (which we assume has to do with the 
fact that the calling convention/decorations appears to play a role, as 
another workaround we found was to switch the delay-loaded API calls 
from '__declspec(dllimport)' to '__attribute__((visibility("hidden")))')

1. Clone https://github.com/pbatard/delayload.git
2. From a MinGW32 (32-bit) prompt issue 'make'
3. Run ./delayload.exe and observe the crash.
4. To test the "hidden" visibility or explicit reference workarounds, 
you can issue 'make clean' and then 'make WORKAROUND1' or 'make 
WORKAROUND2' respectively.


Because none of the "workarounds" we have found are satisfactory for our 
usage, we would really appreciate if this issue could be investigated 
and, if it does turn out to be a binutils bug, remediated.

Regards,

/Pete


[1] https://github.com/pbatard/delayload
[2] 
https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/ea87573f-65ea-44a2-b4bb-ca96c0a136ab%40akeo.ie/#msg58793876
[3] https://stackoverflow.com/a/70416894/1069307


More information about the Binutils mailing list