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.
From: Rémi Bernon rbernon@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;
RTLD_NOLOAD is a GNU extension, so it probably should be guarded out with ifdefs?
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.
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.
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.
This merge request was closed by Rémi Bernon.