├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .gitmodules ├── ImageSource ├── JSPatchMemory.png ├── JSPatchTimes.png ├── MangoMemory.png ├── MangoTimes.png ├── OCRunnerMemory.png └── OCRunnerTimes.png ├── LICENSE ├── OCRunner.podspec ├── OCRunner.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── OCRunner.xcscheme │ └── OCRunnerTests.xcscheme ├── OCRunner ├── Info.plist ├── OCRunner.h ├── ORCoreImp │ ├── ORCoreFunction │ │ ├── ORCoreFunction.h │ │ ├── ORCoreFunctionCall.h │ │ ├── ORCoreFunctionCall.m │ │ ├── ORCoreFunctionCall.s │ │ ├── ORCoreFunctionRegister.h │ │ ├── ORCoreFunctionRegister.m │ │ ├── ORCoreFunctionRegister.s │ │ ├── ORTypeVarPair+libffi.h │ │ └── ORTypeVarPair+libffi.m │ ├── ORCoreImp.h │ └── ORCoreImp.m ├── ORHandleTypeEncode.h ├── ORHandleTypeEncode.m ├── ORInterpreter.h ├── ORInterpreter.m ├── ORTypeVarPair+TypeEncode.h ├── ORTypeVarPair+TypeEncode.m ├── ORffiResultCache.h ├── ORffiResultCache.m ├── RunEnv │ ├── MFBlock.h │ ├── MFBlock.m │ ├── MFMethodMapTable.h │ ├── MFMethodMapTable.m │ ├── MFPropertyMapTable.h │ ├── MFPropertyMapTable.m │ ├── MFScopeChain.h │ ├── MFScopeChain.m │ ├── MFStaticVarTable.h │ ├── MFStaticVarTable.m │ ├── MFValue.h │ ├── MFValue.mm │ ├── MFVarDeclareChain.h │ ├── MFVarDeclareChain.m │ ├── ORGlobalFunctionTable.h │ ├── ORGlobalFunctionTable.m │ ├── ORStructDeclare.h │ ├── ORStructDeclare.m │ ├── ORThreadContext.h │ ├── ORThreadContext.m │ └── runenv.h ├── RunnerClasses+Execute.h ├── RunnerClasses+Execute.m ├── RunnerClasses+Recover.h ├── RunnerClasses+Recover.m ├── Util │ ├── ORSearchedFunction.h │ ├── ORSearchedFunction.m │ ├── ORSystemFunctionPointerTable.h │ ├── ORSystemFunctionPointerTable.m │ ├── SymbolSearch.c │ ├── SymbolSearch.h │ ├── util.h │ └── util.m ├── built-in.h ├── built-in.m └── libffi │ ├── ffi.h │ ├── ffi_arm.h │ ├── ffi_arm64.h │ ├── ffi_i386.h │ ├── ffi_x86_64.h │ ├── ffitarget.h │ ├── ffitarget_arm.h │ ├── ffitarget_arm64.h │ ├── ffitarget_i386.h │ ├── ffitarget_x86_64.h │ └── libffi.a ├── OCRunnerArm64.podspec ├── OCRunnerDemo ├── OCRunnerDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── OCRunnerDemo.xcscheme ├── OCRunnerDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── OCRunnerDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── HotPath │ │ ├── HotViewcontroller.m │ │ └── ViewController1.m │ ├── Info.plist │ ├── OCRunnerDemo-Bridging-Header.h │ ├── PatchGenerator │ ├── SceneDelegate.h │ ├── SceneDelegate.m │ ├── Scripts.bundle │ │ ├── GCDRefrences │ │ └── UIKitRefrences │ ├── SwiftViewController.swift │ ├── SwiftViewController1.swift │ ├── SwiftViewController1.xib │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── OCRunnerDemoTests │ ├── Info.plist │ ├── OCRunnerDemoTests-Bridging-Header.h │ ├── ORParserForTest.h │ └── ORParserForTest.m ├── Podfile └── Podfile.lock ├── OCRunnerTests ├── Info.plist ├── OCRunnerTests-Bridging-Header.h ├── OCRunnerTests.swift ├── ORCoreFunctionTests.m ├── ORTestWithObjc.m └── TestClass │ ├── ORCallOCPropertyBlockTest.h │ ├── ORCallOCPropertyBlockTest.m │ ├── ORCallSuperNoArgTest.h │ ├── ORCallSuperNoArgTest.m │ ├── ORGCDTests.h │ ├── ORGCDTests.m │ ├── ORHookNatvieMultiSuperCall.h │ ├── ORHookNatvieMultiSuperCall.m │ ├── ORRecoverClass.h │ ├── ORRecoverClass.m │ ├── ORTestClassIvar.h │ ├── ORTestClassIvar.m │ ├── ORTestClassProperty.h │ ├── ORTestClassProperty.m │ ├── ORTestORGDealloc.h │ ├── ORTestORGDealloc.m │ ├── ORTestReplaceClass.h │ ├── ORTestReplaceClass.m │ ├── ORWeakPropertyAndIvar.h │ ├── ORWeakPropertyAndIvar.m │ ├── TestFakeModel.h │ └── TestFakeModel.m ├── README-CN.md └── README.md /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | assignees: 'SilverFruity' 5 | --- 6 | 7 | OCRunner version: xxxxx 8 | 9 | description: xxxxxx 10 | 11 | example: xxxxx 12 | 13 | OCRunner 版本号: xxx 14 | 15 | 问题描述: xxx 16 | 17 | bug 示例代码: xxx 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | /OCRunnerDemo/OCRunnerDemo/binarypatch 5 | /OCRunnerDemo/OCRunnerDemo/jsonpatch 6 | /OCRunnerDemo/OCRunnerDemo/binarypatch.ocrr 7 | ## User settings 8 | xcuserdata/ 9 | .ccls-cache/ 10 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 11 | *.xcscmblueprint 12 | *.xccheckout 13 | 14 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 15 | build/ 16 | DerivedData/ 17 | *.moved-aside 18 | *.pbxuser 19 | !default.pbxuser 20 | *.mode1v3 21 | !default.mode1v3 22 | *.mode2v3 23 | !default.mode2v3 24 | *.perspectivev3 25 | !default.perspectivev3 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | 30 | ## App packaging 31 | *.ipa 32 | *.dSYM.zip 33 | *.dSYM 34 | 35 | # CocoaPods 36 | # 37 | # We recommend against adding the Pods directory to your .gitignore. However 38 | # you should judge for yourself, the pros and cons are mentioned at: 39 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 40 | # 41 | OCRunnerDemo/Pods/ 42 | # 43 | # Add this line if you want to avoid checking in source code from the Xcode workspace 44 | # *.xcworkspace 45 | 46 | # Carthage 47 | # 48 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 49 | # Carthage/Checkouts 50 | 51 | Carthage/Build/ 52 | 53 | # fastlane 54 | # 55 | # It is recommended to not store the screenshots in the git repo. 56 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 57 | # For more information about the recommended setup visit: 58 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 59 | 60 | fastlane/report.xml 61 | fastlane/Preview.html 62 | fastlane/screenshots/**/*.png 63 | fastlane/test_output 64 | 65 | # Code Injection 66 | # 67 | # After new code Injection tools there's a generated folder /iOSInjectionProject 68 | # https://github.com/johnno1962/injectionforxcode 69 | 70 | iOSInjectionProject/ 71 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "oc2mango"] 2 | path = oc2mango 3 | url = https://github.com/SilverFruity/oc2mango.git 4 | -------------------------------------------------------------------------------- /ImageSource/JSPatchMemory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/JSPatchMemory.png -------------------------------------------------------------------------------- /ImageSource/JSPatchTimes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/JSPatchTimes.png -------------------------------------------------------------------------------- /ImageSource/MangoMemory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/MangoMemory.png -------------------------------------------------------------------------------- /ImageSource/MangoTimes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/MangoTimes.png -------------------------------------------------------------------------------- /ImageSource/OCRunnerMemory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/OCRunnerMemory.png -------------------------------------------------------------------------------- /ImageSource/OCRunnerTimes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/ImageSource/OCRunnerTimes.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Silver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OCRunner.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "OCRunner" 3 | s.version = "1.3.3" 4 | s.summary = "OCRunner" 5 | s.description = <<-DESC 6 | Execute Objective-C code Dynamically. iOS hotfix SDK. 7 | DESC 8 | s.homepage = "https://github.com/SilverFruity/OCRunner" 9 | s.license = "MIT" 10 | s.author = { "SilverFruity" => "15328044115@163.com" } 11 | s.ios.deployment_target = "9.0" 12 | s.source = { :git => "https://github.com/SilverFruity/OCRunner.git", :tag => "#{s.version}" } 13 | s.source_files = "OCRunner/**/*.{h,m,c,mm}" 14 | s.pod_target_xcconfig = { 15 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' 16 | } 17 | s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } 18 | s.vendored_libraries = 'OCRunner/libffi/libffi.a' 19 | s.dependency "ORPatchFile", "1.2.3" 20 | end 21 | 22 | -------------------------------------------------------------------------------- /OCRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OCRunner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OCRunner.xcodeproj/xcshareddata/xcschemes/OCRunner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 54 | 55 | 61 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /OCRunner.xcodeproj/xcshareddata/xcschemes/OCRunnerTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /OCRunner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /OCRunner/OCRunner.h: -------------------------------------------------------------------------------- 1 | // 2 | // OCRunner.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/8. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for OCRunner. 12 | FOUNDATION_EXPORT double OCRunnerVersionNumber; 13 | 14 | //! Project version string for OCRunner. 15 | FOUNDATION_EXPORT const unsigned char OCRunnerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | #import "ORCoreImp.h" 19 | #import "ORHandleTypeEncode.h" 20 | #import "ORTypeVarPair+TypeEncode.h" 21 | #import "MFBlock.h" 22 | #import "MFValue.h" 23 | #import "MFScopeChain.h" 24 | #import "RunnerClasses+Execute.h" 25 | #import "ORInterpreter.h" 26 | #import "ORStructDeclare.h" 27 | #import "ORSystemFunctionPointerTable.h" 28 | 29 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORCoreFunction.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreFunction.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/14. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #ifndef ORCoreFunction_h 10 | #define ORCoreFunction_h 11 | 12 | #if __has_include("ffi.h") 13 | 14 | #define __libffi__ 15 | #import "ffi.h" 16 | 17 | #else 18 | 19 | # if __has_feature(ptrauth_calls) 20 | # define HAVE_PTRAUTH 1 21 | # endif 22 | 23 | typedef struct{ 24 | NSUInteger NGRN; 25 | NSUInteger NSRN; 26 | NSUInteger NSAA; 27 | }CallRegisterState; 28 | 29 | typedef struct { 30 | CallRegisterState *state; 31 | void **generalRegister; 32 | void *floatRegister; 33 | void *frame; 34 | char *stackMemeries; 35 | void *retPointer; 36 | }CallContext; 37 | 38 | typedef struct { 39 | char *r_typeEncode; 40 | char **arg_typeEncodes; 41 | unsigned nargs; 42 | unsigned flags; 43 | unsigned nfixedargs; //可变参数需要的个数 44 | } ffi_cif; 45 | 46 | typedef enum { 47 | FFI_OK = 0, 48 | FFI_BAD_TYPEDEF, 49 | FFI_BAD_ABI 50 | } ffi_status; 51 | 52 | typedef struct { 53 | void *trampoline_table; 54 | void *trampoline_table_entry; 55 | ffi_cif *cif; 56 | void (*fun)(ffi_cif*,void*,void**,void*); 57 | void *user_data; 58 | } ffi_closure; 59 | 60 | NSUInteger floatPointFlagsWithTypeEncode(const char *typeEncode); 61 | NSUInteger resultFlagsForTypeEncode(const char *retTypeEncode, char **argTypeEncodes, int narg); 62 | void ffi_closure_free(void *ptr); 63 | #endif /* __has_include */ 64 | 65 | typedef struct { 66 | ffi_cif *cif; 67 | ffi_closure *closure; 68 | #ifdef __libffi__ 69 | ffi_type **arg_types; 70 | #endif 71 | void *function_imp; 72 | }or_ffi_result; 73 | void or_ffi_result_free(or_ffi_result *result); 74 | 75 | @class NSArray; 76 | @class MFValue; 77 | @class ORTypeVarPair; 78 | 79 | void core_invoke_function_pointer(ffi_cif *cif, void *funcptr, void **args, void *ret); 80 | __attribute__((overloadable)) 81 | void invoke_functionPointer(void *funptr, NSArray *argValues, MFValue *returnValue, NSUInteger needArgs); 82 | void invoke_functionPointer(void *funptr, NSArray *argValues, MFValue *returnValue); 83 | 84 | 85 | 86 | 87 | or_ffi_result *register_function(void (*fun)(ffi_cif *,void *,void **, void*), 88 | NSArray *args, 89 | ORTypeVarPair *ret) __attribute__((overloadable)); 90 | 91 | or_ffi_result *register_function(void (*fun)(ffi_cif *,void *,void **, void*), 92 | NSArray *args, 93 | ORTypeVarPair *ret, 94 | void *userdata); 95 | 96 | or_ffi_result *register_method(void (*fun)(ffi_cif *,void *,void **, void*), 97 | NSArray *args, 98 | ORTypeVarPair *ret) __attribute__((overloadable)); 99 | 100 | or_ffi_result *register_method(void (*fun)(ffi_cif *,void *,void **, void*), 101 | NSArray *args, 102 | ORTypeVarPair *ret, 103 | void *userdata); 104 | 105 | #endif /* ORCoreFunction_h */ 106 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORCoreFunctionCall.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreFunctionCall.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/7. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | #ifndef __libffi__ 9 | 10 | #define AARCH64_RET_VOID 0 11 | #define AARCH64_RET_INT64 1 12 | #define AARCH64_RET_INT128 2 13 | 14 | #define AARCH64_RET_UNUSED3 3 15 | #define AARCH64_RET_UNUSED4 4 16 | #define AARCH64_RET_UNUSED5 5 17 | #define AARCH64_RET_UNUSED6 6 18 | #define AARCH64_RET_UNUSED7 7 19 | 20 | /* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4, 21 | so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */ 22 | #define AARCH64_RET_S4 8 23 | #define AARCH64_RET_S3 9 24 | #define AARCH64_RET_S2 10 25 | #define AARCH64_RET_S1 11 26 | 27 | #define AARCH64_RET_D4 12 28 | #define AARCH64_RET_D3 13 29 | #define AARCH64_RET_D2 14 30 | #define AARCH64_RET_D1 15 31 | 32 | #define AARCH64_RET_Q4 16 33 | #define AARCH64_RET_Q3 17 34 | #define AARCH64_RET_Q2 18 35 | #define AARCH64_RET_Q1 19 36 | 37 | /* Note that each of the sub-64-bit integers gets two entries. */ 38 | #define AARCH64_RET_UINT8 20 39 | #define AARCH64_RET_UINT16 22 40 | #define AARCH64_RET_UINT32 24 41 | 42 | #define AARCH64_RET_SINT8 26 43 | #define AARCH64_RET_SINT16 28 44 | #define AARCH64_RET_SINT32 30 45 | 46 | #define AARCH64_RET_MASK 31 47 | 48 | #define AARCH64_RET_IN_MEM (1 << 5) 49 | #define AARCH64_RET_NEED_COPY (1 << 6) 50 | 51 | #define AARCH64_FLAG_ARG_V_BIT 7 52 | #define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT) 53 | 54 | //NOTE: https://developer.arm.com/documentation/100986/0000 #Procedure Call Standard for the ARM 64-bit Architecture 55 | //NOTE: https://juejin.im/post/5d14623ef265da1bb47d7635#heading-12 56 | #define G_REG_SIZE 8 57 | #define V_REG_SIZE 16 58 | #define N_G_ARG_REG 8 // The Number Of General Register 59 | #define N_V_ARG_REG 8 // The Number Of Float-Point Register 60 | #define V_REG_TOTAL_SIZE (N_V_ARG_REG * V_REG_SIZE) 61 | #define G_REG_TOTAL_SIZE (N_G_ARG_REG * G_REG_SIZE) 62 | #define CALL_CONTEXT_SIZE (V_REG_TOTAL_SIZE + G_REG_TOTAL_SIZE) 63 | 64 | #define ARGS_SIZE N_V_ARG_REG*V_REG_SIZE+N_G_ARG_REG*G_REG_SIZE 65 | 66 | #define OR_ALIGNMENT 8 67 | // 字节对齐 68 | #define OR_ALIGN(v,a) (v + (a - 1)) / (a); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORCoreFunctionCall.s: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreCall.s 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/7. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | #import "ORCoreFunctionCall.h" 9 | /** 10 | * void ORMultiArgsCFunCall 11 | * x0 void *stack 12 | * x1 void *frame: save x29, x30, sp, ret, flag 13 | * x2 void (*func)(void) 14 | * x3 void *ret 15 | * x4 uint retFlag 16 | */ 17 | #if !__has_include("ffi.h") 18 | .text 19 | .global _ORCoreFunctionCall 20 | _ORCoreFunctionCall: 21 | stp x29, x30, [x1] 22 | stp x3, x4, [x1, 0x10] 23 | mov x29, sp 24 | str x29, [x1, 0x20] 25 | mov x29, x1 26 | mov x9, x2 27 | mov x8, x3 // install struct return 28 | mov sp, x0 29 | ldp q0, q1, [sp] 30 | ldp q2, q3, [sp, 0x20] 31 | ldp q4, q5, [sp, 0x40] 32 | ldp q6, q7, [sp, 0x60] 33 | ldp x0, x1, [sp, 0x80] //128: N_V_ARG_REG*V_REG_SIZE 34 | ldp x2, x3, [sp, 0x80 + 0x10] 35 | ldp x4, x5, [sp, 0x80 + 0x20] 36 | ldp x6, x7, [sp, 0x80 + 0x30] 37 | add sp, sp, 0xc0 //0x80+0x40: ARGS_SIZE+FUNC_POINT 38 | blr x9 39 | ldp x3, x4, [x29, 0x10] 40 | ldr x9, [x29, 0x20] 41 | mov sp, x9 42 | ldp x29, x30, [x29] 43 | 44 | /* Save the return value as directed. */ 45 | adr x5, 0f 46 | and w4, w4, #AARCH64_RET_MASK 47 | add x5, x5, x4, lsl #3 48 | br x5 49 | /* Note that each table entry is 2 insns, and thus 8 bytes. 50 | For integer data, note that we're storing into ffi_arg 51 | and therefore we want to extend to 64 bits; these types 52 | have two consecutive entries allocated for them. */ 53 | .align 4 54 | 0: ret /* VOID */ 55 | nop 56 | 1: str x0, [x3] /* INT64 */ 57 | ret 58 | 2: stp x0, x1, [x3] /* INT128 */ 59 | ret 60 | 3: brk #1000 /* UNUSED */ 61 | ret 62 | 4: brk #1000 /* UNUSED */ 63 | ret 64 | 5: brk #1000 /* UNUSED */ 65 | ret 66 | 6: brk #1000 /* UNUSED */ 67 | ret 68 | 7: brk #1000 /* UNUSED */ 69 | ret 70 | 8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */ 71 | ret 72 | 9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */ 73 | ret 74 | 10: stp s0, s1, [x3] /* S2 */ 75 | ret 76 | 11: str s0, [x3] /* S1 */ 77 | ret 78 | 12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */ 79 | ret 80 | 13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */ 81 | ret 82 | 14: stp d0, d1, [x3] /* D2 */ 83 | ret 84 | 15: str d0, [x3] /* D1 */ 85 | ret 86 | 16: str q3, [x3, #48] /* Q4 */ 87 | nop 88 | 17: str q2, [x3, #32] /* Q3 */ 89 | nop 90 | 18: stp q0, q1, [x3] /* Q2 */ 91 | ret 92 | 19: str q0, [x3] /* Q1 */ 93 | ret 94 | 20: uxtb w0, w0 /* UINT8 */ 95 | str x0, [x3] 96 | 21: ret /* reserved */ 97 | nop 98 | 22: uxth w0, w0 /* UINT16 */ 99 | str x0, [x3] 100 | 23: ret /* reserved */ 101 | nop 102 | 24: mov w0, w0 /* UINT32 */ 103 | str x0, [x3] 104 | 25: ret /* reserved */ 105 | nop 106 | 26: sxtb x0, w0 /* SINT8 */ 107 | str x0, [x3] 108 | 27: ret /* reserved */ 109 | nop 110 | 28: sxth x0, w0 /* SINT16 */ 111 | str x0, [x3] 112 | 29: ret /* reserved */ 113 | nop 114 | 30: sxtw x0, w0 /* SINT32 */ 115 | str x0, [x3] 116 | 31: ret /* reserved */ 117 | nop 118 | ret 119 | #endif 120 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORCoreFunctionRegister.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreFunctionRegister.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/14. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | #ifndef __libffi__ 9 | 10 | #define FFI_CLOSURES 1 11 | #define FFI_TRAMPOLINE_SIZE 16 12 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET 16 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORCoreFunctionRegister.s: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreFunctionRegister.s 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/14. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | #import 9 | #import "ORCoreFunctionCall.h" 10 | #import "ORCoreFunctionRegister.h" 11 | #if !__has_include("ffi.h") 12 | #ifdef __AARCH64EB__ 13 | # define BE(X) X 14 | #else 15 | # define BE(X) 0 16 | #endif 17 | 18 | #ifdef __ILP32__ 19 | #define PTR_REG(n) w##n 20 | #else 21 | #define PTR_REG(n) x##n 22 | #endif 23 | 24 | #ifdef __ILP32__ 25 | #define PTR_SIZE 4 26 | #else 27 | #define PTR_SIZE 8 28 | #endif 29 | 30 | #define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64) 31 | .align 4 32 | .global _ffi_closure_SYSV_V 33 | _ffi_closure_SYSV_V: 34 | stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! 35 | /* Save the argument passing vector registers. */ 36 | stp q0, q1, [sp, #16 + 0] 37 | stp q2, q3, [sp, #16 + 32] 38 | stp q4, q5, [sp, #16 + 64] 39 | stp q6, q7, [sp, #16 + 96] 40 | b 0f 41 | 42 | .align 4 43 | .global _ffi_closure_SYSV 44 | _ffi_closure_SYSV: 45 | stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! 46 | 0: 47 | mov x29, sp 48 | 49 | /* Save the argument passing core registers. */ 50 | stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] 51 | stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] 52 | stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] 53 | stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] 54 | 55 | /* Load ffi_closure_inner arguments. */ 56 | ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */ 57 | ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */ 58 | .Ldo_closure: 59 | add x3, sp, #16 /* load context */ 60 | add x4, sp, #ffi_closure_SYSV_FS /* load stack */ 61 | add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ 62 | mov x6, x8 /* load struct_rval */ 63 | bl _ffi_closure_SYSV_inner 64 | 65 | /* Load the return value as directed. */ 66 | #if defined(HAVE_PTRAUTH) 67 | autiza x1 68 | #endif 69 | adr x1, 0f 70 | and w0, w0, #AARCH64_RET_MASK 71 | add x1, x1, x0, lsl #3 72 | add x3, sp, #16+CALL_CONTEXT_SIZE 73 | br x1 74 | 75 | /* Note that each table entry is 2 insns, and thus 8 bytes. */ 76 | .align 4 77 | 0: b 99f /* VOID */ 78 | nop 79 | 1: ldr x0, [x3] /* INT64 */ 80 | b 99f 81 | 2: ldp x0, x1, [x3] /* INT128 */ 82 | b 99f 83 | 3: brk #1000 /* UNUSED */ 84 | nop 85 | 4: brk #1000 /* UNUSED */ 86 | nop 87 | 5: brk #1000 /* UNUSED */ 88 | nop 89 | 6: brk #1000 /* UNUSED */ 90 | nop 91 | 7: brk #1000 /* UNUSED */ 92 | nop 93 | 8: ldr s3, [x3, #12] /* S4 */ 94 | nop 95 | 9: ldr s2, [x3, #8] /* S3 */ 96 | nop 97 | 10: ldp s0, s1, [x3] /* S2 */ 98 | b 99f 99 | 11: ldr s0, [x3] /* S1 */ 100 | b 99f 101 | 12: ldr d3, [x3, #24] /* D4 */ 102 | nop 103 | 13: ldr d2, [x3, #16] /* D3 */ 104 | nop 105 | 14: ldp d0, d1, [x3] /* D2 */ 106 | b 99f 107 | 15: ldr d0, [x3] /* D1 */ 108 | b 99f 109 | 16: ldr q3, [x3, #48] /* Q4 */ 110 | nop 111 | 17: ldr q2, [x3, #32] /* Q3 */ 112 | nop 113 | 18: ldp q0, q1, [x3] /* Q2 */ 114 | b 99f 115 | 19: ldr q0, [x3] /* Q1 */ 116 | b 99f 117 | 20: ldrb w0, [x3, #BE(7)] /* UINT8 */ 118 | b 99f 119 | 21: brk #1000 /* reserved */ 120 | nop 121 | 22: ldrh w0, [x3, #BE(6)] /* UINT16 */ 122 | b 99f 123 | 23: brk #1000 /* reserved */ 124 | nop 125 | 24: ldr w0, [x3, #BE(4)] /* UINT32 */ 126 | b 99f 127 | 25: brk #1000 /* reserved */ 128 | nop 129 | 26: ldrsb x0, [x3, #BE(7)] /* SINT8 */ 130 | b 99f 131 | 27: brk #1000 /* reserved */ 132 | nop 133 | 28: ldrsh x0, [x3, #BE(6)] /* SINT16 */ 134 | b 99f 135 | 29: brk #1000 /* reserved */ 136 | nop 137 | 30: ldrsw x0, [x3, #BE(4)] /* SINT32 */ 138 | nop 139 | 31: /* reserved */ 140 | 99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS 141 | ret 142 | 143 | 144 | // ffi_closure_trampoline_table_page 145 | .align PAGE_MAX_SHIFT 146 | .text 147 | .global _ffi_closure_trampoline_table_page 148 | _ffi_closure_trampoline_table_page: 149 | .rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE 150 | adr x16, -PAGE_MAX_SIZE 151 | ldp x17, x16, [x16] 152 | br x16 153 | nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller that 16 bytes */ 154 | .endr 155 | #endif 156 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORTypeVarPair+libffi.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTypeVarPair+libffi.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/21. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "RunnerClasses+Execute.h" 10 | #if __has_include("ffi.h") 11 | #import "ffi.h" 12 | 13 | struct ORFuncCallFFiTypeFreeList { 14 | void *_Nullable *_Nonnull list; 15 | int maxLength; 16 | int cursor; 17 | }; 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | __attribute__((overloadable)) 22 | ffi_type *_Nullable typeEncode2ffi_type(const char *typeencode); 23 | 24 | ffi_type *_Nullable typeEncode2ffi_type(const char *typeencode, 25 | struct ORFuncCallFFiTypeFreeList *_Nullable destroyList); 26 | NS_ASSUME_NONNULL_END 27 | #endif 28 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreFunction/ORTypeVarPair+libffi.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTypeVarPair+libffi.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/21. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | #if __has_include("ffi.h") 9 | #import "ORTypeVarPair+libffi.h" 10 | #import "ORTypeVarPair+TypeEncode.h" 11 | #import "ORHandleTypeEncode.h" 12 | #import "ORStructDeclare.h" 13 | 14 | __attribute__((overloadable)) 15 | ffi_type *typeEncode2ffi_type(const char *typeencode) { 16 | return typeEncode2ffi_type(typeencode, NULL); 17 | } 18 | 19 | ffi_type *typeEncode2ffi_type(const char *typeencode, 20 | struct ORFuncCallFFiTypeFreeList *destroyList) { 21 | bool isRegister = destroyList == NULL; 22 | //TypeEncode不能为空 23 | assert(typeencode != nil); 24 | switch (*typeencode) { 25 | case OCTypeChar: 26 | return &ffi_type_sint8; 27 | case OCTypeShort: 28 | return &ffi_type_sint16; 29 | case OCTypeInt: 30 | return &ffi_type_sint32; 31 | case OCTypeLong: 32 | return &ffi_type_sint32; 33 | case OCTypeLongLong: 34 | return &ffi_type_sint64; 35 | 36 | case OCTypeUChar: 37 | return &ffi_type_uint8; 38 | case OCTypeUShort: 39 | return &ffi_type_uint16; 40 | case OCTypeUInt: 41 | return &ffi_type_uint32; 42 | case OCTypeULong: 43 | return &ffi_type_uint32; 44 | case OCTypeULongLong: 45 | return &ffi_type_uint64; 46 | 47 | case OCTypeFloat: 48 | return &ffi_type_float; 49 | case OCTypeDouble: 50 | return &ffi_type_double; 51 | 52 | case OCTypeBOOL: 53 | return &ffi_type_uint8; 54 | 55 | case OCTypeVoid: 56 | return &ffi_type_void; 57 | 58 | case OCTypeObject: 59 | case OCTypeClass: 60 | case OCTypeSEL: 61 | case OCTypePointer: 62 | case OCTypeCString: 63 | case OCTypeArray: 64 | case OCTypeUnion: 65 | return &ffi_type_pointer; 66 | 67 | case OCTypeStruct: 68 | { 69 | ffi_type *type = malloc(sizeof(ffi_type)); 70 | if (isRegister == false && destroyList->cursor < destroyList->maxLength) { 71 | destroyList->list[destroyList->cursor] = type; 72 | destroyList->cursor++; 73 | } 74 | type->type = FFI_TYPE_STRUCT; 75 | type->alignment = 0; 76 | NSString *structName = startStructNameDetect(typeencode); 77 | assert(structName != nil); 78 | ORStructDeclare *declare = [[ORTypeSymbolTable shareInstance] symbolItemForTypeName:structName].declare; 79 | type->elements = malloc(sizeof(void *) * (declare.keys.count + 1)); 80 | if (isRegister == false && destroyList->cursor < destroyList->maxLength) { 81 | destroyList->list[destroyList->cursor] = type->elements; 82 | destroyList->cursor++; 83 | } 84 | type->size = sizeOfTypeEncode(declare.typeEncoding); 85 | for (int i = 0; i < declare.keys.count; i++) { 86 | type->elements[i] = typeEncode2ffi_type(declare.keyTypeEncodes[declare.keys[i]].UTF8String, 87 | destroyList); 88 | } 89 | type->elements[declare.keys.count] = NULL; 90 | return type; 91 | } 92 | } 93 | //不支持的类型 94 | assert(false); 95 | return NULL; 96 | } 97 | 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORImp.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/6/8. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MFBlock.h" 11 | #import "ORCoreFunction.h" 12 | @class MFValue; 13 | extern void blockInter(ffi_cif *cfi,void *ret,void **args, void*userdata); 14 | extern void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata); 15 | extern void getterImp(ffi_cif *cfi,void *ret,void **args, void*userdata); 16 | extern void setterImp(ffi_cif *cfi,void *ret,void **args, void*userdata); 17 | extern MFValue *invoke_sueper_values(id instance, SEL sel, Class classNode, NSArray *argValues); 18 | -------------------------------------------------------------------------------- /OCRunner/ORCoreImp/ORCoreImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORImp.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/6/8. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORCoreImp.h" 10 | #import "MFValue.h" 11 | #import 12 | #import "RunnerClasses+Execute.h" 13 | #import "MFMethodMapTable.h" 14 | #import "MFPropertyMapTable.h" 15 | #import "ORTypeVarPair+TypeEncode.h" 16 | #import "util.h" 17 | #import "ORStructDeclare.h" 18 | #import "ORCoreFunctionCall.h" 19 | #import 20 | 21 | #define FATAL_CHECK(condition, msg) \ 22 | if (!(condition)) {\ 23 | syslog(LOG_ERR, msg);\ 24 | abort();\ 25 | }\ 26 | 27 | void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){ 28 | MFScopeChain *scope = [MFScopeChain scopeChainWithNext:[MFScopeChain topScope]]; 29 | ORMethodImplementation *methodImp = (__bridge ORMethodImplementation *)userdata; 30 | __unsafe_unretained id target = *(__unsafe_unretained id *)args[0]; 31 | SEL sel = *(SEL *)args[1]; 32 | BOOL classMethod = object_isClass(target); 33 | NSMethodSignature *sig = [target methodSignatureForSelector:sel]; 34 | NSMutableArray *argValues = [NSMutableArray array]; 35 | for (NSUInteger i = 2; i < sig.numberOfArguments; i++) { 36 | MFValue *argValue = [[MFValue alloc] initTypeEncode:[sig getArgumentTypeAtIndex:i] pointer:args[i]]; 37 | //针对系统传入的block,检查一次签名,如果没有,将在结构体中添加签名信息. 38 | if (argValue.isObject && argValue.isBlockValue && argValue.objectValue != nil) { 39 | struct MFSimulateBlock *bb = (void *)argValue->realBaseValue.pointerValue; 40 | // 针对传入的block,如果为全局block或栈block,使用copy转换为堆block 41 | if (bb->isa == &_NSConcreteGlobalBlock || bb->isa == &_NSConcreteStackBlock){ 42 | id copied = (__bridge id)Block_copy(argValue->realBaseValue.pointerValue); 43 | argValue.pointer = &copied; 44 | } 45 | if (NSBlockHasSignature(argValue.objectValue) == NO) { 46 | ORTypeVarPair *blockdecl = methodImp.declare.parameterTypes[i - 2]; 47 | if ([blockdecl.var isKindOfClass:[ORFuncVariable class]]) { 48 | NSBlockSetSignature(argValue.objectValue, blockdecl.blockSignature); 49 | } 50 | } 51 | } 52 | [argValues addObject:argValue]; 53 | } 54 | if (classMethod) { 55 | scope.instance = [MFValue valueWithClass:target]; 56 | }else{ 57 | // 方法调用时不应该增加引用计数 58 | scope.instance = [MFValue valueWithUnRetainedObject:target]; 59 | } 60 | 61 | OREntryContext *ctx = [OREntryContext contextWithClass:methodImp.classNode]; 62 | ctx.isDeallocScope = sel == NSSelectorFromString(@"dealloc"); 63 | scope.entryCtx = ctx; 64 | 65 | __autoreleasing MFValue *returnValue = nil; 66 | [ORArgsStack push:argValues]; 67 | returnValue = [methodImp execute:scope]; 68 | if (returnValue.type != TypeVoid && returnValue.pointer != NULL){ 69 | // 类型转换 70 | [returnValue writePointer:ret typeEncode:[sig methodReturnType]]; 71 | } 72 | 73 | if (ctx.isDeallocScope) { 74 | Class instanceClass = scope.classNode; 75 | if (ctx.deferCallOrigDealloc) { 76 | Method deallocMethod = class_getInstanceMethod(instanceClass, NSSelectorFromString(@"ORGdealloc")); 77 | void (*originalDealloc)(__unsafe_unretained id, SEL) = (__typeof__(originalDealloc))method_getImplementation(deallocMethod); 78 | FATAL_CHECK(originalDealloc != NULL, "orig dealloc must exist, otherwise memory leaks"); 79 | originalDealloc(target, NSSelectorFromString(@"dealloc")); 80 | // default is call [super dealloc] 81 | } else { 82 | Class superClass = class_getSuperclass(instanceClass); 83 | Method superDeallocMethod = class_getInstanceMethod(superClass, NSSelectorFromString(@"dealloc")); 84 | void (*superDealloc)(__unsafe_unretained id, SEL) = (__typeof__(superDealloc))method_getImplementation(superDeallocMethod); 85 | FATAL_CHECK(superDealloc != NULL, "super dealloc must exist, otherwise memory leaks"); 86 | superDealloc(target, NSSelectorFromString(@"dealloc")); 87 | } 88 | } 89 | } 90 | 91 | void blockInter(ffi_cif *cfi,void *ret,void **args, void*userdata){ 92 | struct MFSimulateBlock *block = *(void **)args[0]; 93 | MFBlock *mangoBlock = (__bridge MFBlock *)(block->wrapper); 94 | NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:NSBlockGetSignature(mangoBlock.ocBlock)]; 95 | NSMutableArray *argValues = [NSMutableArray array]; 96 | for (NSUInteger i = 1; i < cfi->nargs; i++) { 97 | MFValue *argValue = [[MFValue alloc] initTypeEncode:[sig getArgumentTypeAtIndex:i] pointer:args[i]]; 98 | [argValues addObject:argValue]; 99 | } 100 | __autoreleasing MFValue *value = nil; 101 | [ORArgsStack push:argValues]; 102 | value = [mangoBlock.func execute:mangoBlock.outScope]; 103 | if (value.type != TypeVoid && value.pointer != NULL){ 104 | // 类型转换 105 | [value writePointer:ret typeEncode:[sig methodReturnType]]; 106 | } 107 | } 108 | 109 | 110 | void getterImp(ffi_cif *cfi,void *ret,void **args, void*userdata){ 111 | id target = *(__strong id *)args[0]; 112 | SEL sel = *(SEL *)args[1]; 113 | ORPropertyDeclare *propDef = (__bridge ORPropertyDeclare *)userdata; 114 | NSString *propName = propDef.var.var.varname; 115 | NSMethodSignature *sig = [target methodSignatureForSelector:sel]; 116 | __autoreleasing MFValue *propValue = objc_getAssociatedObject(target, mf_propKey(propName)); 117 | if (!propValue) { 118 | propValue = [MFValue defaultValueWithTypeEncoding:propDef.var.typeEncode]; 119 | } 120 | if (propValue.type != TypeVoid && propValue.pointer != NULL){ 121 | [propValue writePointer:ret typeEncode:sig.methodReturnType]; 122 | } 123 | } 124 | 125 | void setterImp(ffi_cif *cfi,void *ret,void **args, void*userdata){ 126 | id target = *(__strong id *)args[0]; 127 | SEL sel = *(SEL *)args[1]; 128 | const char *argTypeEncode = [[target methodSignatureForSelector:sel] getArgumentTypeAtIndex:2]; 129 | MFValue *value = [MFValue valueWithTypeEncode:argTypeEncode pointer:args[2]]; 130 | ORPropertyDeclare *propDef = (__bridge ORPropertyDeclare *)userdata; 131 | NSString *propName = propDef.var.var.varname; 132 | MFPropertyModifier modifier = propDef.modifier; 133 | if (modifier & MFPropertyModifierMemWeak) { 134 | value.modifier = DeclarationModifierWeak; 135 | } 136 | objc_AssociationPolicy associationPolicy = mf_AssociationPolicy_with_PropertyModifier(modifier); 137 | objc_setAssociatedObject(target, mf_propKey(propName), value, associationPolicy); 138 | } 139 | 140 | 141 | MFValue *invoke_sueper_values(id instance, SEL sel, Class classNode, NSArray *argValues){ 142 | BOOL isClassMethod = object_isClass(instance); 143 | Class superClass; 144 | if (isClassMethod) { 145 | superClass = class_getSuperclass(instance == classNode ? instance : classNode); 146 | }else{ 147 | Class instanceClass = [instance class]; 148 | superClass = class_getSuperclass(instanceClass == classNode ? instanceClass : classNode); 149 | } 150 | struct objc_super *superPtr = &(struct objc_super){instance,superClass}; 151 | NSMutableArray *args = [@[[MFValue valueWithPointer:(void *)superPtr],[MFValue valueWithSEL:sel]] mutableCopy]; 152 | [args addObjectsFromArray:argValues]; 153 | NSMethodSignature *sig = [instance methodSignatureForSelector:sel]; 154 | MFValue *retValue = [MFValue defaultValueWithTypeEncoding:sig.methodReturnType]; 155 | void *funcptr = &objc_msgSendSuper; 156 | invoke_functionPointer(funcptr, args, retValue); 157 | return retValue; 158 | } 159 | -------------------------------------------------------------------------------- /OCRunner/ORHandleTypeEncode.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORHandleTypeEncode.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef enum: char { 11 | OCTypeChar = 'c', 12 | OCTypeShort = 's', 13 | OCTypeInt = 'i', 14 | OCTypeLong = 'l', 15 | OCTypeLongLong = 'q', 16 | 17 | OCTypeUChar = 'C', 18 | OCTypeUShort = 'S', 19 | OCTypeUInt = 'I', 20 | OCTypeULong = 'L', 21 | OCTypeULongLong = 'Q', 22 | OCTypeBOOL = 'B', 23 | 24 | OCTypeFloat = 'f', 25 | OCTypeDouble = 'd', 26 | 27 | OCTypeVoid = 'v', 28 | OCTypeCString = '*', 29 | OCTypeObject = '@', 30 | OCTypeClass = '#', 31 | OCTypeSEL = ':', 32 | 33 | OCTypeArray = '[', 34 | OCTypeStruct = '{', 35 | OCTypeUnion = '(', 36 | OCTypeBit = 'b', 37 | 38 | OCTypePointer = '^', 39 | OCTypeUnknown = '?' 40 | }OCType; 41 | 42 | #define ExternOCTypeString(Type) static const char OCTypeString##Type[2] = {OCType##Type, '\0'}; 43 | ExternOCTypeString(Char) 44 | ExternOCTypeString(Short) 45 | ExternOCTypeString(Int) 46 | ExternOCTypeString(Long) 47 | ExternOCTypeString(LongLong) 48 | 49 | ExternOCTypeString(UChar) 50 | ExternOCTypeString(UShort) 51 | ExternOCTypeString(UInt) 52 | ExternOCTypeString(ULong) 53 | ExternOCTypeString(ULongLong) 54 | ExternOCTypeString(BOOL) 55 | 56 | ExternOCTypeString(Float) 57 | ExternOCTypeString(Double) 58 | ExternOCTypeString(Void) 59 | ExternOCTypeString(CString) 60 | ExternOCTypeString(Object) 61 | ExternOCTypeString(Class) 62 | ExternOCTypeString(SEL) 63 | 64 | ExternOCTypeString(Array) 65 | ExternOCTypeString(Struct) 66 | ExternOCTypeString(Union) 67 | ExternOCTypeString(Bit) 68 | 69 | ExternOCTypeString(Pointer) 70 | ExternOCTypeString(Unknown) 71 | 72 | 73 | 74 | 75 | //NOTE: ignore bit 'b' 76 | #define TypeEncodeCharIsBaseType(chr) (('a'<= chr && chr <= 'z') || ('A'<= chr && chr <= 'Z')) 77 | #define TypeEncodeIsBaseType(code) TypeEncodeCharIsBaseType(*code) 78 | 79 | static const char *OCTypeStringBlock = "@?"; 80 | 81 | 82 | #ifdef __cplusplus 83 | extern "C" { 84 | #endif 85 | 86 | NSString *startRemovePointerOfTypeEncode(const char *typeEncode); 87 | NSUInteger startDetectPointerCount(const char *typeEncode); 88 | NSString *startStructNameDetect(const char *typeEncode); 89 | NSString *startUnionNameDetect(const char *typeEncode); 90 | void structFindMaxFieldSize(const char *typeEncode, int *max); 91 | NSMutableArray * startStructDetect(const char *typeEncode); 92 | NSMutableArray * startUnionDetect(const char *typeEncode); 93 | NSMutableArray * startArrayDetect(const char *typeEncode); 94 | NSString * detectStructMemeryLayoutEncodeCode(const char *typeEncode); 95 | NSMutableArray *detectStructFieldTypeEncodes(const char *typeEncode); 96 | NSMutableArray *detectFieldTypeEncodes(const char *structMemeryLayoutEncodeCode); 97 | BOOL isHomogeneousFloatingPointAggregate(const char *typeEncode); 98 | NSUInteger fieldCountInStructMemeryLayoutEncode(const char *typeEncode); 99 | BOOL isStructWithTypeEncode(const char *typeEncode); 100 | BOOL isStructPointerWithTypeEncode(const char *typeEncode); 101 | BOOL isStructOrStructPointerWithTypeEncode(const char *typeEncode); 102 | BOOL isHFAStructWithTypeEncode(const char *typeEncode); 103 | NSUInteger totalFieldCountWithTypeEncode(const char *typeEncode); 104 | BOOL isIntegerWithTypeEncode(const char *typeEncode); 105 | BOOL isFloatWithTypeEncode(const char *typeEncode); 106 | BOOL isObjectWithTypeEncode(const char *typeEncode); 107 | BOOL isPointerWithTypeEncode(const char *typeEncode); 108 | NSUInteger sizeOfTypeEncode(const char *typeEncode); 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | -------------------------------------------------------------------------------- /OCRunner/ORInterpreter.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORInterpreter.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | @interface ORInterpreter : NSObject 13 | + (instancetype)shared; 14 | + (void)excuteBinaryPatchFile:(NSString *)path; 15 | + (void)excuteJsonPatchFile:(NSString *)path; 16 | + (void)excuteNodes:(NSArray *)nodes; 17 | + (void)recover; 18 | + (void)recoverWithClearEnvironment:(BOOL)clear; 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /OCRunner/ORInterpreter.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORInterpreter.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORInterpreter.h" 10 | #import "RunnerClasses+Execute.h" 11 | #import "RunnerClasses+Recover.h" 12 | #import "MFScopeChain.h" 13 | #import "ORSearchedFunction.h" 14 | #import "MFValue.h" 15 | #import "ORStructDeclare.h" 16 | #import "ORSystemFunctionPointerTable.h" 17 | #import "MFStaticVarTable.h" 18 | #import "ORffiResultCache.h" 19 | 20 | @interface ORInterpreter() 21 | @property (nonatomic, copy)NSArray *currentNodes; 22 | @end 23 | 24 | @implementation ORInterpreter 25 | 26 | + (instancetype)shared{ 27 | static dispatch_once_t onceToken; 28 | static ORInterpreter *_instance = nil; 29 | dispatch_once(&onceToken, ^{ 30 | _instance = [ORInterpreter new]; 31 | }); 32 | return _instance; 33 | } 34 | + (void)excuteBinaryPatchFile:(NSString *)path{ 35 | //加载补丁文件 36 | ORPatchFile *file = [ORPatchFile loadBinaryPatch:path]; 37 | 38 | //如果版本判断未通过,则为nil 39 | if (file == nil) { 40 | return; 41 | } 42 | [self excuteNodes:file.nodes]; 43 | } 44 | 45 | + (void)excuteJsonPatchFile:(NSString *)path{ 46 | //加载补丁文件 47 | ORPatchFile *file = [ORPatchFile loadJsonPatch:path]; 48 | 49 | //如果版本判断未通过,则为nil 50 | if (file == nil) { 51 | return; 52 | } 53 | [self excuteNodes:file.nodes]; 54 | } 55 | 56 | + (void)excuteNodes:(NSArray *)nodes{ 57 | 58 | ORInterpreter.shared.currentNodes = nodes; 59 | 60 | MFScopeChain *scope = [MFScopeChain topScope]; 61 | 62 | //添加函数、变量等 63 | mf_add_built_in(scope); 64 | 65 | //链接函数指针,过滤一次 66 | nodes = [self linkFunctions:nodes scope:scope]; 67 | 68 | //注册Protcol 注册Class 全局函数声明等 69 | for (ORNode *node in nodes) { 70 | [node execute:scope]; 71 | } 72 | } 73 | + (NSArray *)linkFunctions:(NSArray *)nodes scope:(MFScopeChain *)scope{ 74 | NSMutableArray *funcVars = [NSMutableArray array]; 75 | NSMutableArray *normalStatements = [NSMutableArray array]; 76 | NSMutableArray *names = [NSMutableArray array]; 77 | for (id expression in nodes) { 78 | if ([expression isKindOfClass:[ORDeclareExpression class]]) { 79 | ORTypeVarPair *pair = [(ORDeclareExpression *)expression pair]; 80 | NSString *name = pair.var.varname; 81 | if ([pair.var isKindOfClass:[ORFuncVariable class]]) { 82 | if ([ORGlobalFunctionTable.shared getFunctionNodeWithName:name] == nil) { 83 | [funcVars addObject:pair]; 84 | [names addObject:name]; 85 | } 86 | continue; 87 | } 88 | } 89 | //过滤 link functions 90 | [normalStatements addObject:expression]; 91 | } 92 | //获取函数指针 93 | NSDictionary *table = [ORSearchedFunction functionTableForNames:names]; 94 | for (ORTypeVarPair *pair in funcVars) { 95 | ORSearchedFunction *function = table[pair.var.varname]; 96 | function.funPair = pair; 97 | // 将每个ORSearchedFunction都保存在ORGlobalFunctionTable中,保证不会被释放。 98 | // 因为在SymbolSearch.c中,将会给它的pointer成员变量赋值,如果在赋值前,对象被释放了,那么在给function->pointer赋值时将会得到一个访问已经被释放内存的错误。 99 | [[ORGlobalFunctionTable shared] setFunctionNode:function WithName:function.name]; 100 | } 101 | #if DEBUG 102 | NSMutableArray *functionNames = [NSMutableArray array]; 103 | for (ORTypeVarPair *pair in funcVars){ 104 | NSString *functionName = pair.var.varname; 105 | ORSearchedFunction *function = table[functionName]; 106 | if (function.pointer == NULL 107 | && [ORSystemFunctionPointerTable pointerForFunctionName:functionName] == NULL 108 | && [[MFScopeChain topScope] getValueWithIdentifier:functionName] == nil) { 109 | [functionNames addObject:functionName]; 110 | } 111 | } 112 | if (functionNames.count > 0) { 113 | NSMutableString *build_ins = [@"" mutableCopy]; 114 | [build_ins appendString:@"\n|----------------------------------------------|"]; 115 | [build_ins appendString:@"\n|❕you need add ⬇️ code in the application file|"]; 116 | [build_ins appendString:@"\n|----------------------------------------------|\n"]; 117 | for (NSString *name in functionNames) { 118 | NSString *build_in_declare = [NSString stringWithFormat:@"[ORSystemFunctionPointerTable reg:@\"%@\" pointer:&%@];\n",name,name]; 119 | [build_ins appendString:build_in_declare]; 120 | } 121 | [build_ins appendString:@"-----------------------------------------------"]; 122 | NSLog(@"%@", build_ins); 123 | } 124 | #endif 125 | return normalStatements; 126 | } 127 | 128 | + (void)recover{ 129 | [self recoverWithClearEnvironment:YES]; 130 | } 131 | + (void)recoverWithClearEnvironment:(BOOL)clear{ 132 | if (ORInterpreter.shared.currentNodes == nil) { 133 | return; 134 | } 135 | for (ORNode *node in ORInterpreter.shared.currentNodes) { 136 | [node recover]; 137 | } 138 | [[ORffiResultCache shared] clear]; 139 | if (clear) { 140 | [[MFScopeChain topScope] clear]; 141 | [[MFStaticVarTable shareInstance] clear]; 142 | [[ORTypeSymbolTable shareInstance] clear]; 143 | } 144 | ORInterpreter.shared.currentNodes = [NSArray array]; 145 | } 146 | @end 147 | -------------------------------------------------------------------------------- /OCRunner/ORTypeVarPair+TypeEncode.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTypeVarPair+TypeEncode.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/26. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "RunnerClasses+Execute.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORTypeVarPair (TypeEncode) 14 | - (const char *)blockSignature; 15 | - (const char *)typeEncode; 16 | @end 17 | 18 | 19 | 20 | 21 | @interface ORTypeVarPair(Instance) 22 | + (instancetype)typePairWithTypeKind:(TypeKind)type; 23 | + (instancetype)objectTypePair; 24 | + (instancetype)pointerTypePair; 25 | @end 26 | 27 | ORTypeVarPair * ORTypeVarPairForTypeEncode(const char *typeEncode); 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /OCRunner/ORTypeVarPair+TypeEncode.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTypeVarPair+TypeEncode.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/26. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORTypeVarPair+TypeEncode.h" 10 | #import "ORHandleTypeEncode.h" 11 | #import "ORStructDeclare.h" 12 | static const char *baseTypeEncode(ORTypeSpecial *typeSpecial, ORVariable *var){ 13 | TypeKind type = typeSpecial.type; 14 | char encoding[128]; 15 | memset(encoding, 0, 128); 16 | #define append(str) strcat(encoding,str) 17 | NSInteger tmpPtCount = var.ptCount; 18 | while (tmpPtCount > 0) { 19 | if (type == TypeBlock) { 20 | break; 21 | } 22 | if (type == TypeChar && tmpPtCount == 1) { 23 | break; 24 | } 25 | if (type == TypeObject && tmpPtCount == 1) { 26 | break; 27 | } 28 | append("^"); 29 | tmpPtCount--; 30 | } 31 | 32 | #define CaseTypeEncoding(type,code)\ 33 | case type:\ 34 | append(code); break; 35 | 36 | switch (type) { 37 | case TypeChar: 38 | { 39 | if (var.ptCount > 0) 40 | append(OCTypeStringCString); 41 | else 42 | append(OCTypeStringChar); 43 | break; 44 | } 45 | CaseTypeEncoding(TypeInt, OCTypeStringInt) 46 | CaseTypeEncoding(TypeShort, OCTypeStringShort) 47 | CaseTypeEncoding(TypeLong, OCTypeStringLong) 48 | CaseTypeEncoding(TypeLongLong, OCTypeStringLongLong) 49 | CaseTypeEncoding(TypeUChar, OCTypeStringUChar) 50 | CaseTypeEncoding(TypeUInt, OCTypeStringUInt) 51 | CaseTypeEncoding(TypeUShort, OCTypeStringUShort) 52 | CaseTypeEncoding(TypeULong, OCTypeStringULong) 53 | CaseTypeEncoding(TypeULongLong, OCTypeStringULongLong) 54 | CaseTypeEncoding(TypeFloat, OCTypeStringFloat) 55 | CaseTypeEncoding(TypeDouble, OCTypeStringDouble) 56 | CaseTypeEncoding(TypeBOOL, OCTypeStringBOOL) 57 | CaseTypeEncoding(TypeVoid, OCTypeStringVoid) 58 | CaseTypeEncoding(TypeObject, OCTypeStringObject) 59 | CaseTypeEncoding(TypeId, OCTypeStringObject) 60 | CaseTypeEncoding(TypeClass, OCTypeStringClass) 61 | CaseTypeEncoding(TypeSEL, OCTypeStringSEL) 62 | CaseTypeEncoding(TypeBlock, OCTypeStringBlock) 63 | default: 64 | break; 65 | } 66 | append("\0"); 67 | __autoreleasing NSString *resultValue = [NSString stringWithUTF8String:encoding]; 68 | return resultValue.UTF8String; 69 | } 70 | static const char *cArrayTypeEncode(ORTypeSpecial *typeSpecial, ORCArrayVariable *var); 71 | static const char *typeEncode(ORTypeSpecial *typeSpecial, ORVariable *var){ 72 | TypeKind type = typeSpecial.type; 73 | if ([var isKindOfClass:[ORFuncVariable class]]) { 74 | // Block的typeEncode 75 | if (var.isBlock) { 76 | return @"@?".UTF8String; 77 | } 78 | }else if ([var isKindOfClass:[ORCArrayVariable class]]){ 79 | ORSymbolItem *item = [[ORTypeSymbolTable shareInstance] symbolItemForNode:var]; 80 | if (item) { 81 | return item.typeEncode.UTF8String; 82 | } 83 | const char *result = cArrayTypeEncode(typeSpecial, (ORCArrayVariable *)var); 84 | [[ORTypeSymbolTable shareInstance] addCArray:(ORCArrayVariable *)var typeEncode:result]; 85 | return result; 86 | } 87 | do { 88 | if (typeSpecial.name == nil) break; 89 | ORSymbolItem *item = [[ORTypeSymbolTable shareInstance] symbolItemForTypeName:typeSpecial.name]; 90 | if (item == nil) break; 91 | return item.typeEncode.UTF8String; 92 | } while (0); 93 | if (var.ptCount == 0 && type == TypeObject){ 94 | ORSymbolItem *item = [[ORTypeSymbolTable shareInstance] symbolItemForTypeName:typeSpecial.name]; 95 | if (item) { 96 | return item.typeEncode.UTF8String; 97 | } 98 | } 99 | return baseTypeEncode(typeSpecial, var); 100 | } 101 | static const char *cArrayTypeEncode(ORTypeSpecial *typeSpecial, ORCArrayVariable *var){ 102 | if ([(ORIntegerValue *)var.capacity value] == 0) { 103 | return [NSString stringWithFormat:@"^%s",typeEncode(typeSpecial, nil)].UTF8String; 104 | } 105 | ORCArrayVariable *tmp = var; 106 | NSMutableArray *nodes = [NSMutableArray array]; 107 | while (tmp) { 108 | [nodes insertObject:tmp atIndex:0]; 109 | tmp = tmp.prev; 110 | } 111 | char result[100] = {0}; 112 | char buffer[50] = {0}; 113 | char rights[20] = {0}; 114 | for (int i = 0; i < nodes.count; i++) { 115 | ORCArrayVariable *item = nodes[i]; 116 | sprintf(buffer, "[%lld", [(ORIntegerValue *)item.capacity value]); 117 | strcat(result, buffer); 118 | if (i != nodes.count - 1) { 119 | strcat(rights, "]"); 120 | }else{ 121 | sprintf(buffer, "%s]", typeEncode(typeSpecial, nil)); 122 | strcat(result, buffer); 123 | } 124 | } 125 | strcat(result, rights); 126 | NSString *str = [NSString stringWithUTF8String:result]; 127 | return str.UTF8String; 128 | } 129 | 130 | @implementation ORTypeVarPair (TypeEncode) 131 | - (const char *)baseTypeEncode{ 132 | return baseTypeEncode(self.type, self.var);; 133 | } 134 | - (const char *)blockSignature{ 135 | ORFuncVariable *var = (ORFuncVariable *)self.var; 136 | if ([var isKindOfClass:[ORFuncVariable class]] && var.isBlock) { 137 | const char *returnEncode = [self baseTypeEncode]; 138 | __autoreleasing NSMutableString *result = [[NSString stringWithFormat:@"%s@?",returnEncode] mutableCopy]; 139 | for (ORTypeVarPair *arg in var.pairs) { 140 | [result appendFormat:@"%s",arg.typeEncode]; 141 | } 142 | return result.UTF8String; 143 | } 144 | return [self typeEncode]; 145 | } 146 | - (const char *)typeEncode{ 147 | return typeEncode(self.type, self.var); 148 | } 149 | @end 150 | 151 | 152 | 153 | 154 | 155 | 156 | @implementation ORTypeVarPair(Instance) 157 | + (instancetype)typePairWithTypeKind:(TypeKind)type{ 158 | ORTypeVarPair *typePair = [ORTypeVarPair new]; 159 | typePair.type = [ORTypeSpecial new]; 160 | typePair.type.type = type; 161 | typePair.var = [ORVariable new]; 162 | return typePair; 163 | } 164 | + (instancetype)objectTypePair{ 165 | return [ORTypeVarPair typePairWithTypeKind:TypeObject]; 166 | } 167 | + (instancetype)pointerTypePair{ 168 | ORTypeVarPair *typePair = [ORTypeVarPair typePairWithTypeKind:TypeObject]; 169 | typePair.var.ptCount = 1; 170 | return typePair; 171 | } 172 | @end 173 | 174 | ORTypeVarPair * ORTypeVarPairForTypeEncode(const char *typeEncode){ 175 | TypeKind type = TypeVoid; 176 | ORTypeVarPair *pair = [ORTypeVarPair new]; 177 | pair.var = [ORVariable new]; 178 | pair.type = [ORTypeSpecial new]; 179 | NSUInteger pointerCount; 180 | pointerCount = (NSInteger)startDetectPointerCount(typeEncode); 181 | NSString *typename = nil; 182 | const char *removedPointerEncode = startRemovePointerOfTypeEncode(typeEncode).UTF8String; 183 | switch (*removedPointerEncode) { 184 | case OCTypeChar: type =TypeChar; break; 185 | case OCTypeInt: type =TypeInt; break; 186 | case OCTypeShort: type =TypeShort; break; 187 | case OCTypeLong: type =TypeLong; break; 188 | case OCTypeLongLong: type =TypeLongLong; break; 189 | case OCTypeUChar: type =TypeUChar; break; 190 | case OCTypeUInt: type =TypeUInt; break; 191 | case OCTypeUShort: type =TypeUShort; break; 192 | case OCTypeULong: type =TypeULong; break; 193 | case OCTypeULongLong: type =TypeULongLong; break; 194 | case OCTypeBOOL: type =TypeBOOL; break; 195 | case OCTypeFloat: type =TypeFloat; break; 196 | case OCTypeDouble: type =TypeDouble; break; 197 | case OCTypeSEL: type =TypeSEL; break; 198 | case OCTypeCString:{ 199 | type =TypeChar; 200 | pointerCount += 1; 201 | break; 202 | } 203 | case OCTypeClass:{ 204 | type =TypeClass; 205 | typename = @"Class"; 206 | break; 207 | } 208 | case OCTypeObject:{ 209 | type =TypeObject; 210 | break; 211 | } 212 | case OCTypeStruct:{ 213 | type =TypeStruct; 214 | typename = startStructNameDetect(typeEncode); 215 | } 216 | default: 217 | break; 218 | } 219 | pair.type.type = type; 220 | pair.var.ptCount = pointerCount; 221 | pair.type.name = typename; 222 | return pair; 223 | } 224 | -------------------------------------------------------------------------------- /OCRunner/ORffiResultCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORffiResultCache.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/2/2. 6 | // 7 | 8 | #import 9 | #import "ORCoreFunction.h" 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface ORffiResultCache : NSObject 13 | @property (nonatomic, strong)NSMutableDictionary *cache; 14 | + (instancetype)shared; 15 | - (void)saveffiResult:(or_ffi_result *)result WithKey:(NSValue *)key; 16 | - (or_ffi_result *)ffiResultForKey:(NSValue *)key; 17 | - (void)removeForKey:(NSValue *)key; 18 | - (void)clear; 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /OCRunner/ORffiResultCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORffiResultCache.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/2/2. 6 | // 7 | 8 | #import "ORffiResultCache.h" 9 | 10 | @implementation ORffiResultCache 11 | + (instancetype)shared{ 12 | static dispatch_once_t onceToken; 13 | static ORffiResultCache *_instance; 14 | dispatch_once(&onceToken, ^{ 15 | _instance = [ORffiResultCache new]; 16 | }); 17 | return _instance; 18 | } 19 | - (instancetype)init 20 | { 21 | self = [super init]; 22 | if (self) { 23 | self.cache = [NSMutableDictionary dictionary]; 24 | } 25 | return self; 26 | } 27 | - (void)saveffiResult:(or_ffi_result *)result WithKey:(NSValue *)key{ 28 | self.cache[key] = [NSValue valueWithPointer:result]; 29 | } 30 | - (or_ffi_result *)ffiResultForKey:(NSValue *)key{ 31 | return self.cache[key].pointerValue; 32 | } 33 | - (void)removeForKey:(NSValue *)key{ 34 | [self.cache removeObjectForKey:key]; 35 | } 36 | - (void)clear{ 37 | self.cache = [NSMutableDictionary dictionary]; 38 | } 39 | @end 40 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFBlock.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2017/12/26. 6 | // Copyright © 2017年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RunnerClasses+Execute.h" 11 | #import "MFScopeChain.h" 12 | enum { 13 | BLOCK_DEALLOCATING = (0x0001), 14 | BLOCK_REFCOUNT_MASK = (0xfffe), 15 | BLOCK_CREATED_FROM_MFGO = (1 << 23), 16 | BLOCK_NEEDS_FREE = (1 << 24), 17 | BLOCK_HAS_COPY_DISPOSE = (1 << 25), 18 | BLOCK_HAS_CTOR = (1 << 26), 19 | BLOCK_IS_GC = (1 << 27), 20 | BLOCK_IS_GLOBAL = (1 << 28), 21 | BLOCK_USE_STRET = (1 << 29), 22 | BLOCK_HAS_SIGNATURE = (1 << 30) 23 | }; 24 | 25 | struct MFSimulateBlock { 26 | void *isa; 27 | int flags; 28 | int reserved; 29 | void *invoke; 30 | struct MFGOSimulateBlockDescriptor *descriptor; 31 | void *wrapper; 32 | }; 33 | 34 | struct MFGOSimulateBlockDescriptor { 35 | //Block_descriptor_1 36 | struct { 37 | unsigned long int reserved; 38 | unsigned long int size; 39 | }; 40 | 41 | //Block_descriptor_2 42 | struct { 43 | // requires BLOCK_HAS_COPY_DISPOSE 44 | void (*copy)(void *dst, const void *src); 45 | void (*dispose)(const void *); 46 | }; 47 | 48 | //Block_descriptor_3 49 | struct { 50 | // requires BLOCK_HAS_SIGNATURE 51 | const char *signature; 52 | }; 53 | }; 54 | 55 | struct ORFixedBlockDescriptor { 56 | //Block_descriptor_1 57 | struct { 58 | unsigned long int reserved; 59 | unsigned long int size; 60 | }; 61 | 62 | //Block_descriptor_2 63 | struct { 64 | // requires BLOCK_HAS_COPY_DISPOSE 65 | void (*copy)(void *dst, const void *src); 66 | void (*dispose)(const void *); 67 | }; 68 | 69 | //Block_descriptor_3 70 | struct { 71 | // requires BLOCK_HAS_SIGNATURE 72 | const char *signature; 73 | }; 74 | 75 | //FixedBlock dispose 76 | void (*orignalDispose)(const void *); 77 | }; 78 | 79 | const char *NSBlockGetSignature(id block); 80 | BOOL NSBlockHasSignature(id block); 81 | void NSBlockSetSignature(id block, const char *typeencode); 82 | void *simulateNSBlock(const char* typeEncoding, void *imp, void *userdata); 83 | 84 | @class ORTypeVarPair; 85 | @interface MFBlock : NSObject 86 | 87 | @property (strong, nonatomic) MFScopeChain *outScope; 88 | @property (strong, nonatomic) ORFunctionImp *func; 89 | @property (strong, nonatomic) NSMutableArray *paramTypes; 90 | @property (strong, nonatomic) ORTypeVarPair *retType; 91 | - (id)ocBlock; 92 | @end 93 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFBlock.m 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2017/12/26. 6 | // Copyright © 2017年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFBlock.h" 10 | #import "util.h" 11 | #import "RunnerClasses+Execute.h" 12 | #import "MFValue.h" 13 | #import "ORCoreImp.h" 14 | #import "ORTypeVarPair+TypeEncode.h" 15 | 16 | void copy_helper(struct MFSimulateBlock *dst, struct MFSimulateBlock *src) 17 | { 18 | // do not copy anything is this funcion! just retain if need. 19 | if (dst->wrapper) { 20 | CFRetain(dst->wrapper); 21 | } 22 | } 23 | 24 | void dispose_helper(struct MFSimulateBlock *src) 25 | { 26 | if (src->descriptor->signature) { 27 | free((void *)src->descriptor->signature); 28 | } 29 | if (src->descriptor) { 30 | free(src->descriptor); 31 | } 32 | if (src->wrapper) { 33 | CFRelease(src->wrapper); 34 | } 35 | } 36 | void *simulateNSBlock(const char* typeEncoding, void *imp, void *userdata){ 37 | if (typeEncoding != NULL) { 38 | typeEncoding = strdup(typeEncoding); 39 | } 40 | struct MFGOSimulateBlockDescriptor descriptor = { 41 | 0, 42 | sizeof(struct MFSimulateBlock), 43 | (void (*)(void *dst, const void *src))copy_helper, 44 | (void (*)(const void *src))dispose_helper, 45 | typeEncoding 46 | }; 47 | struct MFGOSimulateBlockDescriptor *_descriptor = malloc(sizeof(struct MFGOSimulateBlockDescriptor)); 48 | memcpy(_descriptor, &descriptor, sizeof(struct MFGOSimulateBlockDescriptor)); 49 | struct MFSimulateBlock simulateBlock = { 50 | &_NSConcreteStackBlock, 51 | (BLOCK_HAS_COPY_DISPOSE | BLOCK_CREATED_FROM_MFGO), 52 | 0, 53 | imp, 54 | _descriptor, 55 | userdata 56 | }; 57 | if (typeEncoding != NULL) { 58 | simulateBlock.flags |= BLOCK_HAS_SIGNATURE; 59 | } 60 | return Block_copy(&simulateBlock); 61 | } 62 | const char *NSBlockGetSignature(id block){ 63 | struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block; 64 | int flags = blockRef->flags; 65 | if (flags & BLOCK_HAS_SIGNATURE) { 66 | void *signatureLocation = blockRef->descriptor; 67 | signatureLocation += sizeof(unsigned long int); 68 | signatureLocation += sizeof(unsigned long int); 69 | 70 | if (flags & BLOCK_HAS_COPY_DISPOSE) { 71 | signatureLocation += sizeof(void(*)(void *dst, void *src)); 72 | signatureLocation += sizeof(void (*)(void *src)); 73 | } 74 | 75 | const char *signature = (*(const char **)signatureLocation); 76 | return signature; 77 | } 78 | return NULL; 79 | } 80 | BOOL NSBlockHasSignature(id block){ 81 | struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block; 82 | int flags = blockRef->flags; 83 | return flags & BLOCK_HAS_SIGNATURE; 84 | } 85 | 86 | static void fixedBlockDispose(struct MFSimulateBlock *src) { 87 | struct ORFixedBlockDescriptor *descriptor = (void *)src->descriptor; 88 | if (src->descriptor->signature) { 89 | free((void *)src->descriptor->signature); 90 | } 91 | if (src->descriptor) { 92 | free(src->descriptor); 93 | } 94 | if (descriptor->orignalDispose) { 95 | descriptor->orignalDispose(src); 96 | } 97 | } 98 | void NSBlockSetSignature(id block, const char *typeencode){ 99 | struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block; 100 | // ---- 2021.9.24 TODO: 101 | // 针对 WKWebView 的 navigationDelegate 的 block: 102 | // decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler 103 | // ios 15 下直接写入 signatureLocation 内存会导致 EXC_BAD_ACCESS 错误,同时此 block 是一个堆 block,使用内存地址直接写入按理说应该是没有问题。不知是对此内存做了内存保护🤔?可是当在调试的时候,使用 lldb 调试器写入该地址,却完全没有问题。 104 | // 目前为了规避崩溃问题,既然不能操作 signature 的地址内存,那就直接覆盖 descriptor 的内存 105 | // ⚠️ 此处存在的问题为:使用 malloc 开辟的内存空间,存在内存泄漏的问题。 106 | 107 | // NOTE: 2021.11.25 108 | // 如果 BLOCK_HAS_SIGNATURE 为 false,descriptor 中是不会有 signature 字段的 109 | bool isFixedBlock = false; 110 | if (NSBlockHasSignature(block) == false) { 111 | struct ORFixedBlockDescriptor *des = malloc(sizeof(struct ORFixedBlockDescriptor)); 112 | memcpy(des, blockRef->descriptor, sizeof(struct MFGOSimulateBlockDescriptor)); 113 | blockRef->descriptor = (void *)des; 114 | isFixedBlock = true; 115 | } 116 | 117 | void *signatureLocation = blockRef->descriptor; 118 | signatureLocation += sizeof(unsigned long int); 119 | signatureLocation += sizeof(unsigned long int); 120 | int flags = blockRef->flags; 121 | if (flags & BLOCK_HAS_COPY_DISPOSE) { 122 | signatureLocation += sizeof(void(*)(void *dst, void *src)); 123 | signatureLocation += sizeof(void (*)(void *src)); 124 | } 125 | char *copied = strdup(typeencode); 126 | *(char **)signatureLocation = copied; 127 | blockRef->flags |= BLOCK_HAS_SIGNATURE; 128 | if (isFixedBlock) { 129 | struct ORFixedBlockDescriptor *descriptor = (void *)blockRef->descriptor; 130 | descriptor->orignalDispose = blockRef->descriptor->dispose; 131 | blockRef->descriptor->dispose = (void *)&fixedBlockDispose; 132 | } 133 | } 134 | 135 | @implementation MFBlock{ 136 | void *_blockPtr; 137 | or_ffi_result *_ffi_result; 138 | } 139 | - (instancetype)init 140 | { 141 | self = [super init]; 142 | if (self) { 143 | _blockPtr = NULL; 144 | _ffi_result = NULL; 145 | } 146 | return self; 147 | } 148 | - (id)ocBlock{ 149 | return [self blockPtr]; 150 | } 151 | - (void)setParamTypes:(NSMutableArray *)paramTypes{ 152 | NSMutableArray *types = [@[[ORTypeVarPair typePairWithTypeKind:TypeBlock]] mutableCopy]; 153 | [types addObjectsFromArray:paramTypes]; 154 | _paramTypes = types; 155 | } 156 | - (void *)blockPtr{ 157 | if (_blockPtr != NULL) { 158 | return _blockPtr; 159 | } 160 | const char *typeEncoding = self.retType.typeEncode; 161 | char typeEncodeBuffer[256] = {0}; 162 | strcat(typeEncodeBuffer, typeEncoding); 163 | for (ORTypeVarPair *param in self.paramTypes) { 164 | const char *paramTypeEncoding = param.typeEncode; 165 | strcat(typeEncodeBuffer, paramTypeEncoding); 166 | } 167 | _ffi_result = register_function(&blockInter, self.paramTypes, self.retType); 168 | _blockPtr = simulateNSBlock(typeEncodeBuffer, _ffi_result->function_imp, (__bridge void *)self); 169 | return _blockPtr; 170 | } 171 | 172 | -(void)dealloc{ 173 | if (_ffi_result != NULL) { 174 | or_ffi_result_free(_ffi_result); 175 | } 176 | return; 177 | } 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFMethodMapTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFMethodMapTable.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/23. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RunnerClasses+Execute.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MFMethodMapTableItem:NSObject 15 | 16 | @property (strong, nonatomic) Class clazz; 17 | @property (strong, nonatomic) ORMethodImplementation *methodImp; 18 | 19 | - (instancetype)initWithClass:(Class)clazz method:(ORMethodImplementation *)method; 20 | 21 | @end 22 | 23 | @interface MFMethodMapTable : NSObject 24 | 25 | + (instancetype)shareInstance; 26 | - (void)removeMethodsForClass:(Class)clazz; 27 | - (void)addMethodMapTableItem:(MFMethodMapTableItem *)methodMapTableItem; 28 | - (nullable MFMethodMapTableItem *)getMethodMapTableItemWith:(Class)clazz classMethod:(BOOL)classMethod sel:(SEL)sel; 29 | 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFMethodMapTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFMethodMapTable.m 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/23. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFMethodMapTable.h" 10 | 11 | @implementation MFMethodMapTableItem 12 | - (instancetype)initWithClass:(Class)clazz method:(ORMethodImplementation *)method; { 13 | if (self = [super init]) { 14 | _clazz = clazz; 15 | _methodImp = method; 16 | } 17 | return self; 18 | } 19 | @end 20 | 21 | @implementation MFMethodMapTable{ 22 | CFMutableDictionaryRef classMethodCache; 23 | CFMutableDictionaryRef instanceMethodCache; 24 | } 25 | 26 | + (instancetype)shareInstance{ 27 | static id st_instance; 28 | static dispatch_once_t onceToken; 29 | dispatch_once(&onceToken, ^{ 30 | st_instance = [[MFMethodMapTable alloc] init]; 31 | }); 32 | return st_instance; 33 | } 34 | 35 | - (instancetype)init{ 36 | if (self = [super init]) { 37 | classMethodCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 38 | instanceMethodCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 39 | } 40 | return self; 41 | } 42 | 43 | - (void)addMethodMapTableItem:(MFMethodMapTableItem *)methodMapTableItem{ 44 | if (!methodMapTableItem) return; 45 | 46 | Class class = methodMapTableItem.clazz; 47 | 48 | if (class == NULL) return; 49 | 50 | NSString *sel = [methodMapTableItem.methodImp.declare selectorName]; 51 | 52 | if (!sel) return; 53 | 54 | if (methodMapTableItem.methodImp.declare.isClassMethod){ 55 | CFMutableDictionaryRef classMap = (CFMutableDictionaryRef)CFDictionaryGetValue(classMethodCache, (__bridge const void *)(class)); 56 | if (classMap == NULL){ 57 | classMap = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 58 | CFDictionarySetValue(classMethodCache, (__bridge const void *)(class), classMap); 59 | } 60 | CFDictionarySetValue(classMap, (__bridge CFStringRef)(sel), (__bridge const void *)(methodMapTableItem)); 61 | }else{ 62 | CFMutableDictionaryRef classMap = (CFMutableDictionaryRef)CFDictionaryGetValue(instanceMethodCache, (__bridge const void *)(class)); 63 | if (classMap == NULL){ 64 | classMap = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 65 | CFDictionarySetValue(instanceMethodCache, (__bridge const void *)(class), classMap); 66 | } 67 | CFDictionarySetValue(classMap, (__bridge CFStringRef)(sel), (__bridge const void *)(methodMapTableItem)); 68 | } 69 | } 70 | - (void)removeMethodsForClass:(Class)clazz{ 71 | if (clazz == NULL) return; 72 | const void *key = (__bridge const void *)clazz; 73 | if (CFDictionaryGetValue(classMethodCache, key)) { 74 | CFRelease(CFDictionaryGetValue(classMethodCache, key)); 75 | } 76 | if (CFDictionaryGetValue(instanceMethodCache, key)) { 77 | CFRelease(CFDictionaryGetValue(instanceMethodCache, key)); 78 | } 79 | CFDictionaryRemoveValue(classMethodCache, key); 80 | CFDictionaryRemoveValue(instanceMethodCache, key); 81 | } 82 | 83 | - (MFMethodMapTableItem *)getMethodMapTableItemWith:(Class)clazz classMethod:(BOOL)classMethod sel:(SEL)sel{ 84 | if (clazz == NULL) { return nil; } 85 | 86 | NSString *selector = NSStringFromSelector(sel); 87 | 88 | if (!selector) { return nil; } 89 | 90 | if (classMethod){ 91 | CFDictionaryRef classMap = CFDictionaryGetValue(classMethodCache, (__bridge const void *)(clazz)); 92 | if (classMap == NULL) return nil; 93 | return CFDictionaryGetValue(classMap, (__bridge CFStringRef)(selector)); 94 | }else{ 95 | CFDictionaryRef classMap = CFDictionaryGetValue(instanceMethodCache, (__bridge const void *)(clazz)); 96 | if (classMap == NULL) return nil; 97 | return CFDictionaryGetValue(classMap, (__bridge CFStringRef)(selector)); 98 | } 99 | } 100 | @end 101 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFPropertyMapTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFPropertyMapTable.h 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/4/26. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RunnerClasses+Execute.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MFPropertyMapTableItem:NSObject 15 | 16 | @property (strong, nonatomic) Class clazz; 17 | @property (strong, nonatomic) ORPropertyDeclare *property; 18 | @property (assign, nonatomic) bool added; 19 | - (instancetype)initWithClass:(Class)clazz property:(ORPropertyDeclare *)property; 20 | 21 | @end 22 | 23 | @interface MFPropertyMapTable : NSObject 24 | { 25 | @public 26 | NSMutableDictionary *_dic; 27 | } 28 | + (instancetype)shareInstance; 29 | 30 | - (void)addPropertyMapTableItem:(MFPropertyMapTableItem *)propertyMapTableItem; 31 | - (nullable MFPropertyMapTableItem *)getPropertyMapTableItemWith:(Class)clazz name:(NSString *)name; 32 | - (void)removePropertiesForClass:(Class)clazz; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFPropertyMapTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFPropertyMapTable.m 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/4/26. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFPropertyMapTable.h" 10 | 11 | @implementation MFPropertyMapTableItem 12 | 13 | - (instancetype)initWithClass:(Class)clazz property:(ORPropertyDeclare *)property{ 14 | if (self = [super init]) { 15 | _clazz = clazz; 16 | _property = property; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | 23 | @implementation MFPropertyMapTable{ 24 | CFMutableDictionaryRef _propertyCache; 25 | } 26 | 27 | + (instancetype)shareInstance{ 28 | static id st_instance; 29 | static dispatch_once_t onceToken; 30 | dispatch_once(&onceToken, ^{ 31 | st_instance = [[MFPropertyMapTable alloc] init]; 32 | }); 33 | return st_instance; 34 | } 35 | 36 | - (instancetype)init{ 37 | if (self = [super init]) { 38 | _propertyCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 39 | } 40 | return self; 41 | } 42 | 43 | - (void)addPropertyMapTableItem:(MFPropertyMapTableItem *)propertyMapTableItem{ 44 | if (!propertyMapTableItem) return; 45 | 46 | NSString *propertyName = propertyMapTableItem.property.var.var.varname; 47 | if (!propertyName.length) return; 48 | 49 | Class class = propertyMapTableItem.clazz; 50 | 51 | if (class == NULL) return; 52 | 53 | CFMutableDictionaryRef propertyMap = (CFMutableDictionaryRef)CFDictionaryGetValue(_propertyCache, (__bridge const void *)(class)); 54 | if (propertyMap == NULL){ 55 | propertyMap = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 56 | CFDictionarySetValue(_propertyCache, (__bridge const void *)(class), propertyMap); 57 | } 58 | if (propertyName == nil) return; 59 | CFDictionarySetValue(propertyMap, (__bridge CFStringRef)(propertyName), (__bridge const void *)(propertyMapTableItem)); 60 | } 61 | 62 | - (MFPropertyMapTableItem *)getPropertyMapTableItemWith:(Class)clazz name:(NSString *)name{ 63 | if (clazz == NULL) return nil; 64 | if (name == nil) return nil; 65 | 66 | CFDictionaryRef propertyMap = CFDictionaryGetValue(_propertyCache, (__bridge const void *)(clazz)); 67 | if (propertyMap == NULL) return nil; 68 | 69 | return CFDictionaryGetValue(propertyMap, (__bridge CFStringRef)(name)); 70 | } 71 | 72 | - (void)removePropertiesForClass:(Class)clazz{ 73 | if (clazz == nil) return; 74 | const void *key = (__bridge const void *)clazz; 75 | if (CFDictionaryGetValue(_propertyCache, key)) { 76 | CFRelease(CFDictionaryGetValue(_propertyCache, key)); 77 | } 78 | CFDictionaryRemoveValue(_propertyCache, key); 79 | } 80 | @end 81 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFScopeChain.h: -------------------------------------------------------------------------------- 1 | // 2 | // ANEScopeChain.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/28. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ORThreadContext.h" 11 | #import "ORGlobalFunctionTable.h" 12 | #import "built-in.h" 13 | @class MFValue; 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface OREntryContext: NSObject 17 | @property (strong, nonatomic) Class classNode; 18 | @property (nonatomic, assign)bool isDeallocScope; 19 | @property (nonatomic, assign)bool deferCallOrigDealloc; 20 | @property (nonatomic, assign)bool deferCallSuperDealloc; 21 | + (instancetype)contextWithClass:(Class)classNode; 22 | @end 23 | 24 | extern const void *mf_propKey(NSString *propName); 25 | @interface MFScopeChain: NSObject 26 | @property (strong, nonatomic) NSMutableDictionary *vars; 27 | + (instancetype)topScope; 28 | @property (strong, nonatomic) MFScopeChain *next; 29 | @property (strong, nonatomic) MFValue *instance; 30 | // only in Method or Function's top scope. 31 | @property (strong, nonatomic) OREntryContext *entryCtx; 32 | 33 | - (Class)classNode; 34 | 35 | + (instancetype)scopeChainWithNext:(MFScopeChain *)next; 36 | - (nullable MFValue *)getValueWithIdentifier:(NSString *)identifier endScope:(nullable MFScopeChain *)endScope; 37 | - (nullable MFValue *)recursiveGetValueWithIdentifier:(NSString *)identifier; 38 | - (nullable MFValue *)getValueWithIdentifier:(NSString *)identifer; 39 | - (void)setValue:(MFValue *)value withIndentifier:(NSString *)identier; 40 | - (void)assignWithIdentifer:(NSString *)identifier value:(MFValue *)value; 41 | - (void)removeForIdentifier:(NSString *)key; 42 | - (void)clear; 43 | @end 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFScopeChain.m: -------------------------------------------------------------------------------- 1 | // 2 | // ANEScopeChain.m 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/28. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MFScopeChain.h" 11 | #import "MFValue.h" 12 | #import "MFBlock.h" 13 | #import "MFPropertyMapTable.h" 14 | #import "util.h" 15 | #import "RunnerClasses+Execute.h" 16 | #import "ORTypeVarPair+TypeEncode.h" 17 | 18 | @implementation OREntryContext 19 | + (instancetype)contextWithClass:(Class)classNode { 20 | OREntryContext *ctx = [OREntryContext new]; 21 | ctx->_classNode = classNode; 22 | return ctx; 23 | } 24 | @end 25 | 26 | @interface MFScopeChain() 27 | @end 28 | static MFScopeChain *instance = nil; 29 | @implementation MFScopeChain 30 | + (instancetype)topScope{ 31 | static dispatch_once_t onceToken; 32 | dispatch_once(&onceToken, ^{ 33 | instance = [MFScopeChain new]; 34 | }); 35 | return instance; 36 | } 37 | + (instancetype)scopeChainWithNext:(MFScopeChain *)next{ 38 | MFScopeChain *scope = [MFScopeChain new]; 39 | scope.next = next; 40 | scope.instance = next.instance; 41 | scope.entryCtx = next.entryCtx; 42 | #if DEBUG 43 | MFValue *value = [MFValue valueWithObject:scope]; 44 | value.modifier = DeclarationModifierWeak; 45 | [scope setValue:value withIndentifier:@"$curScope"]; 46 | #endif 47 | return scope; 48 | } 49 | 50 | - (Class)classNode { 51 | return _entryCtx.classNode; 52 | } 53 | 54 | - (instancetype)init{ 55 | if (self = [super init]) { 56 | _vars = [NSMutableDictionary dictionary]; 57 | } 58 | return self; 59 | } 60 | - (void)setValue:(MFValue *)value withIndentifier:(NSString *)identier{ 61 | self.vars[identier] = value; 62 | } 63 | 64 | - (MFValue *)getValueWithIdentifier:(NSString *)identifer{ 65 | MFValue *value = self.vars[identifer]; 66 | return value; 67 | } 68 | 69 | 70 | const void *mf_propKey(NSString *propName) { 71 | static NSMutableDictionary *_propKeys; 72 | static dispatch_once_t onceToken; 73 | dispatch_once(&onceToken, ^{ 74 | _propKeys = [[NSMutableDictionary alloc] init]; 75 | }); 76 | id key = _propKeys[propName]; 77 | if (!key) { 78 | key = [propName copy]; 79 | [_propKeys setObject:key forKey:propName]; 80 | } 81 | return (__bridge const void *)(key); 82 | } 83 | - (NSString *)propNameByIvarName:(NSString *)ivarName{ 84 | if (ivarName.length < 2) { 85 | return nil; 86 | } 87 | 88 | if ([ivarName characterAtIndex:0] != '_') { 89 | return nil; 90 | } 91 | 92 | return [ivarName substringFromIndex:1]; 93 | } 94 | 95 | - (void)assignWithIdentifer:(NSString *)identifier value:(MFValue *)value{ 96 | for (MFScopeChain *pos = self; pos; pos = pos.next) { 97 | if ([identifier characterAtIndex:0] == '_' && pos.instance) { 98 | id instance = [(MFValue *)pos.instance objectValue]; 99 | Class clazz = [instance class]; 100 | NSString *propName = [self propNameByIvarName:identifier]; 101 | if (propName != nil) { 102 | MFPropertyMapTableItem *propItem = [[MFPropertyMapTable shareInstance] getPropertyMapTableItemWith:clazz name:propName]; 103 | ORPropertyDeclare *propDef = propItem.property; 104 | if (propItem.added && propDef) { 105 | MFValue *result = [[MFValue alloc] initTypeEncode:propDef.var.typeEncode pointer:value.pointer]; 106 | MFPropertyModifier modifier = propDef.modifier; 107 | if ((modifier & MFPropertyModifierMemMask) == MFPropertyModifierMemWeak) { 108 | result.modifier = DeclarationModifierWeak; 109 | } 110 | objc_AssociationPolicy associationPolicy = mf_AssociationPolicy_with_PropertyModifier(modifier); 111 | objc_setAssociatedObject(instance, mf_propKey(propName), result, associationPolicy); 112 | return; 113 | } 114 | } 115 | Ivar ivar = class_getInstanceVariable(clazz,identifier.UTF8String); 116 | if(ivar){ 117 | const char *ivarEncoding = ivar_getTypeEncoding(ivar); 118 | if (*ivarEncoding == OCTypeObject) { 119 | object_setIvar(instance, ivar, value.objectValue); 120 | return; 121 | } 122 | void *ptr = (__bridge void *)(instance) + ivar_getOffset(ivar); 123 | [value writePointer:ptr typeEncode:ivarEncoding]; 124 | return; 125 | } 126 | } 127 | MFValue *srcValue = [pos getValueWithIdentifier:identifier]; 128 | if (srcValue) { 129 | [srcValue assignWithNewValue:value]; 130 | return; 131 | } 132 | } 133 | } 134 | 135 | - (MFValue *)getValueWithIdentifier:(NSString *)identifier endScope:(MFScopeChain *)endScope{ 136 | MFScopeChain *pos = self; 137 | // FIX: while self == endScope, will ignore self 138 | do { 139 | if ([identifier characterAtIndex:0] == '_' && pos.instance) { 140 | id instance = [(MFValue *)pos.instance objectValue]; 141 | Class clazz = [instance class]; 142 | NSString *propName = [self propNameByIvarName:identifier]; 143 | if (propName != nil) { 144 | MFPropertyMapTableItem *propItem = [[MFPropertyMapTable shareInstance] getPropertyMapTableItemWith:clazz name:propName]; 145 | ORPropertyDeclare *propDef = propItem.property; 146 | if (propItem.added && propDef) { 147 | MFValue *propValue = objc_getAssociatedObject(instance, mf_propKey(propName)); 148 | if (!propValue) { 149 | return [MFValue defaultValueWithTypeEncoding:propDef.var.typeEncode]; 150 | } 151 | if (propValue.modifier & DeclarationModifierWeak) { 152 | propValue = [propValue copy]; 153 | } 154 | return propValue; 155 | } 156 | } 157 | Ivar ivar = class_getInstanceVariable(clazz, identifier.UTF8String); 158 | if(ivar){ 159 | const char *ivarEncoding = ivar_getTypeEncoding(ivar); 160 | void *ptr = (__bridge void *)(instance) + ivar_getOffset(ivar); 161 | return [[MFValue alloc] initTypeEncode:ivarEncoding pointer:ptr]; 162 | } 163 | } 164 | MFValue *value = [pos getValueWithIdentifier:identifier]; 165 | if (value) { 166 | return value; 167 | } 168 | pos = pos.next; 169 | } while ((pos != endScope) && (self != endScope)); 170 | return nil; 171 | } 172 | 173 | - (MFValue *)recursiveGetValueWithIdentifier:(NSString *)identifier{ 174 | return [self getValueWithIdentifier:identifier endScope:nil]; 175 | } 176 | - (void)removeForIdentifier:(NSString *)key{ 177 | [_vars removeObjectForKey:key]; 178 | } 179 | - (void)clear{ 180 | _vars = [NSMutableDictionary dictionary]; 181 | } 182 | @end 183 | 184 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFStaticVarTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFStaticVarTable.h 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/6/7. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MFValue.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MFStaticVarTable : NSObject 15 | 16 | + (instancetype)shareInstance; 17 | 18 | - (nullable MFValue *)getStaticVarValueWithKey:(NSString *)key; 19 | - (void)setStaticVarValue:(MFValue *)value withKey:(NSString *)key; 20 | - (void)clear; 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFStaticVarTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFStaticVarTable.m 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/6/7. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFStaticVarTable.h" 10 | 11 | @implementation MFStaticVarTable{ 12 | NSMutableDictionary *_dic; 13 | NSLock *_lock; 14 | } 15 | 16 | + (instancetype)shareInstance{ 17 | static id _instance; 18 | static dispatch_once_t onceToken; 19 | dispatch_once(&onceToken, ^{ 20 | _instance = [[self alloc] init]; 21 | }); 22 | return _instance; 23 | } 24 | 25 | - (instancetype)init{ 26 | if (self = [super init]) { 27 | _dic = [NSMutableDictionary dictionary]; 28 | _lock = [[NSLock alloc] init]; 29 | } 30 | return self; 31 | } 32 | 33 | - (MFValue *)getStaticVarValueWithKey:(NSString *)key{ 34 | MFValue *value = nil; 35 | [_lock lock]; 36 | value = _dic[key]; 37 | [_lock unlock]; 38 | return value; 39 | } 40 | 41 | - (void)setStaticVarValue:(MFValue *)value withKey:(NSString *)key{ 42 | if (!value) { 43 | return; 44 | } 45 | [_lock lock]; 46 | _dic[key] = value; 47 | [_lock unlock]; 48 | } 49 | - (void)clear{ 50 | [_lock lock]; 51 | _dic = [NSMutableDictionary dictionary]; 52 | [_lock unlock]; 53 | } 54 | @end 55 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFVarDeclareChain.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFVarDeclareChain.h 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/5/1. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MFVarDeclareChain : NSObject 14 | @property (strong, nonatomic) MFVarDeclareChain *next; 15 | 16 | + (instancetype)varDeclareChainWithNext:(MFVarDeclareChain *)next; 17 | - (BOOL)isInThisNote:(NSString *)indentifer; 18 | - (BOOL)isInChain:(NSString *)indentifer; 19 | - (void)addIndentifer:(NSString *)indentifer; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/MFVarDeclareChain.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFVarDeclareChain.m 3 | // MangoFix 4 | // 5 | // Created by yongpengliang on 2019/5/1. 6 | // Copyright © 2019 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFVarDeclareChain.h" 10 | 11 | @implementation MFVarDeclareChain{ 12 | NSMutableArray *_indentiferArr; 13 | } 14 | 15 | - (instancetype)init{ 16 | if (self = [super init]) { 17 | _indentiferArr = [NSMutableArray array]; 18 | } 19 | return self; 20 | } 21 | 22 | + (instancetype)varDeclareChainWithNext:(MFVarDeclareChain *)next{ 23 | MFVarDeclareChain *chain = [[MFVarDeclareChain alloc] init]; 24 | chain.next = next; 25 | return chain; 26 | } 27 | 28 | - (BOOL)isInThisNote:(NSString *)indentifer{ 29 | return [_indentiferArr indexOfObject:indentifer] != NSNotFound; 30 | } 31 | 32 | - (BOOL)isInChain:(NSString *)indentifer{ 33 | MFVarDeclareChain *chain = self; 34 | while (chain) { 35 | if ([chain isInThisNote:indentifer]) { 36 | return YES; 37 | } 38 | chain = chain.next; 39 | } 40 | return NO; 41 | } 42 | 43 | - (void)addIndentifer:(NSString *)indentifer{ 44 | if (!indentifer.length) { 45 | return; 46 | } 47 | [_indentiferArr addObject:indentifer]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/ORGlobalFunctionTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORFunctionTable.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/9/29. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface ORGlobalFunctionTable : NSObject 13 | + (instancetype)shared; 14 | @property (strong, nonatomic) NSMutableDictionary *functions; 15 | - (void)setFunctionNode:(id)function WithName:(NSString *)name; 16 | - (id)getFunctionNodeWithName:(NSString *)name; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/ORGlobalFunctionTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORFunctionTable.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/9/29. 6 | // 7 | 8 | #import "ORGlobalFunctionTable.h" 9 | 10 | static ORGlobalFunctionTable *ORFunctionTableInstance = nil; 11 | 12 | @implementation ORGlobalFunctionTable 13 | + (instancetype)shared{ 14 | static dispatch_once_t onceToken; 15 | dispatch_once(&onceToken, ^{ 16 | ORFunctionTableInstance = [ORGlobalFunctionTable new]; 17 | }); 18 | return ORFunctionTableInstance; 19 | } 20 | - (instancetype)init 21 | { 22 | self = [super init]; 23 | if (self) { 24 | self.functions = [NSMutableDictionary dictionary]; 25 | } 26 | return self; 27 | } 28 | - (void)setFunctionNode:(id)function WithName:(NSString *)name{ 29 | self.functions[name] = function; 30 | } 31 | - (id)getFunctionNodeWithName:(NSString *)name{ 32 | return self.functions[name]; 33 | } 34 | @end 35 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/ORStructDeclare.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFStructDeclare.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2017/11/16. 6 | // Copyright © 2017年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RunnerClasses+Execute.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORStructDeclare : NSObject 14 | { 15 | @private 16 | NSUInteger size_; 17 | } 18 | 19 | @property (copy, nonatomic) NSString *name; 20 | @property (assign, nonatomic)const char *typeEncoding; 21 | @property (strong, nonatomic) NSArray *keys; 22 | @property (strong, nonatomic) NSDictionary *keyOffsets; 23 | @property (strong, nonatomic) NSDictionary *keySizes; 24 | @property (strong, nonatomic) NSDictionary *keyTypeEncodes; 25 | + (instancetype)structDecalre:(const char *)encode keys:(NSArray *)keys; 26 | - (instancetype)initWithTypeEncode:(const char *)typeEncoding keys:(NSArray *)keys; 27 | - (NSInteger)structSize; 28 | @end 29 | 30 | @interface ORUnionDeclare : NSObject 31 | @property (copy, nonatomic) NSString *name; 32 | @property (assign, nonatomic)const char *typeEncoding; 33 | @property (strong, nonatomic) NSArray *keys; 34 | @property (strong, nonatomic) NSDictionary *keyTypeEncodes; 35 | + (instancetype)unionDecalre:(const char *)encode keys:(NSArray *)keys; 36 | @end 37 | 38 | @interface ORTypeVarPair (Struct) 39 | - (ORStructDeclare *)strcutDeclare; 40 | @end 41 | 42 | @interface ORSymbolItem: NSObject 43 | @property (copy, nonatomic)NSString *typeEncode; 44 | @property (copy, nonatomic)NSString *typeName; 45 | @property (strong, nonatomic, nullable)id declare; 46 | - (BOOL)isStruct; 47 | - (BOOL)isUnion; 48 | - (BOOL)isCArray; 49 | @end 50 | 51 | @interface ORTypeSymbolTable: NSObject 52 | + (instancetype)shareInstance; 53 | 54 | - (ORSymbolItem *)addTypePair:(ORTypeVarPair *)typePair; 55 | - (ORSymbolItem *)addTypePair:(ORTypeVarPair *)item forAlias:(NSString *)alias; 56 | 57 | - (ORSymbolItem *)addUnion:(ORUnionDeclare *)declare; 58 | - (ORSymbolItem *)addStruct:(ORStructDeclare *)declare; 59 | - (ORSymbolItem *)addUnion:(ORUnionDeclare *)declare forAlias:(NSString *)alias; 60 | - (ORSymbolItem *)addStruct:(ORStructDeclare *)declare forAlias:(NSString *)alias; 61 | - (void)addSybolItem:(ORSymbolItem *)item forAlias:(NSString *)alias; 62 | - (ORSymbolItem *)symbolItemForTypeName:(NSString *)typeName; 63 | - (void)addCArray:(ORCArrayVariable *)cArray typeEncode:(const char *)typeEncode; 64 | - (ORSymbolItem *)symbolItemForNode:(ORNode *)node; 65 | - (void)clear; 66 | @end 67 | NS_ASSUME_NONNULL_END 68 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/ORThreadContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORThreadContext.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/6/4. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | @class MFValue; 12 | @class ORMethodImplementation; 13 | @class ORFunctionImp; 14 | @class MFScopeChain; 15 | @interface ORCallFrameStack: NSObject 16 | + (void)pushMethodCall:(ORMethodImplementation *)imp instance:(MFValue *)instance; 17 | + (void)pushFunctionCall:(ORFunctionImp *)imp scope:(MFScopeChain *)scope; 18 | + (void)pop; 19 | + (instancetype)threadStack; 20 | + (NSString *)history; 21 | @end 22 | 23 | @interface ORArgsStack : NSObject 24 | + (void)push:(NSMutableArray *)value; 25 | + (NSMutableArray *)pop; 26 | + (BOOL)isEmpty; 27 | + (NSUInteger)size; 28 | + (instancetype)threadStack; 29 | @end 30 | 31 | @class ORNode; 32 | @interface ORExecuteState: NSObject 33 | @property (nonatomic, strong)ORNode *executingNode; 34 | @end 35 | 36 | @interface ORThreadContext : NSObject 37 | @property (nonatomic, strong)ORArgsStack *argsStack; 38 | @property (nonatomic, strong)ORCallFrameStack *callFrameStack; 39 | + (instancetype)threadContext; 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/ORThreadContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORThreadContext.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/6/4. 6 | // 7 | 8 | #import "ORThreadContext.h" 9 | #import "MFValue.h" 10 | #import "MFScopeChain.h" 11 | @interface ORCallFrameStack() 12 | @property(nonatomic, strong) NSMutableArray *array; 13 | @end 14 | @implementation ORCallFrameStack 15 | - (instancetype)init 16 | { 17 | self = [super init]; 18 | if (self) { 19 | self.array = [NSMutableArray array]; 20 | } 21 | return self; 22 | } 23 | + (void)pushMethodCall:(ORMethodImplementation *)imp instance:(MFValue *)instance{ 24 | [[ORCallFrameStack threadStack].array addObject:@[instance, imp]]; 25 | } 26 | + (void)pushFunctionCall:(ORFunctionImp *)imp scope:(MFScopeChain *)scope{ 27 | [[ORCallFrameStack threadStack].array addObject:@[scope, imp]]; 28 | } 29 | + (void)pop{ 30 | [[ORCallFrameStack threadStack].array removeLastObject]; 31 | } 32 | + (instancetype)threadStack{ 33 | return ORThreadContext.threadContext.callFrameStack; 34 | } 35 | + (NSString *)history{ 36 | NSMutableArray *frames = [ORCallFrameStack threadStack].array; 37 | NSMutableString *log = [@"*OCRunner Frames:*\n" mutableCopy]; 38 | // avoid unsigned int overflow 39 | if (frames.count == 0) { 40 | return [log stringByAppendingString:@"Empty\n"]; 41 | } 42 | for (int i = (int)frames.count - 1; i >= 0; i--) { 43 | NSArray *frame = frames[i]; 44 | if ([frame.firstObject isKindOfClass:[MFValue class]]) { 45 | MFValue *instance = frame.firstObject; 46 | ORMethodImplementation *imp = frame.lastObject; 47 | BOOL isClassMethod = imp.declare.isClassMethod; 48 | id objectValue = instance.objectValue; 49 | const char *className = isClassMethod ? class_getName(objectValue) : object_getClassName(objectValue); 50 | [log appendFormat:@"%@[%s %@]\n", isClassMethod ? @"+" : @"-", className, imp.declare.selectorName]; 51 | }else{ 52 | MFScopeChain *scope = frame.firstObject; 53 | ORFunctionImp *imp = frame.lastObject; 54 | if (imp.declare.funVar.varname == nil){ 55 | [log appendFormat:@"\nBlock Call: Captured external variables '%@' \n",[scope.vars.allKeys componentsJoinedByString:@","]]; 56 | // 比如dispatch_after中的block,此时只会孤零零的提醒你一个Block Call 57 | // 异步调用时,此时通过语法树回溯,可以定位到 block 所在的类以及方法名 58 | if (i == 0) { 59 | ORNode *parent = imp.parentNode; 60 | while (parent != nil ) { 61 | if ([parent isKindOfClass:[ORClass class]]) { 62 | [log appendFormat:@"Block Code in Class: %@\n", [(ORClass *)parent className]]; 63 | }else if ([parent isKindOfClass:[ORMethodImplementation class]]){ 64 | ORMethodImplementation *imp = (ORMethodImplementation *)parent; 65 | [log appendFormat:@"Block Code in Method: %@%@\n", imp.declare.isClassMethod ? @"+" : @"-", imp.declare.selectorName]; 66 | }else if ([parent isKindOfClass:[ORCFuncCall class]]){ 67 | ORCFuncCall *imp = (ORCFuncCall *)parent; 68 | [log appendFormat:@"Block Code in Function call: %@\n", imp.caller.value]; 69 | }else if ([parent isKindOfClass:[ORMethodCall class]]){ 70 | ORMethodCall *imp = (ORMethodCall *)parent; 71 | [log appendFormat:@"Block Code in Method call: %@\n", imp.selectorName]; 72 | }else if ([parent isKindOfClass:[ORDeclareExpression class]]){ 73 | ORDeclareExpression *imp = (ORDeclareExpression *)parent; 74 | [log appendFormat:@"Block Code in Decl: %@ %@\n", imp.pair.type.name, imp.pair.var.varname]; 75 | } 76 | parent = parent.parentNode; 77 | } 78 | } 79 | }else{ 80 | [log appendFormat:@" CFunction: %@\n", imp.declare.funVar.varname]; 81 | } 82 | } 83 | } 84 | return log; 85 | } 86 | @end 87 | 88 | @interface ORArgsStack() 89 | @property(nonatomic, strong) NSMutableArray *array; 90 | @end 91 | @implementation ORArgsStack 92 | - (instancetype)init{ 93 | if (self = [super init]) { 94 | _array = [NSMutableArray array]; 95 | } 96 | return self; 97 | } 98 | + (instancetype)threadStack{ 99 | return ORThreadContext.threadContext.argsStack; 100 | } 101 | + (void)push:(NSMutableArray *)value{ 102 | NSAssert(value, @"value can not be nil"); 103 | [ORArgsStack.threadStack.array addObject:value]; 104 | } 105 | 106 | + (NSMutableArray *)pop{ 107 | NSMutableArray *value = [ORArgsStack.threadStack.array lastObject]; 108 | NSAssert(value, @"stack is empty"); 109 | [ORArgsStack.threadStack.array removeLastObject]; 110 | return value; 111 | } 112 | + (BOOL)isEmpty{ 113 | return [ORArgsStack.threadStack.array count] == 0; 114 | } 115 | + (NSUInteger)size{ 116 | return ORArgsStack.threadStack.array.count; 117 | } 118 | @end 119 | 120 | @implementation ORThreadContext 121 | + (instancetype)threadContext{ 122 | //每一个线程拥有一个独立的上下文 123 | NSMutableDictionary *threadInfo = [[NSThread currentThread] threadDictionary]; 124 | ORThreadContext *ctx = threadInfo[@"ORThreadContext"]; 125 | if (!ctx) { 126 | ctx = [[ORThreadContext alloc] init]; 127 | threadInfo[@"ORThreadContext"] = ctx; 128 | } 129 | return ctx; 130 | } 131 | - (instancetype)init 132 | { 133 | self = [super init]; 134 | if (self) { 135 | self.argsStack = [[ORArgsStack alloc] init]; 136 | self.callFrameStack = [[ORCallFrameStack alloc] init]; 137 | } 138 | return self; 139 | } 140 | @end 141 | -------------------------------------------------------------------------------- /OCRunner/RunEnv/runenv.h: -------------------------------------------------------------------------------- 1 | // 2 | // runenv.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/28. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #ifndef runenv_h 10 | #define runenv_h 11 | 12 | #import "MFMethodMapTable.h" 13 | #import "MFBlock.h" 14 | #import "MFValue.h" 15 | #import "MFScopeChain.h" 16 | 17 | 18 | #endif /* runenv_h */ 19 | -------------------------------------------------------------------------------- /OCRunner/RunnerClasses+Execute.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORunner+Execute.h 3 | // MangoFix 4 | // 5 | // Created by Jiang on 2020/5/8. 6 | // Copyright © 2020 yongpengliang. All rights reserved. 7 | // 8 | 9 | // Cocoapods 10 | #import 11 | // While need compile static framework 12 | //#import "ORPatchFile.h" 13 | #import 14 | 15 | 16 | @class MFValue; 17 | NS_ASSUME_NONNULL_BEGIN 18 | @class MFScopeChain; 19 | @protocol OCExecute 20 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 21 | @end 22 | @interface ORNode (Execute) 23 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 24 | @end 25 | @interface ORTypeSpecial (Execute) 26 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 27 | @end 28 | @interface ORVariable (Execute) 29 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 30 | @end 31 | @interface ORTypeVarPair (Execute) 32 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 33 | @end 34 | @interface ORFuncVariable (Execute) 35 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 36 | @end 37 | @interface ORFuncDeclare (Execute) 38 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 39 | @end 40 | @interface ORValueExpression (Execute) 41 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 42 | @end 43 | @interface ORMethodCall (Execute) 44 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 45 | @end 46 | @interface ORCFuncCall (Execute) 47 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 48 | @end 49 | @interface ORScopeImp (Execute) 50 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 51 | @end 52 | @interface ORFunctionImp (Execute) 53 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 54 | @end 55 | @interface ORSubscriptExpression (Execute) 56 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 57 | @end 58 | @interface ORAssignExpression (Execute) 59 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 60 | @end 61 | @interface ORDeclareExpression (Execute) 62 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 63 | @end 64 | @interface ORUnaryExpression (Execute) 65 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 66 | @end 67 | @interface ORBinaryExpression (Execute) 68 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 69 | @end 70 | @interface ORTernaryExpression (Execute) 71 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 72 | @end 73 | 74 | @interface ORIfStatement (Execute) 75 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 76 | @end 77 | @interface ORWhileStatement (Execute) 78 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 79 | @end 80 | @interface ORDoWhileStatement (Execute) 81 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 82 | @end 83 | @interface ORCaseStatement (Execute) 84 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 85 | @end 86 | @interface ORSwitchStatement (Execute) 87 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 88 | @end 89 | @interface ORForStatement (Execute) 90 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 91 | @end 92 | @interface ORForInStatement (Execute) 93 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 94 | @end 95 | @interface ORReturnStatement (Execute) 96 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 97 | @end 98 | @interface ORBreakStatement (Execute) 99 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 100 | @end 101 | @interface ORContinueStatement (Execute) 102 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 103 | @end 104 | @interface ORPropertyDeclare (Execute) 105 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 106 | @property (nonatomic, assign, readonly) const objc_property_attribute_t * propertyAttributes; 107 | @end 108 | @interface ORMethodDeclare (Execute) 109 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 110 | @end 111 | @interface ORMethodImplementation (Execute) 112 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 113 | @end 114 | @interface ORClass (Execute) 115 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 116 | @end 117 | 118 | @interface ORStructExpressoin (Execute) 119 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 120 | @end 121 | 122 | @interface OREnumExpressoin (Execute) 123 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 124 | @end 125 | 126 | @interface ORTypedefExpressoin (Execute) 127 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 128 | @end 129 | 130 | @interface ORProtocol (Execute) 131 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 132 | @end 133 | 134 | @interface ORCArrayVariable (Execute) 135 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 136 | @end 137 | 138 | @interface ORUnionExpressoin (Execute) 139 | - (nullable MFValue *)execute:(MFScopeChain *)scope; 140 | @end 141 | 142 | NS_ASSUME_NONNULL_END 143 | -------------------------------------------------------------------------------- /OCRunner/RunnerClasses+Recover.h: -------------------------------------------------------------------------------- 1 | // 2 | // RunnerClasses+Reverse.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/2/1. 6 | // 7 | 8 | #import 9 | #import "RunnerClasses+Execute.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | @protocol OCRecover 13 | - (void)recover; 14 | @end 15 | 16 | @interface ORNode (Recover) 17 | - (void)recover; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /OCRunner/RunnerClasses+Recover.m: -------------------------------------------------------------------------------- 1 | // 2 | // RunnerClasses+Reverse.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2021/2/1. 6 | // 7 | 8 | #import "RunnerClasses+Recover.h" 9 | #import "MFScopeChain.h" 10 | #import "util.h" 11 | #import "MFMethodMapTable.h" 12 | #import "MFPropertyMapTable.h" 13 | #import "MFVarDeclareChain.h" 14 | #import "MFBlock.h" 15 | #import "MFValue.h" 16 | #import "MFStaticVarTable.h" 17 | #import "ORStructDeclare.h" 18 | #import 19 | #import "ORTypeVarPair+TypeEncode.h" 20 | #import "ORCoreImp.h" 21 | #import "ORSearchedFunction.h" 22 | #import "ORffiResultCache.h" 23 | void recover_method(BOOL isClassMethod, Class clazz, SEL sel){ 24 | NSString *orgSelName = [NSString stringWithFormat:@"ORG%@",NSStringFromSelector(sel)]; 25 | SEL orgsel = NSSelectorFromString(orgSelName); 26 | Method ocMethod; 27 | if (isClassMethod) { 28 | ocMethod = class_getClassMethod(clazz, orgsel); 29 | }else{ 30 | ocMethod = class_getInstanceMethod(clazz, orgsel); 31 | } 32 | if (ocMethod) { 33 | const char *typeEncoding = method_getTypeEncoding(ocMethod); 34 | Class c2 = isClassMethod ? objc_getMetaClass(class_getName(clazz)) : clazz; 35 | IMP orgImp = class_getMethodImplementation(c2, orgsel); 36 | class_replaceMethod(c2, sel, orgImp, typeEncoding); 37 | } 38 | } 39 | 40 | @implementation ORNode (Reverse) 41 | - (void)recover{ 42 | 43 | } 44 | @end 45 | 46 | @implementation ORClass (Reverse) 47 | - (void)deallocffiReusltForKey:(NSValue *)key{ 48 | or_ffi_result *result = [[ORffiResultCache shared] ffiResultForKey:key]; 49 | if (result) { 50 | [[ORffiResultCache shared] removeForKey:key]; 51 | or_ffi_result_free(result); 52 | } 53 | } 54 | - (void)recover{ 55 | Class class = NSClassFromString(self.className); 56 | // Reverse时,释放ffi_closure和ffi_type 57 | for (ORMethodImplementation *imp in self.methods) { 58 | SEL sel = NSSelectorFromString(imp.declare.selectorName); 59 | BOOL isClassMethod = imp.declare.isClassMethod; 60 | recover_method(isClassMethod, class, sel); 61 | [self deallocffiReusltForKey:[NSValue valueWithPointer:(__bridge void *)imp]]; 62 | CFRelease((__bridge CFTypeRef)(imp)); 63 | } 64 | for (ORPropertyDeclare *prop in self.properties){ 65 | NSString *name = prop.var.var.varname; 66 | if ([[MFPropertyMapTable shareInstance] getPropertyMapTableItemWith:class name:name].added == NO) { 67 | continue; 68 | } 69 | NSString *str1 = [[name substringWithRange:NSMakeRange(0, 1)] uppercaseString]; 70 | NSString *str2 = name.length > 1 ? [name substringFromIndex:1] : @""; 71 | SEL getterSEL = NSSelectorFromString(name); 72 | SEL setterSEL = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",str1,str2]); 73 | recover_method(NO, class, getterSEL); 74 | recover_method(NO, class, setterSEL); 75 | [self deallocffiReusltForKey:[NSValue valueWithPointer:(__bridge void *)prop]]; 76 | CFRelease((__bridge CFTypeRef)(prop)); 77 | } 78 | [[MFMethodMapTable shareInstance] removeMethodsForClass:class]; 79 | [[MFPropertyMapTable shareInstance] removePropertiesForClass:class]; 80 | 81 | Class classVar = [[MFScopeChain topScope] recursiveGetValueWithIdentifier:self.className].classValue; 82 | if (classVar != nil && classVar == class) { 83 | objc_disposeClassPair(classVar); 84 | } 85 | } 86 | 87 | @end 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /OCRunner/Util/ORSearchedFunction.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORSearchedFunction.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/6/9. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RunnerClasses+Execute.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | @class ORTypeVarPair; 13 | @class ORFuncVariable; 14 | @interface ORSearchedFunction : NSObject 15 | @property (nonatomic,strong)ORTypeVarPair *funPair; 16 | @property (nonatomic,strong,readonly)ORFuncVariable *funVar; 17 | @property (nonatomic,copy)NSString *name; 18 | @property (nonatomic,assign)void *pointer; 19 | + (instancetype)functionWithName:(NSString *)name; 20 | + (NSDictionary *)functionTableForNames:(NSArray *)names; 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /OCRunner/Util/ORSearchedFunction.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORSearchedFunction.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/6/9. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORSearchedFunction.h" 10 | #import "SymbolSearch.h" 11 | #import "RunnerClasses+Execute.h" 12 | #import "ORThreadContext.h" 13 | #import "MFValue.h" 14 | #import "ORTypeVarPair+TypeEncode.h" 15 | #import "ORCoreImp.h" 16 | #import "ORHandleTypeEncode.h" 17 | #import "ORStructDeclare.h" 18 | #import "ORSystemFunctionPointerTable.h" 19 | @implementation ORSearchedFunction 20 | - (ORFuncVariable *)funVar{ 21 | return (ORFuncVariable *)self.funPair.var; 22 | } 23 | + (instancetype)functionWithName:(NSString *)name{ 24 | ORSearchedFunction *function = [ORSearchedFunction new]; 25 | function.name = name; 26 | return function; 27 | } 28 | + (NSDictionary *)functionTableForNames:(NSArray *)names{ 29 | //函数声明去重,解决多次链接的问题,因为最后一次查找始终会为NULL 30 | names = [[NSSet setWithArray:names] allObjects]; 31 | struct FunctionSearch searches[names.count]; 32 | NSMutableDictionary *table = [NSMutableDictionary dictionary]; 33 | for (int i = 0; i < names.count; i++) { 34 | NSString *name = names[i]; 35 | ORSearchedFunction *result = [ORSearchedFunction functionWithName:name]; 36 | searches[i] = makeFunctionSearch(name.UTF8String, &result->_pointer); 37 | table[name] = result; 38 | } 39 | search_symbols(searches, names.count); 40 | return table; 41 | } 42 | - (nullable MFValue *)execute:(nonnull MFScopeChain *)scope { 43 | NSArray *args = [ORArgsStack pop]; 44 | const char *org_typeencode = self.funPair.typeEncode; 45 | if (org_typeencode == NULL) { 46 | NSLog(@"OCRunner Error: Unknow return type of C function '%@'", self.name); 47 | return [MFValue nullValue]; 48 | } 49 | 50 | // 根据声明的类型进行转换 51 | do { 52 | if (self.funVar == nil) break; 53 | NSAssert([self.funVar isKindOfClass:[ORFuncVariable class]], @"funVar must be ORFuncVariable"); 54 | ORFuncVariable *funcDecl = self.funVar; 55 | NSArray *declArgs = funcDecl.pairs; 56 | // ignore 'void xxx(void)' 57 | if (declArgs.count == 1 && declArgs[0].type.type == TypeVoid && declArgs[0].var.ptCount == 0) break; 58 | for (int i = 0; i < declArgs.count; i++) { 59 | args[i].typeEncode = declArgs[i].typeEncode; 60 | } 61 | } while (0); 62 | 63 | MFValue *returnValue = [MFValue defaultValueWithTypeEncoding:org_typeencode]; 64 | void *funcptr = self.pointer != NULL ? self.pointer : [ORSystemFunctionPointerTable pointerForFunctionName:self.name]; 65 | if (funcptr == NULL) { 66 | NSLog(@"OCRunner Error: Not found the pointer of C function '%@'", self.name); 67 | return [MFValue nullValue]; 68 | } 69 | if (!self.funVar.isMultiArgs) { 70 | invoke_functionPointer(funcptr, args, returnValue); 71 | //多参数 72 | }else{ 73 | invoke_functionPointer(funcptr, args, returnValue, self.funVar.pairs.count); 74 | } 75 | return returnValue; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /OCRunner/Util/ORSystemFunctionPointerTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORSystemFunctionTable.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/17. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORSystemFunctionPointerTable : NSObject 14 | + (void)reg:(NSString *)name pointer:(void *)pointer; 15 | + (void *)pointerForFunctionName:(NSString *)name; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /OCRunner/Util/ORSystemFunctionPointerTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORSystemFunctionTable.m 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/7/17. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORSystemFunctionPointerTable.h" 10 | 11 | @implementation ORSystemFunctionPointerTable 12 | { 13 | NSMutableDictionary *_table; 14 | } 15 | - (instancetype)init 16 | { 17 | self = [super init]; 18 | if (self) { 19 | _table = [NSMutableDictionary dictionary]; 20 | } 21 | return self; 22 | } 23 | + (instancetype)shareInstance{ 24 | static id st_instance; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | st_instance = [[ORSystemFunctionPointerTable alloc] init]; 28 | }); 29 | return st_instance; 30 | } 31 | + (void)reg:(NSString *)name pointer:(void *)pointer{ 32 | [ORSystemFunctionPointerTable shareInstance]->_table[name] = [NSValue valueWithPointer:pointer]; 33 | } 34 | + (void *)pointerForFunctionName:(NSString *)name{ 35 | NSValue *value = [ORSystemFunctionPointerTable shareInstance]->_table[name]; 36 | return value.pointerValue; 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /OCRunner/Util/SymbolSearch.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef SymbolSearch_h 25 | #define SymbolSearch_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | struct FunctionSearch { 41 | const char *name; 42 | void **pointer; 43 | }; 44 | struct FunctionSearch makeFunctionSearch(const char *name, void *pointer); 45 | 46 | FISHHOOK_VISIBILITY 47 | int search_symbols(struct FunctionSearch rebindings[], size_t rebindings_nel); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif //__cplusplus 52 | 53 | #endif //fishhook_h 54 | -------------------------------------------------------------------------------- /OCRunner/Util/util.h: -------------------------------------------------------------------------------- 1 | // 2 | // util.h 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/16. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #ifndef util_h 10 | #define util_h 11 | #import 12 | #include 13 | #import "RunnerClasses+Execute.h" 14 | 15 | inline static char *removeTypeEncodingPrefix(char *typeEncoding){ 16 | if(typeEncoding == NULL) return NULL; 17 | while (*typeEncoding == 'r' || // const 18 | *typeEncoding == 'n' || // in 19 | *typeEncoding == 'N' || // inout 20 | *typeEncoding == 'o' || // out 21 | *typeEncoding == 'O' || // bycopy 22 | *typeEncoding == 'R' || // byref 23 | *typeEncoding == 'V') { // oneway 24 | typeEncoding++; // cutoff useless prefix 25 | } 26 | return typeEncoding; 27 | } 28 | 29 | const char * mf_str_append(const char *str1, const char *str2); 30 | 31 | size_t mf_size_with_encoding(const char *typeEncoding); 32 | 33 | NSString * mf_struct_name_with_encoding(const char *typeEncoding); 34 | 35 | //void mf_struct_data_with_dic(void *structData, NSDictionary *dic, MFStructDeclare *declare); 36 | 37 | objc_AssociationPolicy mf_AssociationPolicy_with_PropertyModifier(MFPropertyModifier); 38 | 39 | #endif /* util_h */ 40 | -------------------------------------------------------------------------------- /OCRunner/Util/util.m: -------------------------------------------------------------------------------- 1 | // 2 | // util.m 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/16. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | 10 | #import "util.h" 11 | #import "runenv.h" 12 | 13 | 14 | const char * mf_str_append(const char *str1, const char *str2){ 15 | size_t len = strlen(str1) + strlen(str2); 16 | char *ret = malloc(sizeof(char) * (len + 1)); 17 | strcpy(ret, str1); 18 | strcat(ret, str2); 19 | return ret; 20 | } 21 | 22 | size_t mf_size_with_encoding(const char *typeEncoding){ 23 | NSUInteger size; 24 | NSUInteger alignp; 25 | NSGetSizeAndAlignment(typeEncoding, &size, &alignp); 26 | return size; 27 | } 28 | 29 | 30 | objc_AssociationPolicy mf_AssociationPolicy_with_PropertyModifier(MFPropertyModifier modifier){ 31 | objc_AssociationPolicy associationPolicy = OBJC_ASSOCIATION_RETAIN_NONATOMIC; 32 | switch (modifier & MFPropertyModifierMemMask) { 33 | case MFPropertyModifierMemStrong: 34 | case MFPropertyModifierMemWeak: 35 | case MFPropertyModifierMemAssign: 36 | switch (modifier & MFPropertyModifierAtomicMask) { 37 | case MFPropertyModifierAtomic: 38 | associationPolicy = OBJC_ASSOCIATION_RETAIN; 39 | break; 40 | case MFPropertyModifierNonatomic: 41 | associationPolicy = OBJC_ASSOCIATION_RETAIN_NONATOMIC; 42 | break; 43 | default: 44 | break; 45 | } 46 | break; 47 | case MFPropertyModifierMemCopy: 48 | switch (modifier & MFPropertyModifierAtomicMask) { 49 | case MFPropertyModifierAtomic: 50 | associationPolicy = OBJC_ASSOCIATION_COPY; 51 | break; 52 | case MFPropertyModifierNonatomic: 53 | associationPolicy = OBJC_ASSOCIATION_COPY_NONATOMIC; 54 | break; 55 | default: 56 | break; 57 | } 58 | break; 59 | 60 | default: 61 | break; 62 | } 63 | return associationPolicy; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /OCRunner/built-in.h: -------------------------------------------------------------------------------- 1 | // 2 | // built-in.h 3 | // OCRunner 4 | // 5 | // Created by Jiang on 2020/5/28. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #ifndef built_in_h 10 | #define built_in_h 11 | @class MFScopeChain; 12 | extern void mf_add_built_in(MFScopeChain *scope); 13 | 14 | 15 | #endif /* built_in_h */ 16 | -------------------------------------------------------------------------------- /OCRunner/built-in.m: -------------------------------------------------------------------------------- 1 | // 2 | // built-in.m 3 | // MangoFix 4 | // 5 | // Created by jerry.yong on 2018/2/28. 6 | // Copyright © 2018年 yongpengliang. All rights reserved. 7 | // 8 | 9 | #import "MFValue.h" 10 | #import "MFScopeChain.h" 11 | #import "ORStructDeclare.h" 12 | #import 13 | #import "ORSystemFunctionPointerTable.h" 14 | static void add_gcd_build_in(MFScopeChain *scope){ 15 | [scope setValue:[MFValue valueWithBlock:^void(dispatch_once_t *onceTokenPtr, 16 | dispatch_block_t _Nullable handler){ 17 | dispatch_once(onceTokenPtr,handler); 18 | }] withIndentifier:@"dispatch_once"]; 19 | 20 | [ORSystemFunctionPointerTable reg:@"dispatch_get_main_queue" pointer:&dispatch_get_main_queue]; 21 | [ORSystemFunctionPointerTable reg:@"dispatch_block_notify" pointer:&dispatch_block_notify]; 22 | [ORSystemFunctionPointerTable reg:@"dispatch_block_testcancel" pointer:&dispatch_block_testcancel]; 23 | [ORSystemFunctionPointerTable reg:@"CATransform3DIsIdentity" pointer:&CATransform3DIsIdentity]; 24 | [ORSystemFunctionPointerTable reg:@"CATransform3DEqualToTransform" pointer:&CATransform3DEqualToTransform]; 25 | [ORSystemFunctionPointerTable reg:@"CATransform3DMakeTranslation" pointer:&CATransform3DMakeTranslation]; 26 | [ORSystemFunctionPointerTable reg:@"CATransform3DMakeRotation" pointer:&CATransform3DMakeRotation]; 27 | [ORSystemFunctionPointerTable reg:@"CATransform3DTranslate" pointer:&CATransform3DTranslate]; 28 | [ORSystemFunctionPointerTable reg:@"CATransform3DRotate" pointer:&CATransform3DRotate]; 29 | [ORSystemFunctionPointerTable reg:@"CATransform3DConcat" pointer:&CATransform3DConcat]; 30 | [ORSystemFunctionPointerTable reg:@"CATransform3DInvert" pointer:&CATransform3DInvert]; 31 | [ORSystemFunctionPointerTable reg:@"CGAffineTransformMake" pointer:&CGAffineTransformMake]; 32 | [ORSystemFunctionPointerTable reg:@"CGPointEqualToPoint" pointer:&CGPointEqualToPoint]; 33 | [ORSystemFunctionPointerTable reg:@"CGSizeEqualToSize" pointer:&CGSizeEqualToSize]; 34 | [ORSystemFunctionPointerTable reg:@"dispatch_block_perform" pointer:&dispatch_block_perform]; 35 | 36 | /* queue */ 37 | [scope setValue:[MFValue valueWithLongLong:DISPATCH_QUEUE_PRIORITY_HIGH] withIndentifier:@"DISPATCH_QUEUE_PRIORITY_HIGH"]; 38 | [scope setValue:[MFValue valueWithLongLong:DISPATCH_QUEUE_PRIORITY_DEFAULT] withIndentifier:@"DISPATCH_QUEUE_PRIORITY_DEFAULT"]; 39 | [scope setValue:[MFValue valueWithLongLong:DISPATCH_QUEUE_PRIORITY_LOW] withIndentifier:@"DISPATCH_QUEUE_PRIORITY_LOW"]; 40 | [scope setValue:[MFValue valueWithLongLong:DISPATCH_QUEUE_PRIORITY_BACKGROUND] withIndentifier:@"DISPATCH_QUEUE_PRIORITY_BACKGROUND"]; 41 | 42 | [scope setValue:[MFValue valueWithObject:DISPATCH_QUEUE_CONCURRENT] withIndentifier:@"DISPATCH_QUEUE_CONCURRENT"]; 43 | [scope setValue:[MFValue nullValue] withIndentifier:@"DISPATCH_QUEUE_SERIAL"]; 44 | 45 | /*dispatch_source*/ 46 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_PROC] withIndentifier:@"DISPATCH_SOURCE_TYPE_PROC"]; 47 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_READ] withIndentifier:@"DISPATCH_SOURCE_TYPE_READ"]; 48 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_SIGNAL] withIndentifier:@"DISPATCH_SOURCE_TYPE_SIGNAL"]; 49 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_TIMER] withIndentifier:@"DISPATCH_SOURCE_TYPE_TIMER"]; 50 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_VNODE] withIndentifier:@"DISPATCH_SOURCE_TYPE_VNODE"]; 51 | [scope setValue:[MFValue valueWithPointer:(void *)DISPATCH_SOURCE_TYPE_WRITE] withIndentifier:@"DISPATCH_SOURCE_TYPE_WRITE"]; 52 | } 53 | 54 | static void add_build_in_function(MFScopeChain *scope){ 55 | 56 | 57 | } 58 | static void add_build_in_var(MFScopeChain *scope){ 59 | [scope setValue:[MFValue valueWithObject:NSRunLoopCommonModes] withIndentifier:@"NSRunLoopCommonModes"]; 60 | [scope setValue:[MFValue valueWithObject:NSDefaultRunLoopMode] withIndentifier:@"NSDefaultRunLoopMode"]; 61 | 62 | [scope setValue:[MFValue valueWithDouble:M_PI] withIndentifier:@"M_PI"]; 63 | [scope setValue:[MFValue valueWithDouble:M_PI_2] withIndentifier:@"M_PI_2"]; 64 | [scope setValue:[MFValue valueWithDouble:M_PI_4] withIndentifier:@"M_PI_4"]; 65 | [scope setValue:[MFValue valueWithDouble:M_1_PI] withIndentifier:@"M_1_PI"]; 66 | [scope setValue:[MFValue valueWithDouble:M_2_PI] withIndentifier:@"M_2_PI"]; 67 | 68 | UIDevice *device = [UIDevice currentDevice]; 69 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 70 | [scope setValue:[MFValue valueWithObject:device.systemVersion] withIndentifier:@"$systemVersion"]; 71 | [scope setValue:[MFValue valueWithObject:[infoDictionary objectForKey:@"CFBundleShortVersionString"]] withIndentifier:@"$appVersion"]; 72 | [scope setValue:[MFValue valueWithObject:[infoDictionary objectForKey:@"CFBundleVersion"]] withIndentifier:@"$buildVersion"]; 73 | 74 | #if defined(__LP64__) && __LP64__ 75 | BOOL is32BitDevice = NO; 76 | #else 77 | BOOL is32BitDevice = YES; 78 | #endif 79 | [scope setValue:[MFValue valueWithBOOL:is32BitDevice ] withIndentifier:@"$is32BitDevice"];; 80 | } 81 | #import "ORInterpreter.h" 82 | void mf_add_built_in(MFScopeChain *scope){ 83 | static dispatch_once_t onceToken; 84 | dispatch_once(&onceToken, ^{ 85 | add_build_in_function(scope); 86 | add_build_in_var(scope); 87 | add_gcd_build_in(scope); 88 | }); 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /OCRunner/libffi/ffi.h: -------------------------------------------------------------------------------- 1 | #ifdef __arm64__ 2 | 3 | #include "ffi_arm64.h" 4 | 5 | 6 | #endif 7 | #ifdef __i386__ 8 | 9 | #include "ffi_i386.h" 10 | 11 | 12 | #endif 13 | #ifdef __arm__ 14 | 15 | #include "ffi_arm.h" 16 | 17 | 18 | #endif 19 | #ifdef __x86_64__ 20 | 21 | #include "ffi_x86_64.h" 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /OCRunner/libffi/ffitarget.h: -------------------------------------------------------------------------------- 1 | #ifdef __arm64__ 2 | 3 | #include "ffitarget_arm64.h" 4 | 5 | 6 | #endif 7 | #ifdef __i386__ 8 | 9 | #include "ffitarget_i386.h" 10 | 11 | 12 | #endif 13 | #ifdef __arm__ 14 | 15 | #include "ffitarget_arm.h" 16 | 17 | 18 | #endif 19 | #ifdef __x86_64__ 20 | 21 | #include "ffitarget_x86_64.h" 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /OCRunner/libffi/ffitarget_arm.h: -------------------------------------------------------------------------------- 1 | /* -----------------------------------------------------------------*-C-*- 2 | ffitarget.h - Copyright (c) 2012 Anthony Green 3 | Copyright (c) 2010 CodeSourcery 4 | Copyright (c) 1996-2003 Red Hat, Inc. 5 | 6 | Target configuration macros for ARM. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | ``Software''), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | 28 | ----------------------------------------------------------------------- */ 29 | 30 | #ifndef LIBFFI_TARGET_H 31 | #define LIBFFI_TARGET_H 32 | 33 | #ifndef LIBFFI_H 34 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 35 | #endif 36 | 37 | #ifndef LIBFFI_ASM 38 | typedef unsigned long ffi_arg; 39 | typedef signed long ffi_sarg; 40 | 41 | typedef enum ffi_abi { 42 | FFI_FIRST_ABI = 0, 43 | FFI_SYSV, 44 | FFI_VFP, 45 | FFI_LAST_ABI, 46 | #ifdef __ARM_PCS_VFP 47 | FFI_DEFAULT_ABI = FFI_VFP, 48 | #else 49 | FFI_DEFAULT_ABI = FFI_SYSV, 50 | #endif 51 | } ffi_abi; 52 | #endif 53 | 54 | #define FFI_EXTRA_CIF_FIELDS \ 55 | int vfp_used; \ 56 | unsigned short vfp_reg_free, vfp_nargs; \ 57 | signed char vfp_args[16] \ 58 | 59 | #define FFI_TARGET_SPECIFIC_VARIADIC 60 | #define FFI_TARGET_HAS_COMPLEX_TYPE 61 | 62 | /* ---- Definitions for closures ----------------------------------------- */ 63 | 64 | #define FFI_CLOSURES 1 65 | #define FFI_GO_CLOSURES 1 66 | #define FFI_NATIVE_RAW_API 0 67 | 68 | #if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE 69 | 70 | #ifdef __MACH__ 71 | #define FFI_TRAMPOLINE_SIZE 12 72 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET 8 73 | #else 74 | #error "No trampoline table implementation" 75 | #endif 76 | 77 | #else 78 | #define FFI_TRAMPOLINE_SIZE 12 79 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /OCRunner/libffi/ffitarget_arm64.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | ``Software''), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 21 | 22 | #ifndef LIBFFI_TARGET_H 23 | #define LIBFFI_TARGET_H 24 | 25 | #ifndef LIBFFI_H 26 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 27 | #endif 28 | 29 | #ifndef LIBFFI_ASM 30 | #ifdef __ILP32__ 31 | #define FFI_SIZEOF_ARG 8 32 | #define FFI_SIZEOF_JAVA_RAW 4 33 | typedef unsigned long long ffi_arg; 34 | typedef signed long long ffi_sarg; 35 | #else 36 | typedef unsigned long ffi_arg; 37 | typedef signed long ffi_sarg; 38 | #endif 39 | 40 | typedef enum ffi_abi 41 | { 42 | FFI_FIRST_ABI = 0, 43 | FFI_SYSV, 44 | FFI_LAST_ABI, 45 | FFI_DEFAULT_ABI = FFI_SYSV 46 | } ffi_abi; 47 | #endif 48 | 49 | /* ---- Definitions for closures ----------------------------------------- */ 50 | 51 | #define FFI_CLOSURES 1 52 | #define FFI_NATIVE_RAW_API 0 53 | 54 | #if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE 55 | 56 | #ifdef __MACH__ 57 | #define FFI_TRAMPOLINE_SIZE 16 58 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET 16 59 | #else 60 | #error "No trampoline table implementation" 61 | #endif 62 | 63 | #else 64 | #define FFI_TRAMPOLINE_SIZE 24 65 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE 66 | #endif 67 | 68 | /* ---- Internal ---- */ 69 | 70 | #if defined (__APPLE__) 71 | #define FFI_TARGET_SPECIFIC_VARIADIC 72 | #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs 73 | #else 74 | /* iOS reserves x18 for the system. Disable Go closures until 75 | a new static chain is chosen. */ 76 | #define FFI_GO_CLOSURES 1 77 | #endif 78 | 79 | #define FFI_TARGET_HAS_COMPLEX_TYPE 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /OCRunner/libffi/ffitarget_i386.h: -------------------------------------------------------------------------------- 1 | #ifdef __i386__ 2 | 3 | /* -----------------------------------------------------------------*-C-*- 4 | ffitarget.h - Copyright (c) 2012, 2014 Anthony Green 5 | Copyright (c) 1996-2003, 2010 Red Hat, Inc. 6 | Copyright (C) 2008 Free Software Foundation, Inc. 7 | 8 | Target configuration macros for x86 and x86-64. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | ``Software''), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included 19 | in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | 30 | ----------------------------------------------------------------------- */ 31 | 32 | #ifndef LIBFFI_TARGET_H 33 | #define LIBFFI_TARGET_H 34 | 35 | #ifndef LIBFFI_H 36 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 37 | #endif 38 | 39 | /* ---- System specific configurations ----------------------------------- */ 40 | 41 | /* For code common to all platforms on x86 and x86_64. */ 42 | #define X86_ANY 43 | 44 | #if defined (X86_64) && defined (__i386__) 45 | #undef X86_64 46 | #define X86 47 | #endif 48 | 49 | #ifdef X86_WIN64 50 | #define FFI_SIZEOF_ARG 8 51 | #define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */ 52 | #endif 53 | 54 | #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 55 | #define FFI_TARGET_HAS_COMPLEX_TYPE 56 | 57 | /* ---- Generic type definitions ----------------------------------------- */ 58 | 59 | #ifndef LIBFFI_ASM 60 | #ifdef X86_WIN64 61 | #ifdef _MSC_VER 62 | typedef unsigned __int64 ffi_arg; 63 | typedef __int64 ffi_sarg; 64 | #else 65 | typedef unsigned long long ffi_arg; 66 | typedef long long ffi_sarg; 67 | #endif 68 | #else 69 | #if defined __x86_64__ && defined __ILP32__ 70 | #define FFI_SIZEOF_ARG 8 71 | #define FFI_SIZEOF_JAVA_RAW 4 72 | typedef unsigned long long ffi_arg; 73 | typedef long long ffi_sarg; 74 | #else 75 | typedef unsigned long ffi_arg; 76 | typedef signed long ffi_sarg; 77 | #endif 78 | #endif 79 | 80 | typedef enum ffi_abi { 81 | FFI_FIRST_ABI = 0, 82 | 83 | /* ---- Intel x86 Win32 ---------- */ 84 | #ifdef X86_WIN32 85 | FFI_SYSV, 86 | FFI_STDCALL, 87 | FFI_THISCALL, 88 | FFI_FASTCALL, 89 | FFI_MS_CDECL, 90 | FFI_PASCAL, 91 | FFI_REGISTER, 92 | FFI_LAST_ABI, 93 | #ifdef _MSC_VER 94 | FFI_DEFAULT_ABI = FFI_MS_CDECL 95 | #else 96 | FFI_DEFAULT_ABI = FFI_SYSV 97 | #endif 98 | 99 | #elif defined(X86_WIN64) 100 | FFI_WIN64, 101 | FFI_LAST_ABI, 102 | FFI_DEFAULT_ABI = FFI_WIN64 103 | 104 | #else 105 | /* ---- Intel x86 and AMD x86-64 - */ 106 | FFI_SYSV, 107 | FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ 108 | FFI_THISCALL, 109 | FFI_FASTCALL, 110 | FFI_STDCALL, 111 | FFI_PASCAL, 112 | FFI_REGISTER, 113 | FFI_LAST_ABI, 114 | #if defined(__i386__) || defined(__i386) 115 | FFI_DEFAULT_ABI = FFI_SYSV 116 | #else 117 | FFI_DEFAULT_ABI = FFI_UNIX64 118 | #endif 119 | #endif 120 | } ffi_abi; 121 | #endif 122 | 123 | /* ---- Definitions for closures ----------------------------------------- */ 124 | 125 | #define FFI_CLOSURES 1 126 | #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) 127 | #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) 128 | #define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) 129 | #define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) 130 | 131 | #if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) 132 | #define FFI_TRAMPOLINE_SIZE 24 133 | #define FFI_NATIVE_RAW_API 0 134 | #else 135 | #ifdef X86_WIN32 136 | #define FFI_TRAMPOLINE_SIZE 52 137 | #else 138 | #ifdef X86_WIN64 139 | #define FFI_TRAMPOLINE_SIZE 29 140 | #define FFI_NATIVE_RAW_API 0 141 | #define FFI_NO_RAW_API 1 142 | #else 143 | #define FFI_TRAMPOLINE_SIZE 10 144 | #endif 145 | #endif 146 | #ifndef X86_WIN64 147 | #define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ 148 | #endif 149 | #endif 150 | 151 | #endif 152 | 153 | 154 | 155 | #endif -------------------------------------------------------------------------------- /OCRunner/libffi/ffitarget_x86_64.h: -------------------------------------------------------------------------------- 1 | /* -----------------------------------------------------------------*-C-*- 2 | ffitarget.h - Copyright (c) 2012, 2014 Anthony Green 3 | Copyright (c) 1996-2003, 2010 Red Hat, Inc. 4 | Copyright (C) 2008 Free Software Foundation, Inc. 5 | 6 | Target configuration macros for x86 and x86-64. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | ``Software''), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | 28 | ----------------------------------------------------------------------- */ 29 | 30 | #ifndef LIBFFI_TARGET_H 31 | #define LIBFFI_TARGET_H 32 | 33 | #ifndef LIBFFI_H 34 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 35 | #endif 36 | 37 | /* ---- System specific configurations ----------------------------------- */ 38 | 39 | /* For code common to all platforms on x86 and x86_64. */ 40 | #define X86_ANY 41 | 42 | #if defined (X86_64) && defined (__i386__) 43 | #undef X86_64 44 | #define X86 45 | #endif 46 | 47 | #ifdef X86_WIN64 48 | #define FFI_SIZEOF_ARG 8 49 | #define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */ 50 | #endif 51 | 52 | #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 53 | #ifndef _MSC_VER 54 | #define FFI_TARGET_HAS_COMPLEX_TYPE 55 | #endif 56 | 57 | /* ---- Generic type definitions ----------------------------------------- */ 58 | 59 | #ifndef LIBFFI_ASM 60 | #ifdef X86_WIN64 61 | #ifdef _MSC_VER 62 | typedef unsigned __int64 ffi_arg; 63 | typedef __int64 ffi_sarg; 64 | #else 65 | typedef unsigned long long ffi_arg; 66 | typedef long long ffi_sarg; 67 | #endif 68 | #else 69 | #if defined __x86_64__ && defined __ILP32__ 70 | #define FFI_SIZEOF_ARG 8 71 | #define FFI_SIZEOF_JAVA_RAW 4 72 | typedef unsigned long long ffi_arg; 73 | typedef long long ffi_sarg; 74 | #else 75 | typedef unsigned long ffi_arg; 76 | typedef signed long ffi_sarg; 77 | #endif 78 | #endif 79 | 80 | typedef enum ffi_abi { 81 | #if defined(X86_WIN64) 82 | FFI_FIRST_ABI = 0, 83 | FFI_WIN64, 84 | FFI_LAST_ABI, 85 | FFI_DEFAULT_ABI = FFI_WIN64 86 | 87 | #elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) 88 | FFI_FIRST_ABI = 1, 89 | FFI_UNIX64, 90 | FFI_WIN64, 91 | FFI_EFI64 = FFI_WIN64, 92 | FFI_LAST_ABI, 93 | FFI_DEFAULT_ABI = FFI_UNIX64 94 | 95 | #elif defined(X86_WIN32) 96 | FFI_FIRST_ABI = 0, 97 | FFI_SYSV = 1, 98 | FFI_STDCALL = 2, 99 | FFI_THISCALL = 3, 100 | FFI_FASTCALL = 4, 101 | FFI_MS_CDECL = 5, 102 | FFI_PASCAL = 6, 103 | FFI_REGISTER = 7, 104 | FFI_LAST_ABI, 105 | FFI_DEFAULT_ABI = FFI_MS_CDECL 106 | #else 107 | FFI_FIRST_ABI = 0, 108 | FFI_SYSV = 1, 109 | FFI_THISCALL = 3, 110 | FFI_FASTCALL = 4, 111 | FFI_STDCALL = 5, 112 | FFI_PASCAL = 6, 113 | FFI_REGISTER = 7, 114 | FFI_MS_CDECL = 8, 115 | FFI_LAST_ABI, 116 | FFI_DEFAULT_ABI = FFI_SYSV 117 | #endif 118 | } ffi_abi; 119 | #endif 120 | 121 | /* ---- Definitions for closures ----------------------------------------- */ 122 | 123 | #define FFI_CLOSURES 1 124 | #define FFI_GO_CLOSURES 1 125 | 126 | #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) 127 | #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) 128 | #define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) 129 | #define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) 130 | 131 | #if defined (X86_64) || defined(X86_WIN64) \ 132 | || (defined (__x86_64__) && defined (X86_DARWIN)) 133 | # define FFI_TRAMPOLINE_SIZE 24 134 | # define FFI_NATIVE_RAW_API 0 135 | #else 136 | # define FFI_TRAMPOLINE_SIZE 12 137 | # define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ 138 | #endif 139 | 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /OCRunner/libffi/libffi.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/OCRunner/libffi/libffi.a -------------------------------------------------------------------------------- /OCRunnerArm64.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "OCRunnerArm64" 3 | s.version = "1.2.0" 4 | s.summary = "OCRunnerArm64" 5 | s.description = <<-DESC 6 | Only Support Arm64, Execute Objective-C code Dynamically. iOS hotfix SDK. 7 | DESC 8 | s.homepage = "https://github.com/SilverFruity/OCRunner" 9 | s.license = "MIT" 10 | s.author = { "SilverFruity" => "15328044115@163.com" } 11 | s.ios.deployment_target = "9.0" 12 | s.source = { :git => "https://github.com/SilverFruity/OCRunner.git", :tag => "#{s.version}" } 13 | s.source_files = "OCRunner/*.{h,m,c}","OCRunner/ORCoreImp/**/*.{h,m,c,s}","OCRunner/RunEnv/*.{h,m,c}","OCRunner/Util/*.{h,m,c}" 14 | s.pod_target_xcconfig = { 'VALID_ARCHS' => 'arm64 arm64e', 'VALID_ARCHS[sdk=iphonesimulator*]' => '' } 15 | s.dependency "ORPatchFile", "1.2.0" 16 | end 17 | 18 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo.xcodeproj/xcshareddata/xcschemes/OCRunnerDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | @property (nonatomic, strong) UIWindow *window; 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | #import 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | 21 | NSString *binaryPatchFilePath = [[NSBundle mainBundle] pathForResource:@"binarypatch" ofType:nil]; 22 | [ORInterpreter excuteBinaryPatchFile:binaryPatchFilePath]; 23 | 24 | // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 25 | // [ORInterpreter reverse]; 26 | // }); 27 | 28 | #if __x86_64__ && TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC 29 | NSLog(@"SIMULATOR"); 30 | #endif 31 | return YES; 32 | } 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/HotPath/HotViewcontroller.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | CGRect CGRectZero = CGRectMake(0, 0, 0, 0); 6 | 7 | typedef NS_ENUM(NSInteger, UITableViewStyle) { 8 | UITableViewStylePlain, // regular table view 9 | UITableViewStyleGrouped, // sections are grouped together 10 | UITableViewStyleInsetGrouped // grouped sections are inset with rounded corners 11 | }; 12 | 13 | typedef NS_ENUM(NSInteger, UITableViewCellSelectionStyle) { 14 | UITableViewCellSelectionStyleNone, 15 | UITableViewCellSelectionStyleBlue, 16 | UITableViewCellSelectionStyleGray, 17 | UITableViewCellSelectionStyleDefault 18 | }; 19 | 20 | @implementation OCRunnerDemo.SwiftViewController 21 | - (void)updateFrame:(NSObject *)arg arg1:(NSNumber *)arg1{ 22 | [self ORGupdateFrame:arg arg1:arg1]; 23 | NSLog(@"OC updateFrame %@ %@",arg,arg1); 24 | } 25 | @end 26 | 27 | @interface HotFixController : UIViewController 28 | @property (nonatomic, strong) UITableView *tableView; 29 | @property (nonatomic, copy) void (^block)(void); 30 | @end 31 | 32 | @implementation HotFixController 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | self.view.backgroundColor = [UIColor whiteColor]; 37 | [self.view addSubview:self.tableView]; 38 | self.tableView.backgroundColor = [UIColor redColor]; 39 | [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { 40 | make.left.bottom.right.top.mas_equalTo(self.view); 41 | }]; 42 | } 43 | 44 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 45 | return 0; 46 | } 47 | 48 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 49 | return nil; 50 | } 51 | 52 | - (UITableView *)tableView { 53 | if (!_tableView) { 54 | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:(UITableViewStyleGrouped)]; 55 | _tableView.delegate = self; 56 | _tableView.dataSource = self; 57 | _tableView.separatorStyle = UITableViewCellSelectionStyleNone; 58 | _tableView.showsVerticalScrollIndicator = NO; 59 | _tableView.estimatedRowHeight = 0; 60 | _tableView.estimatedSectionHeaderHeight = 0; 61 | _tableView.estimatedSectionFooterHeight = 0; 62 | _tableView.backgroundColor = [UIColor whiteColor]; 63 | __weak typeof(self) weakSelf = self; 64 | _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ 65 | __strong id strongSelf = weakSelf; 66 | [strongSelf.tableView.mj_header endRefreshing]; 67 | }]; 68 | [self.tableView.mj_header endRefreshingWithCompletionBlock:^{ 69 | __strong id strongSelf = weakSelf; 70 | strongSelf.block(); 71 | }]; 72 | } 73 | return _tableView; 74 | } 75 | - (void)dealloc{ 76 | NSLog(@"HotFixController dealloc"); 77 | } 78 | @end 79 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/HotPath/ViewController1.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | 12 | typedef NS_ENUM(NSInteger, UIBarButtonItemStyle) { 13 | UIBarButtonItemStylePlain, 14 | UIBarButtonItemStyleBordered, 15 | UIBarButtonItemStyleDone, 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) { 19 | WKNavigationActionPolicyCancel, 20 | WKNavigationActionPolicyAllow, 21 | WKNavigationActionPolicyDownload 22 | }; 23 | void cfunctionCallBlock(void (^block)(NSString *)){ 24 | if (block) block(@"cfunctionCallBlock"); 25 | } 26 | @interface ShareInstance: NSObject 27 | @property (nonatomic,copy)NSDictionary *cache; 28 | @end 29 | @implementation ShareInstance 30 | 31 | + (instancetype)shared{ 32 | static id _instance = nil; 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | _instance = [ShareInstance new]; 36 | }); 37 | return _instance; 38 | } 39 | - (instancetype)init 40 | { 41 | self = [super init]; 42 | self.cache = @{@"1":@"100",@"2":@"2"}; 43 | return self; 44 | } 45 | - (NSString *)cacheForKey:(NSString *)key{ 46 | return self.cache[key]; 47 | } 48 | @end 49 | 50 | 51 | @interface ViewController () 52 | 53 | @end 54 | 55 | @implementation ViewController 56 | 57 | 58 | - (void)viewDidLoad { 59 | [super viewDidLoad]; 60 | int *a = malloc(4); 61 | *a = 1; 62 | NSLog(@"a: %ld",*a); 63 | [@[@"1",@"2",@"3"] enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 64 | *stop = YES; 65 | NSLog(@"stop: %ld",*stop); 66 | NSLog(@"obj: %@",obj); 67 | }]; 68 | 69 | UIButton *swiftButton = [[UIButton alloc] initWithFrame:CGRectMake(150,150,200,40)]; 70 | [swiftButton setTitle:@"SwiftViewController" forState:UIControlStateNormal]; 71 | [swiftButton setTitleColor:UIColor.blueColor forState:UIControlStateNormal]; 72 | [swiftButton addTarget:self action:@selector(pushSwiftControlelr1) forControlEvents:UIControlEventTouchUpInside]; 73 | [self.view addSubview:swiftButton]; 74 | 75 | self.view.backgroundColor = UIColor.whiteColor; 76 | UIView *view = [[UIView alloc] init]; 77 | view.backgroundColor = [UIColor redColor]; 78 | [self.view addSubview:view]; 79 | [view mas_makeConstraints:^(MASConstraintMaker *make) { 80 | make.center.equalTo(self.view); 81 | make.width.equalTo(@(200)); 82 | make.height.equalTo(@(200)); 83 | }]; 84 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 85 | [UIView animateWithDuration:0.25 animations:^{ 86 | view.transform = CGAffineTransformScale(view.transform, 0.5, 0.5); 87 | }]; 88 | }); 89 | UIView *frameView = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 50, 50)]; 90 | frameView.backgroundColor = [UIColor greenColor]; 91 | [self.view addSubview:frameView]; 92 | 93 | UILabel *label = [UILabel new]; 94 | [self.view addSubview:label]; 95 | [label mas_makeConstraints:^(MASConstraintMaker *make) { 96 | make.centerX.equalTo(self.view); 97 | make.top.equalTo(self.view).offset(100); 98 | }]; 99 | label.text = [[ShareInstance shared] cacheForKey:@"1"]; 100 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"点击" style:UIBarButtonItemStylePlain target:self action:@selector(showNext:)]; 101 | NSLog(@"%@",@(-1)); 102 | 103 | id vc = [[UIApplication sharedApplication].keyWindow.rootViewController childViewControllers].firstObject; 104 | [vc updateFrame:[NSObject new] arg1:@(10)]; 105 | [self sendStackBlock]; 106 | [self receiveStackBlock:nil]; 107 | [self receiveStackBlock:^(NSString *str){ NSLog(@"%@",str); }]; 108 | cfunctionCallBlock(nil); 109 | cfunctionCallBlock(^(NSString *str){ NSLog(@"%@",str); }); 110 | [self ORGviewDidLoad]; 111 | } 112 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ 113 | decisionHandler(WKNavigationActionPolicyAllow); 114 | } 115 | - (void)receiveStackBlock:(void (^)(NSString *))block{ 116 | if (block) block(@"receiveStackBlock:"); 117 | } 118 | - (void)showNext:(UIBarButtonItem *)sender{ 119 | HotFixController *vc = [HotFixController new]; 120 | __weak id weakVC = vc; 121 | vc.block = ^{ 122 | __strong id strongSelf = weakVC; 123 | [weakVC.navigationController popViewControllerAnimated:YES]; 124 | NSLog(@"%@",$curScope.vars[@"strongSelf"]); 125 | }; 126 | vc.view.backgroundColor = [UIColor whiteColor]; 127 | [self.navigationController pushViewController:vc animated:YES]; 128 | NSLog(@"xxxxxxx%@", sender); 129 | } 130 | - (void)pushSwiftControlelr1{ 131 | UIViewController *vc = [[NSClassFromString(@"OCRunnerDemo.SwiftViewController1") alloc] init]; 132 | [self.navigationController pushViewController:vc animated:YES]; 133 | } 134 | 135 | @end 136 | 137 | int fibonaccia(int n){ 138 | if (n == 1 || n == 2) 139 | return 1; 140 | return fibonaccia(n - 1) + fibonaccia(n - 2); 141 | } 142 | fibonaccia(20); 143 | 144 | void mainFunc() { 145 | NSLog(@"call mainFunc"); 146 | } 147 | mainFunc(); 148 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleVersion 25 | 1 26 | LSRequiresIPhoneOS 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/OCRunnerDemo-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "ViewController.h" 6 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/PatchGenerator: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SilverFruity/OCRunner/bbb10975656eac156ce66d0b21a6dc2892ad6317/OCRunnerDemo/OCRunnerDemo/PatchGenerator -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SceneDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.m 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "SceneDelegate.h" 10 | 11 | @interface SceneDelegate () 12 | 13 | @end 14 | 15 | @implementation SceneDelegate 16 | 17 | 18 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 19 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 20 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 21 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 22 | } 23 | 24 | 25 | - (void)sceneDidDisconnect:(UIScene *)scene { 26 | // Called as the scene is being released by the system. 27 | // This occurs shortly after the scene enters the background, or when its session is discarded. 28 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 29 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 30 | } 31 | 32 | 33 | - (void)sceneDidBecomeActive:(UIScene *)scene { 34 | // Called when the scene has moved from an inactive state to an active state. 35 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 36 | } 37 | 38 | 39 | - (void)sceneWillResignActive:(UIScene *)scene { 40 | // Called when the scene will move from an active state to an inactive state. 41 | // This may occur due to temporary interruptions (ex. an incoming phone call). 42 | } 43 | 44 | 45 | - (void)sceneWillEnterForeground:(UIScene *)scene { 46 | // Called as the scene transitions from the background to the foreground. 47 | // Use this method to undo the changes made on entering the background. 48 | } 49 | 50 | 51 | - (void)sceneDidEnterBackground:(UIScene *)scene { 52 | // Called as the scene transitions from the foreground to the background. 53 | // Use this method to save data, release shared resources, and store enough scene-specific state information 54 | // to restore the scene back to its current state. 55 | } 56 | 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/Scripts.bundle/GCDRefrences: -------------------------------------------------------------------------------- 1 | typedef id dispatch_source_t; 2 | typedef id dispatch_group_t; 3 | typedef id dispatch_queue_t; 4 | typedef id dispatch_queue_global_t; 5 | typedef id dispatch_queue_main_t; 6 | typedef id dispatch_semaphore_t; 7 | typedef id dispatch_object_t; 8 | typedef long intptr_t; 9 | typedef long long dispatch_once_t; 10 | typedef uint64_t dispatch_time_t; 11 | 12 | typedef unsigned long uintptr_t; 13 | 14 | typedef enum: unsigned long{ 15 | DISPATCH_BLOCK_BARRIER = 0x1, 16 | DISPATCH_BLOCK_DETACHED = 0x2, 17 | DISPATCH_BLOCK_ASSIGN_CURRENT = 0x4, 18 | DISPATCH_BLOCK_NO_QOS_CLASS = 0x8, 19 | DISPATCH_BLOCK_INHERIT_QOS_CLASS = 0x10, 20 | DISPATCH_BLOCK_ENFORCE_QOS_CLASS = 0x20 21 | }dispatch_block_flags; 22 | 23 | typedef enum: unsigned int{ 24 | QOS_CLASS_USER_INTERACTIVE = 0x21, 25 | QOS_CLASS_USER_INITIATED = 0x19, 26 | QOS_CLASS_DEFAULT = 0x15, 27 | QOS_CLASS_UTILITY = 0x11, 28 | QOS_CLASS_BACKGROUND = 0x09, 29 | QOS_CLASS_UNSPECIFIED = 0x00 30 | }qos_class_t; 31 | 32 | typedef qos_class_t dispatch_qos_class_t; 33 | 34 | dispatch_queue_global_t 35 | dispatch_get_global_queue(long identifier, unsigned long flags); 36 | 37 | dispatch_queue_main_t 38 | dispatch_get_main_queue(void); 39 | 40 | dispatch_queue_t 41 | dispatch_queue_create(const char * label, dispatch_queue_attr_t attr); 42 | 43 | void 44 | dispatch_after(dispatch_time_t when, dispatch_queue_t queue, 45 | dispatch_block_t block); 46 | 47 | void 48 | dispatch_async(dispatch_queue_t queue, dispatch_block_t block); 49 | 50 | void 51 | dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); 52 | 53 | void 54 | dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); 55 | 56 | void 57 | dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); 58 | 59 | void 60 | dispatch_apply(size_t iterations, 61 | dispatch_queue_t queue, 62 | void (^block)(size_t)); 63 | 64 | dispatch_group_t 65 | dispatch_group_create(void); 66 | 67 | void 68 | dispatch_group_async(dispatch_group_t group, 69 | dispatch_queue_t queue, 70 | dispatch_block_t block); 71 | 72 | long 73 | dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout); 74 | 75 | void 76 | dispatch_group_notify(dispatch_group_t group, 77 | dispatch_queue_t queue, 78 | dispatch_block_t block); 79 | 80 | void 81 | dispatch_group_enter(dispatch_group_t group); 82 | 83 | void 84 | dispatch_group_leave(dispatch_group_t group); 85 | 86 | dispatch_block_t 87 | dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block); 88 | 89 | dispatch_block_t 90 | dispatch_block_create_with_qos_class(dispatch_block_flags_t flags, 91 | dispatch_qos_class_t qos_class, int relative_priority, 92 | dispatch_block_t block); 93 | 94 | void 95 | dispatch_block_perform(dispatch_block_flags_t flags, dispatch_block_t block); 96 | 97 | long 98 | dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout); 99 | 100 | void 101 | dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, 102 | dispatch_block_t notification_block); 103 | 104 | long 105 | dispatch_block_testcancel(dispatch_block_t block); 106 | 107 | void 108 | dispatch_block_cancel(dispatch_block_t block); 109 | 110 | 111 | dispatch_semaphore_t 112 | dispatch_semaphore_create(long value); 113 | 114 | long 115 | dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); 116 | 117 | long 118 | dispatch_semaphore_signal(dispatch_semaphore_t dsema); 119 | 120 | 121 | unsigned long long NSEC_PER_SEC = 1000000000; 122 | unsigned long long NSEC_PER_MSEC = 1000000; 123 | unsigned long long USEC_PER_SEC = 1000000; 124 | unsigned long long NSEC_PER_USEC = 1000; 125 | 126 | unsigned long long DISPATCH_TIME_NOW = 0; 127 | unsigned long long DISPATCH_TIME_FOREVER = ~0; 128 | 129 | dispatch_time_t 130 | dispatch_time(dispatch_time_t when, int64_t delta); 131 | 132 | void 133 | dispatch_resume(dispatch_object_t object); 134 | 135 | void 136 | dispatch_suspend(dispatch_object_t object); 137 | 138 | dispatch_source_t 139 | dispatch_source_create(dispatch_source_type_t type, 140 | uintptr_t handle, 141 | unsigned long mask, 142 | dispatch_queue_t _Nullable queue); 143 | 144 | void 145 | dispatch_source_set_event_handler(dispatch_source_t source, 146 | dispatch_block_t _Nullable handler); 147 | 148 | void 149 | dispatch_source_set_cancel_handler(dispatch_source_t source, 150 | dispatch_block_t _Nullable handler); 151 | 152 | void 153 | dispatch_source_cancel(dispatch_source_t source); 154 | 155 | long 156 | dispatch_source_testcancel(dispatch_source_t source); 157 | 158 | uintptr_t 159 | dispatch_source_get_handle(dispatch_source_t source); 160 | 161 | unsigned long 162 | dispatch_source_get_mask(dispatch_source_t source); 163 | 164 | unsigned long 165 | dispatch_source_get_data(dispatch_source_t source); 166 | 167 | void 168 | dispatch_source_merge_data(dispatch_source_t source, unsigned long value); 169 | 170 | void 171 | dispatch_source_set_timer(dispatch_source_t source, 172 | dispatch_time_t start, 173 | uint64_t interval, 174 | uint64_t leeway); 175 | 176 | void 177 | dispatch_source_set_registration_handler(dispatch_source_t source, 178 | dispatch_block_t _Nullable handler); 179 | 180 | void * malloc(int __size); 181 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/SwiftViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftViewController.swift 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2021/4/9. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SwiftViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.view.backgroundColor = UIColor.white; 16 | if self.navigationController?.viewControllers.count ?? 1 == 1 { 17 | let vc = ViewController.init() 18 | self.navigationController?.pushViewController(vc, animated: true) 19 | } 20 | } 21 | @objc dynamic func updateFrame(_ arg: NSObject, arg1: NSNumber){ 22 | print("\(self): call swift @objc updateFrame arg:\(arg) arg1: \(arg1)") 23 | } 24 | 25 | /* 26 | // MARK: - Navigation 27 | 28 | // In a storyboard-based application, you will often want to do a little preparation before navigation 29 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 30 | // Get the new view controller using segue.destination. 31 | // Pass the selected object to the new view controller. 32 | } 33 | */ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/SwiftViewController1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftViewController1.swift 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2021/4/29. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SwiftViewController1: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | 20 | /* 21 | // MARK: - Navigation 22 | 23 | // In a storyboard-based application, you will often want to do a little preparation before navigation 24 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 25 | // Get the new view controller using segue.destination. 26 | // Pass the selected object to the new view controller. 27 | } 28 | */ 29 | 30 | } 31 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/SwiftViewController1.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | #import 13 | 14 | @interface ShareInstance: NSObject 15 | @property (nonatomic,copy)NSDictionary *cache; 16 | @end 17 | @implementation ShareInstance 18 | 19 | + (instancetype)shared{ 20 | static id _instance = nil; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | _instance = [ShareInstance new]; 24 | }); 25 | return _instance; 26 | } 27 | - (instancetype)init 28 | { 29 | self = [super init]; 30 | self.cache = @{@"1":@"0",@"2":@"2"}; 31 | return self; 32 | } 33 | - (NSString *)cacheForKey:(NSString *)key{ 34 | return self.cache[key]; 35 | } 36 | @end 37 | 38 | 39 | @interface ViewController () 40 | @property (nonatomic, strong)WKWebView *webView; 41 | @end 42 | 43 | @implementation ViewController 44 | 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | WKWebView *webView = [WKWebView new]; 49 | webView.navigationDelegate = self; 50 | [self.view addSubview:webView]; 51 | [webView mas_makeConstraints:^(MASConstraintMaker *make) { 52 | make.width.height.equalTo(@(150)); 53 | make.right.equalTo(self.view); 54 | make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom); 55 | }]; 56 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]]; 57 | } 58 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ 59 | decisionHandler(WKNavigationActionPolicyAllow); 60 | } 61 | - (void)sendStackBlock{ 62 | __weak typeof(self) weakSelf = self; 63 | [self receiveStackBlock:^(NSString *str) { 64 | NSLog(@"%@",weakSelf); 65 | NSLog(@"%@",str); 66 | }]; 67 | [self receiveStackBlock:^(NSString *str) { 68 | NSLog(@"global block %@",str); 69 | }]; 70 | } 71 | - (void)receiveStackBlock:(void (^)(NSString *str))block{ 72 | if (block) { 73 | block(@"123"); 74 | } 75 | } 76 | - (void)showNext:(UIBarButtonItem *)sender{ 77 | UIViewController *vc = [NSClassFromString(@"HotFixController") new]; 78 | if (vc) { 79 | [self.navigationController pushViewController:vc animated:YES]; 80 | } 81 | } 82 | @end 83 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OCRunnerDemo 4 | // 5 | // Created by Jiang on 2020/5/23. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemoTests/OCRunnerDemoTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "ORTestReplaceClass.h" 6 | #import "ORTestClassProperty.h" 7 | #import "ORTestClassIvar.h" 8 | #import "ORCallOCPropertyBlockTest.h" 9 | #import "ORCallSuperNoArgTest.h" 10 | #import "ORGCDTests.h" 11 | #import "ORWeakPropertyAndIvar.h" 12 | #import "ORParserForTest.h" 13 | 14 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemoTests/ORParserForTest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORParserForTest.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by APPLE on 2021/6/16. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORParserForTest : Parser 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /OCRunnerDemo/OCRunnerDemoTests/ORParserForTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORParserForTest.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by APPLE on 2021/6/16. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORParserForTest.h" 10 | 11 | @implementation ORParserForTest 12 | - (AST *)parseCodeSource:(CodeSource *)source{ 13 | [super parseCodeSource:source]; 14 | do { 15 | NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; 16 | NSString *filePath = [cachePath stringByAppendingPathComponent:@"BinaryPatch.png"]; 17 | ORPatchFile *file = [[ORPatchFile alloc] initWithNodes:GlobalAst.nodes]; 18 | filePath = [file dumpAsBinaryPatch:filePath]; 19 | ORPatchFile *newFile = [ORPatchFile loadBinaryPatch:filePath]; 20 | if (newFile) { 21 | GlobalAst = [AST new]; 22 | [GlobalAst merge:newFile.nodes]; 23 | } 24 | } while (0); 25 | return GlobalAst; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /OCRunnerDemo/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | source 'https://github.com/CocoaPods/Specs.git' 3 | platform :ios, '11.0' 4 | 5 | target 'OCRunnerDemo' do 6 | # Comment the next line if you don't want to use dynamic frameworks 7 | use_frameworks! 8 | pod 'MJRefresh' 9 | pod 'MJExtension' 10 | pod 'Masonry' 11 | pod 'ORPatchFile', :path => '../oc2mango' 12 | pod 'OCRunner', :path => '../' 13 | target 'OCRunnerDemoTests' do 14 | inherit! :search_paths 15 | pod 'oc2mangoLib', :path => '../oc2mango' 16 | pod 'MJExtension' 17 | end 18 | 19 | end 20 | 21 | 22 | post_install do |installer| 23 | installer.generated_projects.each do |project| 24 | project.targets.each do |target| 25 | target.build_configurations.each do |config| 26 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /OCRunnerDemo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Masonry (1.1.0) 3 | - MJExtension (3.4.0) 4 | - MJRefresh (3.7.2) 5 | - oc2mangoLib (1.2.1): 6 | - ORPatchFile (= 1.2.2) 7 | - OCRunner (1.2.12): 8 | - ORPatchFile (= 1.2.2) 9 | - ORPatchFile (1.2.2) 10 | 11 | DEPENDENCIES: 12 | - Masonry 13 | - MJExtension 14 | - MJRefresh 15 | - oc2mangoLib (from `../oc2mango`) 16 | - OCRunner (from `../`) 17 | - ORPatchFile (from `../oc2mango`) 18 | 19 | SPEC REPOS: 20 | https://github.com/CocoaPods/Specs.git: 21 | - Masonry 22 | - MJExtension 23 | - MJRefresh 24 | 25 | EXTERNAL SOURCES: 26 | oc2mangoLib: 27 | :path: "../oc2mango" 28 | OCRunner: 29 | :path: "../" 30 | ORPatchFile: 31 | :path: "../oc2mango" 32 | 33 | SPEC CHECKSUMS: 34 | Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 35 | MJExtension: 6c15c7b93398447252c0defdb8d69d02d218a41e 36 | MJRefresh: 30997d30b347c8e9508a4db11e3a690da0c9b85a 37 | oc2mangoLib: f24f75a921e2e8e5f3ae9f4bb95156d20224e868 38 | OCRunner: 999fa1088df2d8508935d10a6c41215ce0b316b8 39 | ORPatchFile: 64d0ffc7eeb96374c901dc2873903b99d36e9bbe 40 | 41 | PODFILE CHECKSUM: d046c5d40020c3b90c89a244ebcf4e5d41a68fed 42 | 43 | COCOAPODS: 1.12.0 44 | -------------------------------------------------------------------------------- /OCRunnerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /OCRunnerTests/OCRunnerTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | //#import 5 | #import "ORTestReplaceClass.h" 6 | #import "ORTestClassProperty.h" 7 | #import "ORTestClassIvar.h" 8 | #import "ORCallOCPropertyBlockTest.h" 9 | #import "ORCallSuperNoArgTest.h" 10 | #import "ORGCDTests.h" 11 | -------------------------------------------------------------------------------- /OCRunnerTests/ORCoreFunctionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORCoreFunctionTests.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2020/7/17. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | @interface ORCoreFunctionTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ORCoreFunctionTests 17 | 18 | - (void)setUp { 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | } 25 | int functionCall1(){ 26 | return 100; 27 | } 28 | - (void)testFunctionCallReturn{ 29 | MFValue * result = [MFValue defaultValueWithTypeEncoding:"i"]; 30 | void *funcptr = &functionCall1; 31 | invoke_functionPointer(funcptr, @[], result); 32 | int intValue = *(int *)result.pointer; 33 | XCTAssert(intValue == 100); 34 | } 35 | - (void)testCallStructPointer{ 36 | MFValue *result = [MFValue defaultValueWithTypeEncoding:@encode(CGAffineTransform)]; 37 | ORStructDeclare *declare = [ORStructDeclare structDecalre:@encode(CGAffineTransform) keys:@[@"a",@"b",@"c",@"d",@"tx",@"ty"]]; 38 | [[ORTypeSymbolTable shareInstance] addStruct:declare]; 39 | void *funcptr = &CGAffineTransformScale; 40 | invoke_functionPointer(funcptr, @[[[MFValue alloc] initTypeEncode:@encode(CGAffineTransform) pointer:&CGAffineTransformIdentity], 41 | [MFValue valueWithDouble:0.5], 42 | [MFValue valueWithDouble:0.5]], result); 43 | } 44 | - (void)testCallMultiFunctionPointer{ 45 | MFValue *result = [MFValue voidValue]; 46 | void *funcptr = &NSLog; 47 | invoke_functionPointer(funcptr, @[[MFValue valueWithObject:@"%@"],[MFValue valueWithObject:@"123"]], result, 1); 48 | } 49 | 50 | - (void)testCallFunctionPointer{ 51 | ORStructDeclare *rectDecl = [ORStructDeclare structDecalre:@encode(CGRect) keys:@[@"origin",@"size"]]; 52 | ORStructDeclare *pointDecl = [ORStructDeclare structDecalre:@encode(CGPoint) keys:@[@"x",@"y"]]; 53 | ORStructDeclare *sizeDecl = [ORStructDeclare structDecalre:@encode(CGSize) keys:@[@"width",@"height"]]; 54 | 55 | [[ORTypeSymbolTable shareInstance] addStruct:rectDecl]; 56 | [[ORTypeSymbolTable shareInstance] addStruct:pointDecl]; 57 | [[ORTypeSymbolTable shareInstance] addStruct:sizeDecl]; 58 | 59 | MFValue *result1 = [MFValue defaultValueWithTypeEncoding:@encode(CGRect)]; 60 | void *funcptr = &CGRectMake; 61 | invoke_functionPointer(funcptr, @[[MFValue valueWithDouble:1], 62 | [MFValue valueWithDouble:2], 63 | [MFValue valueWithDouble:3], 64 | [MFValue valueWithDouble:4]], result1); 65 | CGRect rect1 = *(CGRect *)result1.pointer; 66 | XCTAssert(CGRectEqualToRect(CGRectMake(1, 2, 3, 4), rect1)); 67 | 68 | 69 | UIView *view = [UIView new]; 70 | CGRect rect = CGRectMake(1, 2, 3, 4); 71 | MFValue *result = [MFValue voidValue]; 72 | void *funcptr1 = &objc_msgSend; 73 | invoke_functionPointer(funcptr1, @[[MFValue valueWithObject:view], 74 | [MFValue valueWithSEL:@selector(setFrame:)], 75 | [[MFValue alloc] initTypeEncode:@encode(CGRect) pointer:&rect]], result); 76 | 77 | XCTAssert(CGRectEqualToRect(view.frame, rect)); 78 | } 79 | 80 | void testRegister1(ffi_cif *cif, void* ret, void **args, void *userdata){ 81 | MFValue *ivalue = [MFValue valueWithTypeEncode:OCTypeStringInt pointer:args[0]]; 82 | MFValue *fvalue = [MFValue valueWithTypeEncode:OCTypeStringFloat pointer:args[1]]; 83 | assert(ivalue.intValue == 100); 84 | float temp = 0.1; 85 | assert(fvalue.floatValue == temp); 86 | *(int *)ret = 100; 87 | } 88 | - (void)testRegisterFunctionCall{ 89 | int (*func)(int a, float b) = register_function(&testRegister1, @[[ORTypeVarPair typePairWithTypeKind:TypeInt] 90 | ,[ORTypeVarPair typePairWithTypeKind:TypeFloat]], 91 | [ORTypeVarPair typePairWithTypeKind:TypeInt])->function_imp; 92 | int res = func(100, 0.1); 93 | XCTAssert(res == 100); 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORCallOCPropertyBlockTest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCallOCPropertyBlockTest.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORCallOCPropertyBlockTest : NSObject 14 | @property(copy,nonatomic) id(^propertyBlock)(id,id); 15 | - (NSString *)testCallOCReturnBlock; 16 | 17 | - (NSDictionary *)testCapture; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORCallOCPropertyBlockTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORCallOCPropertyBlockTest.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORCallOCPropertyBlockTest.h" 10 | 11 | @implementation ORCallOCPropertyBlockTest 12 | - (instancetype)init{ 13 | if (self = [super init]) { 14 | _propertyBlock = ^(id arg1,id arg2){ 15 | return [NSString stringWithFormat:@"%@%@",arg1,arg2]; 16 | }; 17 | } 18 | return self; 19 | } 20 | 21 | - (NSString * (^)(id,id))returnBlockMethod{ 22 | id block = ^(id arg1,id arg2){ 23 | return [NSString stringWithFormat:@"%@%@",arg1,arg2]; 24 | }; 25 | return block; 26 | } 27 | 28 | - (id)testCallOCReturnBlock{ 29 | return nil; 30 | } 31 | @end 32 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORCallSuperNoArgTest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCallSuperNoArgTest.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | 14 | @interface MFCallSuperNoArgTestSupserTest : NSObject 15 | 16 | - (BOOL)testCallSuperNoArgTestSupser; 17 | 18 | @property(nonatomic, assign, getter=customGetterTest, setter=customSetterTest:) BOOL test; 19 | 20 | @end 21 | 22 | @interface MFCallSuperNoArgTest : MFCallSuperNoArgTestSupserTest 23 | 24 | - (BOOL)testCallSuperNoArgTestSupser; 25 | 26 | @end 27 | 28 | @interface Car : NSObject 29 | 30 | - (int)run; 31 | 32 | @end 33 | 34 | @interface BMW : Car 35 | 36 | - (int)run; 37 | 38 | @end 39 | 40 | @interface MiniBMW : BMW 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORCallSuperNoArgTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORCallSuperNoArgTest.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORCallSuperNoArgTest.h" 10 | 11 | 12 | 13 | @implementation MFCallSuperNoArgTestSupserTest 14 | 15 | - (BOOL)testCallSuperNoArgTestSupser{ 16 | return NO; 17 | } 18 | 19 | @end 20 | 21 | @implementation MFCallSuperNoArgTest 22 | 23 | - (BOOL)testCallSuperNoArgTestSupser{ 24 | return [super testCallSuperNoArgTestSupser]; 25 | } 26 | 27 | @end 28 | 29 | #pragma mark - Car 30 | 31 | @implementation Car 32 | 33 | - (int)run 34 | { 35 | return 0; 36 | } 37 | 38 | @end 39 | 40 | #pragma mark - BMW 41 | 42 | @implementation BMW 43 | 44 | - (int)run 45 | { 46 | return 1; 47 | } 48 | 49 | @end 50 | 51 | #pragma mark - MiniBMW 52 | 53 | @implementation MiniBMW 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORGCDTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORORGCDTests.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/20. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORGCDTests : NSObject 14 | + (instancetype)sharedInstance; 15 | - (void)testGCDWithCompletionBlock:(void(^)(NSString * data))completion; 16 | - (void)testGCDAfterWithCompletionBlock:(void(^)(NSString * data))completion; 17 | - (BOOL)testDispatchSemaphore; 18 | - (NSInteger)testDispatchSource; 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORGCDTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORORGCDTests.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/20. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORGCDTests.h" 10 | 11 | @implementation ORGCDTests 12 | - (void)testGCDWithCompletionBlock:(void (^)(NSString * _Nonnull))completion{ 13 | 14 | } 15 | 16 | - (void)testGCDAfterWithCompletionBlock:(void (^)(NSString * _Nonnull))completion{ 17 | 18 | } 19 | - (BOOL)testDispatchSemaphore{ 20 | return NO; 21 | } 22 | -(NSInteger)testDispatchSource{ 23 | return 0; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORHookNatvieMultiSuperCall.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORHookNatvieMultiSuperCall.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2022/8/15. 6 | // Copyright © 2022 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NativeFinalObject: NSObject 14 | - (int)test:(int)count; 15 | @end 16 | @interface NativeHotBaseController: NativeFinalObject 17 | @end 18 | @interface NativeViewController3 : NativeHotBaseController 19 | @end 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORHookNatvieMultiSuperCall.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORHookNatvieMultiSuperCall.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2022/8/15. 6 | // Copyright © 2022 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORHookNatvieMultiSuperCall.h" 10 | 11 | @implementation NativeFinalObject 12 | - (int)test:(int)count { 13 | return count + 1; 14 | } 15 | @end 16 | 17 | 18 | @implementation NativeHotBaseController 19 | - (int)test:(int)count { 20 | return [super test:count + 1]; 21 | } 22 | @end 23 | 24 | @implementation NativeViewController3 25 | - (int)test:(int)count { 26 | return [super test:count + 1]; 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORRecoverClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORRecoverClass.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2021/2/23. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORRecoverClass : NSObject 14 | @property (nonatomic, assign)int value1; 15 | @property (nonatomic, copy)NSString *value2; 16 | + (int)classMethodTest; 17 | - (int)methodTest1; 18 | - (int)methodTest2; 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORRecoverClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORRecoverClass.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2021/2/23. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORRecoverClass.h" 10 | 11 | @implementation ORRecoverClass 12 | + (int)classMethodTest{ 13 | return 1; 14 | } 15 | - (int)methodTest1{ 16 | return 1; 17 | } 18 | - (int)methodTest2{ 19 | return 1; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestClassIvar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestClassIvar.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORTestClassIvar : NSObject 14 | { 15 | @public 16 | NSString *_objectIvar; 17 | int _intIvar; 18 | unsigned int _uintIvar; 19 | double _doubleIvar; 20 | __strong id _object; 21 | } 22 | - (void)ivarRefrenceCount:(id)object; 23 | - (nullable NSString *)testObjectIvar; 24 | - (int)testIntIvar; 25 | - (unsigned int)testUIntIvar; 26 | - (double)testDoubleIvar; 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestClassIvar.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestClassIvar.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORTestClassIvar.h" 10 | 11 | @implementation ORTestClassIvar 12 | - (void)ivarRefrenceCount:(id)object{ 13 | _object = object; 14 | } 15 | - (id)testObjectIvar{ 16 | return nil; 17 | } 18 | - (int)testIntIvar{ 19 | return 0; 20 | } 21 | - (unsigned int)testUIntIvar{ 22 | return 0; 23 | } 24 | - (double)testDoubleIvar{ 25 | return 0; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestClassProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestClassProperty.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORTestClassProperty : NSObject 14 | @property(nonatomic,copy)NSString *strTypeProperty; 15 | @property (assign, nonatomic) NSInteger num; 16 | - (instancetype)initDeallocFlag:(NSMutableString *)flag; 17 | - (NSString *)testObjectPropertyTest; 18 | - (NSString *)testIvarx; 19 | - (NSInteger)testProMathAdd; 20 | 21 | - (NSInteger)testBasePropertyTest; 22 | - (NSInteger)testPropertyIvar; 23 | - (nullable id)testWeakObject; 24 | - (nullable NSString *)testStrongObject; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestClassProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestClassProperty.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/15. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORTestClassProperty.h" 10 | 11 | @implementation ORTestClassProperty 12 | { 13 | NSMutableString *_flag; 14 | } 15 | - (instancetype)initDeallocFlag:(NSMutableString *)flag{ 16 | self = [super init]; 17 | _flag = flag; 18 | return self; 19 | } 20 | - (NSString *)testObjectPropertyTest{ 21 | return nil; 22 | } 23 | - (NSString *)testIvarx{ 24 | return @""; 25 | } 26 | - (NSInteger)testProMathAdd{ 27 | return 0; 28 | } 29 | -(NSInteger)testBasePropertyTest{ 30 | return 0; 31 | } 32 | - (NSInteger)testPropertyIvar{ 33 | return 0; 34 | } 35 | - (void)dealloc 36 | { 37 | [_flag appendString:@"has_dealloc"]; 38 | } 39 | @end 40 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestORGDealloc.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestORGDealloc.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2023/7/29. 6 | // Copyright © 2023 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORTestORGDealloc : NSObject 14 | @property (nonatomic, assign)int *counter; 15 | - (instancetype)initWithCounter:(int *)counter; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestORGDealloc.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestORGDealloc.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2023/7/29. 6 | // Copyright © 2023 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORTestORGDealloc.h" 10 | 11 | @implementation ORTestORGDealloc 12 | - (instancetype)initWithCounter:(int *)counter { 13 | self = [super init]; 14 | _counter = counter; 15 | return self; 16 | } 17 | 18 | - (void)dealloc { 19 | *_counter += 10; 20 | } 21 | @end 22 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestReplaceClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestReplaceClass.h 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/14. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORTestReplaceClass : NSObject 14 | - (int)test; 15 | - (int)arg1:(NSNumber *)arg1; 16 | - (int)arg1:(NSNumber *)arg1 arg2:(NSNumber *)arg2; 17 | - (void *)valueAdress; 18 | + (BOOL)testClassMethodReplaceTest; 19 | - (NSInteger)testOriginalMethod; 20 | - (NSInteger)testAddGlobalVar; 21 | - (NSDictionary *(^)(void))testMethodParameterListAndReturnValueWithString:(NSString *)str block:(NSString *(^)(NSString *))block; 22 | - (int)testNoSignatureBlock:(int(^)(int))arg; 23 | - (NSString *)testInputStackBlock; 24 | - (void)receiveStackBlock:(void (^)(NSString *str))block; 25 | 26 | - (void)test6ArgsMethoCall:(int)arg1 arg2:(int)arg2 arg3:(int)arg3 arg4:(int)arg4 arg5:(int)arg5 arg6:(int)arg6; 27 | - (int)scriptReceiveCArray:(int *)array len:(int)len; 28 | - (int)receiveCArray:(int *)array len:(int)len; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORTestReplaceClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORTestReplaceClass.m 3 | // OCRunnerTests 4 | // 5 | // Created by Jiang on 2020/5/14. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORTestReplaceClass.h" 10 | 11 | @implementation ORTestReplaceClass 12 | - (int)test{ 13 | return 0; 14 | } 15 | - (int)arg1:(NSNumber *)arg1{ 16 | return 0; 17 | } 18 | - (int)arg1:(NSNumber *)arg1 arg2:(NSNumber *)arg2{ 19 | return 0; 20 | } 21 | + (BOOL)testClassMethodReplaceTest{ 22 | return NO; 23 | } 24 | - (NSInteger)testOriginalMethod{ 25 | return 1; 26 | } 27 | - (NSInteger)testAddGlobalVar{ 28 | return 1; 29 | } 30 | - (NSDictionary* (^)(void))testMethodParameterListAndReturnValueWithString:(NSString *)str block:(NSString *(^)(NSString *))block{ 31 | return nil; 32 | } 33 | - (int)testNoSignatureBlock:(int(^)(int))arg{ 34 | return 0; 35 | } 36 | - (NSString *)testInputStackBlock{ 37 | __block NSString *result = @""; 38 | __weak typeof(self) weakSelf = self; 39 | [self receiveStackBlock:^(NSString * _Nonnull str) { 40 | result = str; 41 | NSLog(@"%@",weakSelf); 42 | }]; 43 | return result; 44 | } 45 | - (void)receiveStackBlock:(void (^)(NSString *str))block{ 46 | block(@"123"); 47 | } 48 | - (void)test6ArgsMethoCall:(int)arg1 arg2:(int)arg2 arg3:(int)arg3 arg4:(int)arg4 arg5:(int)arg5 arg6:(int)arg6{ 49 | } 50 | - (int)scriptReceiveCArray:(int *)array len:(int)len{ 51 | return 0; 52 | } 53 | - (int)receiveCArray:(int *)array len:(int)len{ 54 | int r = 0; 55 | for (int i = 0; i < len; i++) { 56 | r += array[i]; 57 | } 58 | return r; 59 | } 60 | @end 61 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORWeakPropertyAndIvar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORWeakPropertyAndIvar.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2020/12/9. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORWeakPropertyAndIvar : NSObject 14 | @property (nonatomic, strong)NSMutableString *container; 15 | - (instancetype)initWithContainer:(NSMutableString *)container; 16 | - (void)propertyStrong; 17 | - (void)propertyWeak; 18 | - (void)ivarStrong; 19 | - (void)ivarWeak; 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/ORWeakPropertyAndIvar.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORWeakPropertyAndIvar.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by Jiang on 2020/12/9. 6 | // Copyright © 2020 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "ORWeakPropertyAndIvar.h" 10 | 11 | @implementation ORWeakPropertyAndIvar 12 | - (instancetype)initWithContainer:(NSMutableString *)container 13 | { 14 | self = [super init]; 15 | if (self) { 16 | self.container = container; 17 | } 18 | return self; 19 | } 20 | - (void)dealloc 21 | { 22 | [self.container appendString:@"dealloc"]; 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/TestFakeModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestFakeModel.h 3 | // OCRunnerDemoTests 4 | // 5 | // Created by carefree on 2021/11/25. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TestFakeSubModel : NSObject 14 | 15 | @property (nonatomic, assign) CGFloat numberToFloat; 16 | @property (nonatomic, copy) NSString *numberToString; 17 | @property (nonatomic, assign) NSInteger stringToInteger; 18 | 19 | @end 20 | 21 | @interface TestFakeModel : NSObject 22 | @property (nonatomic, assign) NSInteger numberToInteger; 23 | @property (nonatomic, copy) NSString *numberToString; 24 | @property (nonatomic, strong) TestFakeSubModel *sub; 25 | @end 26 | 27 | @interface TestFakeModel (TestProperty) 28 | @property (nonatomic, assign) int categoryProperty; 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /OCRunnerTests/TestClass/TestFakeModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestFakeModel.m 3 | // OCRunnerDemoTests 4 | // 5 | // Created by carefree on 2021/11/25. 6 | // Copyright © 2021 SilverFruity. All rights reserved. 7 | // 8 | 9 | #import "TestFakeModel.h" 10 | 11 | @implementation TestFakeSubModel 12 | 13 | @end 14 | 15 | @implementation TestFakeModel 16 | 17 | @end 18 | --------------------------------------------------------------------------------