Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggestion: build without PIE on macOS, if possible? #928

Open
iliana opened this issue Feb 20, 2023 · 10 comments
Open

suggestion: build without PIE on macOS, if possible? #928

iliana opened this issue Feb 20, 2023 · 10 comments

Comments

@iliana
Copy link
Contributor

iliana commented Feb 20, 2023

The Linux and Windows builds of VVVVVV are not position-independent executables because the compilers used for these releases do not enable PIE by default. This allows autosplitters on Linux and Windows to hardcode relevant memory addresses for different versions (or since 64be99d, run the program with -addresses to prevent needing to hardcode future versions).

macOS's compiler enables PIE by default, thus enabling address space layout randomization, which resulted in me making some wild implementation-specific memory searching code. -addresses won't address the issue for macOS because the addresses will be different every time the program starts.

A flag to disable PIE for Linux builds may help in the future as well; if the build environment ends up being updated from CentOS 7, generally any newer Linux distro will enable PIE by default.

(I am posting this issue in the hopes that someone who understands CMake and Clang options more than me will consider updating the build scripts; I am attempting to come up with a solution on my own as well, though.)

@InfoTeddy
Copy link
Contributor

This sounds reasonable to add to the CMakeLists.txt. Should be as simple as something like a -fno-pie or similar to the compiler, but I haven't checked yet.

@InfoTeddy
Copy link
Contributor

Preliminary searching suggests both GCC and Clang support -no-pie, but it seems to not exist in all versions of those compilers. Not sure where the version cutoff is. Not sure what the equivalent flag is for MSVC.

@iliana
Copy link
Contributor Author

iliana commented Feb 21, 2023

I tried adding a long pile of no-pie flags and still couldn't get macOS to build me a version without PIE.

diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt
index 7f181ef..2615b15 100644
--- a/desktop_version/CMakeLists.txt
+++ b/desktop_version/CMakeLists.txt
@@ -439,6 +439,11 @@ else()
     endif()
 endif()

+if(NOT MSVC)
+    target_compile_options(VVVVVV PRIVATE -no-pie -fno-pie -fno-PIE -Wl,-no_pie)
+    target_link_libraries(VVVVVV -no-pie -fno-pie)
+endif()
+
 # Yes, more Apple Crap
 if(APPLE)
     find_library(FOUNDATION NAMES Foundation)

Some particularly damning compiler spew (thanks, lld!):

ld: warning: -no_pie is deprecated when targeting new OS versions
ld: warning: -no_pie ignored for arm64
$ otool -hv VVVVVV 
VVVVVV:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64        ALL  0x00     EXECUTE    24       2520   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE

So maybe there is not really a good solution here in the long run.

@InfoTeddy
Copy link
Contributor

Yeah, it seems to me that macOS is strictly enforcing PIE in the future for whatever reason.

@iliana
Copy link
Contributor Author

iliana commented Feb 21, 2023

An alternative, possibly-silly suggestion to help out future autosplitters on platforms where memory scanning is inevitable, and thus the -addresses option is not as useful, might be to add a static string to the start of some objects, e.g.:

diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h
index 6dc2517..904b19e 100644
--- a/desktop_version/src/Game.h
+++ b/desktop_version/src/Game.h
@@ -133,6 +133,8 @@ struct CustomLevelStat
 class Game
 {
 public:
+    char magic[16];
+
     void init(void);
 
 
diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp
index 847044d..e124392 100644
--- a/desktop_version/src/Game.cpp
+++ b/desktop_version/src/Game.cpp
@@ -158,6 +158,8 @@ end:
 
 void Game::init(void)
 {
+    SDL_strlcpy(magic, "[vVvVvV]game", 16);
+
     roomx = 0;
     roomy = 0;
     prevroomx = 0;

It's likely only one marker string is necessary because you can rely on relative offsets based on -addresses for the various globals.

If this seems like an acceptable I'll make sure that memory string is actually unique and open a PR.

@InfoTeddy
Copy link
Contributor

Yes, this is acceptable. It's something I was considering too. Though, use sizeof(magic) instead of duplicating the length of the array.

iliana added a commit to iliana/VVVVVV that referenced this issue Feb 21, 2023
The `-addresses` command-line option added in 64be99d helps
autosplitters on platforms where VVVVVV is not built as a
position-independent executable. macOS has made it increasingly
difficult, or impossible, to build binaries without PIE.

Adding an obvious string to search for will help tools that need to deal
with versions of VVVVVV built with PIE. The bytestring to search for is
`[vVvVvV]game`, followed by four null bytes (to avoid finding it in the
program code section). This identifies the beginning of the game object;
addresses to other objects can be figured out by relative offsets
printed by `-addresses`, since ASLR can only change where the globals
begin.

Partially fixes TerryCavanagh#928; it may still be advisable to figure out how to
explicitly disable PIE on Windows/Linux.
@iliana
Copy link
Contributor Author

iliana commented Feb 21, 2023

oh, the commit message closed the issue anyway. oops

@InfoTeddy InfoTeddy reopened this Feb 21, 2023
@InfoTeddy
Copy link
Contributor

lmao

@InfoTeddy
Copy link
Contributor

Here are some things I found that may help. I do not have macOS, so I can't test any of these.

According to this 2-year-old blog post, LLDB will disable ASLR by default. How it does this I do not know. Might be worth looking into.

In the latest CMake version, there is a POSITION_INDEPENDENT_CODE property as well as a CheckPIESupported function. Maybe these can be used to definitively conclude if macOS allows disabling PIE or not.

@leo60228
Copy link
Contributor

leo60228 commented Sep 8, 2023

lldb starts the application via posix_spawn with the undocumented _POSIX_SPAWN_DISABLE_ASLR flag (0x0100) set via posix_spawnattr_setflags. It may be safest for vitellary to do that itself. Spawning VVVVVV as a subprocess might also avoid problems with Linux distributions that enable restricted ptrace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants