loader: Build the preloader for x86-64.
This commit is contained in:
parent
fe031c937d
commit
0a0862001b
1
.gitignore
vendored
1
.gitignore
vendored
@ -262,6 +262,7 @@ loader/wine
|
|||||||
loader/wine-installed
|
loader/wine-installed
|
||||||
loader/wine-preloader
|
loader/wine-preloader
|
||||||
loader/wine64
|
loader/wine64
|
||||||
|
loader/wine64-preloader
|
||||||
programs/Makeprog.rules
|
programs/Makeprog.rules
|
||||||
programs/rpcss/epm.h
|
programs/rpcss/epm.h
|
||||||
programs/rpcss/epm_s.c
|
programs/rpcss/epm_s.c
|
||||||
|
7
configure
vendored
7
configure
vendored
@ -12736,11 +12736,12 @@ MAIN_BINARY="wine"
|
|||||||
|
|
||||||
test "x$enable_win64" != "xyes" || MAIN_BINARY="wine64"
|
test "x$enable_win64" != "xyes" || MAIN_BINARY="wine64"
|
||||||
|
|
||||||
case $host_cpu in
|
|
||||||
*i[3456789]86*)
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
linux*)
|
linux*)
|
||||||
EXTRA_BINARIES="wine-preloader"
|
case $host_cpu in
|
||||||
|
*i[3456789]86*) EXTRA_BINARIES="wine-preloader"
|
||||||
|
;;
|
||||||
|
x86_64*) EXTRA_BINARIES="wine64-preloader"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
@ -1863,11 +1863,11 @@ esac
|
|||||||
AC_SUBST(MAIN_BINARY,"wine")
|
AC_SUBST(MAIN_BINARY,"wine")
|
||||||
test "x$enable_win64" != "xyes" || MAIN_BINARY="wine64"
|
test "x$enable_win64" != "xyes" || MAIN_BINARY="wine64"
|
||||||
|
|
||||||
case $host_cpu in
|
|
||||||
*i[[3456789]]86*)
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
linux*)
|
linux*)
|
||||||
AC_SUBST(EXTRA_BINARIES,"wine-preloader") ;;
|
case $host_cpu in
|
||||||
|
*i[[3456789]]86*) AC_SUBST(EXTRA_BINARIES,"wine-preloader") ;;
|
||||||
|
x86_64*) AC_SUBST(EXTRA_BINARIES,"wine64-preloader") ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -9,9 +9,10 @@ EXTRA_BINARIES = @EXTRA_BINARIES@
|
|||||||
|
|
||||||
PROGRAMS = \
|
PROGRAMS = \
|
||||||
wine \
|
wine \
|
||||||
wine64 \
|
|
||||||
wine-installed \
|
wine-installed \
|
||||||
wine-preloader
|
wine-preloader \
|
||||||
|
wine64 \
|
||||||
|
wine64-preloader
|
||||||
|
|
||||||
MANPAGE = wine.man
|
MANPAGE = wine.man
|
||||||
|
|
||||||
@ -32,8 +33,8 @@ all: $(MAIN_BINARY) wine-installed $(EXTRA_BINARIES)
|
|||||||
LIBPTHREAD = @LIBPTHREAD@
|
LIBPTHREAD = @LIBPTHREAD@
|
||||||
LDEXECFLAGS = @LDEXECFLAGS@
|
LDEXECFLAGS = @LDEXECFLAGS@
|
||||||
|
|
||||||
wine-preloader: preloader.o Makefile.in
|
wine-preloader wine64-preloader: preloader.o Makefile.in
|
||||||
$(CC) -o $@ -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c000000 preloader.o $(LIBPORT) $(LDFLAGS)
|
$(CC) -o $@ -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000 preloader.o $(LIBPORT) $(LDFLAGS)
|
||||||
|
|
||||||
$(MAIN_BINARY): main.o Makefile.in
|
$(MAIN_BINARY): main.o Makefile.in
|
||||||
$(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_LOCAL)
|
$(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_LOCAL)
|
||||||
|
@ -164,6 +164,13 @@ static int pre_exec(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__linux__) && defined(__x86_64__)
|
||||||
|
|
||||||
|
static int pre_exec(void)
|
||||||
|
{
|
||||||
|
return 1; /* we have a preloader on x86-64 */
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__FreeBSD__) && defined(__i386__)
|
#elif defined(__FreeBSD__) && defined(__i386__)
|
||||||
|
|
||||||
static int pre_exec(void)
|
static int pre_exec(void)
|
||||||
|
@ -108,10 +108,17 @@
|
|||||||
|
|
||||||
static struct wine_preload_info preload_info[] =
|
static struct wine_preload_info preload_info[] =
|
||||||
{
|
{
|
||||||
|
#ifdef __i386__
|
||||||
{ (void *)0x00000000, 0x00010000 }, /* low 64k */
|
{ (void *)0x00000000, 0x00010000 }, /* low 64k */
|
||||||
{ (void *)0x00010000, 0x00100000 }, /* DOS area */
|
{ (void *)0x00010000, 0x00100000 }, /* DOS area */
|
||||||
{ (void *)0x00110000, 0x67ef0000 }, /* low memory area */
|
{ (void *)0x00110000, 0x67ef0000 }, /* low memory area */
|
||||||
{ (void *)0x7f000000, 0x03000000 }, /* top-down allocations + shared heap + virtual heap */
|
{ (void *)0x7f000000, 0x03000000 }, /* top-down allocations + shared heap + virtual heap */
|
||||||
|
#else
|
||||||
|
{ (void *)0x000000010000, 0x00100000 }, /* DOS area */
|
||||||
|
{ (void *)0x000000110000, 0x67ef0000 }, /* low memory area */
|
||||||
|
{ (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */
|
||||||
|
{ (void *)0x7ffffe000000, 0x01ff0000 }, /* top-down allocations + virtual heap */
|
||||||
|
#endif
|
||||||
{ 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */
|
{ 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */
|
||||||
{ 0, 0 } /* end of list */
|
{ 0, 0 } /* end of list */
|
||||||
};
|
};
|
||||||
@ -166,6 +173,8 @@ void *__stack_chk_guard = 0;
|
|||||||
void __stack_chk_fail_local(void) { return; }
|
void __stack_chk_fail_local(void) { return; }
|
||||||
void __stack_chk_fail(void) { return; }
|
void __stack_chk_fail(void) { return; }
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
/* data for setting up the glibc-style thread-local storage in %gs */
|
/* data for setting up the glibc-style thread-local storage in %gs */
|
||||||
|
|
||||||
static int thread_data[256];
|
static int thread_data[256];
|
||||||
@ -333,6 +342,126 @@ static inline int wld_prctl( int code, long arg )
|
|||||||
return SYSCALL_RET(ret);
|
return SYSCALL_RET(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The _start function is the entry and exit point of this program
|
||||||
|
*
|
||||||
|
* It calls wld_start, passing a pointer to the args it receives
|
||||||
|
* then jumps to the address wld_start returns.
|
||||||
|
*/
|
||||||
|
void _start(void);
|
||||||
|
extern char _end[];
|
||||||
|
__ASM_GLOBAL_FUNC(_start,
|
||||||
|
"movq %rsp,%rax\n\t"
|
||||||
|
"leaq -144(%rsp),%rsp\n\t" /* allocate some space for extra aux values */
|
||||||
|
"movq %rsp,%rdi\n\t" /* ptr to orig stack pointer */
|
||||||
|
"movq %rax,(%rdi)\n\t" /* orig stack pointer */
|
||||||
|
"call wld_start\n\t"
|
||||||
|
"movq (%rsp),%rsp\n\t" /* new stack pointer */
|
||||||
|
"pushq %rax\n\t" /* ELF interpreter entry point */
|
||||||
|
"xorq %rax,%rax\n\t"
|
||||||
|
"xorq %rcx,%rcx\n\t"
|
||||||
|
"xorq %rdx,%rdx\n\t"
|
||||||
|
"xorq %rsi,%rsi\n\t"
|
||||||
|
"xorq %rdi,%rdi\n\t"
|
||||||
|
"xorq %r8,%r8\n\t"
|
||||||
|
"xorq %r9,%r9\n\t"
|
||||||
|
"xorq %r10,%r10\n\t"
|
||||||
|
"xorq %r11,%r11\n\t"
|
||||||
|
"ret")
|
||||||
|
|
||||||
|
#define SYSCALL_RET(ret) (((ret) < 0 && (ret) > -4096) ? -1 : (ret))
|
||||||
|
|
||||||
|
static inline __attribute__((noreturn)) void wld_exit( int code )
|
||||||
|
{
|
||||||
|
for (;;) /* avoid warning */
|
||||||
|
__asm__ __volatile__( "syscall" : : "a" (SYS_exit), "D" (code) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wld_open( const char *name, int flags )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall" : "=a" (ret) : "0" (SYS_open), "D" (name), "S" (flags) );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wld_close( int fd )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall" : "=a" (ret) : "0" (SYS_close), "D" (fd) );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ssize_t wld_read( int fd, void *buffer, size_t len )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall"
|
||||||
|
: "=a" (ret)
|
||||||
|
: "0" (SYS_read), "D" (fd), "S" (buffer), "d" (len)
|
||||||
|
: "memory" );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ssize_t wld_write( int fd, const void *buffer, size_t len )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall" : "=a" (ret) : "0" (SYS_write), "D" (fd), "S" (buffer), "d" (len) );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wld_mprotect( const void *addr, size_t len, int prot )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall" : "=a" (ret) : "0" (SYS_mprotect), "D" (addr), "S" (len), "d" (prot) );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
|
||||||
|
__ASM_GLOBAL_FUNC( wld_mmap,
|
||||||
|
"movq %rcx,%r10\n\t"
|
||||||
|
"movq $9,%rax\n\t" /* SYS_mmap */
|
||||||
|
"syscall\n\t"
|
||||||
|
"ret" );
|
||||||
|
|
||||||
|
static inline uid_t wld_getuid(void)
|
||||||
|
{
|
||||||
|
uid_t ret;
|
||||||
|
__asm__( "syscall" : "=a" (ret) : "0" (SYS_getuid) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uid_t wld_geteuid(void)
|
||||||
|
{
|
||||||
|
uid_t ret;
|
||||||
|
__asm__( "syscall" : "=a" (ret) : "0" (SYS_geteuid) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gid_t wld_getgid(void)
|
||||||
|
{
|
||||||
|
gid_t ret;
|
||||||
|
__asm__( "syscall" : "=a" (ret) : "0" (SYS_getgid) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gid_t wld_getegid(void)
|
||||||
|
{
|
||||||
|
gid_t ret;
|
||||||
|
__asm__( "syscall" : "=a" (ret) : "0" (SYS_getegid) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wld_prctl( int code, int arg )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
__asm__ __volatile__( "syscall" : "=a" (ret) : "D" (SYS_prctl), "S" (code), "d" (arg) );
|
||||||
|
return SYSCALL_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error preloader not implemented for this CPU
|
||||||
|
#endif
|
||||||
|
|
||||||
/* replacement for libc functions */
|
/* replacement for libc functions */
|
||||||
|
|
||||||
@ -594,8 +723,13 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||||||
( header->e_ident[3] != 'F' ) )
|
( header->e_ident[3] != 'F' ) )
|
||||||
fatal_error( "%s: not an ELF binary... don't know how to load it\n", name );
|
fatal_error( "%s: not an ELF binary... don't know how to load it\n", name );
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
if( header->e_machine != EM_386 )
|
if( header->e_machine != EM_386 )
|
||||||
fatal_error("%s: not an i386 ELF binary... don't know how to load it\n", name );
|
fatal_error("%s: not an i386 ELF binary... don't know how to load it\n", name );
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
if( header->e_machine != EM_X86_64 )
|
||||||
|
fatal_error("%s: not an x86-64 ELF binary... don't know how to load it\n", name );
|
||||||
|
#endif
|
||||||
|
|
||||||
if (header->e_phnum > sizeof(loadcmds)/sizeof(loadcmds[0]))
|
if (header->e_phnum > sizeof(loadcmds)/sizeof(loadcmds[0]))
|
||||||
fatal_error( "%s: oops... not enough space for load commands\n", name );
|
fatal_error( "%s: oops... not enough space for load commands\n", name );
|
||||||
@ -1082,7 +1216,13 @@ void* wld_start( void **stack )
|
|||||||
if (reserve) preload_reserve( reserve );
|
if (reserve) preload_reserve( reserve );
|
||||||
for (i = 0; preload_info[i].size; i++)
|
for (i = 0; preload_info[i].size; i++)
|
||||||
{
|
{
|
||||||
if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
|
if ((char *)av >= (char *)preload_info[i].addr &&
|
||||||
|
(char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
|
{
|
||||||
|
remove_preload_range( i );
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
|
||||||
MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 ) == (void *)-1)
|
MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 ) == (void *)-1)
|
||||||
{
|
{
|
||||||
/* don't warn for low 64k */
|
/* don't warn for low 64k */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user