Alexandre Julliard : ntdll: Load the Unix library only when __wine_init_unix_lib() is called.

Alexandre Julliard julliard at winehq.org
Mon Mar 22 17:15:52 CDT 2021


Module: wine
Branch: master
Commit: 89340bb762300c76a40cb4b62ba0f0d779306125
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=89340bb762300c76a40cb4b62ba0f0d779306125

Author: Alexandre Julliard <julliard at 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 at 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;
 }
 
 




More information about the wine-cvs mailing list