From c01bd008dba6dadfda37e1964a1cc3359ed4ff50 Mon Sep 17 00:00:00 2001 From: Dan Sumorok Date: Sat, 6 Jul 2013 17:09:37 -0400 Subject: [PATCH] Hack to load code below 4GB, and to make 32-bit vm allocates work. --- BasiliskII/src/Unix/configure.ac | 26 +++++++++++++++++++------- BasiliskII/src/Unix/sigsegv.h | 2 +- BasiliskII/src/Unix/vm_alloc.cpp | 32 ++++++++++++++++++-------------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/BasiliskII/src/Unix/configure.ac b/BasiliskII/src/Unix/configure.ac index 095ee4c5..e5c3cd27 100644 --- a/BasiliskII/src/Unix/configure.ac +++ b/BasiliskII/src/Unix/configure.ac @@ -772,18 +772,20 @@ if [[ "x$WANT_SDL" = "xyes" ]]; then EXTRASYSSRCS="$EXTRASYSSRCS ../SDL/SDLMain.m" fi fi + +AC_MSG_CHECKING([whether __LP64__ is defined]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if !defined(__LP64__) + # error __LP64__ not defined + #endif + ]])], + [AC_MSG_RESULT(yes); LP64_DEFINED=yes], + [AC_MSG_RESULT(no)]) + if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support]) VIDEOSRCS="../SDL/video_sdl.cpp" KEYCODES="../SDL/keycodes" if [[ "x$ac_cv_framework_Carbon" = "xyes" ]]; then - AC_MSG_CHECKING([whether __LP64__ is defined]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if !defined(__LP64__) - # error __LP64__ not defined - #endif - ]])], - [AC_MSG_RESULT(yes); LP64_DEFINED=yes], - [AC_MSG_RESULT(no)]) if [[ "x$LP64_DEFINED" = "xyes" ]]; then EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm ../pict.c" else @@ -1774,6 +1776,16 @@ if [[ "x$HAVE_IPA" = "xyes" ]]; then LDFLAGS="$LDFLAGS -O3 -OPT:Olimit=0 -IPA" fi +if [[ "x$LP64_DEFINED" = "xyes" ] && [ "x$have_mach_vm" = "xyes" ]]; then +LIBS+=" -Wl,-pagezero_size,0x20000000" +LIBS+=" -Wl,-segaddr,__TEXT,0x60000000" +LIBS+=" -Wl,-segaddr,__PAGEZERO,0x20000000" +fi + +if [[ ${OS_TYPE} = darwin ]]; then +LIBS+=" -Wl,-no_pie" +fi + dnl Generate Makefile. AC_SUBST(DEFINES) AC_SUBST(SYSSRCS) diff --git a/BasiliskII/src/Unix/sigsegv.h b/BasiliskII/src/Unix/sigsegv.h index 8fdada9e..26a9e5eb 100644 --- a/BasiliskII/src/Unix/sigsegv.h +++ b/BasiliskII/src/Unix/sigsegv.h @@ -106,7 +106,7 @@ extern "C" { #define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(rax)) /* RAX is the first GPR we consider */ #endif #ifdef __x86_64__ -#define SIGSEGV_FAULT_ADDRESS_FAST (((uint64_t)code[1])|0x100000000) +#define SIGSEGV_FAULT_ADDRESS_FAST code[1] #else #define SIGSEGV_FAULT_ADDRESS_FAST code[1] #endif diff --git a/BasiliskII/src/Unix/vm_alloc.cpp b/BasiliskII/src/Unix/vm_alloc.cpp index 57dd8169..4d3569c0 100644 --- a/BasiliskII/src/Unix/vm_alloc.cpp +++ b/BasiliskII/src/Unix/vm_alloc.cpp @@ -221,6 +221,9 @@ void vm_exit(void) /* Allocate zero-filled memory of SIZE bytes. The mapping is private and default protection bits are read / write. The return value is the actual mapping address chosen or VM_MAP_FAILED for errors. */ +#if defined(HAVE_MACH_VM) +static void *last_alloc = NULL; +#endif void * vm_acquire(size_t size, int options) { @@ -238,24 +241,18 @@ void * vm_acquire(size_t size, int options) #endif #if defined(HAVE_MACH_VM) - static size_t addrOffset = 0x80000000; + static size_t addrOffset = 0x20000000; kern_return_t ret_code; static uint8 *base32 = NULL; if(options & VM_MAP_32BIT) { #ifdef __LP64__ - if((size < 0x08000000) && (addrOffset < 0x100000000ULL) && (base32 != NULL)) { - addr = (void *)(base32 + addrOffset); - ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, - size, VM_FLAGS_FIXED); - addrOffset += 0x08000000; - } else { - ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, - size, VM_FLAGS_ANYWHERE); - if((ret_code == KERN_SUCCESS) && (base32 == NULL)) { - base32 = (uint8_t *)addr; - } - + addr = base32 + addrOffset; + ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, + size, VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE); + if(ret_code == KERN_SUCCESS) { + last_alloc = addr; + base32 = base32 + size; } #else // vm_allocate() returns a zero-filled memory region @@ -325,9 +322,16 @@ int vm_acquire_fixed(void * addr, size_t size, int options) #if defined(HAVE_MACH_VM) // vm_allocate() returns a zero-filled memory region + #ifdef __LP64__ - kern_return_t ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, + if(addr != last_alloc) { + return -1; + } + + kern_return_t ret_code = vm_allocate(mach_task_self(), + (vm_address_t *)&addr, size, VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE); + #else kern_return_t ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, VM_FLAGS_FIXED);