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
case $host_cpu in
*i[3456789]86*)
echo "$as_me:$LINENO: checking whether we can relocate the executable to 0x00110000" >&5
echo $ECHO_N "checking whether we can relocate the executable to 0x00110000... $ECHO_C" >&6
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 0x77f00000... $ECHO_C" >&6
if test "${ac_cv_ld_reloc_exec+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x00110400"
if test "$cross_compiling" = yes; then
ac_cv_ld_reloc_exec="no"
else
cat >conftest.$ac_ext <<_ACEOF
ac_wine_try_cflags_saved=$CFLAGS
CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x77f00400"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <unistd.h>
int main() { return (sbrk(32*1024*1024) == (void *)-1); }
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest$ac_exeext
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&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 $ac_try) 2>&5
ac_status=$?
......@@ -14212,22 +14225,20 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(exit $ac_status); }; }; then
ac_cv_ld_reloc_exec="yes"
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
( exit $ac_status )
ac_cv_ld_reloc_exec="no"
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
CFLAGS="$saved_CFLAGS"
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$ac_wine_try_cflags_saved
fi
echo "$as_me:$LINENO: result: $ac_cv_ld_reloc_exec" >&5
echo "${ECHO_T}$ac_cv_ld_reloc_exec" >&6
if test "$ac_cv_ld_reloc_exec" = "yes"
then
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x00110400"
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x77f00400"
fi
;;
esac
......@@ -14528,7 +14539,7 @@ esac
case $host_os in
linux*)
WINE_BINARIES="wine-glibc wine-kthread wine-pthread"
WINE_BINARIES="wine-glibc wine-kthread wine-pthread wine-preloader"
MAIN_BINARY="wine-glibc"
......
......@@ -905,16 +905,12 @@ case $host_os in
case $host_cpu in
*i[[3456789]]86*)
AC_CACHE_CHECK([whether we can relocate the executable to 0x00110000], ac_cv_ld_reloc_exec,
[saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wl,--section-start,.interp=0x00110400"
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"])
AC_CACHE_CHECK([whether we can relocate the executable to 0x77f00000], ac_cv_ld_reloc_exec,
[WINE_TRY_CFLAGS([-Wl,--section-start,.interp=0x77f00400],
ac_cv_ld_reloc_exec="yes", ac_cv_ld_reloc_exec="no")])
if test "$ac_cv_ld_reloc_exec" = "yes"
then
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x00110400"
LDEXECFLAGS="$LDEXECFLAGS -Wl,--section-start,.interp=0x77f00400"
fi
;;
esac
......@@ -980,7 +976,7 @@ esac
case $host_os in
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")
;;
*)
......
......@@ -1462,10 +1462,10 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
if (argv && envp)
{
/* first, try for a WINELOADER environment variable */
argv[0] = getenv("WINELOADER");
if (argv[0]) execve( argv[0], argv, envp );
const char *loader = getenv("WINELOADER");
if (loader) wine_exec_wine_binary( loader, argv, envp, TRUE );
/* now use the standard search strategy */
wine_exec_wine_binary( NULL, argv, envp );
wine_exec_wine_binary( NULL, argv, envp, TRUE );
}
err = errno;
write( execfd[1], &err, sizeof(err) );
......
......@@ -512,7 +512,7 @@ static void start_server( const char *oldcwd )
" specified in the WINESERVER environment variable", p );
}
/* 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" );
}
waitpid( pid, &status, 0 );
......@@ -703,7 +703,7 @@ static void create_config_dir(void)
argv[2] = "--prefix";
argv[3] = tmp_dir;
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 );
fatal_perror( "could not exec wineprefixcreate" );
}
......
......@@ -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_user_name(void);
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 */
......
......@@ -271,20 +271,50 @@ const char *wine_get_user_name(void)
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) */
/* if name is null, default to the name of the current binary */
void wine_exec_wine_binary( const char *name, char **argv, char **envp )
void wine_exec_wine_binary( const char *name, char **argv, char **envp, int use_preloader )
{
const char *path, *pos, *ptr;
if (!envp) envp = environ;
if (!name) name = argv0_name;
if (name && strchr( name, '/' ))
{
argv[0] = (char *)name;
preloader_exec( argv, envp, use_preloader );
return;
}
else if (!name) name = argv0_name;
/* first, try bin directory */
argv[0] = xmalloc( sizeof(BINDIR "/") + strlen(name) );
strcpy( argv[0], BINDIR "/" );
strcat( argv[0], name );
execve( argv[0], argv, envp );
preloader_exec( argv, envp, use_preloader );
free( argv[0] );
/* 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 )
argv[0] = xmalloc( strlen(argv0_path) + strlen(name) + 1 );
strcpy( argv[0], argv0_path );
strcat( argv[0], name );
execve( argv[0], argv, envp );
preloader_exec( argv, envp, use_preloader );
free( argv[0] );
}
......@@ -310,7 +340,7 @@ void wine_exec_wine_binary( const char *name, char **argv, char **envp )
memcpy( argv[0], pos, ptr - pos );
strcpy( argv[0] + (ptr - pos), "/" );
strcat( argv[0] + (ptr - pos), name );
execve( argv[0], argv, envp );
preloader_exec( argv, envp, use_preloader );
pos = ptr;
}
free( argv[0] );
......
......@@ -2,4 +2,5 @@ Makefile
wine
wine-glibc
wine-kthread
wine-preloader
wine-pthread
......@@ -8,6 +8,7 @@ C_SRCS = \
glibc.c \
kthread.c \
main.c \
preloader.c \
pthread.c
KTHREAD_OBJS = kthread.o main.o
......@@ -24,7 +25,10 @@ LIBPTHREAD = @LIBPTHREAD@
LDEXECFLAGS = @LDEXECFLAGS@
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
$(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS)
......
......@@ -93,13 +93,12 @@ int main( int argc, char *argv[] )
strcpy( new_loader, "WINELOADER=" );
strcat( new_loader, new_name );
putenv( new_loader );
argv[0] = new_name;
execv( argv[0], argv );
wine_exec_wine_binary( new_name, argv, NULL, TRUE );
}
else
{
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] );
exit(1);
......
......@@ -21,6 +21,10 @@
#include <stdio.h>
#include <stdlib.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
......@@ -28,6 +32,14 @@
int main( int argc, char *argv[] )
{
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) );
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