Hot-fix iOS/macOS apps using WebAssembly payloads. Compile C code to WASM and replace Objective-C methods at runtime.
WasmPatch bridges Objective-C and WebAssembly. It compiles C code into WebAssembly modules and lets those modules call any Objective-C class or method dynamically.
This gives apps the ability to:
- 🔧 Hot-fix bugs without shipping a new binary
- ✨ Add features via WebAssembly payloads
- 🔄 Replace methods at runtime (class and instance)
| Feature | Description |
|---|---|
| 🧱 WASM Compilation | Compile C code to WebAssembly with clang/LLVM |
| 🔗 Objective-C Bridge | Call any Obj-C class or method from WebAssembly |
| 🔄 Method Replacement | Hot-fix by replacing Obj-C methods at runtime |
| 🍎 Cross-Platform | Works on both iOS and macOS |
| 🛠️ Runtime Diagnostics | Load state, reset hooks, and inspect last runtime error |
| 🧪 Regression Assets | Test case bundle and fixture hosts for bridge validation |
graph TD
A[C Code] --> B[clang/LLVM]
B --> C[WebAssembly Module]
C --> D[WasmPatch Runtime]
D --> E[Objective-C Runtime]
E --> F[Hot-fix Applied!]
style A fill:#f9f,color:#000
style C fill:#bbf,color:#000
style F fill:#bfb,color:#000
- Write your patch logic in C
- Compile to WebAssembly using
clang/LLVM - Load the wasm module in your app
- Call Objective-C classes/methods from WebAssembly
- Replace methods on the fly
# Install LLVM with WebAssembly target
brew install llvm
# Or use the provided script
sh Tool/install-llvm.shgit clone https://github.com/everettjf/WasmPatch.git
cd WasmPatch# Simplest entry point
sh Tool/build-patch.sh your_patch.c
# Optional explicit output path
sh Tool/build-patch.sh your_patch.c build/your_patch.wasm#import <WasmPatch/WAPPatchLoader.h>
NSError *error = nil;
WAPPatchLoaderOptions *options = [WAPPatchLoader recommendedOptions];
options.expectedSHA256Hex = @"<optional sha256>";
BOOL success = [WAPPatchLoader loadPatchNamed:@"your_patch"
inBundle:NSBundle.mainBundle
options:options
error:&error];
if (!success) {
NSLog(@"load failed: %@", error.localizedDescription);
NSLog(@"runtime detail: %@", error.userInfo[WAPPatchLoaderRuntimeMessageKey]);
}Low-level C API is still available when you need it:
#import <WasmPatch/WasmPatch.h>
BOOL success = wap_load_file("your_patch.wasm");
if (success) {
NSLog(@"loaded");
} else {
NSLog(@"load failed: %s", wap_last_error());
}WasmPatch/
├── WasmPatch/ # Core framework
│ ├── WasmPatch.h # Public C API
│ ├── core/runtime/ # WASM runtime and exports
│ └── core/method/ # Obj-C method bridge and hooks
├── Tool/ # Build tools
│ ├── c2wasm.sh # C to WASM compiler
│ └── install-llvm.sh # LLVM installer
├── TestCase/ # Test cases
│ ├── compile-testcase.sh # Test compiler
│ └── WasmPatch-TestCase/ # Sample host classes and wasm fixtures
├── Image/ # Documentation images
├── Demo/ # Demo projects
│ ├── iOS/ # iOS demo
│ └── macOS/ # macOS demo
└── README.md
bool wap_load_file(const char * path);
bool wap_load_data(const void * bytes, unsigned int size);
void wap_reset_runtime(void);
bool wap_runtime_is_loaded(void);
const char * wap_last_error(void);NSError *error = nil;
WAPPatchLoaderOptions *options = [WAPPatchLoader recommendedOptions];
options.allowReload = YES;
options.resetBeforeLoad = YES;
[WAPPatchLoader loadPatchAtPath:path options:options error:&error];
[WAPPatchLoader loadPatchNamed:@"objc" inBundle:bundle options:options error:&error];
[WAPPatchLoader loadPatchData:data options:options error:&error];
[WAPPatchLoader reset];Error handling:
if (error.code == WAPPatchLoaderErrorCodeSHA256Mismatch) {
NSLog(@"patch tampered: %@", error.userInfo[WAPPatchLoaderRuntimeMessageKey]);
}// advanced_patch.c
#include <wasmpatch.h>
int entry() {
WAPObject message = new_objc_nsstring("WasmPatch detected request");
call_class_method_1("NetworkManager", "logRequest:", message);
dealloc_object(message);
replace_instance_method("NetworkManager", "sendRequest:", "wasm_custom_send_request");
return 0;
}| Requirement | Version | Description |
|---|---|---|
| macOS | 10.14+ | Development environment |
| Xcode | 11+ | iOS/macOS SDK |
| LLVM/Clang | 14+ | C to WASM compilation |
| wabt | latest | wasm2wat tooling |
# Build the framework
cd WasmPatch/WasmPatch.xcodeproj
xcodebuild -project WasmPatch.xcodeproj \
-scheme WasmPatch \
-configuration Release \
-sdk iphoneos build
# Build for macOS
xcodebuild -project WasmPatch.xcodeproj \
-scheme WasmPatch \
-configuration Release \
-sdk macosx build# Compile testcase wasm fixtures
cd TestCase
sh compile-testcase.sh
# Compile your own patch with defaults
sh Tool/build-patch.sh path/to/patch.c
# Verify wasm modules
wasm2wat your_patch.wasm -o your_patch.watProduction validation:
sh Tool/validate-production.shmacOS host validation only:
sh Tool/run-macos-validation.sh| Platform | Support | Min Version |
|---|---|---|
| iOS | ✅ Full | 10.0 |
| macOS | ✅ Full | 10.14 |
| Simulator | ✅ Full | Same as above |
| Test Case | Description |
|---|---|
objc.c |
Objective-C bridge coverage and method replacement fixture |
CallMe |
Host methods for bridge argument/result validation |
ReplaceMe |
Host methods used for runtime replacement verification |
Run all tests:
sh TestCase/compile-testcase.sh- Stronger than the original prototype on diagnostics, reset safety, and scripting.
- Still behind best-in-class hotfix platforms on sandboxing, signature coverage, ABI compatibility testing, and release automation.
sh Tool/build-patch.sh your_patch.c
sh Tool/validate-production.shIf both pass, the current repo state is ready for internal release and integration validation.
Contributions are welcome! Areas to help:
- 🐛 Bug fixes
- ✨ New features
- 📝 Documentation
- 🧪 Test cases
- 💡 Performance improvements
WasmPatch is released under the MIT License.
Inspired by:
- WebAssembly - Binary format
- Fishhook - Symbol rebinding
- JSPatch - Hot-fix concept
有问题?去 Issues 提问!
Made with ❤️ by Everett
Project Link: https://github.com/everettjf/WasmPatch
