From ce56b2c7f780e0e2bc02f0647c59c14047797268 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Mon, 7 Dec 2015 23:21:44 +0000 Subject: [PATCH 1/5] Aligned hook for better OS X support --- src/hook.c | 127 +++++++++++++++++++++---------------------------- src/openrct2.c | 2 +- 2 files changed, 55 insertions(+), 74 deletions(-) diff --git a/src/hook.c b/src/hook.c index be83f39dc3..36a80cf789 100644 --- a/src/hook.c +++ b/src/hook.c @@ -53,73 +53,6 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in int rargssize = numrargs * 4; - data[i++] = 0x50; // push eax - - // move stack down for possible existing arguments - for (int j = 0; j < stacksize; j++) { - data[i++] = 0x8B; // mov eax, [esp+x] - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) + 4); - - data[i++] = 0x89; // mov [esp+x], eax - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) - ((registerssaved + stacksize) * 4)); - } - - if (numrargs > 0) { - // push the registers to be on the stack to access as arguments - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = -((registerssaved + stacksize) * 4) + 4; - - for (signed int j = numrargs - 1; j >= 0; j--) { - switch (registerargs[j]) { - case EAX: data[i++] = 0x50; break; - case EBX: data[i++] = 0x53; break; - case ECX: data[i++] = 0x51; break; - case EDX: data[i++] = 0x52; break; - case ESI: data[i++] = 0x56; break; - case EDI: data[i++] = 0x57; break; - case EBP: data[i++] = 0x55; break; - } - } - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = rargssize + ((registerssaved + stacksize) * 4) - 4; - } - - - data[i++] = 0xE8; // call - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - - int sizec = i; - - data[i++] = 0x8B; // push eax, [esp] - puts eip in eax - data[i++] = 0x04; - data[i++] = 0xE4; - - data[i++] = 0x83; // add eax, x - data[i++] = 0xC0; - int sizeoffset = i; - data[i++] = 0; // set to returnlocation offset later - - data[i++] = 0x89; // mov [esp-20h], eax - put return address on stack - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)(-(registerssaved * 4) - rargssize - (stacksize * 4)) + 4; - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = 4; - - data[i++] = 0x58; // pop eax - if (!(registersreturned & EAX)) { data[i++] = 0x50; // push eax } @@ -142,15 +75,56 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0x57; // push edi } - data[i++] = 0x83; // sub esp, x - data[i++] = 0xEC; - data[i++] = 4 + (stacksize * 4) + rargssize; + data[i++] = 0x50; //push eax + data[i++] = 0x89; //mov eax, esp + data[i++] = 0xE0; + data[i++] = 0x83; //sub eax, (numargs + 1)*4 + data[i++] = 0xC0; + data[i++] = (numrargs) * 4; + data[i++] = 0x83; //and eax, 0xC + data[i++] = 0xE0; + data[i++] = 0x0C; + data[i++] = 0x83; //sub eax, 0x18 + data[i++] = 0xE8; + data[i++] = 0x18; + data[i++] = 0xF7; //neg eax + data[i++] = 0xD8; + data[i++] = 0xA3; //mov [0x9ABDA8], eax + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + data[i++] = 0x58; //pop eax + data[i++] = 0x2B; //sub esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; - data[i++] = 0xE9; // jmp + // work out distance to nearest 0xC + // (esp - numargs * 4) & 0xC + // move to align - 4 + // save that amount + + if (numrargs > 0) { + // push the registers to be on the stack to access as arguments + for (signed int j = numrargs - 1; j >= 0; j--) { + switch (registerargs[j]) { + case EAX: data[i++] = 0x50; break; + case EBX: data[i++] = 0x53; break; + case ECX: data[i++] = 0x51; break; + case EDX: data[i++] = 0x52; break; + case ESI: data[i++] = 0x56; break; + case EDI: data[i++] = 0x57; break; + case EBP: data[i++] = 0x55; break; + } + } + } + + data[i++] = 0xE8; // call *((int *)&data[i]) = (newaddress - address - i - 4); i += 4; - data[sizeoffset] = i - sizec; - // returnlocation: switch (eaxDestinationRegister) { @@ -190,6 +164,13 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0xEC; data[i++] = (signed char)(stacksize * -4) - rargssize; + data[i++] = 0x03; //add esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + if (!(registersreturned & EDI)) { data[i++] = 0x5F; // pop edi } diff --git a/src/openrct2.c b/src/openrct2.c index 6bb2fcd81b..0821ce5788 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -647,7 +647,7 @@ static void openrct2_setup_rct2_hooks() addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when 0x6E7FF3 is decompiled addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0, 0); // remove when all callers are decompiled addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0, 0); // remove when all callers are decompiled - addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX, 0); // remove when all callers are decompiled + addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, 0, EAX); // remove when all callers are decompiled addhook(0x006C42D9, (int)scrolling_text_setup, 0, (int[]){EAX, ECX, EBP, END}, 0, EBX); // remove when all callers are decompiled addhook(0x006C2321, (int)gfx_get_string_width, 0, (int[]){ESI, END}, 0, ECX); // remove when all callers are decompiled addhook(0x006C2555, (int)format_string, 0, (int[]){EDI, EAX, ECX, END}, 0, 0); // remove when all callers are decompiled From 1bafbde11390b00fca46736784fc13747a9aac34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Mon, 7 Dec 2015 00:28:50 +0100 Subject: [PATCH 2/5] Shift segments in Mach-O to outside of required AS Mach-O defaults to having .text segment starting at 0x1000 RVA, which clashes with the address space required for mmap to work properly. This change tells linker to move the segment outside of required AS, and then some, so that mmap can properly allocate required addresses without evicting anything else. --- CMakeLists.txt | 5 ++++- src/openrct2.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14ebfa3de6..0bddb2fd87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,10 @@ if (UNIX) # force 32bit build for now and set necessary flags to compile code as is set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer") - set(CMAKE_SHARED_LINKER_FLAGS "-m32") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") + if (APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-image_base,0x3401000") + endif (APPLE) set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) diff --git a/src/openrct2.c b/src/openrct2.c index 0821ce5788..ae89b80586 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -566,7 +566,7 @@ static bool openrct2_setup_rct2_segment() exit(1); } - void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0); + void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE | MAP_FILE, gExeFd, 0); err = errno; log_warning("mmapped file to %p", fbase); if (fbase == MAP_FAILED) From 1456049dfbc1afad60d8e0a880b168821110cb5c Mon Sep 17 00:00:00 2001 From: Duncan Date: Tue, 8 Dec 2015 12:27:38 +0000 Subject: [PATCH 3/5] Fixed alignment of hook --- src/hook.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/hook.c b/src/hook.c index 36a80cf789..757d873ce7 100644 --- a/src/hook.c +++ b/src/hook.c @@ -78,17 +78,12 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0x50; //push eax data[i++] = 0x89; //mov eax, esp data[i++] = 0xE0; - data[i++] = 0x83; //sub eax, (numargs + 1)*4 - data[i++] = 0xC0; - data[i++] = (numrargs) * 4; + data[i++] = 0x83; //sub eax, (0xC + numargs*4) & 0xF + data[i++] = 0xE8; + data[i++] = (0xC + numrargs * 4) & 0xF; data[i++] = 0x83; //and eax, 0xC data[i++] = 0xE0; data[i++] = 0x0C; - data[i++] = 0x83; //sub eax, 0x18 - data[i++] = 0xE8; - data[i++] = 0x18; - data[i++] = 0xF7; //neg eax - data[i++] = 0xD8; data[i++] = 0xA3; //mov [0x9ABDA8], eax data[i++] = 0xA8; data[i++] = 0xBD; From af382b1884c039f68f2be664c0db54f84d3da09f Mon Sep 17 00:00:00 2001 From: Kyle Kirbatski Date: Tue, 8 Dec 2015 17:36:38 -0600 Subject: [PATCH 4/5] Switched to -sectcreate instead of mmap on OS X --- CMakeLists.txt | 6 +++--- src/openrct2.c | 49 +++++++++++++------------------------------------ 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bddb2fd87..ae1be6c228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,11 +61,11 @@ file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "lib/argparse/*.c" "lib/cu if (UNIX) # force 32bit build for now and set necessary flags to compile code as is - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") if (APPLE) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-image_base,0x3401000") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -sectcreate rct2_text __text /Users/kkirbatski/Desktop/openrct2_text -sectcreate rct2_data __data /Users/kkirbatski/Desktop/openrct2_data -segaddr rct2_data 0x8a4000 -segprot rct2_data rwx rwx -segaddr rct2_text 0x4010000 -segprot rct2_text rwx rwx -fno-pie -read_only_relocs suppress") endif (APPLE) set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) diff --git a/src/openrct2.c b/src/openrct2.c index ae89b80586..7a8c9c0959 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -60,8 +60,8 @@ bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -void *gDataSegment; -void *gTextSegment; +//unsigned char __attribute__((section ("rct2_text,__text"))) gTextSegment[0x004A3000]; +//unsigned char __attribute__((section ("rct2_data,__data"))) gDataSegment[0x01429000 - 0x8a4000]; int gExeFd; #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) @@ -472,7 +472,7 @@ static bool openrct2_setup_rct2_segment() // POSIX OSes will run OpenRCT2 as a native application and then load in the Windows PE, mapping the appropriate addresses as // necessary. Windows does not need to do this as OpenRCT2 runs as a DLL loaded from the Windows PE. #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - #define RDATA_OFFSET 0x004A4000 + /*#define RDATA_OFFSET 0x004A4000 #define DATASEG_OFFSET 0x005E2000 const char *exepath = "openrct2.exe"; @@ -551,19 +551,20 @@ static bool openrct2_setup_rct2_segment() log_error("Found already mapped pages in region we want to claim. This means something accessed memory before we got to and following mmap (or next malloc) call will likely fail."); } // section: rw data - gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0); - if (gDataSegment != (void *)0x8a4000) { - log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); - exit(1); + + void* asdf = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_SHARED, 0, 0); + if (asdf != (void *)0x8a4000) { + log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); + exit(1); } len = 0x004A3000; // section: text - gTextSegment = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); - if (gTextSegment != (void *)(0x401000)) + void* ffaa = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); + if (ffaa != (void *)(0x401000)) { - log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); - exit(1); + log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); + exit(1); } void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE | MAP_FILE, gExeFd, 0); @@ -584,7 +585,7 @@ static bool openrct2_setup_rct2_segment() { err = errno; log_error("Failed to unmap file! errno = %d", err); - } + }*/ #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Check that the expected data is at various addresses. @@ -610,30 +611,6 @@ static bool openrct2_release_rct2_segment() { bool result = true; #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB - int err; - err = munmap(gDataSegment, len); - if (err != 0) - { - err = errno; - log_error("Failed to unmap data segment! errno = %d", err); - result = false; - } - len = 0x004A3000; - err = munmap(gTextSegment, len); - if (err != 0) - { - err = errno; - log_error("Failed to unmap text segment! errno = %d", err); - result = false; - } - err = close(gExeFd); - if (err != 0) - { - err = errno; - log_error("Failed to close file! errno = %d", err); - result = false; - } #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) return result; } From c9be2e1bc99a60ea446a46bf6fb27013d0d1f5ff Mon Sep 17 00:00:00 2001 From: LRFLEW Date: Tue, 8 Dec 2015 21:06:21 -0600 Subject: [PATCH 5/5] Resolved struct packing error and crash on OS X --- CMakeLists.txt | 20 ++++++++++++- src/network/network.h | 6 ++++ src/openrct2.c | 67 +++++++++++++++++++++++++++++-------------- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae1be6c228..36fa04b30d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ if (UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") if (APPLE) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -sectcreate rct2_text __text /Users/kkirbatski/Desktop/openrct2_text -sectcreate rct2_data __data /Users/kkirbatski/Desktop/openrct2_data -segaddr rct2_data 0x8a4000 -segprot rct2_data rwx rwx -segaddr rct2_text 0x4010000 -segprot rct2_text rwx rwx -fno-pie -read_only_relocs suppress") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -sectcreate rct2_text __text ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_text -sectcreate rct2_data __data ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_data -segaddr rct2_data 0x8a4000 -segprot rct2_data rwx rwx -segaddr rct2_text 0x401000 -segprot rct2_text rwx rwx -fno-pie -read_only_relocs suppress") endif (APPLE) set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) @@ -104,6 +104,24 @@ if (APPLE) TARGET_LINK_LIBRARIES(${PROJECT} ${ICONV_LIBRARIES}) endif (APPLE) +# handle creating the rct2 text and data files on OS X +if (APPLE) + add_custom_command( + OUTPUT openrct2_text + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_text bs=4096 skip=1 count=1187 + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_command( + OUTPUT openrct2_data + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1188 count=318 + COMMAND dd if=/dev/zero of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 seek=318 count=2630 conv=notrunc + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1506 seek=2948 count=1 conv=notrunc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_target(segfiles DEPENDS openrct2_text openrct2_data) + add_dependencies(${PROJECT} segfiles) +endif (APPLE) + # install into ${CMAKE_INSTALL_PREFIX}/bin/ #install (TARGETS ${PROJECT} DESTINATION bin) diff --git a/src/network/network.h b/src/network/network.h index 56260ce5f2..3eefa4f923 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -90,6 +90,12 @@ extern "C" { #define ioctlsocket ioctl #endif // _WIN32 +// Fixes issues on OS X +#if defined(_RCT2_H_) && !defined(_MSC_VER) +// use similar struct packing as MSVC for our structs +#pragma pack(1) +#endif + #ifdef __cplusplus #include diff --git a/src/openrct2.c b/src/openrct2.c index 7a8c9c0959..74fd4848f5 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -40,14 +40,14 @@ #include "util/util.h" #include "world/mapgen.h" -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) #include #include #include #include #include #include -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; utf8 gOpenRCT2StartupActionPath[512] = { 0 }; @@ -59,11 +59,11 @@ bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -//unsigned char __attribute__((section ("rct2_text,__text"))) gTextSegment[0x004A3000]; -//unsigned char __attribute__((section ("rct2_data,__data"))) gDataSegment[0x01429000 - 0x8a4000]; +#if defined(__unix__) +void *gDataSegment; +void *gTextSegment; int gExeFd; -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) /** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */ int _finished; @@ -471,8 +471,8 @@ static bool openrct2_setup_rct2_segment() { // POSIX OSes will run OpenRCT2 as a native application and then load in the Windows PE, mapping the appropriate addresses as // necessary. Windows does not need to do this as OpenRCT2 runs as a DLL loaded from the Windows PE. -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - /*#define RDATA_OFFSET 0x004A4000 +#if defined(__unix__) + #define RDATA_OFFSET 0x004A4000 #define DATASEG_OFFSET 0x005E2000 const char *exepath = "openrct2.exe"; @@ -551,23 +551,22 @@ static bool openrct2_setup_rct2_segment() log_error("Found already mapped pages in region we want to claim. This means something accessed memory before we got to and following mmap (or next malloc) call will likely fail."); } // section: rw data - - void* asdf = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_SHARED, 0, 0); - if (asdf != (void *)0x8a4000) { - log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); - exit(1); + gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0); + if (gDataSegment != (void *)0x8a4000) { + log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); + exit(1); } len = 0x004A3000; // section: text - void* ffaa = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); - if (ffaa != (void *)(0x401000)) + gTextSegment = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); + if (gTextSegment != (void *)(0x401000)) { - log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); - exit(1); + log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); + exit(1); } - void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE | MAP_FILE, gExeFd, 0); + void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0); err = errno; log_warning("mmapped file to %p", fbase); if (fbase == MAP_FAILED) @@ -585,8 +584,8 @@ static bool openrct2_setup_rct2_segment() { err = errno; log_error("Failed to unmap file! errno = %d", err); - }*/ -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + } +#endif // defined(__unix__) // Check that the expected data is at various addresses. // Start at 0x9a6000, which is start of .data, to skip the region containing addresses to DLL @@ -610,8 +609,32 @@ static bool openrct2_setup_rct2_segment() static bool openrct2_release_rct2_segment() { bool result = true; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) + int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB + int err; + err = munmap(gDataSegment, len); + if (err != 0) + { + err = errno; + log_error("Failed to unmap data segment! errno = %d", err); + result = false; + } + len = 0x004A3000; + err = munmap(gTextSegment, len); + if (err != 0) + { + err = errno; + log_error("Failed to unmap text segment! errno = %d", err); + result = false; + } + err = close(gExeFd); + if (err != 0) + { + err = errno; + log_error("Failed to close file! errno = %d", err); + result = false; + } +#endif // defined(__unix__) return result; }