Commit 307f5d00 authored by Brendan Shanks's avatar Brendan Shanks Committed by Alexandre Julliard

loader: On Mac, reserve an area starting at 4GB to force Rosetta's allocations higher.

On Apple Silicon, Rosetta allocates memory starting at 0x100000000 (the 4GB line) before the preloader runs. The .NET 3.5 installer and DirectX Jun2010 redistributable both contain non-relocatable EXEs with that base address, which fail to run. The workaround is to create an empty linker section at that address, which is mapped by the kernel before Rosetta runs and forces Rosetta's allocations higher in memory. The linker section runs from 0x100000000-0x114000000. Rosetta's allocations are ~132MB, and should end below 0x120000000. This is not an exact science: a non-relocatable EXE with base address between 0x114000000-0x120000000 will fail to run. If one is discovered, the section size will need to be changed. Signed-off-by: 's avatarBrendan Shanks <bshanks@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 720611e2
...@@ -8727,7 +8727,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ...@@ -8727,7 +8727,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
WINELOADER_LDFLAGS="-Wl,-pie,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist" WINELOADER_LDFLAGS="-Wl,-pie,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
wine_can_build_preloader=yes wine_can_build_preloader=yes
WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7d400000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist" WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7d400000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist,-segaddr,WINE_4GB_RESERVE,0x100000000"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,-no_new_main -e _main" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,-no_new_main -e _main" >&5
$as_echo_n "checking whether the compiler supports -Wl,-no_new_main -e _main... " >&6; } $as_echo_n "checking whether the compiler supports -Wl,-no_new_main -e _main... " >&6; }
if ${ac_cv_cflags__Wl__no_new_main__e__main+:} false; then : if ${ac_cv_cflags__Wl__no_new_main__e__main+:} false; then :
......
...@@ -753,7 +753,7 @@ case $host_os in ...@@ -753,7 +753,7 @@ case $host_os in
WINELOADER_LDFLAGS="-Wl,-pie,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist" WINELOADER_LDFLAGS="-Wl,-pie,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
wine_can_build_preloader=yes wine_can_build_preloader=yes
WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7d400000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist" WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7d400000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist,-segaddr,WINE_4GB_RESERVE,0x100000000"
WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main], WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main],
[WINEPRELOADER_LDFLAGS="-Wl,-no_new_main $WINEPRELOADER_LDFLAGS" [WINEPRELOADER_LDFLAGS="-Wl,-no_new_main $WINEPRELOADER_LDFLAGS"
WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main -nostartfiles -nodefaultlibs],, WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main -nostartfiles -nodefaultlibs],,
......
...@@ -54,6 +54,17 @@ ...@@ -54,6 +54,17 @@
#include "wine/asm.h" #include "wine/asm.h"
#include "main.h" #include "main.h"
/* Rosetta on Apple Silicon allocates memory starting at 0x100000000 (the 4GB line)
* before the preloader runs, which prevents any nonrelocatable EXEs with that
* base address from running.
*
* This empty linker section forces Rosetta's allocations (currently ~132 MB)
* to start at 0x114000000, and they should end below 0x120000000.
*/
#if defined(__x86_64__)
__asm__(".zerofill WINE_4GB_RESERVE,WINE_4GB_RESERVE,___wine_4gb_reserve,0x14000000");
#endif
#ifndef LC_MAIN #ifndef LC_MAIN
#define LC_MAIN 0x80000028 #define LC_MAIN 0x80000028
struct entry_point_command struct entry_point_command
...@@ -79,6 +90,7 @@ static struct wine_preload_info preload_info[] = ...@@ -79,6 +90,7 @@ static struct wine_preload_info preload_info[] =
{ (void *)0x000000010000, 0x00100000 }, /* DOS area */ { (void *)0x000000010000, 0x00100000 }, /* DOS area */
{ (void *)0x000000110000, 0x67ef0000 }, /* low memory area */ { (void *)0x000000110000, 0x67ef0000 }, /* low memory area */
{ (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */ { (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */
{ (void *)0x000100000000, 0x14000000 }, /* WINE_4GB_RESERVE section */
{ (void *)0x7ffd00000000, 0x01ff0000 }, /* top-down allocations + virtual heap */ { (void *)0x7ffd00000000, 0x01ff0000 }, /* top-down allocations + virtual heap */
#endif /* __i386__ */ #endif /* __i386__ */
{ 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */ { 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */
...@@ -395,6 +407,10 @@ static int preloader_overlaps_range( const void *start, const void *end ) ...@@ -395,6 +407,10 @@ static int preloader_overlaps_range( const void *start, const void *end )
struct target_segment_command *seg = (struct target_segment_command*)cmd; struct target_segment_command *seg = (struct target_segment_command*)cmd;
const void *seg_start = (const void*)(seg->vmaddr + slide); const void *seg_start = (const void*)(seg->vmaddr + slide);
const void *seg_end = (const char*)seg_start + seg->vmsize; const void *seg_end = (const char*)seg_start + seg->vmsize;
static const char reserved_segname[] = "WINE_4GB_RESERVE";
if (!wld_strncmp( seg->segname, reserved_segname, sizeof(reserved_segname)-1 ))
continue;
if (end > seg_start && start <= seg_end) if (end > seg_start && start <= seg_end)
{ {
......
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