A Swift package for locating and dynamically linking to symbols in MachO frameworks at runtime.
SymbolLocator provides a mechanism to access Darwin OS's non-public framework APIs through dynamic symbol resolution. It works by:
- Creating symbol stubs that map to their corresponding implementations in frameworks
- Dynamically loading the framework symbols at runtime using
dlopen
anddlsym
- Supporting both x86_64 and ARM64 architectures
// Define a stub for a SwiftUI framework function
DEFINE_SL_STUB_SLF(CGSizeHasZero, SwiftUI, _$sSo6CGSizeV7SwiftUIE7hasZeroSbvg);
// The stub can now be called like a regular function
bool hasZero = CGSizeHasZero(size);
SymbolLocator provides several macros for defining stubs:
DEFINE_SL_STUB_SLF(symbolName, framework, mangledName)
- For System Library FrameworksDEFINE_SL_STUB_SLPF(symbolName, framework, mangledName)
- For Private System Library FrameworksDEFINE_SL_STUB(symbolName, "path", mangledName)
- For any framework with custom path
SymbolLocator offers "safe" versions of stub macros that handle symbol resolution failures gracefully:
DEFINE_SL_SAFE_STUB_SLF(symbolName, framework, mangledName)
DEFINE_SL_SAFE_STUB_SLPF(symbolName, framework, mangledName)
DEFINE_SL_SAFE_STUB(symbolName, "path", mangledName)
When a symbol cannot be resolved at runtime, these safe stubs:
- Log an error message with information about the missing symbol
- Return without crashing instead of attempting to call a null function pointer
- Provide runtime resilience against API changes or missing symbols
Important Note: Safe stubs only prevent crashes for functions that return void
. For functions that return values, you must still check if the symbol exists before calling, as a missing implementation will cause undefined behavior when the caller attempts to use the return value.
// Define a safe stub for a void-returning function
DEFINE_SL_SAFE_STUB_SLF(TestStub_UNKNOWN_SYMBOL_VOID, UIKit, _$s5UIKit14UpdateUIElementyyF);
@_silgen_name("TestStub_UNKNOWN_SYMBOL_VOID")
func unknown_symbol_void()
unknown_symbol_void()
// This will not crash even if _$s5UIKit14UpdateUIElementyyF cannot be resolved in UIKit at runtime
To find the mangled name of a Swift symbol:
- Use
nm -g /System/Library/Frameworks/Framework.framework/Framework | grep functionName
- Or examine framework symbols with Hopper Disassembler
SymbolLocator supports both: x86_64 and arm64 architectures.
See LICENSE for details.