```markdown # Summary: Dynamic Interposing, Linking, and Build Configuration (macOS / Xcode / SwiftPM) ## Main Topic Techniques and configuration patterns for: - **Intercepting and shadowing C/C++ functions** using `dyld` interposing - **Hooking low-level functions** like `__cxa_throw` to capture stack traces - **Controlling Xcode’s preview dylib linking** - **Propagating defines and optional frameworks** across Xcode projects and Swift packages - **Detecting sandbox vs. DMG runtime environments** --- ## Key Decisions & Solutions ### 1. Shadowing System C Functions via `dyld` Interposing - Use `__DATA,__interpose` section with dyld to redirect system calls. - Example interpose tuple: ```c __attribute__((used)) static struct { void *new_func; void *orig_func; } _interposers[] __attribute__((section("__DATA, __interpose"))) = { { (void*)my_open, (void*)open } }; ``` - Optionally use `dyld_dynamic_interpose()` for runtime registration. - Reference: [HackTricks macOS Function Hooking](https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-function-hooking.html) ---------- ### 2. Interposing `__cxa_throw` to Capture Stack Traces - Replace C++ ABI’s `__cxa_throw` to log stack traces at throw time. - Example implementation: ```c extern "C" void __cxa_throw(void*, std::type_info*, void (*)(void*)) __attribute__((noreturn)); extern "C" void my___cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*)) __attribute__((noreturn)) { void* frames[128]; int n = backtrace(frames, 128); // Store stack trace... __real___cxa_throw(thrown_exception, tinfo, dest); } __attribute__((used)) static struct { const void* replacement; const void* replacee; } _interposers[] __attribute__((section("__DATA,__interpose"))) = { { (const void*)my___cxa_throw, (const void*)__cxa_throw }, }; ``` - Hook is used for debugging; not recommended in production. ---------- ### 3. Disable `__preview.dylib` Linking in Xcode - Build setting: `ENABLE_DEBUG_DYLIB = NO` - Steps: 1. Select target → **Build Settings** 2. Search for `ENABLE_DEBUG_DYLIB` 3. Set to **NO** (for Debug or all configurations) 4. Clean and rebuild - Prevents automatic SwiftUI preview dylib injection. ---------- ### 4. Propagating `#define` Flags into Swift Packages - **Not supported directly.** - Packages build in isolation; app-level defines (`SWIFT_ACTIVE_COMPILATION_CONDITIONS`) don’t propagate. - Solutions: - Define flags in the package: ```swift .target( name: "MyLib", swiftSettings: [.define("USE_FOO")] ) ``` - Pass global flags: `swift build -Xswiftc -D USE_FOO` - Expose feature variants via separate targets or products. ---------- ### 5. Detecting Sandbox vs. DMG App Runtime #### Detect App Sandbox ```swift import Security func isSandboxed() -> Bool { let task = SecTaskCreateFromSelf(nil)! if let v = SecTaskCopyValueForEntitlement(task, "com.apple.security.app-sandbox" as CFString, nil) as? NSNumber { return v.boolValue } return false } ``` #### Detect App Store vs. DMG - **Modern (macOS 14+):** ```swift import StoreKit func installOrigin() async -> Bool { if case .verified(_) = try? await AppTransaction.shared { return true // App Store } return false } ``` - **Legacy:** ```swift if let url = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: url.path) { // App Store receipt found } ``` ---------- ### 6. Using Optional Frameworks from a Swift Package - **App’s optional linkage does not propagate** to packages. - Alternatives: 1. Add `linkerSettings` or `unsafeFlags` in the package: ```swift .target( name: "Child", linkerSettings: [ .unsafeFlags(["-weak_framework", "Foo"]) ] ) ``` 2. Use `#if canImport(Foo)` inside the package to guard code. 3. Offer multiple package products (e.g., `Core` and `WithFoo`). 4. As last resort, `dlopen()` the framework dynamically. ---------- ## Important Snippets Collected - **Dyld Interpose Example** - **`__cxa_throw` hook for backtrace** - **Disabling SwiftUI `__preview.dylib`** - **Sandbox/App Store detection functions** - **SwiftPM `swiftSettings` and weak framework linking** ---------- ## Unresolved / Future Considerations - Testing cross-target define propagation via unified SwiftPM workspace. - Verifying `dyld_dynamic_interpose()` availability on latest macOS. - Providing a reusable utility to report sandbox + install origin combined.