https://sourceware.org/bugzilla/show_bug.cgi?id=32675
--- Comment #19 from Sourceware Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jan Beulich <jbeul...@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3cad19db4e6b72195b22be1f93c81a2b229e4c07 commit 3cad19db4e6b72195b22be1f93c81a2b229e4c07 Author: LIU Hao <lh_mo...@126.com> Date: Fri Jun 13 07:52:29 2025 +0200 bfd,ld,dlltool: Emit delay-load import data into its own section A delay-import symbol (of a function) is resolved when a call to it is made. The delay loader may overwrite the `__imp_` pointer to the actual function after it has been resolved, which requires the pointer itself be in a writeable section. Previously it was placed in the ordinary Import Address Table (IAT), which is emitted into the `.idata` section, which had been changed to read-only in db00f6c3aceabbf03acdb69e74b59b2d2b043cd7, which caused segmentation faults when functions from delay-import library were called. This is PR 32675. This commit makes DLLTOOL emit delay-import IAT into `.didat`, as specified by Microsoft. Most of the code is copied from `.idata`, except that this section is writeable. As a side-effect of this, PR 14339 is also fixed. Using this DEF: ``` ; ws2_32.def LIBRARY "WS2_32.DLL" EXPORTS WSAGetLastError ``` and this C program: ``` // delay.c #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #include <stdio.h> ///////////////////////////////////////////////////////// // User code ///////////////////////////////////////////////////////// DWORD WINAPI WSAGetLastError(void); extern PVOID __imp_WSAGetLastError; int main(void) { fprintf(stderr, "before delay load, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError); SetLastError(123); fprintf(stderr, "WSAGetLastError() = %d\n", WSAGetLastError()); fprintf(stderr, "after delay load, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError); __imp_WSAGetLastError = (PVOID) 1234567; fprintf(stderr, "after plain write, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError); } ///////////////////////////////////////////////////////// // Overridden `__delayLoadHelper2` facility ///////////////////////////////////////////////////////// extern char __ImageBase[]; PVOID WINAPI ResolveDelayLoadedAPI(PVOID ParentModuleBase, LPCVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook, FARPROC* ThunkAddress, ULONG Flags); FARPROC WINAPI DelayLoadFailureHook(LPCSTR name, LPCSTR function); FARPROC WINAPI __delayLoadHelper2(LPCVOID pidd, FARPROC* ppfnIATEntry) { return ResolveDelayLoadedAPI(&__ImageBase, pidd, NULL, (PVOID) DelayLoadFailureHook, ppfnIATEntry, 0); } ``` This program used to crash: ``` $ dlltool -nn -d ws2_32.def -y delay_ws2_32.a $ gcc -g delay.c delay_ws2_32.a -o delay.exe $ ./delay.exe before delay load, __imp_WSAGetLastError = 00007FF6937215C6 Segmentation fault ``` After this commit, it loads and calls `WSAGetLastError()` properly, and `__imp_WSAGetLastError` is writeable: ``` $ dlltool -nn -d ws2_32.def -y delay_ws2_32.a $ gcc -g delay.c delay_ws2_32.a -o delay.exe $ ./delay.exe before delay load, __imp_WSAGetLastError = 00007FF76E2215C6 WSAGetLastError() = 123 after delay load, __imp_WSAGetLastError = 00007FFF191FA720 after plain write, __imp_WSAGetLastError = 000000000012D687 ``` Reference: https://learn.microsoft.com/en-us/windows/win32/secbp/pe-metadata#import-handling Co-authored-by: Jeremy Drake <sourceware-bugzi...@jdrake.com> Signed-off-by: LIU Hao <lh_mo...@126.com> Signed-off-by: Jeremy Drake <sourceware-bugzi...@jdrake.com> -- You are receiving this mail because: You are on the CC list for the bug.