Hi,

Thanks for looking into this. We probably need something like that in mingw-w64, but unfortunately, it's more complicated for Wine.


On 11.02.2025 04:18, LIU Hao wrote:
Since Binutils 2.44, the import address table (abbr. IAT) is now read-only,
in alignment with Microsoft LINK and LLD. It is now required to make the IAT
writeable before modifying it.

Similar code exists in Microsoft delayhlp.cpp.

Reference:https://devblogs.microsoft.com/oldnewthing/20221006-07/?p=107257
Reference:https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=db00f6c3aceabbf03acdb69e74b59b2d2b043cd7
Reference:https://bugs.winehq.org/show_bug.cgi?id=57819
Reference:https://sourceware.org/bugzilla/show_bug.cgi?id=32675
Signed-off-by: LIU Hao<lh_mo...@126.com>


This isn't entirely true for other linkers. While those linkers do place .idata sections, including the IAT itself, in .rdata, they don’t use .idata sections for delay imports. Instead, they implement delay loading within the linker itself rather than relying on special delay import libraries, placing the delay IAT in the .data section.

I’ve seen a blog claim that MSVC makes them read-only, but in my testing with modern MSVC, that doesn’t appear to be the case, perhaps they realized it wasn’t a good fit and reverted the change? I’m not sure.

I say it’s not a good fit because changing permissions like that is generally a bad idea. Another thread might be executing code that relies on data in the same page remaining read-only or might be performing similar permission changes for other reasons. Taking a lock only protects against concurrent __delayLoadHelper2 calls.

Wine provides its own __delayLoadHelper2 implementation, which simply forwards the call to the public ResolveDelayLoadedAPI function. I’m attaching a hack that does the same for mingw-w64 (since it’s a Windows 8 API, it’s not something mingw-w64 could use by default). ResolveDelayLoadedAPI doesn’t seem to perform the protection change. at least in this case, though maybe there’s a way to trigger it? Either way, the test case crashes. The only workaround would be modifying Wine’s __delayLoadHelper2 to duplicate ResolveDelayLoadedAPI inside a static library and add the necessary permission changes.

That’s unfortunate. If anyone has a better idea, please let me know. Ideally, I’d like to restore the previous behavior for delay load imports. Wine doesn’t use dlltool to create delay load import libraries; it generates them itself. In theory, this gives Wine more flexibility, but I haven’t found a way to make it work.


  SetEntryHookBypass:
+  while(InterlockedExchange(&gDelayLoadLock, 1) != 0)
+    Sleep(100);


You could just use a critical section.


Thanks,

Jacek
diff --git a/mingw-w64-crt/misc/delayimp.c b/mingw-w64-crt/misc/delayimp.c
index 6ced2d327..1b5864ba9 100644
--- a/mingw-w64-crt/misc/delayimp.c
+++ b/mingw-w64-crt/misc/delayimp.c
@@ -135,9 +135,11 @@ static int WINAPI FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh,HMODULE hmod)
 static volatile LONG gDelayLoadLock = 0;
 
 FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry);
+WINBASEAPI void *WINAPI DelayLoadFailureHook( LPCSTR name, LPCSTR function );
 
 FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry)
 {
+  return ResolveDelayLoadedAPI( &__ImageBase, pidd, NULL, DelayLoadFailureHook, ppfnIATEntry, 0 );
   InternalImgDelayDescr idd = {
     pidd->grAttrs,(LPCTSTR) PtrFromRVA(pidd->rvaDLLName),(HMODULE *) PtrFromRVA(pidd->rvaHmod),
     (PImgThunkData) PtrFromRVA(pidd->rvaIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaINT),
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to