Module: wine Branch: master Commit: 89340bb762300c76a40cb4b62ba0f0d779306125 URL: https://source.winehq.org/git/wine.git/?a=commit;h=89340bb762300c76a40cb4b62...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Mar 22 16:03:22 2021 +0100
ntdll: Load the Unix library only when __wine_init_unix_lib() is called.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/loader.c | 40 ++++++++++++++++++++++++---------------- dlls/ntdll/unix/unix_private.h | 4 ++-- dlls/ntdll/unix/virtual.c | 36 +++++++++++++++++++++--------------- 3 files changed, 47 insertions(+), 33 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 9e43358a26d..1c95b84e965 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1111,30 +1111,38 @@ already_loaded:
/*********************************************************************** - * dlopen_unix_dll + * init_unix_lib */ -static NTSTATUS dlopen_unix_dll( void *module, const char *name ) +static NTSTATUS CDECL init_unix_lib( void *module, DWORD reason, const void *ptr_in, void *ptr_out ) { - void *unix_module, *handle, *entry; + NTSTATUS (CDECL *init_func)( HMODULE, DWORD, const void *, void * ); const IMAGE_NT_HEADERS *nt; - NTSTATUS status = STATUS_INVALID_IMAGE_FORMAT; + const char *name; + void *handle, *entry, *unix_module; + NTSTATUS status;
- handle = dlopen( name, RTLD_NOW ); - if (!handle) return STATUS_DLL_NOT_FOUND; - if (!(nt = dlsym( handle, "__wine_spec_nt_header" ))) goto done; - if (!(entry = dlsym( handle, "__wine_init_unix_lib" ))) goto done; + if ((status = get_builtin_unix_info( module, &name, &handle, &entry ))) return status;
- unix_module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); - status = set_builtin_unix_handle( module, handle, entry ); - if (!status) + if (!entry) { + if (!name) return STATUS_DLL_NOT_FOUND; + if (!(handle = dlopen( name, RTLD_NOW ))) return STATUS_DLL_NOT_FOUND; + + if (!(nt = dlsym( handle, "__wine_spec_nt_header" )) || + !(entry = dlsym( handle, "__wine_init_unix_lib" ))) + { + dlclose( handle ); + set_builtin_unix_info( module, NULL, NULL, NULL ); + return STATUS_INVALID_IMAGE_FORMAT; + } + TRACE( "loaded %s for %p\n", debugstr_a(name), module ); + unix_module = (void *)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); map_so_dll( nt, unix_module ); fixup_ntdll_imports( name, unix_module ); - return status; + set_builtin_unix_info( module, NULL, handle, entry ); } -done: - dlclose( handle ); - return status; + init_func = entry; + return init_func( module, reason, ptr_in, ptr_out ); }
@@ -1393,7 +1401,7 @@ done: if (!status && ext) { strcpy( ext, ".so" ); - dlopen_unix_dll( *module, ptr ); + set_builtin_unix_info( *module, ptr, NULL, NULL ); } free( file ); return status; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index c00a6ee6aa8..5877a00bac8 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -203,8 +203,8 @@ extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; extern void *get_builtin_so_handle( void *module ) DECLSPEC_HIDDEN; -extern NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry ) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL init_unix_lib( void *module, DWORD reason, const void *ptr_in, void *ptr_out ) DECLSPEC_HIDDEN; +extern NTSTATUS get_builtin_unix_info( void *module, const char **name, void **handle, void **entry ) DECLSPEC_HIDDEN; +extern NTSTATUS set_builtin_unix_info( void *module, const char *name, void *handle, void *entry ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; extern BOOL get_thread_times( int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index bff4569b615..4edc7d0261e 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -90,6 +90,7 @@ struct builtin_module ino_t ino; void *handle; void *module; + char *unix_name; void *unix_handle; void *unix_entry; }; @@ -570,6 +571,7 @@ static void add_builtin_module( void *module, void *handle, const struct stat *s if (!(builtin = malloc( sizeof(*builtin) ))) return; builtin->handle = handle; builtin->module = module; + builtin->unix_name = NULL; builtin->unix_handle = NULL; builtin->unix_entry = NULL; if (st) @@ -641,9 +643,9 @@ void *get_builtin_so_handle( void *module )
/*********************************************************************** - * set_builtin_unix_handle + * get_builtin_unix_info */ -NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry ) +NTSTATUS get_builtin_unix_info( void *module, const char **name, void **handle, void **entry ) { sigset_t sigset; NTSTATUS status = STATUS_DLL_NOT_FOUND; @@ -653,13 +655,10 @@ NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry ) LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) { if (builtin->module != module) continue; - if (!builtin->unix_handle) - { - builtin->unix_handle = handle; - builtin->unix_entry = entry; - status = STATUS_SUCCESS; - } - else status = STATUS_IMAGE_ALREADY_LOADED; + *name = builtin->unix_name; + *handle = builtin->unix_handle; + *entry = builtin->unix_entry; + status = STATUS_SUCCESS; break; } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); @@ -668,24 +667,31 @@ NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry )
/*********************************************************************** - * init_unix_lib + * set_builtin_unix_info */ -NTSTATUS CDECL init_unix_lib( void *module, DWORD reason, const void *ptr_in, void *ptr_out ) +NTSTATUS set_builtin_unix_info( void *module, const char *name, void *handle, void *entry ) { sigset_t sigset; - NTSTATUS (CDECL *init_func)( HMODULE, DWORD, const void *, void * ) = NULL; + NTSTATUS status = STATUS_DLL_NOT_FOUND; struct builtin_module *builtin;
server_enter_uninterrupted_section( &virtual_mutex, &sigset ); LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) { if (builtin->module != module) continue; - init_func = builtin->unix_entry; + if (!builtin->unix_handle) + { + free( builtin->unix_name ); + builtin->unix_name = name ? strdup( name ) : NULL; + builtin->unix_handle = handle; + builtin->unix_entry = entry; + status = STATUS_SUCCESS; + } + else status = STATUS_IMAGE_ALREADY_LOADED; break; } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); - if (!init_func) return STATUS_DLL_NOT_FOUND; - return init_func( module, reason, ptr_in, ptr_out ); + return status; }