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

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-03-22 16:03:22 +01:00
parent 81bbc4872e
commit 89340bb762
3 changed files with 56 additions and 42 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,33 @@ 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;
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;
*name = builtin->unix_name;
*handle = builtin->unix_handle;
*entry = builtin->unix_entry;
status = STATUS_SUCCESS;
break;
}
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
return status;
}
/***********************************************************************
* set_builtin_unix_info
*/
NTSTATUS set_builtin_unix_info( void *module, const char *name, void *handle, void *entry )
{
sigset_t sigset;
NTSTATUS status = STATUS_DLL_NOT_FOUND;
@ -655,6 +681,8 @@ NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry )
if (builtin->module != module) continue;
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;
@ -667,28 +695,6 @@ NTSTATUS set_builtin_unix_handle( void *module, void *handle, void *entry )
}
/***********************************************************************
* init_unix_lib
*/
NTSTATUS CDECL init_unix_lib( void *module, DWORD reason, const void *ptr_in, void *ptr_out )
{
sigset_t sigset;
NTSTATUS (CDECL *init_func)( HMODULE, DWORD, const void *, void * ) = NULL;
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;
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 );
}
/***********************************************************************
* free_ranges_lower_bound
*