Add macOS Apple Silicon (arm64) support#51
Open
Simon9997 wants to merge 2 commits intocoolxv:masterfrom
Open
Conversation
macOS (especially Apple Silicon) enforces W^X on the __TEXT segment at the page-table level and caps mprotect by the segment's maxprot. Two issues previously prevented cpp-stub from patching its own text segment on an M-chip Mac: 1. mprotect cannot raise __TEXT to PROT_WRITE|PROT_EXEC. 2. Even with a writable alias obtained via mach_vm_remap, a plain store instruction that happens to sit on the same physical page as the destination deadlocks the current thread. Fixes: * src/stub.h: on __APPLE__, obtain a writable alias of the target page(s) via mach_vm_remap(VM_INHERIT_SHARE) + mach_vm_protect(RW) and route every write through libSystem's memcpy (invoked through a volatile function pointer) so the store opcodes live on libSystem's pages rather than our own __TEXT. The aarch64 REPLACE_FAR macro is specialized for Apple to build the trampoline in a local buffer and memcpy it across. All non-Apple branches keep the original logic. * tool/macos_enable_stub.sh: post-link helper that walks the Mach-O load commands, patches __TEXT's maxprot to rwx, and ad-hoc re-signs the binary with codesign. Required once per test executable (see issue coolxv#49). * test/Makefile.darwin.clang: new Darwin Makefile that drives clang++ and runs macos_enable_stub.sh automatically. * .github/workflows/make-test-multi-platform.yml: enable macOS-13 (Intel) and macOS-latest (Apple Silicon) jobs using the new Makefile, replacing the commented-out stubs. * README / README_zh: document the new macOS support. Verified on macOS 26.4 arm64 (M-chip): test_function, test_class_member_function, test_variadic_function all pass, and repeated set/reset cycles behave correctly. Refs: coolxv#49 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Downstream users no longer need to invoke tool/macos_enable_stub.sh themselves. The repo now ships: * CMakeLists.txt — INTERFACE target cpp-stub. When add_subdirectory'd, a cmake_language(DEFER) callback runs at end-of-config, finds every executable that links cpp-stub, and attaches the enable-stub post-build step automatically on Apple. A cpp_stub_enable(target) helper is exposed for the transitive-link corner case. * mk/cpp-stub.mk — Makefile fragment. Defines CPP_STUB_INCLUDE and a CPP_STUB_POSTLINK macro that expands to the enable-stub invocation on macOS and to ':' (no-op) elsewhere, so one rule works on every platform. * example/cmake_smoke/ — self-contained CMake project that just links cpp-stub and expects the patch+sign to happen with zero manual steps. Exercised by CI on both macos-13 and macos-latest. * test/Makefile.darwin.clang now dogfoods mk/cpp-stub.mk. * README.md / README_zh.md gain a 'macOS integration' section showing the zero-step CMake path, the one-line Make path, and a snippet for Xcode/Bazel/other build systems. * .github/workflows/make-test-multi-platform.yml gains a second step per macOS runner that configures and runs example/cmake_smoke, proving end-to-end that a downstream CMake project need do nothing beyond target_link_libraries(... cpp-stub). Verified locally on macOS 26.4 arm64: CMake smoke + Makefile-based tests all pass, and the existing test matrix (test_function, test_class_member_function, test_variadic_function) is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds runtime support for cpp-stub on macOS, including Apple Silicon (M-chip).
Previously, calling
Stub::seton arm64 macOS failed withstub set memory protect to w+r+x faildbecause:mprotectby the Mach-O segment'smaxprot, and__TEXTdefaults tor-x.maxprotisn't enough — you cannot simultaneously hold write + execute on the same physical page via the original mapping.Refs #49.
Changes
src/stub.h: on__APPLE__, obtain a writable alias viamach_vm_remap(VM_INHERIT_SHARE)+mach_vm_protect(RW), and route every write through libSystem'smemcpy(called through avolatilefunction pointer) so the store opcodes are not co-located with the destination. The aarch64REPLACE_FARmacro is specialized for Apple to stage the trampoline in a stack buffer and memcpy it across. All non-Apple branches are unchanged.tool/macos_enable_stub.sh: post-link helper that walks the Mach-O load commands, patches__TEXT'smaxprottorwx, and ad-hoc re-signs withcodesign. Required once per macOS binary that uses cpp-stub.test/Makefile.darwin.clang: Darwin build recipe that filters Linux/Windows-only tests and automatically runs the enable-stub helper on each produced binary..github/workflows/make-test-multi-platform.yml: enablemacos-13(Intel) andmacos-latest(Apple Silicon) matrix entries using the new Makefile; drop the old commented-out macOS stubs.README/README_zh: document the new macOS support.Verification
Locally on macOS 26.4 arm64 (M-chip),
test_function,test_class_member_function, andtest_variadic_functionall pass viamake -f Makefile.darwin.clang. Repeated set/re-set/reset cycles behave correctly. CI will additionally validate onmacos-13(Intel) andmacos-latest(Apple Silicon).