diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index a8e7530c0ca..73dfb7b6c7e 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -26,11 +26,15 @@ #include "wine/port.h" #include +#include #include #include #ifdef HAVE_SYS_MMAN_H # include #endif +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif #ifdef HAVE_SYS_UTSNAME_H #include #endif @@ -558,6 +562,121 @@ static void apple_main_thread(void) } #endif /* __APPLE__ */ + +#ifdef __ANDROID__ + +static int pre_exec(void) +{ +#if defined(__i386__) || defined(__x86_64__) + return 1; /* we have a preloader */ +#else + return 0; /* no exec needed */ +#endif +} + +#elif defined(__linux__) && (defined(__i386__) || defined(__arm__)) + +static void check_vmsplit( void *stack ) +{ + if (stack < (void *)0x80000000) + { + /* if the stack is below 0x80000000, assume we can safely try a munmap there */ + if (munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL) + ERR( "Warning: memory above 0x80000000 doesn't seem to be accessible.\n" + "Wine requires a 3G/1G user/kernel memory split to work properly.\n" ); + } +} + +static void set_max_limit( int limit ) +{ + struct rlimit rlimit; + + if (!getrlimit( limit, &rlimit )) + { + rlimit.rlim_cur = rlimit.rlim_max; + setrlimit( limit, &rlimit ); + } +} + +static int pre_exec(void) +{ + int temp; + + check_vmsplit( &temp ); + set_max_limit( RLIMIT_AS ); +#ifdef __i386__ + return 1; /* we have a preloader on x86 */ +#else + return 0; +#endif +} + +#elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__)) + +static int pre_exec(void) +{ + return 1; /* we have a preloader on x86-64/arm64 */ +} + +#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) + +static int pre_exec(void) +{ + return 1; /* we have a preloader */ +} + +#elif (defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__)) + +static int pre_exec(void) +{ + struct rlimit rl; + + rl.rlim_cur = 0x02000000; + rl.rlim_max = 0x02000000; + setrlimit( RLIMIT_DATA, &rl ); + return 1; +} + +#else + +static int pre_exec(void) +{ + return 0; /* no exec needed */ +} + +#endif + + +/*********************************************************************** + * check_command_line + * + * Check if command line is one that needs to be handled specially. + */ +static void check_command_line( int argc, char *argv[] ) +{ + static const char usage[] = + "Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n" + " wine --help Display this help and exit\n" + " wine --version Output version information and exit"; + + if (argc <= 1) + { + fprintf( stderr, "%s\n", usage ); + exit(1); + } + if (!strcmp( argv[1], "--help" )) + { + printf( "%s\n", usage ); + exit(0); + } + if (!strcmp( argv[1], "--version" )) + { + printf( "%s\n", get_build_id() ); + exit(0); + } +} + + /*********************************************************************** * __wine_main * @@ -571,6 +690,21 @@ void __wine_main( int argc, char *argv[], char *envp[] ) HMODULE module; wine_init_argv0_path( argv[0] ); + + if (!getenv( "WINELOADERNOEXEC" )) /* first time around */ + { + static char noexec[] = "WINELOADERNOEXEC=1"; + + putenv( noexec ); + check_command_line( argc, argv ); + if (pre_exec()) + { + wine_exec_wine_binary( NULL, argv, getenv( "WINELOADER" )); + ERR( "could not exec the wine loader\n" ); + exit(1); + } + } + __wine_main_argc = argc; __wine_main_argv = argv; __wine_main_environ = envp; diff --git a/loader/main.c b/loader/main.c index 9f9165ff936..0e6b6f66b50 100644 --- a/loader/main.c +++ b/loader/main.c @@ -279,6 +279,14 @@ int main( int argc, char *argv[] ) int i; void *handle; + if ((handle = load_ntdll( argv[0] ))) + { + void (*init_func)(int, char **, char **) = dlsym( handle, "__wine_main" ); + if (init_func) init_func( argc, argv, environ ); + fprintf( stderr, "wine: __wine_main function not found in ntdll.so\n" ); + exit(1); + } + if (!getenv( "WINELOADERNOEXEC" )) /* first time around */ { static char noexec[] = "WINELOADERNOEXEC=1"; @@ -294,14 +302,6 @@ int main( int argc, char *argv[] ) } } - if ((handle = load_ntdll( argv[0] ))) - { - void (*init_func)(int, char **, char **) = dlsym( handle, "__wine_main" ); - if (init_func) init_func( argc, argv, environ ); - fprintf( stderr, "wine: __wine_main function not found in ntdll.so\n" ); - exit(1); - } - if (wine_main_preload_info) { for (i = 0; wine_main_preload_info[i].size; i++)