Commit b1abca8a authored by Alexandre Julliard's avatar Alexandre Julliard

Initial version of the Wine preloader, used to reserve memory

areas at startup. Based on the work of Mike McCormack.
parent ed8a41c7
...@@ -14180,31 +14180,44 @@ echo "${ECHO_T}$ac_cv_c_export_dynamic" >&6 ...@@ -14180,31 +14180,44 @@ echo "${ECHO_T}$ac_cv_c_export_dynamic" >&6
case $host_cpu in case $host_cpu in
*i[3456789]86*) *i[3456789]86*)
echo "$as_me:$LINENO: checking whether we can relocate the executable to 0x00110000" >&5 echo "$as_me:$LINENO: checking whether we can relocate the executable to 0x77f00000" >&5
echo $ECHO_N "checking whether we can relocate the executable to 0x00110000... $ECHO_C" >&6 echo $ECHO_N "checking whether we can relocate the executable to 0x77f00000... $ECHO_C" >&6
if test "${ac_cv_ld_reloc_exec+set}" = set; then if test "${ac_cv_ld_reloc_exec+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6 echo $ECHO_N "(cached) $ECHO_C" >&6
else else
saved_CFLAGS="$CFLAGS" ac_wine_try_cflags_saved=$CFLAGS
CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x00110400" CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x77f00400"
if test "$cross_compiling" = yes; then cat >conftest.$ac_ext <<_ACEOF
ac_cv_ld_reloc_exec="no"
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */ /* confdefs.h. */
_ACEOF _ACEOF
cat confdefs.h >>conftest.$ac_ext cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */ /* end confdefs.h. */
#include <unistd.h>
int main() { return (sbrk(32*1024*1024) == (void *)-1); } int
main ()
{
;
return 0;
}
_ACEOF _ACEOF
rm -f conftest$ac_exeext rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5 (eval $ac_link) 2>conftest.er1
ac_status=$? ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && { ac_try='./conftest$ac_exeext' (exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5 (eval $ac_try) 2>&5
ac_status=$? ac_status=$?
...@@ -14212,22 +14225,20 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ...@@ -14212,22 +14225,20 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(exit $ac_status); }; }; then (exit $ac_status); }; }; then
ac_cv_ld_reloc_exec="yes" ac_cv_ld_reloc_exec="yes"
else else
echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5 sed 's/^/| /' conftest.$ac_ext >&5
( exit $ac_status )
ac_cv_ld_reloc_exec="no" ac_cv_ld_reloc_exec="no"
fi fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext rm -f conftest.err conftest.$ac_objext \
fi conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saved_CFLAGS" CFLAGS=$ac_wine_try_cflags_saved
fi fi
echo "$as_me:$LINENO: result: $ac_cv_ld_reloc_exec" >&5 echo "$as_me:$LINENO: result: $ac_cv_ld_reloc_exec" >&5
echo "${ECHO_T}$ac_cv_ld_reloc_exec" >&6 echo "${ECHO_T}$ac_cv_ld_reloc_exec" >&6
if test "$ac_cv_ld_reloc_exec" = "yes" if test "$ac_cv_ld_reloc_exec" = "yes"
then then
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x00110400" LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x77f00400"
fi fi
;; ;;
esac esac
...@@ -14528,7 +14539,7 @@ esac ...@@ -14528,7 +14539,7 @@ esac
case $host_os in case $host_os in
linux*) linux*)
WINE_BINARIES="wine-glibc wine-kthread wine-pthread" WINE_BINARIES="wine-glibc wine-kthread wine-pthread wine-preloader"
MAIN_BINARY="wine-glibc" MAIN_BINARY="wine-glibc"
......
...@@ -905,16 +905,12 @@ case $host_os in ...@@ -905,16 +905,12 @@ case $host_os in
case $host_cpu in case $host_cpu in
*i[[3456789]]86*) *i[[3456789]]86*)
AC_CACHE_CHECK([whether we can relocate the executable to 0x00110000], ac_cv_ld_reloc_exec, AC_CACHE_CHECK([whether we can relocate the executable to 0x77f00000], ac_cv_ld_reloc_exec,
[saved_CFLAGS="$CFLAGS" [WINE_TRY_CFLAGS([-Wl,--section-start,.interp=0x77f00400],
CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x00110400" ac_cv_ld_reloc_exec="yes", ac_cv_ld_reloc_exec="no")])
AC_TRY_RUN([#include <unistd.h>
int main() { return (sbrk(32*1024*1024) == (void *)-1); }],
ac_cv_ld_reloc_exec="yes", ac_cv_ld_reloc_exec="no", ac_cv_ld_reloc_exec="no")
CFLAGS="$saved_CFLAGS"])
if test "$ac_cv_ld_reloc_exec" = "yes" if test "$ac_cv_ld_reloc_exec" = "yes"
then then
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x00110400" LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x77f00400"
fi fi
;; ;;
esac esac
...@@ -980,7 +976,7 @@ esac ...@@ -980,7 +976,7 @@ esac
case $host_os in case $host_os in
linux*) linux*)
AC_SUBST(WINE_BINARIES,"wine-glibc wine-kthread wine-pthread") AC_SUBST(WINE_BINARIES,"wine-glibc wine-kthread wine-pthread wine-preloader")
AC_SUBST(MAIN_BINARY,"wine-glibc") AC_SUBST(MAIN_BINARY,"wine-glibc")
;; ;;
*) *)
......
...@@ -1462,10 +1462,10 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW ...@@ -1462,10 +1462,10 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
if (argv && envp) if (argv && envp)
{ {
/* first, try for a WINELOADER environment variable */ /* first, try for a WINELOADER environment variable */
argv[0] = getenv("WINELOADER"); const char *loader = getenv("WINELOADER");
if (argv[0]) execve( argv[0], argv, envp ); if (loader) wine_exec_wine_binary( loader, argv, envp, TRUE );
/* now use the standard search strategy */ /* now use the standard search strategy */
wine_exec_wine_binary( NULL, argv, envp ); wine_exec_wine_binary( NULL, argv, envp, TRUE );
} }
err = errno; err = errno;
write( execfd[1], &err, sizeof(err) ); write( execfd[1], &err, sizeof(err) );
......
...@@ -512,7 +512,7 @@ static void start_server( const char *oldcwd ) ...@@ -512,7 +512,7 @@ static void start_server( const char *oldcwd )
" specified in the WINESERVER environment variable", p ); " specified in the WINESERVER environment variable", p );
} }
/* now use the standard search strategy */ /* now use the standard search strategy */
wine_exec_wine_binary( argv[0], argv, NULL ); wine_exec_wine_binary( argv[0], argv, NULL, FALSE );
fatal_error( "could not exec wineserver\n" ); fatal_error( "could not exec wineserver\n" );
} }
waitpid( pid, &status, 0 ); waitpid( pid, &status, 0 );
...@@ -703,7 +703,7 @@ static void create_config_dir(void) ...@@ -703,7 +703,7 @@ static void create_config_dir(void)
argv[2] = "--prefix"; argv[2] = "--prefix";
argv[3] = tmp_dir; argv[3] = tmp_dir;
argv[4] = NULL; argv[4] = NULL;
wine_exec_wine_binary( argv[0], (char **)argv, NULL ); wine_exec_wine_binary( argv[0], (char **)argv, NULL, FALSE );
rmdir( tmp_dir ); rmdir( tmp_dir );
fatal_perror( "could not exec wineprefixcreate" ); fatal_perror( "could not exec wineprefixcreate" );
} }
......
...@@ -33,7 +33,7 @@ extern const char *wine_get_config_dir(void); ...@@ -33,7 +33,7 @@ extern const char *wine_get_config_dir(void);
extern const char *wine_get_server_dir(void); extern const char *wine_get_server_dir(void);
extern const char *wine_get_user_name(void); extern const char *wine_get_user_name(void);
extern void wine_init_argv0_path( const char *argv0 ); extern void wine_init_argv0_path( const char *argv0 );
extern void wine_exec_wine_binary( const char *name, char **argv, char **envp ); extern void wine_exec_wine_binary( const char *name, char **argv, char **envp, int use_preloader );
/* dll loading */ /* dll loading */
......
...@@ -271,20 +271,50 @@ const char *wine_get_user_name(void) ...@@ -271,20 +271,50 @@ const char *wine_get_user_name(void)
return user_name; return user_name;
} }
/* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
static void preloader_exec( char **argv, char **envp, int use_preloader )
{
#ifdef linux
if (use_preloader)
{
static const char preloader[] = "wine-preloader";
char *p, *full_name;
if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
else p++;
full_name = xmalloc( p - argv[0] + sizeof(preloader) );
memcpy( full_name, argv[0], p - argv[0] );
memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
if (envp) execve( full_name, argv, envp );
else execv( full_name, argv );
free( full_name );
return;
}
#else
if (envp) execve( argv[0], argv, envp );
else execv( argv[0], argv );
#endif
}
/* exec a wine internal binary (either the wine loader or the wine server) */ /* exec a wine internal binary (either the wine loader or the wine server) */
/* if name is null, default to the name of the current binary */ void wine_exec_wine_binary( const char *name, char **argv, char **envp, int use_preloader )
void wine_exec_wine_binary( const char *name, char **argv, char **envp )
{ {
const char *path, *pos, *ptr; const char *path, *pos, *ptr;
if (!envp) envp = environ; if (name && strchr( name, '/' ))
if (!name) name = argv0_name; {
argv[0] = (char *)name;
preloader_exec( argv, envp, use_preloader );
return;
}
else if (!name) name = argv0_name;
/* first, try bin directory */ /* first, try bin directory */
argv[0] = xmalloc( sizeof(BINDIR "/") + strlen(name) ); argv[0] = xmalloc( sizeof(BINDIR "/") + strlen(name) );
strcpy( argv[0], BINDIR "/" ); strcpy( argv[0], BINDIR "/" );
strcat( argv[0], name ); strcat( argv[0], name );
execve( argv[0], argv, envp ); preloader_exec( argv, envp, use_preloader );
free( argv[0] ); free( argv[0] );
/* now try the path of argv0 of the current binary */ /* now try the path of argv0 of the current binary */
...@@ -293,7 +323,7 @@ void wine_exec_wine_binary( const char *name, char **argv, char **envp ) ...@@ -293,7 +323,7 @@ void wine_exec_wine_binary( const char *name, char **argv, char **envp )
argv[0] = xmalloc( strlen(argv0_path) + strlen(name) + 1 ); argv[0] = xmalloc( strlen(argv0_path) + strlen(name) + 1 );
strcpy( argv[0], argv0_path ); strcpy( argv[0], argv0_path );
strcat( argv[0], name ); strcat( argv[0], name );
execve( argv[0], argv, envp ); preloader_exec( argv, envp, use_preloader );
free( argv[0] ); free( argv[0] );
} }
...@@ -310,7 +340,7 @@ void wine_exec_wine_binary( const char *name, char **argv, char **envp ) ...@@ -310,7 +340,7 @@ void wine_exec_wine_binary( const char *name, char **argv, char **envp )
memcpy( argv[0], pos, ptr - pos ); memcpy( argv[0], pos, ptr - pos );
strcpy( argv[0] + (ptr - pos), "/" ); strcpy( argv[0] + (ptr - pos), "/" );
strcat( argv[0] + (ptr - pos), name ); strcat( argv[0] + (ptr - pos), name );
execve( argv[0], argv, envp ); preloader_exec( argv, envp, use_preloader );
pos = ptr; pos = ptr;
} }
free( argv[0] ); free( argv[0] );
......
...@@ -2,4 +2,5 @@ Makefile ...@@ -2,4 +2,5 @@ Makefile
wine wine
wine-glibc wine-glibc
wine-kthread wine-kthread
wine-preloader
wine-pthread wine-pthread
...@@ -8,6 +8,7 @@ C_SRCS = \ ...@@ -8,6 +8,7 @@ C_SRCS = \
glibc.c \ glibc.c \
kthread.c \ kthread.c \
main.c \ main.c \
preloader.c \
pthread.c pthread.c
KTHREAD_OBJS = kthread.o main.o KTHREAD_OBJS = kthread.o main.o
...@@ -24,7 +25,10 @@ LIBPTHREAD = @LIBPTHREAD@ ...@@ -24,7 +25,10 @@ LIBPTHREAD = @LIBPTHREAD@
LDEXECFLAGS = @LDEXECFLAGS@ LDEXECFLAGS = @LDEXECFLAGS@
wine-glibc: glibc.o Makefile.in wine-glibc: glibc.o Makefile.in
$(CC) -o $@ $(LDEXECFLAGS) glibc.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(CC) -o $@ glibc.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS)
wine-preloader: preloader.o Makefile.in
$(CC) -o $@ -static -nostartfiles -Wl,-Ttext=0x78000000 preloader.o $(LIBPORT) $(LDFLAGS)
wine-kthread: $(KTHREAD_OBJS) Makefile.in wine-kthread: $(KTHREAD_OBJS) Makefile.in
$(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS) $(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS)
......
...@@ -93,13 +93,12 @@ int main( int argc, char *argv[] ) ...@@ -93,13 +93,12 @@ int main( int argc, char *argv[] )
strcpy( new_loader, "WINELOADER=" ); strcpy( new_loader, "WINELOADER=" );
strcat( new_loader, new_name ); strcat( new_loader, new_name );
putenv( new_loader ); putenv( new_loader );
argv[0] = new_name; wine_exec_wine_binary( new_name, argv, NULL, TRUE );
execv( argv[0], argv );
} }
else else
{ {
wine_init_argv0_path( argv[0] ); wine_init_argv0_path( argv[0] );
wine_exec_wine_binary( threads, argv, NULL ); wine_exec_wine_binary( threads, argv, NULL, TRUE );
} }
fprintf( stderr, "wine: could not exec %s\n", argv[0] ); fprintf( stderr, "wine: could not exec %s\n", argv[0] );
exit(1); exit(1);
......
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "wine/library.h" #include "wine/library.h"
#include "main.h"
/* the preloader will set this variable */
const struct wine_preload_info *wine_main_preload_info = NULL;
/********************************************************************** /**********************************************************************
* main * main
...@@ -28,6 +32,14 @@ ...@@ -28,6 +32,14 @@
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
{ {
char error[1024]; char error[1024];
int i;
if (wine_main_preload_info)
{
for (i = 0; wine_main_preload_info[i].size; i++)
wine_mmap_add_reserved_area( wine_main_preload_info[i].addr,
wine_main_preload_info[i].size );
}
wine_init( argc, argv, error, sizeof(error) ); wine_init( argc, argv, error, sizeof(error) );
fprintf( stderr, "wine: failed to initialize: %s\n", error ); fprintf( stderr, "wine: failed to initialize: %s\n", error );
......
/*
* Definitions for Wine main program
*
* Copyright 2004 Mike McCormack for Codeweavers
* Copyright 2004 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_LOADER_MAIN_H
#define __WINE_LOADER_MAIN_H
struct wine_preload_info
{
void *addr;
size_t size;
};
#endif /* __WINE_LOADER_MAIN_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment