ntdll: Move the wineloader exec support to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-05-19 14:08:16 +02:00
parent e619429035
commit fb310724f6
5 changed files with 141 additions and 121 deletions

View File

@ -67,6 +67,7 @@ server_EXTRADEFS = \
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\"
unix_loader_EXTRADEFS = \
-DBINDIR=\"${bindir}\" \
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" \
-DBIN_TO_DATADIR=\"`$(MAKEDEP) -R ${bindir} ${datadir}/wine`\"

View File

@ -1074,6 +1074,7 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd )
static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
const char *unixdir, char *winedebug, const pe_image_info_t *pe_info )
{
const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64);
pid_t pid;
int stdin_fd = -1, stdout_fd = -1;
char **argv;
@ -1103,7 +1104,8 @@ static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int soc
if (winedebug) putenv( winedebug );
if (unixdir) chdir( unixdir );
exec_wineloader( argv, socketfd, pe_info );
unix_funcs->exec_wineloader( argv, socketfd, is_child_64bit,
pe_info->base, pe_info->base + pe_info->map_size );
_exit(1);
}
@ -1533,12 +1535,14 @@ NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status )
if (!status)
{
const int is_child_64bit = (pe_info.cpu == CPU_x86_64 || pe_info.cpu == CPU_ARM64);
char **argv = build_argv( &strW, 2 );
if (argv)
{
do
{
status = exec_wineloader( argv, socketfd[0], &pe_info );
status = unix_funcs->exec_wineloader( argv, socketfd[0], is_child_64bit,
pe_info.base, pe_info.base + pe_info.map_size );
}
#ifdef __APPLE__
while (errno == ENOTSUP && terminate_main_thread());

View File

@ -121,12 +121,6 @@ static const enum cpu_type client_cpu = CPU_ARM64;
#error Unsupported CPU
#endif
#if defined(linux) || defined(__APPLE__)
static const BOOL use_preloader = TRUE;
#else
static const BOOL use_preloader = FALSE;
#endif
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
const char *build_dir = NULL;
@ -1229,119 +1223,6 @@ int server_pipe( int fd[2] )
}
/***********************************************************************
* preloader_exec
*/
static void preloader_exec( char **argv )
{
if (use_preloader)
{
static const char *preloader = "wine-preloader";
char *p;
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
else p++;
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
memcpy( argv[0], argv[1], p - argv[1] );
strcpy( argv[0] + (p - argv[1]), preloader );
#ifdef __APPLE__
{
posix_spawnattr_t attr;
posix_spawnattr_init( &attr );
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
posix_spawnattr_destroy( &attr );
}
#endif
execv( argv[0], argv );
free( argv[0] );
}
execv( argv[1], argv + 1 );
}
/***********************************************************************
* exec_wineloader
*
* argv[0] and argv[1] must be reserved for the preloader and loader respectively.
*/
NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info )
{
const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64);
const char *path, *loader = argv0;
const char *loader_env = getenv( "WINELOADER" );
char *p, preloader_reserve[64], socket_env[64];
ULONGLONG res_start = pe_info->base;
ULONGLONG res_end = pe_info->base + pe_info->map_size;
if (!is_win64 ^ !is_child_64bit)
{
/* remap WINELOADER to the alternate 32/64-bit version if necessary */
if (loader_env)
{
int len = strlen( loader_env );
char *env = malloc( sizeof("WINELOADER=") + len + 2 );
if (!env) return STATUS_NO_MEMORY;
strcpy( env, "WINELOADER=" );
strcat( env, loader_env );
if (is_child_64bit)
{
strcat( env, "64" );
}
else
{
len += sizeof("WINELOADER=") - 1;
if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
}
loader = env;
putenv( env );
}
else loader = is_child_64bit ? "wine64" : "wine";
}
signal( SIGPIPE, SIG_DFL );
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
(ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
putenv( preloader_reserve );
putenv( socket_env );
if (build_dir)
{
argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" );
preloader_exec( argv );
return STATUS_INVALID_IMAGE_FORMAT;
}
if ((p = strrchr( loader, '/' ))) loader = p + 1;
argv[1] = build_path( bin_dir, loader );
preloader_exec( argv );
argv[1] = getenv( "WINELOADER" );
if (argv[1]) preloader_exec( argv );
if ((path = getenv( "PATH" )))
{
for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
{
argv[1] = build_path( p, loader );
preloader_exec( argv );
}
}
argv[1] = build_path( BINDIR, loader );
preloader_exec( argv );
return STATUS_INVALID_IMAGE_FORMAT;
}
/***********************************************************************
* exec_wineserver
*

View File

@ -29,6 +29,7 @@
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
@ -50,6 +51,11 @@
# undef GetCurrentThread
# include <pthread.h>
# include <mach-o/getsect.h>
# include <crt_externs.h>
# include <spawn.h>
# ifndef _POSIX_SPAWN_DISABLE_ASLR
# define _POSIX_SPAWN_DISABLE_ASLR 0x0100
# endif
#endif
#include "ntstatus.h"
@ -76,6 +82,14 @@ extern int __wine_main_argc;
extern char **__wine_main_argv;
extern char **__wine_main_environ;
#if defined(linux) || defined(__APPLE__)
static const BOOL use_preloader = TRUE;
#else
static const BOOL use_preloader = FALSE;
#endif
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
static int main_argc;
static char **main_argv;
static char **main_envp;
@ -344,6 +358,121 @@ static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen )
}
static void preloader_exec( char **argv )
{
if (use_preloader)
{
static const char *preloader = "wine-preloader";
char *p;
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
else p++;
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
memcpy( argv[0], argv[1], p - argv[1] );
strcpy( argv[0] + (p - argv[1]), preloader );
#ifdef __APPLE__
{
posix_spawnattr_t attr;
posix_spawnattr_init( &attr );
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
posix_spawnattr_destroy( &attr );
}
#endif
execv( argv[0], argv );
free( argv[0] );
}
execv( argv[1], argv + 1 );
}
static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit )
{
char *p, *path;
if (build_dir)
{
argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" );
preloader_exec( argv );
return STATUS_INVALID_IMAGE_FORMAT;
}
if ((p = strrchr( loader, '/' ))) loader = p + 1;
argv[1] = build_path( bin_dir, loader );
preloader_exec( argv );
argv[1] = getenv( "WINELOADER" );
if (argv[1]) preloader_exec( argv );
if ((path = getenv( "PATH" )))
{
for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
{
argv[1] = build_path( p, loader );
preloader_exec( argv );
}
}
argv[1] = build_path( BINDIR, loader );
preloader_exec( argv );
return STATUS_INVALID_IMAGE_FORMAT;
}
/***********************************************************************
* exec_wineloader
*
* argv[0] and argv[1] must be reserved for the preloader and loader respectively.
*/
static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_64bit,
ULONGLONG res_start, ULONGLONG res_end )
{
const char *loader = argv0;
const char *loader_env = getenv( "WINELOADER" );
char preloader_reserve[64], socket_env[64];
if (!is_win64 ^ !is_child_64bit)
{
/* remap WINELOADER to the alternate 32/64-bit version if necessary */
if (loader_env)
{
int len = strlen( loader_env );
char *env = malloc( sizeof("WINELOADER=") + len + 2 );
if (!env) return STATUS_NO_MEMORY;
strcpy( env, "WINELOADER=" );
strcat( env, loader_env );
if (is_child_64bit)
{
strcat( env, "64" );
}
else
{
len += sizeof("WINELOADER=") - 1;
if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
}
loader = env;
putenv( env );
}
else loader = is_child_64bit ? "wine64" : "wine";
}
signal( SIGPIPE, SIG_DFL );
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
(ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
putenv( preloader_reserve );
putenv( socket_env );
return loader_exec( loader, argv, is_child_64bit );
}
/*************************************************************************
* map_so_dll
*
@ -619,6 +748,7 @@ static struct unix_funcs unix_funcs =
get_version,
get_build_id,
get_host_version,
exec_wineloader,
map_so_dll,
mmap_add_reserved_area,
mmap_remove_reserved_area,

View File

@ -36,6 +36,10 @@ struct unix_funcs
const char * (CDECL *get_build_id)(void);
void (CDECL *get_host_version)( const char **sysname, const char **release );
/* loader functions */
NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit,
ULONGLONG res_start, ULONGLONG res_end );
/* virtual memory functions */
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size );