From: probono Subject: [PATCH] Allow to specify private ld-linux Message-Id: Date: Wed, 12 Dec 2018 07:49:50 +0100 This patch allows to tell Wine to use a privately bundled ld-linux.so.2 (and related glibc and other libraries) instead of looking for them in the host system. This greatly simplifies packaging Wine as a self-standing bundle for Linux (e.g., AppDir, AppImage), making it possible to run Wine without installation, even on 64-bit systems on which 32-bit compatibility libraries are not installed. The problem statement has been described in more detail by me in https://www.winehq.org/pipermail/wine-devel/2017-November/119906.html The approach was suggested by Alexandre Julliard in https://www.winehq.org/pipermail/wine-devel/2017-November/119944.html All credit for this patch goes to Hackerl, on whose behalf I am posting. Source: https://github.com/Hackerl/wine/commit/4f7f784.patch Discussion: https://github.com/Hackerl/Wine_Appimage/issues/11 From: Hackerl <490021209@qq.com> Signed-off-by: Hackerl <490021209@qq.com> --- libs/wine/config.c | 21 ++++++++++++++++++++- loader/preloader.c | 10 +++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libs/wine/config.c b/libs/wine/config.c index 083e263ee3d..e89c2c63a95 100644 --- a/libs/wine/config.c +++ b/libs/wine/config.c @@ -562,7 +562,26 @@ static void preloader_exec( char **argv, int use_preloader ) free( new_argv ); free( full_name ); } - execv( argv[0], argv ); + else + { + char * wineloader = getenv("WINELDLIBRARY"); + + if (wineloader == NULL) + execv( argv[0], argv ); + + char **last_arg = argv; + + while (*last_arg) last_arg++; + + char ** new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) ); + memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) ); + + new_argv[0] = wineloader; + + execv(wineloader, new_argv); + + free( new_argv ); + } } /* exec a wine internal binary (either the wine loader or the wine server) */ diff --git a/loader/preloader.c b/loader/preloader.c index 13a6ad86b20..55af8383773 100644 --- a/loader/preloader.c +++ b/loader/preloader.c @@ -1255,7 +1255,7 @@ void* wld_start( void **stack ) { long i, *pargc; char **argv, **p; - char *interp, *reserve = NULL; + char *interp = NULL, *reserve = NULL; struct wld_auxv new_av[8], delete_av[3], *av; struct wld_link_map main_binary_map, ld_so_map; struct wine_preload_info **wine_main_preload_info; @@ -1270,8 +1270,11 @@ void* wld_start( void **stack ) /* skip over the environment */ while (*p) { - static const char res[] = "WINEPRELOADRESERVE="; + static const char res[] = "WINEPRELOADRESERVE=", loader[] = "WINELDLIBRARY="; + if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1; + if (!wld_strncmp( *p, loader, sizeof(loader)-1 )) interp = *p + sizeof(loader) - 1; + p++; } @@ -1323,7 +1326,8 @@ void* wld_start( void **stack ) map_so_lib( argv[1], &main_binary_map ); /* load the ELF interpreter */ - interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp; + if (interp == NULL) + interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp; map_so_lib( interp, &ld_so_map ); /* store pointer to the preload info into the appropriate main binary variable */