├── .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 |
--------------------------------------------------------------------------------