ntdll: Move the wineloader exec support to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e619429035
commit
fb310724f6
|
@ -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`\"
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue