[PATCH 0/1] MR1498: ntdll: Use RTLD_NOLOAD to find already mapped modules.
This makes it possible to detect modules that weren't unmapped from dlclose, and that we should not fixup again. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49640 This usually happens with C++ winelibs, where some C++ symbols may be inlined into the winelib, then later resolved in preference over other symbol definitions when libstdc++ loads. This results in circular dependency between the winelib and libstdc++, making dlclose no-op. In this case, reloading the lib later and calling `map_so_dll` on it again will fixup the RVAs again, ending up with invalid addresses. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498
From: Rémi Bernon <rbernon(a)codeweavers.com> This makes it possible to detect modules that weren't unmapped from dlclose, and that we should not fixup again. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49640 --- dlls/ntdll/unix/loader.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 3bb7f056b2a..cd2019be582 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1274,9 +1274,11 @@ static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void * { void *module, *handle; const IMAGE_NT_HEADERS *nt; + BOOL mapped = FALSE; callback_module = (void *)1; - handle = dlopen( so_name, RTLD_NOW ); + if ((handle = dlopen( so_name, RTLD_NOW | RTLD_NOLOAD ))) mapped = TRUE; + else handle = dlopen( so_name, RTLD_NOW ); if (!handle) { WARN( "failed to load .so lib %s: %s\n", debugstr_a(so_name), dlerror() ); @@ -1293,7 +1295,7 @@ static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void * { module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); if (get_builtin_so_handle( module )) goto already_loaded; - if (map_so_dll( nt, module )) + if (!mapped && map_so_dll( nt, module )) { dlclose( handle ); return STATUS_NO_MEMORY; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/1498
RTLD_NOLOAD is a GNU extension, so it probably should be guarded out with ifdefs? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498#note_17019
On Tue Nov 22 21:41:00 2022 +0000, Zebediah Figura wrote:
RTLD_NOLOAD is a GNU extension, so it probably should be guarded out with ifdefs? I considered doing that, then I saw it was used in winemac.drv, and I could find some reference in FreeBSD manual about it as well. I have no idea how portable it is, I'm find adding ifdefs around if that feels necessary.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498#note_17021
On Tue Nov 22 21:41:00 2022 +0000, Rémi Bernon wrote:
I considered doing that, then I saw it was used in winemac.drv, and I could find some reference in FreeBSD manual about it as well. I have no idea how portable it is, I'm find adding ifdefs around if that feels necessary. FreeBSD tends to be closer to Linux in general, but from looking up man pages on the Internet it looks like NetBSD and OpenBSD support NOLOAD too, so I guess it's probably safe enough.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498#note_17056
On Tue Nov 22 21:48:34 2022 +0000, Zebediah Figura wrote:
FreeBSD tends to be closer to Linux in general, but from looking up man pages on the Internet it looks like NetBSD and OpenBSD support NOLOAD too, so I guess it's probably safe enough. Instead of relying on dlopen for this, I'd suggest making map_so_dll() not do anything if it finds an existing DOS header.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498#note_17082
This merge request was closed by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1498
participants (3)
-
Alexandre Julliard (@julliard) -
Rémi Bernon -
Zebediah Figura (@zfigura)