mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to implement preloader for Mac OS.
This commit is contained in:
parent
5392d42292
commit
b5d451ae12
@ -0,0 +1,49 @@
|
||||
From 3174d46a02a1112d2f31a16ad895731fbbaddf21 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Mon, 12 Jun 2017 00:18:37 +0200
|
||||
Subject: libs/wine: Do not restrict base address of main thread on 64 bit mac
|
||||
os.
|
||||
|
||||
---
|
||||
libs/wine/loader.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libs/wine/loader.c b/libs/wine/loader.c
|
||||
index e362a1d1939..5f37dc978ba 100644
|
||||
--- a/libs/wine/loader.c
|
||||
+++ b/libs/wine/loader.c
|
||||
@@ -700,6 +700,7 @@ struct apple_stack_info
|
||||
* Callback for wine_mmap_enum_reserved_areas to allocate space for
|
||||
* the secondary thread's stack.
|
||||
*/
|
||||
+#ifndef _WIN64
|
||||
static int apple_alloc_thread_stack( void *base, size_t size, void *arg )
|
||||
{
|
||||
struct apple_stack_info *info = arg;
|
||||
@@ -716,6 +717,7 @@ static int apple_alloc_thread_stack( void *base, size_t size, void *arg )
|
||||
info->desired_size, PROT_READ|PROT_WRITE, MAP_FIXED );
|
||||
return (info->stack != (void *)-1);
|
||||
}
|
||||
+#endif
|
||||
|
||||
/***********************************************************************
|
||||
* apple_create_wine_thread
|
||||
@@ -733,6 +735,7 @@ static void apple_create_wine_thread( void *init_func )
|
||||
|
||||
if (!pthread_attr_init( &attr ))
|
||||
{
|
||||
+#ifndef _WIN64
|
||||
struct apple_stack_info info;
|
||||
|
||||
/* Try to put the new thread's stack in the reserved area. If this
|
||||
@@ -744,6 +747,7 @@ static void apple_create_wine_thread( void *init_func )
|
||||
wine_mmap_remove_reserved_area( info.stack, info.desired_size, 0 );
|
||||
pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size );
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (!pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ) &&
|
||||
!pthread_create( &thread, &attr, init_func, NULL ))
|
||||
--
|
||||
2.13.1
|
||||
|
@ -0,0 +1,723 @@
|
||||
From e3a9a59d25e11351bf8ff6ed0578c5defbad84ae Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 12 Jun 2017 00:16:08 +0200
|
||||
Subject: loader: Implement preloader for Mac OS.
|
||||
|
||||
---
|
||||
Makefile.in | 1 +
|
||||
configure.ac | 32 ++++-
|
||||
dlls/ntdll/virtual.c | 2 -
|
||||
libs/wine/config.c | 2 +-
|
||||
loader/Makefile.in | 4 +-
|
||||
loader/main.c | 44 ++----
|
||||
loader/preloader.c | 386 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
7 files changed, 420 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 22b2ae72305..29b6cbdd535 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -89,6 +89,7 @@ WINELOADER_PROGRAMS = @WINELOADER_PROGRAMS@
|
||||
WINELOADER_DEPENDS = @WINELOADER_DEPENDS@
|
||||
WINELOADER_INSTALL = @WINELOADER_INSTALL@
|
||||
WINELOADER_LDFLAGS = @WINELOADER_LDFLAGS@
|
||||
+WINEPRELOADER_LDFLAGS = @WINEPRELOADER_LDFLAGS@
|
||||
LIBWINE_SHAREDLIB = @LIBWINE_SHAREDLIB@
|
||||
LIBWINE_IMPORTLIB = @LIBWINE_IMPORTLIB@
|
||||
LIBWINE_INSTALL_LIB = @LIBWINE_INSTALL_LIB@
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5aaa20c22b6..433e7fa959c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -709,6 +709,7 @@ AC_SUBST(LDRPATH_INSTALL,"")
|
||||
AC_SUBST(LDRPATH_LOCAL,"")
|
||||
AC_SUBST(LDEXECFLAGS,"")
|
||||
AC_SUBST(WINELOADER_LDFLAGS,"")
|
||||
+AC_SUBST(WINEPRELOADER_LDFLAGS,"")
|
||||
LIBEXT="so"
|
||||
DLLEXT=".so"
|
||||
IMPLIBEXT="def"
|
||||
@@ -767,9 +768,26 @@ case $host_os in
|
||||
AC_SUBST(APPLICATIONSERVICES_LIBS,"-framework ApplicationServices")
|
||||
AC_SUBST(CORESERVICES_LIBS,"-framework CoreServices")
|
||||
AC_SUBST(APPKIT_LIBS,"-framework AppKit")
|
||||
- WINELOADER_LDFLAGS="-image_base 0x7bf00000 -Wl,-pagezero_size,0x1000,-segaddr,WINE_DOS,0x00001000,-segaddr,WINE_SHAREDHEAP,0x7f000000,-sectcreate,__TEXT,__info_plist,wine_info.plist"
|
||||
+
|
||||
+ WINELOADER_LDFLAGS="-Wl,-image_base,0x7bf00000,-pie,-sectcreate,__TEXT,__info_plist,wine_info.plist"
|
||||
+ WINE_TRY_CFLAGS([-fPIC -Wl,--export-dynamic],
|
||||
+ [WINELOADER_LDFLAGS="-Wl,--export-dynamic $WINELOADER_LDFLAGS"])
|
||||
+
|
||||
+ WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7c400000,-sectcreate,__TEXT,__info_plist,wine_info.plist"
|
||||
+ WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main],
|
||||
+ [WINEPRELOADER_LDFLAGS="-Wl,-no_new_main $WINEPRELOADER_LDFLAGS"])
|
||||
WINE_TRY_CFLAGS([-Wl,-no_pie],
|
||||
- [WINELOADER_LDFLAGS="-Wl,-no_pie $WINELOADER_LDFLAGS"])
|
||||
+ [WINEPRELOADER_LDFLAGS="-Wl,-no_pie $WINEPRELOADER_LDFLAGS"])
|
||||
+
|
||||
+ case $host_cpu in
|
||||
+ *i[[3456789]]86*)
|
||||
+ WINELOADER_LDFLAGS="-Wl,-pagezero_size,0x0 $WINELOADER_LDFLAGS"
|
||||
+ WINEPRELOADER_LDFLAGS="-Wl,-pagezero_size,0x0 $WINEPRELOADER_LDFLAGS" ;;
|
||||
+ *x86_64*)
|
||||
+ WINELOADER_LDFLAGS="-Wl,-pagezero_size,0x1000 $WINELOADER_LDFLAGS"
|
||||
+ WINEPRELOADER_LDFLAGS="-Wl,-pagezero_size,0x1000 $WINEPRELOADER_LDFLAGS" ;;
|
||||
+ esac
|
||||
+
|
||||
if test "$ac_cv_header_DiskArbitration_DiskArbitration_h" = "yes"
|
||||
then
|
||||
dnl DiskArbitration API is not public on Darwin < 8.0, use it only if header found
|
||||
@@ -882,6 +900,7 @@ case $host_os in
|
||||
enable_wineandroid_drv=${enable_wineandroid_drv:-yes}
|
||||
WINE_TRY_CFLAGS([-fPIC -Wl,--export-dynamic],
|
||||
[WINELOADER_LDFLAGS="-Wl,--export-dynamic"])
|
||||
+ WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000"
|
||||
WINE_TRY_CFLAGS([-fPIC -Wl,--rpath,\$ORIGIN/../lib],
|
||||
[LDRPATH_INSTALL="-Wl,--rpath,\\\$\$ORIGIN/\`\$(MAKEDEP) -R \${bindir} \${libdir}\`"
|
||||
LDRPATH_LOCAL="-Wl,--rpath,\\\$\$ORIGIN/\$(top_builddir)/libs/wine"],
|
||||
@@ -926,6 +945,7 @@ case $host_os in
|
||||
|
||||
WINE_TRY_CFLAGS([-fPIC -Wl,--export-dynamic],
|
||||
[WINELOADER_LDFLAGS="-Wl,--export-dynamic"])
|
||||
+ WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000"
|
||||
|
||||
WINE_TRY_CFLAGS([-fPIC -Wl,--rpath,\$ORIGIN/../lib],
|
||||
[LDRPATH_INSTALL="-Wl,--rpath,\\\$\$ORIGIN/\`\$(MAKEDEP) -R \${bindir} \${libdir}\`:\$(DESTDIR)\${libdir}"
|
||||
@@ -2085,6 +2105,14 @@ case $host_os in
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
+ darwin*|macosx*)
|
||||
+ case $host_cpu in
|
||||
+ *i[[3456789]]86*|x86_64*)
|
||||
+ test "$wine_binary" = wine || WINE_IGNORE_FILE("loader/wine-preloader")
|
||||
+ WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
|
||||
+ ;;
|
||||
+ esac
|
||||
+ ;;
|
||||
esac
|
||||
|
||||
dnl **** Check for functions ****
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 0d3fa1e5715..3a280a4b0d8 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -1941,11 +1941,9 @@ void virtual_release_address_space(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
-#ifndef __APPLE__ /* dyld doesn't support parts of the WINE_DOS segment being unmapped */
|
||||
range.base = (char *)0x20000000;
|
||||
range.limit = (char *)0x7f000000;
|
||||
while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */;
|
||||
-#endif
|
||||
}
|
||||
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
diff --git a/libs/wine/config.c b/libs/wine/config.c
|
||||
index 7daf38a07b5..7223ecd89cf 100644
|
||||
--- a/libs/wine/config.c
|
||||
+++ b/libs/wine/config.c
|
||||
@@ -1709,7 +1709,7 @@ void wine_exec_wine_binary( const char *name, char **argv, const char *env_var )
|
||||
|
||||
if (!name) name = argv0_name; /* no name means default loader */
|
||||
|
||||
-#ifdef linux
|
||||
+#if defined(linux) || defined(__APPLE__)
|
||||
use_preloader = !strendswith( name, "wineserver" );
|
||||
#else
|
||||
use_preloader = 0;
|
||||
diff --git a/loader/Makefile.in b/loader/Makefile.in
|
||||
index 4fb91ff5417..b715f022578 100644
|
||||
--- a/loader/Makefile.in
|
||||
+++ b/loader/Makefile.in
|
||||
@@ -26,7 +26,7 @@ wine64_DEPS = $(WINELOADER_DEPENDS)
|
||||
wine64_LDFLAGS = $(WINELOADER_LDFLAGS) $(LDEXECFLAGS) -lwine $(PTHREAD_LIBS)
|
||||
|
||||
wine_preloader_OBJS = preloader.o
|
||||
-wine_preloader_LDFLAGS = -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000
|
||||
+wine_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS)
|
||||
|
||||
wine64_preloader_OBJS = preloader.o
|
||||
-wine64_preloader_LDFLAGS = -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000
|
||||
+wine64_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS)
|
||||
diff --git a/loader/main.c b/loader/main.c
|
||||
index 13740c7b3c5..5212e3f0798 100644
|
||||
--- a/loader/main.c
|
||||
+++ b/loader/main.c
|
||||
@@ -50,30 +50,6 @@
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
|
||||
-#ifndef __clang__
|
||||
-__asm__(".zerofill WINE_DOS, WINE_DOS, ___wine_dos, 0x40000000");
|
||||
-__asm__(".zerofill WINE_SHAREDHEAP, WINE_SHAREDHEAP, ___wine_shared_heap, 0x03000000");
|
||||
-extern char __wine_dos[0x40000000], __wine_shared_heap[0x03000000];
|
||||
-#else
|
||||
-__asm__(".zerofill WINE_DOS, WINE_DOS");
|
||||
-__asm__(".zerofill WINE_SHAREDHEAP, WINE_SHAREDHEAP");
|
||||
-static char __wine_dos[0x40000000] __attribute__((section("WINE_DOS, WINE_DOS")));
|
||||
-static char __wine_shared_heap[0x03000000] __attribute__((section("WINE_SHAREDHEAP, WINE_SHAREDHEAP")));
|
||||
-#endif
|
||||
-
|
||||
-static const struct wine_preload_info wine_main_preload_info[] =
|
||||
-{
|
||||
- { __wine_dos, sizeof(__wine_dos) }, /* DOS area + PE exe */
|
||||
- { __wine_shared_heap, sizeof(__wine_shared_heap) }, /* shared user data + shared heap */
|
||||
- { 0, 0 } /* end of list */
|
||||
-};
|
||||
-
|
||||
-static inline void reserve_area( void *addr, size_t size )
|
||||
-{
|
||||
- wine_anon_mmap( addr, size, PROT_NONE, MAP_FIXED | MAP_NORESERVE );
|
||||
- wine_mmap_add_reserved_area( addr, size );
|
||||
-}
|
||||
-
|
||||
static const char *get_macho_library_path( const char *libname )
|
||||
{
|
||||
unsigned int path_len, libname_len = strlen( libname );
|
||||
@@ -94,18 +70,11 @@ static const char *get_macho_library_path( const char *libname )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-#else /* __APPLE__ */
|
||||
+#endif /* __APPLE__ */
|
||||
|
||||
/* the preloader will set this variable */
|
||||
const struct wine_preload_info *wine_main_preload_info = NULL;
|
||||
|
||||
-static inline void reserve_area( void *addr, size_t size )
|
||||
-{
|
||||
- wine_mmap_add_reserved_area( addr, size );
|
||||
-}
|
||||
-
|
||||
-#endif /* __APPLE__ */
|
||||
-
|
||||
/***********************************************************************
|
||||
* check_command_line
|
||||
*
|
||||
@@ -315,6 +284,13 @@ static int pre_exec(void)
|
||||
return 1; /* we have a preloader on x86-64 */
|
||||
}
|
||||
|
||||
+#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)
|
||||
@@ -360,12 +336,10 @@ int main( int argc, char *argv[] )
|
||||
}
|
||||
}
|
||||
|
||||
-#ifndef __APPLE__
|
||||
if (wine_main_preload_info)
|
||||
-#endif
|
||||
{
|
||||
for (i = 0; wine_main_preload_info[i].size; i++)
|
||||
- reserve_area( wine_main_preload_info[i].addr, wine_main_preload_info[i].size );
|
||||
+ wine_mmap_add_reserved_area( wine_main_preload_info[i].addr, wine_main_preload_info[i].size );
|
||||
}
|
||||
|
||||
wine_init( argc, argv, error, sizeof(error) );
|
||||
diff --git a/loader/preloader.c b/loader/preloader.c
|
||||
index 5e6add7830f..b3e80527309 100644
|
||||
--- a/loader/preloader.c
|
||||
+++ b/loader/preloader.c
|
||||
@@ -4,6 +4,8 @@
|
||||
* Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2004 Mike McCormack for CodeWeavers
|
||||
* Copyright (C) 2004 Alexandre Julliard
|
||||
+ * Copyright (C) 2017 Michael Müller
|
||||
+ * Copyright (C) 2017 Sebastian Lackner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -90,15 +92,14 @@
|
||||
#ifdef HAVE_SYS_LINK_H
|
||||
# include <sys/link.h>
|
||||
#endif
|
||||
+#ifdef HAVE_MACH_O_LOADER_H
|
||||
+#include <mach/thread_status.h>
|
||||
+#include <mach-o/loader.h>
|
||||
+#include <mach-o/dyld.h>
|
||||
+#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
-/* ELF definitions */
|
||||
-#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
|
||||
-#define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
|
||||
-
|
||||
-#define MAP_BASE_ADDR(l) 0
|
||||
-
|
||||
#ifndef MAP_COPY
|
||||
#define MAP_COPY MAP_PRIVATE
|
||||
#endif
|
||||
@@ -117,12 +118,25 @@ static struct wine_preload_info preload_info[] =
|
||||
{ (void *)0x000000010000, 0x00100000 }, /* DOS area */
|
||||
{ (void *)0x000000110000, 0x67ef0000 }, /* low memory area */
|
||||
{ (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */
|
||||
+#ifdef __APPLE__
|
||||
+ /* address below exceeds maximum allowed user space address in mac os */
|
||||
+ { (void *)0x7fff40000000, 0x01ff0000 }, /* top-down allocations + virtual heap */
|
||||
+#else
|
||||
{ (void *)0x7ffffe000000, 0x01ff0000 }, /* top-down allocations + virtual heap */
|
||||
#endif
|
||||
+#endif
|
||||
{ 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */
|
||||
{ 0, 0 } /* end of list */
|
||||
};
|
||||
|
||||
+#ifndef __APPLE__
|
||||
+
|
||||
+/* ELF definitions */
|
||||
+#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
|
||||
+#define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
|
||||
+
|
||||
+#define MAP_BASE_ADDR(l) 0
|
||||
+
|
||||
/* debugging */
|
||||
#undef DUMP_SEGMENTS
|
||||
#undef DUMP_AUX_INFO
|
||||
@@ -168,6 +182,8 @@ struct wld_auxv
|
||||
} a_un;
|
||||
};
|
||||
|
||||
+#endif /* !__APPLE__ */
|
||||
+
|
||||
/*
|
||||
* The __bb_init_func is an empty function only called when file is
|
||||
* compiled with gcc flags "-fprofile-arcs -ftest-coverage". This
|
||||
@@ -182,6 +198,196 @@ void *__stack_chk_guard = 0;
|
||||
void __stack_chk_fail_local(void) { return; }
|
||||
void __stack_chk_fail(void) { return; }
|
||||
|
||||
+#ifdef __APPLE__
|
||||
+#ifdef __i386__
|
||||
+
|
||||
+static const size_t page_mask = 0xfff;
|
||||
+#define TARGET_CPU_TYPE CPU_TYPE_X86
|
||||
+#define TARGET_MH_MAGIC MH_MAGIC
|
||||
+#define TARGET_SEGMENT_COMMAND LC_SEGMENT
|
||||
+#define target_mach_header mach_header
|
||||
+#define target_segment_command segment_command
|
||||
+#define target_thread_state_t i386_thread_state_t
|
||||
+#ifdef __DARWIN_UNIX03
|
||||
+#define target_thread_ip(x) (x)->__eip
|
||||
+#else
|
||||
+#define target_thread_ip(x) (x)->eip
|
||||
+#endif
|
||||
+
|
||||
+#define SYSCALL_FUNC( name, nr ) \
|
||||
+ __ASM_GLOBAL_FUNC( name, \
|
||||
+ "\tmovl $" #nr ",%eax\n" \
|
||||
+ "\tint $0x80\n" \
|
||||
+ "\tjnb 1f\n" \
|
||||
+ "\tmovl $-1,%eax\n" \
|
||||
+ "1:\tret\n" )
|
||||
+
|
||||
+#define SYSCALL_NOERR( name, nr ) \
|
||||
+ __ASM_GLOBAL_FUNC( name, \
|
||||
+ "\tmovl $" #nr ",%eax\n" \
|
||||
+ "\tint $0x80\n" \
|
||||
+ "\tret\n" )
|
||||
+
|
||||
+__ASM_GLOBAL_FUNC( start,
|
||||
+ __ASM_CFI("\t.cfi_undefined %eip\n")
|
||||
+ /* The first 16 bytes are used as a function signature on i386 */
|
||||
+ "\t.byte 0x6a,0x00\n" /* pushl $0 */
|
||||
+ "\t.byte 0x89,0xe5\n" /* movl %esp,%ebp */
|
||||
+ "\t.byte 0x83,0xe4,0xf0\n" /* andl $-16,%esp */
|
||||
+ "\t.byte 0x83,0xec,0x10\n" /* subl $16,%esp */
|
||||
+ "\t.byte 0x8b,0x5d,0x04\n" /* movl 4(%ebp),%ebx */
|
||||
+ "\t.byte 0x89,0x5c,0x24,0x00\n" /* movl %ebx,0(%esp) */
|
||||
+
|
||||
+ "\tleal 4(%ebp),%eax\n"
|
||||
+ "\tmovl %eax,0(%esp)\n" /* stack */
|
||||
+ "\tleal 8(%esp),%eax\n"
|
||||
+ "\tmovl %eax,4(%esp)\n" /* &is_unix_thread */
|
||||
+ "\tmovl $0,(%eax)\n"
|
||||
+ "\tcall _wld_start\n"
|
||||
+
|
||||
+ "\tmovl 4(%ebp),%edi\n"
|
||||
+ "\tdecl %edi\n" /* argc */
|
||||
+ "\tleal 12(%ebp),%esi\n" /* argv */
|
||||
+ "\tleal 4(%esi,%edi,4),%edx\n" /* env */
|
||||
+ "\tmovl %edx,%ecx\n" /* apple data */
|
||||
+ "1:\tmovl (%ecx),%ebx\n"
|
||||
+ "\tadd $4,%ecx\n"
|
||||
+ "\torl %ebx,%ebx\n"
|
||||
+ "\tjnz 1b\n"
|
||||
+
|
||||
+ "\tcmpl $0,8(%esp)\n"
|
||||
+ "\tjne 2f\n"
|
||||
+
|
||||
+ /* LC_MAIN */
|
||||
+ "\tmovl %edi,0(%esp)\n" /* argc */
|
||||
+ "\tmovl %esi,4(%esp)\n" /* argv */
|
||||
+ "\tmovl %edx,8(%esp)\n" /* env */
|
||||
+ "\tmovl %ecx,12(%esp)\n" /* apple data */
|
||||
+ "\tcall *%eax\n"
|
||||
+ "\tmovl %eax,(%esp)\n"
|
||||
+ "\tcall _wld_exit\n"
|
||||
+ "\thlt\n"
|
||||
+
|
||||
+ /* LC_UNIXTHREAD */
|
||||
+ "2:\tmovl (%ecx),%ebx\n"
|
||||
+ "\tadd $4,%ecx\n"
|
||||
+ "\torl %ebx,%ebx\n"
|
||||
+ "\tjnz 2b\n"
|
||||
+
|
||||
+ "\tsubl %ebp,%ecx\n"
|
||||
+ "\tsubl $8,%ecx\n"
|
||||
+ "\tleal 4(%ebp),%esp\n"
|
||||
+ "\tsubl %ecx,%esp\n"
|
||||
+
|
||||
+ "\tmovl %edi,(%esp)\n" /* argc */
|
||||
+ "\tleal 4(%esp),%edi\n"
|
||||
+ "\tshrl $2,%ecx\n"
|
||||
+ "\tcld\n"
|
||||
+ "\trep; movsd\n" /* argv, ... */
|
||||
+
|
||||
+ "\tmovl $0,%ebp\n"
|
||||
+ "\tjmpl *%eax\n" )
|
||||
+
|
||||
+#elif defined(__x86_64__)
|
||||
+
|
||||
+static const size_t page_mask = 0xfff;
|
||||
+#define TARGET_CPU_TYPE CPU_TYPE_X86_64
|
||||
+#define TARGET_MH_MAGIC MH_MAGIC_64
|
||||
+#define TARGET_SEGMENT_COMMAND LC_SEGMENT_64
|
||||
+#define target_mach_header mach_header_64
|
||||
+#define target_segment_command segment_command_64
|
||||
+#define target_thread_state_t x86_thread_state64_t
|
||||
+#ifdef __DARWIN_UNIX03
|
||||
+#define target_thread_ip(x) (x)->__rip
|
||||
+#else
|
||||
+#define target_thread_ip(x) (x)->rip
|
||||
+#endif
|
||||
+
|
||||
+#define SYSCALL_FUNC( name, nr ) \
|
||||
+ __ASM_GLOBAL_FUNC( name, \
|
||||
+ "\tmovq %rcx, %r10\n" \
|
||||
+ "\tmovq $(" #nr "|0x2000000),%rax\n" \
|
||||
+ "\tsyscall\n" \
|
||||
+ "\tjnb 1f\n" \
|
||||
+ "\tmovq $-1,%rax\n" \
|
||||
+ "1:\tret\n" )
|
||||
+
|
||||
+#define SYSCALL_NOERR( name, nr ) \
|
||||
+ __ASM_GLOBAL_FUNC( name, \
|
||||
+ "\tmovq %rcx, %r10\n" \
|
||||
+ "\tmovq $(" #nr "|0x2000000),%rax\n" \
|
||||
+ "\tsyscall\n" \
|
||||
+ "\tret\n" )
|
||||
+
|
||||
+__ASM_GLOBAL_FUNC( start,
|
||||
+ __ASM_CFI("\t.cfi_undefined %rip\n")
|
||||
+ "\tpushq $0\n"
|
||||
+ "\tmovq %rsp,%rbp\n"
|
||||
+ "\tandq $-16,%rsp\n"
|
||||
+ "\tsubq $16,%rsp\n"
|
||||
+
|
||||
+ "\tleaq 8(%rbp),%rdi\n" /* stack */
|
||||
+ "\tmovq %rsp,%rsi\n" /* &is_unix_thread */
|
||||
+ "\tmovq $0,(%rsi)\n"
|
||||
+ "\tcall _wld_start\n"
|
||||
+
|
||||
+ "\tmovq 8(%rbp),%rdi\n"
|
||||
+ "\tdec %rdi\n" /* argc */
|
||||
+ "\tleaq 24(%rbp),%rsi\n" /* argv */
|
||||
+ "\tleaq 8(%rsi,%rdi,8),%rdx\n" /* env */
|
||||
+ "\tmovq %rdx,%rcx\n" /* apple data */
|
||||
+ "1:\tmovq (%rcx),%r8\n"
|
||||
+ "\taddq $8,%rcx\n"
|
||||
+ "\torq %r8,%r8\n"
|
||||
+ "\tjnz 1b\n"
|
||||
+
|
||||
+ "\tcmpl $0,0(%rsp)\n"
|
||||
+ "\tjne 2f\n"
|
||||
+
|
||||
+ /* LC_MAIN */
|
||||
+ "\taddq $16,%rsp\n"
|
||||
+ "\tcall *%rax\n"
|
||||
+ "\tmovq %rax,%rdi\n"
|
||||
+ "\tcall _wld_exit\n"
|
||||
+ "\thlt\n"
|
||||
+
|
||||
+ /* LC_UNIXTHREAD */
|
||||
+ "2:\tmovq (%rcx),%r8\n"
|
||||
+ "\taddq $8,%rcx\n"
|
||||
+ "\torq %r8,%r8\n"
|
||||
+ "\tjnz 2b\n"
|
||||
+
|
||||
+ "\tsubq %rbp,%rcx\n"
|
||||
+ "\tsubq $16,%rcx\n"
|
||||
+ "\tleaq 8(%rbp),%rsp\n"
|
||||
+ "\tsubq %rcx,%rsp\n"
|
||||
+
|
||||
+ "\tmovq %rdi,(%rsp)\n" /* argc */
|
||||
+ "\tleaq 8(%rsp),%rdi\n"
|
||||
+ "\tshrq $3,%rcx\n"
|
||||
+ "\tcld\n"
|
||||
+ "\trep; movsq\n" /* argv, ... */
|
||||
+
|
||||
+ "\tmovq $0,%rbp\n"
|
||||
+ "\tjmpq *%rax\n" )
|
||||
+
|
||||
+#else
|
||||
+#error preloader not implemented for this CPU
|
||||
+#endif
|
||||
+
|
||||
+void wld_exit( int code ) __attribute__((noreturn));
|
||||
+SYSCALL_NOERR( wld_exit, 1 /* SYS_exit */ );
|
||||
+
|
||||
+ssize_t wld_write( int fd, const void *buffer, size_t len );
|
||||
+SYSCALL_FUNC( wld_write, 4 /* SYS_write */ );
|
||||
+
|
||||
+void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
|
||||
+SYSCALL_FUNC( wld_mmap, 197 /* SYS_mmap */ );
|
||||
+
|
||||
+void *wld_munmap( void *start, size_t len );
|
||||
+SYSCALL_FUNC( wld_munmap, 73 /* SYS_munmap */ );
|
||||
+
|
||||
+#else /* __APPLE__ */
|
||||
#ifdef __i386__
|
||||
|
||||
/* data for setting up the glibc-style thread-local storage in %gs */
|
||||
@@ -458,16 +664,17 @@ SYSCALL_NOERR( wld_getegid, 108 /* SYS_getegid */ );
|
||||
#else
|
||||
#error preloader not implemented for this CPU
|
||||
#endif
|
||||
+#endif /* __APPLE__ */
|
||||
|
||||
/* replacement for libc functions */
|
||||
|
||||
-static int wld_strcmp( const char *str1, const char *str2 )
|
||||
+static inline int wld_strcmp( const char *str1, const char *str2 )
|
||||
{
|
||||
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
return *str1 - *str2;
|
||||
}
|
||||
|
||||
-static int wld_strncmp( const char *str1, const char *str2, size_t len )
|
||||
+static inline int wld_strncmp( const char *str1, const char *str2, size_t len )
|
||||
{
|
||||
if (len <= 0) return 0;
|
||||
while ((--len > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
@@ -560,6 +767,8 @@ static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char
|
||||
wld_exit(1);
|
||||
}
|
||||
|
||||
+#ifndef __APPLE__
|
||||
+
|
||||
#ifdef DUMP_AUX_INFO
|
||||
/*
|
||||
* Dump interesting bits of the ELF auxv_t structure that is passed
|
||||
@@ -1039,6 +1248,8 @@ found:
|
||||
return (void *)(symtab[idx].st_value + map->l_addr);
|
||||
}
|
||||
|
||||
+#endif /* !__APPLE__ */
|
||||
+
|
||||
/*
|
||||
* preload_reserve
|
||||
*
|
||||
@@ -1070,6 +1281,7 @@ static void preload_reserve( const char *str )
|
||||
|
||||
/* sanity checks */
|
||||
if (end <= start) start = end = NULL;
|
||||
+#ifndef __APPLE__
|
||||
else if ((char *)end > preloader_start &&
|
||||
(char *)start <= preloader_end)
|
||||
{
|
||||
@@ -1077,6 +1289,7 @@ static void preload_reserve( const char *str )
|
||||
start, end, preloader_start, preloader_end );
|
||||
start = end = NULL;
|
||||
}
|
||||
+#endif /* !__APPLE__ */
|
||||
|
||||
/* check for overlap with low memory areas */
|
||||
for (i = 0; preload_info[i].size; i++)
|
||||
@@ -1101,7 +1314,7 @@ error:
|
||||
}
|
||||
|
||||
/* check if address is in one of the reserved ranges */
|
||||
-static int is_addr_reserved( const void *addr )
|
||||
+static inline int is_addr_reserved( const void *addr )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1125,6 +1338,159 @@ static void remove_preload_range( int i )
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef __APPLE__
|
||||
+
|
||||
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
|
||||
+MAKE_FUNCPTR(dlopen);
|
||||
+MAKE_FUNCPTR(dlsym);
|
||||
+MAKE_FUNCPTR(_dyld_image_count);
|
||||
+MAKE_FUNCPTR(_dyld_get_image_header);
|
||||
+MAKE_FUNCPTR(_dyld_get_image_vmaddr_slide);
|
||||
+#undef MAKE_FUNCPTR
|
||||
+
|
||||
+extern int _dyld_func_lookup( const char *dyld_func_name, void **address );
|
||||
+
|
||||
+static struct target_mach_header *find_executable( intptr_t *slide )
|
||||
+{
|
||||
+ struct target_mach_header *mh;
|
||||
+ int i;
|
||||
+
|
||||
+ /* skip our own executable */
|
||||
+ for (i = 1; i < p_dyld_image_count(); i++)
|
||||
+ {
|
||||
+ mh = (struct target_mach_header *)p_dyld_get_image_header( i );
|
||||
+ if (!mh) continue;
|
||||
+ if (mh->magic != TARGET_MH_MAGIC) continue;
|
||||
+ if (mh->cputype != TARGET_CPU_TYPE) continue;
|
||||
+ if (mh->filetype != MH_EXECUTE) continue;
|
||||
+
|
||||
+ *slide = p_dyld_get_image_vmaddr_slide( i );
|
||||
+ return mh;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *get_entry_point( struct target_mach_header *mh, intptr_t slide, int *unix_thread )
|
||||
+{
|
||||
+ struct entry_point_command *entry;
|
||||
+ target_thread_state_t *state;
|
||||
+ struct load_command *cmd;
|
||||
+ int i;
|
||||
+
|
||||
+ /* try LC_MAIN first */
|
||||
+ cmd = (struct load_command *)(mh + 1);
|
||||
+ for (i = 0; i < mh->ncmds; i++)
|
||||
+ {
|
||||
+ if (cmd->cmd == LC_MAIN)
|
||||
+ {
|
||||
+ *unix_thread = FALSE;
|
||||
+ entry = (struct entry_point_command *)cmd;
|
||||
+ return (char *)mh + entry->entryoff;
|
||||
+ }
|
||||
+ cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
|
||||
+ }
|
||||
+
|
||||
+ /* then try LC_UNIXTHREAD */
|
||||
+ cmd = (struct load_command *)(mh + 1);
|
||||
+ for (i = 0; i < mh->ncmds; i++)
|
||||
+ {
|
||||
+ if (cmd->cmd == LC_UNIXTHREAD)
|
||||
+ {
|
||||
+ *unix_thread = TRUE;
|
||||
+ state = (target_thread_state_t *)((char *)cmd + 16);
|
||||
+ return (void *)(target_thread_ip(state) + slide);
|
||||
+ }
|
||||
+ cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+};
|
||||
+
|
||||
+static inline void get_dyld_func( const char *name, void **func )
|
||||
+{
|
||||
+ _dyld_func_lookup( name, func );
|
||||
+ if (!*func) fatal_error( "Failed to get function pointer for %s\n", name );
|
||||
+}
|
||||
+
|
||||
+#define LOAD_POSIX_DYLD_FUNC(f) get_dyld_func( "__dyld_" #f, (void **)&p##f )
|
||||
+#define LOAD_MACHO_DYLD_FUNC(f) get_dyld_func( "_" #f, (void **)&p##f )
|
||||
+
|
||||
+void *wld_start( void *stack, int *is_unix_thread )
|
||||
+{
|
||||
+ struct wine_preload_info **wine_main_preload_info;
|
||||
+ char **argv, **p, *reserve = NULL;
|
||||
+ struct target_mach_header *mh;
|
||||
+ void *mod, *entry;
|
||||
+ intptr_t slide;
|
||||
+ int *pargc, i;
|
||||
+
|
||||
+ pargc = stack;
|
||||
+ argv = (char **)pargc + 1;
|
||||
+ if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] );
|
||||
+
|
||||
+ /* skip over the parameters */
|
||||
+ p = argv + *pargc + 1;
|
||||
+
|
||||
+ /* skip over the environment */
|
||||
+ while (*p)
|
||||
+ {
|
||||
+ static const char res[] = "WINEPRELOADRESERVE=";
|
||||
+ if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
|
||||
+ p++;
|
||||
+ }
|
||||
+
|
||||
+ /* reserve memory that Wine needs */
|
||||
+ if (reserve) preload_reserve( reserve );
|
||||
+ for (i = 0; preload_info[i].size; i++)
|
||||
+ {
|
||||
+ int flags = MAP_PRIVATE | MAP_ANON;
|
||||
+ void *ret;
|
||||
+
|
||||
+ if (!preload_info[i].addr)
|
||||
+ flags |= MAP_FIXED;
|
||||
+
|
||||
+ ret = wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE, flags, -1, 0 );
|
||||
+ if (ret != (void *)-1 && ret != preload_info[i].addr)
|
||||
+ {
|
||||
+ wld_munmap(ret, preload_info[i].size);
|
||||
+ ret = (void *)-1;
|
||||
+ }
|
||||
+ if (ret == (void *)-1)
|
||||
+ {
|
||||
+ wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
|
||||
+ preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size );
|
||||
+ remove_preload_range( i );
|
||||
+ i--;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ LOAD_POSIX_DYLD_FUNC( dlopen );
|
||||
+ LOAD_POSIX_DYLD_FUNC( dlsym );
|
||||
+ LOAD_MACHO_DYLD_FUNC( _dyld_image_count );
|
||||
+ LOAD_MACHO_DYLD_FUNC( _dyld_get_image_header );
|
||||
+ LOAD_MACHO_DYLD_FUNC( _dyld_get_image_vmaddr_slide );
|
||||
+
|
||||
+ /* load the main binary */
|
||||
+ if (!(mod = pdlopen( argv[1], RTLD_NOW )))
|
||||
+ fatal_error( "%s: could not load binary\n", argv[1] );
|
||||
+
|
||||
+ /* store pointer to the preload info into the appropriate main binary variable */
|
||||
+ wine_main_preload_info = pdlsym( mod, "wine_main_preload_info" );
|
||||
+ if (wine_main_preload_info) *wine_main_preload_info = preload_info;
|
||||
+ else wld_printf( "wine_main_preload_info not found\n" );
|
||||
+
|
||||
+ /* there is no way to translate the dlopen handle to the mach header :-( */
|
||||
+ if (!(mh = find_executable( &slide )))
|
||||
+ fatal_error( "%s: could not find mach header\n", argv[1] );
|
||||
+ if (!(entry = get_entry_point( mh, slide, is_unix_thread )))
|
||||
+ fatal_error( "%s: could not find entry point\n", argv[1] );
|
||||
+
|
||||
+ return entry;
|
||||
+}
|
||||
+
|
||||
+#else /* __APPLE__ */
|
||||
+
|
||||
/*
|
||||
* is_in_preload_range
|
||||
*
|
||||
@@ -1293,3 +1659,5 @@ void* wld_start( void **stack )
|
||||
|
||||
return (void *)ld_so_map.l_entry;
|
||||
}
|
||||
+
|
||||
+#endif /* __APPLE__ */
|
||||
--
|
||||
2.13.1
|
||||
|
3
patches/loader-OSX_Preloader/definition
Normal file
3
patches/loader-OSX_Preloader/definition
Normal file
@ -0,0 +1,3 @@
|
||||
Fixes: [33159] Implement preloader for Mac OS
|
||||
Depends: Staging
|
||||
Depends: configure-Absolute_RPATH
|
@ -203,6 +203,7 @@ patch_enable_all ()
|
||||
enable_krnl386_exe16__lclose16="$1"
|
||||
enable_libs_Debug_Channel="$1"
|
||||
enable_libs_Unicode_Collation="$1"
|
||||
enable_loader_OSX_Preloader="$1"
|
||||
enable_makedep_PARENTSPEC="$1"
|
||||
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
|
||||
enable_mountmgr_DosDevices="$1"
|
||||
@ -846,6 +847,9 @@ patch_enable ()
|
||||
libs-Unicode_Collation)
|
||||
enable_libs_Unicode_Collation="$2"
|
||||
;;
|
||||
loader-OSX_Preloader)
|
||||
enable_loader_OSX_Preloader="$2"
|
||||
;;
|
||||
makedep-PARENTSPEC)
|
||||
enable_makedep_PARENTSPEC="$2"
|
||||
;;
|
||||
@ -2477,6 +2481,17 @@ if test "$enable_ntdll_ApiSetMap" -eq 1; then
|
||||
enable_ntdll_ThreadTime=1
|
||||
fi
|
||||
|
||||
if test "$enable_loader_OSX_Preloader" -eq 1; then
|
||||
if test "$enable_Staging" -gt 1; then
|
||||
abort "Patchset Staging disabled, but loader-OSX_Preloader depends on that."
|
||||
fi
|
||||
if test "$enable_configure_Absolute_RPATH" -gt 1; then
|
||||
abort "Patchset configure-Absolute_RPATH disabled, but loader-OSX_Preloader depends on that."
|
||||
fi
|
||||
enable_Staging=1
|
||||
enable_configure_Absolute_RPATH=1
|
||||
fi
|
||||
|
||||
if test "$enable_kernel32_SetFileCompletionNotificationModes" -eq 1; then
|
||||
if test "$enable_ntdll_FileNameInformation" -gt 1; then
|
||||
abort "Patchset ntdll-FileNameInformation disabled, but kernel32-SetFileCompletionNotificationModes depends on that."
|
||||
@ -5115,6 +5130,27 @@ if test "$enable_libs_Unicode_Collation" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset loader-OSX_Preloader
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * Staging, configure-Absolute_RPATH
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#33159] Implement preloader for Mac OS
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * Makefile.in, configure.ac, dlls/ntdll/virtual.c, libs/wine/config.c, libs/wine/loader.c, loader/Makefile.in,
|
||||
# | loader/main.c, loader/preloader.c
|
||||
# |
|
||||
if test "$enable_loader_OSX_Preloader" -eq 1; then
|
||||
patch_apply loader-OSX_Preloader/0001-libs-wine-Do-not-restrict-base-address-of-main-threa.patch
|
||||
patch_apply loader-OSX_Preloader/0002-loader-Implement-preloader-for-Mac-OS.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Michael Müller", "libs/wine: Do not restrict base address of main thread on 64 bit mac os.", 1 },';
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "loader: Implement preloader for Mac OS.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset makedep-PARENTSPEC
|
||||
# |
|
||||
# | Modified files:
|
||||
|
Loading…
Reference in New Issue
Block a user