Skip to content

macOS/Apple Silicon: run.sh kills itself — DYLD_INSERT_LIBRARIES leaks into the arm64e arch helper #107

Description

@Ramanathan0310

Summary

On Apple Silicon, the Apple-Silicon branch added in #79 makes run.sh / run_bepinex.sh fail before the game is ever launched. The script exports DYLD_INSERT_LIBRARIES into its own environment and then execs /usr/bin/arch. Because /usr/bin/arch is an arm64e binary and libdoorstop.dylib ships only x86_64 + arm64 slices, dyld refuses to inject into arch and terminates it. The game never starts.

This is independent of the Unity-version hooking problem — it blocks Doorstop on Apple Silicon regardless of the game.

Environment

  • macOS 27.0 (build 26A5388g), Darwin 27.0.0, Apple M4
  • BepInEx 6.0.0-be.785+6abdba4 (Unity.Mono macos-x64), Doorstop 4.5.0

The failing code

if [ -n "${is_apple_silicon}" ]; then
    export ARCHPREFERENCE="arm64,x86_64"
    exec arch -e DYLD_INSERT_LIBRARIES="${DYLD_INSERT_LIBRARIES}" "$executable_path" "$@"

DYLD_INSERT_LIBRARIES was exported ~20 lines earlier, so it is in arch's own environment, not just the child's. The existing comment says "arch also strips the DYLD_INSERT_LIBRARIES env var so we have to pass that in manually" — on current macOS it doesn't silently strip it, it hard-errors:

dyld[38519]: terminating because inserted dylib 'libdoorstop.dylib' could not be loaded:
  tried: '.../libdoorstop.dylib' (fat file, but missing compatible architecture
  (have 'x86_64,arm64', need 'arm64e')), ...
$ lipo -archs /usr/bin/arch
x86_64 arm64e
$ lipo -archs /usr/bin/env
x86_64 arm64e
$ lipo -archs libdoorstop.dylib
x86_64 arm64

Minimal reproduction

cd <game root with libdoorstop.dylib>
DYLD_INSERT_LIBRARIES=libdoorstop.dylib /usr/bin/arch -e FOO=bar /usr/bin/true
# -> dyld terminates arch with the error above

Fix

Remove the variable from the helper's environment, then let arch -e re-add it for the game only:

if [ -n "${is_apple_silicon}" ]; then
    export ARCHPREFERENCE="arm64,x86_64"

    doorstop_insert="${DYLD_INSERT_LIBRARIES}"
    unset DYLD_INSERT_LIBRARIES
    exec arch -e DYLD_INSERT_LIBRARIES="${doorstop_insert}" "$executable_path" "$@"

Verified working — Doorstop then loads into the game process normally.

Important: env -u DYLD_INSERT_LIBRARIES arch ... does not work. /usr/bin/env is arm64e too, so it dies exactly the same way before it can unset anything. The unset must be the shell builtin, with no intermediate process.

Alternative

Shipping an arm64e slice in libdoorstop.dylib would also avoid this, but the unset fix is a one-line change and doesn't depend on the dylib's slices.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions