├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_en.md
├── docs
├── _config.yml
├── images
│ ├── architecture.png
│ └── logo.png
└── sponsor
│ ├── weixin.JPG
│ └── zhifubao.JPG
├── huatuo
├── CommonDef.cpp
├── CommonDef.h
├── HuatuoApi.cpp
├── HuatuoConfig.cpp
├── HuatuoConfig.h
├── ModuleManager.cpp
├── ModuleManager.h
├── interpreter
│ ├── Engine.cpp
│ ├── Engine.h
│ ├── InstrinctDef.h
│ ├── Instruction.cpp
│ ├── Instruction.h
│ ├── Interpreter.cpp
│ ├── Interpreter.h
│ ├── InterpreterDefs.cpp
│ ├── InterpreterDefs.h
│ ├── InterpreterModule.cpp
│ ├── InterpreterModule.h
│ ├── Interpreter_Execute.cpp
│ ├── MemoryUtil.h
│ ├── MethodBridge.cpp
│ ├── MethodBridge.h
│ ├── MethodBridge_arm64.cpp
│ └── MethodBridge_x64.cpp
├── metadata
│ ├── AOTHomologousImage.cpp
│ ├── AOTHomologousImage.h
│ ├── Assembly.cpp
│ ├── Assembly.h
│ ├── BlobReader.h
│ ├── Coff.h
│ ├── Image.cpp
│ ├── Image.h
│ ├── InterpreterImage.cpp
│ ├── InterpreterImage.h
│ ├── MetadataDef.h
│ ├── MetadataModule.cpp
│ ├── MetadataModule.h
│ ├── MetadataUtil.cpp
│ ├── MetadataUtil.h
│ ├── Opcodes.cpp
│ ├── Opcodes.h
│ ├── RawImage.cpp
│ ├── RawImage.h
│ ├── Tables.h
│ ├── VTableSetup.cpp
│ └── VTableSetup.h
└── transform
│ ├── BasicBlockSpliter.cpp
│ ├── BasicBlockSpliter.h
│ ├── TemporaryMemoryArena.cpp
│ ├── TemporaryMemoryArena.h
│ ├── Transform.cpp
│ └── Transform.h
└── scripts
└── iOSBuild
├── CMakeLists.txt
├── external
└── CMakeLists.txt
├── gen_lump.sh
└── objective
└── CMakeLists.txt
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: ['https://raw.githubusercontent.com/focus-creative-games/huatuo/main/docs/sponsor/weixin.JPG','https://raw.githubusercontent.com/focus-creative-games/huatuo/main/docs/sponsor/zhifubao.JPG']
14 |
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /huatuo/test
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 focus-creative-games
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # huatuo
3 |
4 | [](https://github.com/focus-creative-games/huatuo/blob/main/LICENSE)
5 |
6 |
7 |
8 | 
9 |
10 |
11 |
12 | huatuo是一个**特性完整、零成本、高性能、低内存**的**近乎完美**的Unity全平台原生c#热更方案。
13 |
14 | huatuo扩充了il2cpp的代码,使它由纯[AOT](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) runtime变成‘AOT+Interpreter’ 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以**AOT+interpreter**混合模式执行。从底层彻底支持了热更新。
15 |
16 | huatuo**开创性地实现了 `differential hybrid dll` 技术**====。即可以对AOT dll任意增删改,huatuo会智能地让变化或者新增的类和函数以interpreter模式运行,但未改动的类和函数以AOT方式运行,让热更新的游戏逻辑的运行性能基本达到原生AOT的水平。
17 |
18 | ## 特性
19 |
20 | - 特性完整。 近乎完整实现了[ECMA-335规范](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/),除了 下文中"限制和注意事项" 之外的特性都支持。
21 | - 零学习和使用成本。 huatuo将纯AOT runtime增强为完整的runtime,使得热更新代码与AOT代码无缝工作。脚本类与AOT类在同一个运行时内,可以随意写继承、反射、多线程(volatile、ThreadStatic、Task、async)之类的代码。不需要额外写任何特殊代码、没有代码生成,也没有什么特殊限制。
22 | - 执行高效。实现了一个极其高效的寄存器解释器,所有指标都大幅优于其他热更新方案。[性能测试报告](https://xxx/huatuo/performance/benchmark/#性能测试报告)
23 | - 内存高效。 热更新脚本中定义的类跟普通c#类占用一样的内存空间,远优于其他热更新方案。[内存占用报告](https://xxx/huatuo/performance/benchmark/#内存占用报告)
24 | - 原生支持hotfix修复AOT部分代码。几乎不增加任何开发和运行开销。
25 | - **开创性地实现了 `differential hybrid dll` 技术**。即可以将某个热更新dll先AOT形式打包,后面可以对该dll任意增删改,huatuo会智能地让变化或者新增的类和函数以interpreter模式运行,但未改动的类和函数以AOT方式运行。这意味着热更新的游戏逻辑的运行性能将接近原生AOT的水平。
26 |
27 | ## 工作原理
28 |
29 | huatuo从mono的[hybrid mode execution](https://developpaper.com/new-net-interpreter-mono-has-arrived/)技术中得到启发,为unity的il2cpp之类的AOT runtime额外提供了interpreter模块,将它们由纯AOT运行时改造为"AOT + Interpreter"混合运行方式。
30 |
31 | 
32 |
33 | 更具体地说,huatuo做了以下几点工作:
34 |
35 | - 实现了一个高效的元数据(dll)解析库
36 | - 改造了元数据管理模块,实现了元数据的动态注册
37 | - 实现了一个IL指令集到自定义的寄存器指令集的compiler
38 | - 实现了一个高效的寄存器解释器
39 | - 额外提供大量的instinct函数,提升解释器性能
40 | - 提供hotfix AOT的支持
41 |
42 | ## 与其他流行的c#热更新方案的区别
43 |
44 | ### 本质比较
45 |
46 | huatuo是原生的c#热更新方案。通俗地说,il2cpp相当于mono的aot模块,huatuo相当于mono的interpreter模块,两者合一成为完整mono。huatuo使得il2cpp变成一个全功能的runtime,原生(即通过System.Reflection.Assembly.Load)支持动态加载dll,从而支持ios平台的热更新。
47 |
48 | 正因为huatuo是原生runtime级别实现,热更新部分的类型与主工程AOT部分类型是完全等价并且无缝统一的。可以随意调用、继承、反射、多线程,不需要生成代码或者写适配器。
49 |
50 | 其他热更新方案则是独立vm,与il2cpp的关系本质上相当于mono中嵌入lua的关系。因此类型系统不统一,为了让热更新类型能够继承AOT部分类型,需要写适配器,并且解释器中的类型不能为主工程的类型系统所识别。特性不完整、开发麻烦、运行效率低下。
51 |
52 | ### 实际使用体验或者特性比较
53 |
54 | - huatuo学习和使用成本几乎为零。huatuo让il2cpp变成全功能的runtime,学习和使用成本几乎为零,几乎零侵入性。而其他方案则有大量的坑和需要规避的规则,学习和使用成本,需要对原项目作大量改造。
55 | - huatuo可以使用所有c#的特性。而其他方案往往有大量的限制。
56 | - huatuo中可以直接支持使用和继承主工程中的类型。其他方案要写适配器或者生成代码。
57 | - huatuo中热更新部分元数据与AOT元数据无缝统一。像反射代码能够正常工作的,AOT部分也可以通过标准Reflection接口创建出热更新对象。其他方案做不到。
58 | - huatuo对多线程支持良好。像多线程、ThreadStatic、async等等特性都是huatuo直接支持,其他方案除了async特性外均难以支持。
59 | - huatuo中Unity工作流与原生几乎完全相同。huatuo中热更新MonoBehaviour可以直接挂载在热更新资源上,并且正确工作。其他方案不行。
60 | - huatuo兼容性极高。各种第三方库只要在il2cpp下能工作,在huatuo下也能正常工作。其他方案往往要大量魔改源码。
61 | - huatuo内存效率极高。huatuo中热更新类型与主工程的AOT类型完全等价,占用一样多的空间。其他方案的同等类型则是假类型,不仅不能被runtime识别,还多占了数倍空间。
62 | - huatuo执行效率高。huatuo中热更新部分与主工程AOT部分交互属于il2cpp内部交互,效率极高。而其他方案则是独立虚拟机与il2cpp之间的效率,不仅交互麻烦还效率低下。
63 |
64 | ## 文档
65 |
66 | - [文档站](https://xxx/),**推荐使用**
67 | - [FAQ](https://xxx/huatuo/faq/)
68 | - [限制和注意事项](https://xxx/huatuo/performance/limit/)
69 | - [示例项目](https://github.com/focus-creative-games/huatuo_trial)
70 | - [==>致谢名单<==](https://xxx/huatuo/donate/)
71 |
72 | ## 稳定性状况
73 |
74 | === **庆祝于 2021.6.7 第一款使用huatuo的android和iOS双端休闲游戏正式上线** ===,7月份还有几款中重游戏上线或者对外测试。
75 |
76 | 技术评估上目前稳定性处于Beta版本。由于huatuo技术原理的先进性,bug本质上不多,稳定得非常快。
77 |
78 | - 目前PC、Android、iOS 已跑通所有单元测试,可稳定体验使用。
79 | - 测试了游戏常用库和框架的兼容性,兼容性良好。只要能在il2cpp backend下工作的库都可以在huatuo下正常工作。甚至那些与il2cpp因为AOT问题不兼容的库,现在因为huatuo对il2cpp的能力扩充,反而可以正常运行了。具体参见 [兼容性报告](https://xxx/huatuo/performance/compatible/)
80 | - 已经有几十个大中型游戏项目较完整地接入huatuo,并且其中一些在紧锣密鼓作上线前测试。具体参见收集的一些 [完整接入的商业项目列表](https://xxx/huatuo/ref_project/)
81 |
82 | ## RoadMap
83 |
84 | huatuo虽然与il2cpp相关,但绝大多数核心代码独立于il2cpp,很容易移植(预计一个月)到其他不支持AOT+Interpreter的CLR平台。无论unity如何版本变迁,哪怕废弃了il2cpp改用.net 6+,huatuo会持续跟进,稳定地提供跨平台的CLR热更新服务,直至某天.net官方直接支持AOT+Interpreter,则huatuo完成其历史使命。
85 |
86 | - 支持Unity 2019、2020和2021系列版本 (2022.6 -)
87 | - 支持32位 (2022.6 - 2022.7)
88 | - 指令优化,编译后指令数减少到原来1/4-1/2,基础指令和大多数对象模型指令有100%-300%的性能提升。 (2022.7 -)
89 | - 支持增量式gc (2022.8 -)
90 |
91 | ## license
92 |
93 | Huatuo is licensed under the [MIT](https://github.com/xxx/huatuo/blob/main/LICENSE) license
94 |
--------------------------------------------------------------------------------
/README_en.md:
--------------------------------------------------------------------------------
1 | #huatuo
2 |
3 | [](https://opensource.org/licenses/MIT)
4 |
5 |
6 |
7 | 
8 |
9 |
10 |
11 | Huatuo is a near-perfect C# hot update solution with complete features, zero cost, high performance, and low memory.
12 |
13 | huatuo provides interpreter modules for pure AOT CLRs such as il2cpp, so that apps based on them can efficiently use the **AOT+interpreter** hybrid mode not only on the Android platform, but also on IOS, Consoles and other platforms that limit JIT. Execute, from the bottom to fully support the hot update.
14 |
15 | ## Features
16 |
17 | - Features complete. Nearly complete implementation of the [ECMA-335 specification](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), except for the features below "Limitations and Notes" are supported.
18 | - Zero learning and usage costs. huatuo enhances the pure AOT runtime into a full CLR runtime, making hot update code work seamlessly with AOT code. Script classes are in the same runtime as AOT classes, even code like reflection, multi-threading (volatile, ThreadStatic, Task, async) works fine. There is no need to write any special code, no code generation, and no special restrictions.
19 | - Execute efficiently. Implemented an extremely efficient register interpreter that outperformed other hot update schemes by a large margin by all metrics. [Performance test report](https://xxx.github.io/huatuo/performance/benchmark/)
20 | - Memory efficient. The classes defined in the hot update script occupy the same memory space as ordinary C# classes, which is far superior to other hot update solutions. [Memory usage report](https://xxx.github.io/huatuo/performance/benchmark/#%E5%86%85%E5%AD%98%E5%8D%A0%E7%94%A8%E6%8A%A5%E5%91%8A)
21 | - Native support for hotfix to repair part of AOT code. Adds almost no development and runtime overhead.
22 |
23 | ## working principle
24 |
25 | Inspired by mono's [Hybrid mode execution](https://developpaper.com/new-net-interpreter-mono-has-arrived/) technology, huatuo provides additional interpreter modules for AOT runtimes such as unity's il2cpp , transforming them from pure AOT runtime to "AOT + Interpreter" hybrid operation mode, which completely supports hot update from the bottom.
26 |
27 | 
28 |
29 | More specifically, huatuo does the following:
30 |
31 | - Implemented an efficient metadata (dll) parsing library
32 | - Modified the metadata management module of il2cpp to realize the dynamic registration of metadata
33 | - Implemented a compiler from an IL instruction set to a custom register instruction set
34 | - Implemented an efficient register interpreter
35 | - Provide a large number of instinct functions additionally to improve the performance of the interpreter
36 | - Provide hotfix AOT support (in progress)
37 |
38 | ## Documentation
39 |
40 | - ~~[wiki](https://github.com/xxx/huatuo/wiki/home)~~
41 | - [Document](https://xxx.github.io/),**recommend**
42 | - [FAQ](https://xxx.github.io/huatuo/faq/)
43 | - [Best Practices](https://xxx.github.io/huatuo/start_up/best_practices/)
44 | - [Source Structure and Trace Debugging](https://xxx.github.io/huatuo/source_inspect/)
45 | - [Sample Project](https://github.com/xxx/huatuo_trial)
46 | - [==>Acknowledgments<==](https://xxx.github.io/huatuo/donate/)
47 |
48 | ## Stability status
49 |
50 | In terms of technical evaluation, the current stability is between the Alpha version and the Beta version.
51 |
52 | - Completed unit tests for most instructions. Only a few instructions such as calli and initblk that are difficult to construct directly in C# do not have corresponding unit tests added.
53 | - Completing various syntax tests against the c# specification.
54 | - Tested the compatibility of common game libraries and frameworks, and the compatibility is good. See [Compatibility Report](docs/compatible.md)
55 | - [luban](https://github.com/xxx/luban) config can be loaded correctly
56 | - Can correctly run lightweight games like [2048](https://github.com/dgkanatsios/2048)
57 | - Can run small games like [StarForce](https://github.com/EllanJiang/StarForce)
58 | - Helping some small, medium and large (there is a heavy MMORPG project) to migrate and test huatuo. It is expected that large-scale game projects such as MMORPG can be successfully run this month.
59 |
60 | ## Limitations and Notes
61 |
62 | **Features not included in the restrictions are all supported by huatuo**. Please stop asking if huatuo supports a certain feature.
63 |
64 | - Support 5.x, 2017-2022 full series of versions, but not every minor version. For details, see [Currently Supported Unity Versions](https://xxx.github.io/huatuo/support_versions/).
65 | - Unable to create instances of **hot update non-enumeration value types** of ordinary AOT generics (**delegate, Nullable, arrays (including multi-dimensional) are not limited, hot update generics are also completely unlimited**) instance of the type. For example, List<HotUpdateValueType> is not supported but List<int>, List<HotUpdateClass> and List<HotUpdateEnum> are supported. For specific reasons, see [AOT generic limitation and principle introduction](https://xxx.github.io/huatuo/performance/generic_limit/). This will be more completely resolved in the July version, and there will be no restrictions after that.
66 | - The default async task that returns **custom value type** is temporarily not supported, and native value types such as int and enumeration and class types are not restricted. The reason is that the compiler will generate the generic class instantiation of AsyncTaskMethodBuilder<T> for async by default. If you use custom Task and AsyncTaskMethodBuilder like ETask, there are no restrictions. This limitation of native async will be resolved in subsequent versions.
67 | - **Note to use link.xml or code reference to avoid Unity cutting code. Avoid the error that the function can be called during the development period, but the function cannot be found after the release. We will provide default templates in the future.
68 | - BeginInvoke and EndInvoke of delegate are not supported. It just doesn't feel necessary to do it.
69 | - Due to the limitation of Unity's resource management mechanism (the script uuid has been determined during packaging, and the GUID corresponding to the hot update script cannot be found), the hot update MonoBehaviour needs to be compiled into an independent dll and mounted on the resource to be correctly reversed change
70 | - Incremental gc is not supported yet. Due to the tight time, it is too late to carefully deal with the memory barrier details of incremental gc. This issue will be resolved soon.
71 | - Temporarily does not support C# source code debugging of the real machine after packaging, but can print the error stack (only accurate to the function), and can also track and debug in the Debug project generated by Build. You can use the usual mono debugging for debugging during the development period under the Editor.
72 |
73 |
74 |
75 | ## RoadMap
76 |
77 | Although huatuo is related to il2cpp, most of the core code is independent of il2cpp and can be easily ported (expected one month) to other CLR platforms that do not support AOT+Interpreter. No matter how the version of Unity changes, even if il2cpp is abandoned and .net 6+ is used, huatuo will continue to follow up and stably provide cross-platform CLR hot update service until one day when .net officially supports AOT+Interpreter, huatuo will complete its historical mission.
78 |
79 | - Continue to fix bugs to make a medium and large game work properly (2022.4)
80 | - Continue to follow up the version update of Unity and support more Unity versions. See [Currently Supported Unity Versions](https://xxx.github.io/huatuo/support_versions/)
81 | - Support hotfix bug in AOT part (2022.6)
82 | - Remove most common AOT generic class restrictions (2022.6)
83 | - Support incremental gc. (2022.6)
84 | - Instruction optimization, the number of instructions after compilation is reduced to 1/4-1/2, and the performance of basic instructions and most object model instructions is improved by 100%-300%. (2022.6 preview version)
85 | - Support for extern functions (2022.7)
86 | - Other memory and efficiency optimizations, and code refactoring
87 | - **===godot engine support ===**(2022.12)
88 |
89 | ## license
90 |
91 | Huatuo is licensed under the [MIT](https://github.com/xxx/huatuo/blob/main/LICENSE) license
92 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/docs/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuyoogame/huatuo/04fea98e5929426519c3b85fba26397644661167/docs/images/architecture.png
--------------------------------------------------------------------------------
/docs/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuyoogame/huatuo/04fea98e5929426519c3b85fba26397644661167/docs/images/logo.png
--------------------------------------------------------------------------------
/docs/sponsor/weixin.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuyoogame/huatuo/04fea98e5929426519c3b85fba26397644661167/docs/sponsor/weixin.JPG
--------------------------------------------------------------------------------
/docs/sponsor/zhifubao.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuyoogame/huatuo/04fea98e5929426519c3b85fba26397644661167/docs/sponsor/zhifubao.JPG
--------------------------------------------------------------------------------
/huatuo/CommonDef.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "CommonDef.h"
4 |
5 |
6 | namespace huatuo
7 | {
8 | void LogPanic(const char* errMsg)
9 | {
10 | std::cerr << "panic:" << std::endl;
11 | std::cerr << "\t" << errMsg << std::endl;
12 | exit(1);
13 | }
14 |
15 | const char* GetAssemblyNameFromPath(const char* assPath)
16 | {
17 | const char* last = nullptr;
18 | for (const char* p = assPath; *p; p++)
19 | {
20 | if (*p == '/' || *p == '\\')
21 | {
22 | last = p + 1;
23 | }
24 | }
25 | return last ? last : assPath;
26 | }
27 |
28 | const char* CopyString(const char* src)
29 | {
30 | size_t len = std::strlen(src);
31 | char* dst = (char*)IL2CPP_MALLOC(len + 1);
32 | std::strcpy(dst, src);
33 | return dst;
34 | }
35 |
36 | const char* ConcatNewString(const char* s1, const char* s2)
37 | {
38 | size_t len1 = std::strlen(s1);
39 | size_t len = len1 + std::strlen(s2);
40 | char* dst = (char*)IL2CPP_MALLOC(len + 1);
41 | std::strcpy(dst, s1);
42 | strcpy(dst + len1, s2);
43 | return dst;
44 | }
45 |
46 | void* CopyBytes(const void* src, size_t length)
47 | {
48 | void* dst = IL2CPP_MALLOC(length);
49 | std::memcpy(dst, src, length);
50 | return dst;
51 | }
52 | }
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/huatuo/CommonDef.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "huatuo-compatible-adaptor.h"
8 |
9 | #include "codegen/il2cpp-codegen.h"
10 | #include "utils/Memory.h"
11 | #include "utils/StringView.h"
12 | #include "vm/GlobalMetadataFileInternals.h"
13 | #include "vm/Exception.h"
14 | #include "vm/Class.h"
15 | #include "icalls/mscorlib/System/Type.h"
16 | #ifdef HUATUO_UNITY_2021_OR_NEW
17 | #include "icalls/mscorlib/System/RuntimeType.h"
18 | #else
19 | #include "icalls/mscorlib/System/MonoType.h"
20 | #endif
21 |
22 | namespace huatuo
23 | {
24 | typedef uint8_t byte;
25 |
26 | #if IL2CPP_TARGET_ARM64 || IL2CPP_TARGET_ARMV7
27 | #define HUATUO_TARGET_ARM 1
28 | #else
29 | #define HUATUO_TARGET_ARM 0
30 | #endif
31 |
32 | #define TEMP_FORMAT(var, fmt, ...) char var[600]; \
33 | snprintf(var, sizeof(var), fmt, __VA_ARGS__);
34 |
35 | void LogPanic(const char* errMsg);
36 |
37 | const char* GetAssemblyNameFromPath(const char* assPath);
38 |
39 | const char* CopyString(const char* src);
40 |
41 | const char* ConcatNewString(const char* s1, const char* s2);
42 |
43 | void* CopyBytes(const void* src, size_t length);
44 |
45 | struct CStringHash
46 | {
47 | size_t operator()(const char* s) const noexcept
48 | {
49 | uint32_t hash = 0;
50 |
51 | for (; *s; ++s)
52 | {
53 | hash += *s;
54 | hash += (hash << 10);
55 | hash ^= (hash >> 6);
56 | }
57 |
58 | hash += (hash << 3);
59 | hash ^= (hash >> 11);
60 | hash += (hash << 15);
61 |
62 | return hash;
63 | }
64 | };
65 |
66 | struct CStringEqualTo
67 | {
68 | bool operator()(const char* _Left, const char* _Right) const
69 | {
70 | return std::strcmp(_Left, _Right) == 0;
71 | }
72 | };
73 |
74 | inline il2cpp::utils::StringView CStringToStringView(const char* str)
75 | {
76 | return il2cpp::utils::StringView(str, std::strlen(str));
77 | }
78 |
79 | inline std::string GetKlassCStringFullName(const Il2CppType* type)
80 | {
81 | Il2CppString* typeName = GetKlassFullName(type);
82 | return il2cpp::utils::StringUtils::Utf16ToUtf8(typeName->chars);
83 | }
84 |
85 | inline void RaiseHuatuoNotSupportedException(const char* msg)
86 | {
87 | TEMP_FORMAT(errMsg, "huatuo doesn't support %s", msg);
88 | return il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetNotSupportedException(errMsg));
89 | }
90 |
91 | inline void RaiseHuatuoExecutionEngineException(const char* msg)
92 | {
93 | return il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(msg));
94 | }
95 |
96 | inline void RaiseMethodNotFindException(const Il2CppType* type, const char* methodName)
97 | {
98 | if (!type)
99 | {
100 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetTypeLoadException("type not exists"));
101 | }
102 |
103 | std::string fullName = GetKlassCStringFullName(type);
104 | TEMP_FORMAT(errMsg, "MethodNotFind %s::%s", fullName.c_str(), methodName);
105 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetMissingMethodException(errMsg));
106 | }
107 |
108 | inline void AppendTypeName(std::string& s, const Il2CppType* type)
109 | {
110 | s.append(GetKlassCStringFullName(type));
111 | }
112 |
113 | inline std::string GetMethodNameWithSignature(const MethodInfo* method)
114 | {
115 | std::string name;
116 | AppendTypeName(name, method->return_type);
117 | name.append(" ");
118 |
119 | name.append(GetKlassCStringFullName(&method->klass->byval_arg));
120 | name.append("::");
121 | name.append(method->name);
122 | if (method->genericMethod && method->genericMethod->context.method_inst)
123 | {
124 | name.append("<");
125 | const Il2CppGenericInst* gi= method->genericMethod->context.method_inst;
126 | for (uint32_t i = 0; i < gi->type_argc; i++)
127 | {
128 | if (i > 0)
129 | {
130 | name.append(",");
131 | }
132 | AppendTypeName(name, gi->type_argv[i]);
133 | }
134 | name.append(">");
135 | }
136 | name.append("(");
137 | for (uint8_t i = 0; i < method->parameters_count; i++)
138 | {
139 | if (i > 0)
140 | {
141 | name.append(",");
142 | }
143 | AppendTypeName(name, GET_METHOD_PARAMETER_TYPE(method->parameters[i]));
144 | }
145 | name.append(")");
146 | return name;
147 | }
148 |
149 | inline void RaiseAOTGenericMethodNotInstantiatedException(const MethodInfo* method)
150 | {
151 | std::string methodName = GetMethodNameWithSignature(method);
152 | TEMP_FORMAT(errMsg, "AOT generic method not instantiated in aot module. %s", methodName.c_str());
153 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetMissingMethodException(errMsg));
154 | }
155 |
156 | inline void RaiseMissingFieldException(const Il2CppType* type, const char* fieldName)
157 | {
158 | if (!type)
159 | {
160 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetTypeLoadException("type not exists"));
161 | }
162 | std::string stdFullName = GetKlassCStringFullName(type);
163 | TEMP_FORMAT(errMsg, "field %s::%s not exists", stdFullName.c_str(), fieldName);
164 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetMissingFieldException(errMsg));
165 | }
166 |
167 | }
168 |
169 |
170 |
--------------------------------------------------------------------------------
/huatuo/HuatuoApi.cpp:
--------------------------------------------------------------------------------
1 | #include "CommonDef.h"
2 |
3 | #include "metadata/AOTHomologousImage.h"
4 | #include "HuatuoConfig.h"
5 |
6 | extern "C"
7 | {
8 |
9 | IL2CPP_EXPORT int32_t HuatuoApi_LoadMetadataForAOTAssembly(void* dllBytes, uint32_t dllSize)
10 | {
11 | return huatuo::metadata::AOTHomologousImage::LoadMetadataForAOTAssembly(dllBytes, dllSize);
12 | }
13 |
14 | IL2CPP_EXPORT uint32_t HuatuoApi_GetInterpreterThreadObjectStackSize()
15 | {
16 | return huatuo::HuatuoConfig::GetInterpreterThreadObjectStackSize();
17 | }
18 |
19 | IL2CPP_EXPORT void HuatuoApi_SetInterpreterThreadObjectStackSize(uint32_t size)
20 | {
21 | huatuo::HuatuoConfig::SetInterpreterThreadObjectStackSize(size);
22 | }
23 |
24 | IL2CPP_EXPORT uint32_t HuatuoApi_GetInterpreterThreadFrameStackSize()
25 | {
26 | return huatuo::HuatuoConfig::GetInterpreterThreadFrameStackSize();
27 | }
28 |
29 | IL2CPP_EXPORT void HuatuoApi_SetInterpreterThreadFrameStackSize(uint32_t size)
30 | {
31 | huatuo::HuatuoConfig::SetInterpreterThreadFrameStackSize(size);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/huatuo/HuatuoConfig.cpp:
--------------------------------------------------------------------------------
1 | #include "HuatuoConfig.h"
2 |
3 | namespace huatuo
4 | {
5 | HuatuoConfig HuatuoConfig::_ins;
6 |
7 | uint32_t HuatuoConfig::s_threadObjectStackSize = 1024 * 128;
8 | uint32_t HuatuoConfig::s_threadFrameStackSize = 1024 * 2;
9 | }
--------------------------------------------------------------------------------
/huatuo/HuatuoConfig.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CommonDef.h"
4 |
5 | namespace huatuo
6 | {
7 | class HuatuoConfig
8 | {
9 |
10 | public:
11 | static HuatuoConfig& GetIns()
12 | {
13 | return _ins;
14 | }
15 |
16 | static uint32_t GetInterpreterThreadObjectStackSize()
17 | {
18 | return s_threadObjectStackSize;
19 | }
20 |
21 | static void SetInterpreterThreadObjectStackSize(uint32_t count)
22 | {
23 | s_threadObjectStackSize = count;
24 | }
25 |
26 | static uint32_t GetInterpreterThreadFrameStackSize()
27 | {
28 | return s_threadFrameStackSize;
29 | }
30 |
31 | static void SetInterpreterThreadFrameStackSize(uint32_t count)
32 | {
33 | s_threadFrameStackSize = count;
34 | }
35 |
36 | private:
37 | static HuatuoConfig _ins;
38 |
39 | private:
40 | static uint32_t s_threadObjectStackSize;
41 | static uint32_t s_threadFrameStackSize;
42 | };
43 | }
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/huatuo/ModuleManager.cpp:
--------------------------------------------------------------------------------
1 | #include "ModuleManager.h"
2 |
3 | #include "vm/Exception.h"
4 | #include "vm/String.h"
5 | #include "vm/Assembly.h"
6 | #include "vm/Class.h"
7 | #include "vm/Object.h"
8 | #include "vm/Reflection.h"
9 | #include "icalls/mscorlib/System.Reflection/Assembly.h"
10 |
11 | #include "interpreter/InterpreterModule.h"
12 | #include "metadata/MetadataModule.h"
13 | #include "transform/Transform.h"
14 |
15 |
16 | namespace huatuo
17 | {
18 |
19 | void ModuleManager::Initialize()
20 | {
21 | metadata::MetadataModule::Initialize();
22 | interpreter::InterpreterModule::Initialize();
23 | }
24 | }
--------------------------------------------------------------------------------
/huatuo/ModuleManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CommonDef.h"
4 | #include "HuatuoConfig.h"
5 |
6 | namespace huatuo
7 | {
8 |
9 |
10 |
11 | class ModuleManager
12 | {
13 | public:
14 | static void Initialize();
15 | };
16 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/Engine.cpp:
--------------------------------------------------------------------------------
1 | #include "Engine.h"
2 |
3 | #include "Interpreter.h"
4 | #include "MemoryUtil.h"
5 |
6 | namespace huatuo
7 | {
8 | namespace interpreter
9 | {
10 |
11 | InterpFrame* InterpFrameGroup::EnterFrame(const InterpMethodInfo* imi, StackObject* argBase, bool withArgStack)
12 | {
13 | ptrdiff_t oldStackTop = _machineState.GetStackTop();
14 | InterpFrame* newFrame;
15 | if (withArgStack)
16 | {
17 | StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize - imi->argStackObjectSize);
18 |
19 | newFrame = _machineState.PushFrame();
20 | *newFrame = { imi, argBase, oldStackTop, nullptr, nullptr, nullptr, {}, {} };
21 | }
22 | else
23 | {
24 | StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize);
25 |
26 | newFrame = _machineState.PushFrame();
27 | *newFrame = { imi, stackBasePtr, oldStackTop, nullptr, nullptr, nullptr, {}, {} };
28 |
29 | // if not prepare arg stack. copy from args
30 | if (!withArgStack && imi->args)
31 | {
32 | IL2CPP_ASSERT(imi->argCount == metadata::GetActualArgumentNum(imi->method));
33 | if (imi->isTrivialCopyArgs)
34 | {
35 | std::memcpy(stackBasePtr, argBase, imi->argStackObjectSize * sizeof(StackObject));
36 | }
37 | else
38 | {
39 | CopyArgs(stackBasePtr, argBase, imi->args, imi->argCount, imi->argStackObjectSize);
40 | }
41 | }
42 | }
43 | PUSH_STACK_FRAME(imi->method);
44 | return newFrame;
45 | }
46 |
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/huatuo/interpreter/Engine.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "../CommonDef.h"
6 |
7 | #include "gc/GarbageCollector.h"
8 | #include "vm/Exception.h"
9 | #include "vm/StackTrace.h"
10 |
11 | #include "../metadata/MetadataDef.h"
12 | #include "../HuatuoConfig.h"
13 |
14 | #include "InterpreterDefs.h"
15 |
16 |
17 | #if DEBUG
18 | #define PUSH_STACK_FRAME(method) do { \
19 | Il2CppStackFrameInfo stackFrameInfo = { method, (uintptr_t)method->methodPointer }; \
20 | il2cpp::vm::StackTrace::PushFrame(stackFrameInfo); \
21 | } while(0)
22 |
23 | #define POP_STACK_FRAME() do { il2cpp::vm::StackTrace::PopFrame(); } while(0)
24 |
25 | #else
26 | #define PUSH_STACK_FRAME(method)
27 | #define POP_STACK_FRAME()
28 | #endif
29 |
30 | namespace huatuo
31 | {
32 | namespace interpreter
33 | {
34 |
35 | class MachineState
36 | {
37 | public:
38 | MachineState()
39 | {
40 | HuatuoConfig& hc = HuatuoConfig::GetIns();
41 | _stackSize = hc.GetInterpreterThreadObjectStackSize();
42 | _stackBase = (StackObject*)il2cpp::gc::GarbageCollector::AllocateFixed(hc.GetInterpreterThreadObjectStackSize() * sizeof(StackObject), nullptr);
43 | std::memset(_stackBase, 0, _stackSize * sizeof(StackObject));
44 | _stackTopIdx = 0;
45 |
46 | _frameBase = (InterpFrame*)IL2CPP_CALLOC(hc.GetInterpreterThreadFrameStackSize(), sizeof(InterpFrame));
47 | _frameCount = hc.GetInterpreterThreadFrameStackSize();
48 | _frameTopIdx = 0;
49 | }
50 |
51 | ~MachineState()
52 | {
53 | il2cpp::gc::GarbageCollector::FreeFixed(_stackBase);
54 | }
55 |
56 | StackObject* AllocArgments(uint32_t argCount)
57 | {
58 | if (_stackTopIdx + argCount > _stackSize)
59 | {
60 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocArguments"));
61 | }
62 | StackObject* args = _stackBase + _stackTopIdx;
63 | _stackTopIdx += argCount;
64 | return args;
65 | }
66 |
67 | StackObject* GetStackBasePtr() const
68 | {
69 | return _stackBase;
70 | }
71 |
72 | ptrdiff_t GetStackTop() const
73 | {
74 | return _stackTopIdx;
75 | }
76 |
77 | StackObject* AllocStackSlot(uint32_t slotNum)
78 | {
79 | if (_stackTopIdx + slotNum > _stackSize)
80 | {
81 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocStackSlot"));
82 | }
83 | StackObject* dataPtr = _stackBase + _stackTopIdx;
84 | _stackTopIdx += slotNum;
85 | return dataPtr;
86 | }
87 |
88 | void SetStackTop(ptrdiff_t oldTop)
89 | {
90 | _stackTopIdx = oldTop;
91 | }
92 |
93 | uint32_t GetFrameTopIdx() const
94 | {
95 | return _frameTopIdx;
96 | }
97 |
98 | InterpFrame* PushFrame()
99 | {
100 | if (_frameTopIdx >= _frameCount)
101 | {
102 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocFrame"));
103 | }
104 | return _frameBase + _frameTopIdx++;
105 | }
106 |
107 | void PopFrame()
108 | {
109 | IL2CPP_ASSERT(_frameTopIdx > 0);
110 | --_frameTopIdx;
111 | }
112 |
113 | void PopFrameN(uint32_t count)
114 | {
115 | IL2CPP_ASSERT(count > 0 && _frameTopIdx >= count);
116 | _frameTopIdx -= count;
117 | }
118 |
119 | InterpFrame* GetTopFrame() const
120 | {
121 | if (_frameTopIdx > 0)
122 | {
123 | return _frameBase + _frameTopIdx - 1;
124 | }
125 | else
126 | {
127 | return nullptr;
128 | }
129 | }
130 |
131 | //const InterpFrame* GetFrameBaseMinusOne() const
132 | //{
133 | // return _frameBase - 1;
134 | //}
135 |
136 | void PushExecutingImage(const Il2CppImage* image)
137 | {
138 | _executingImageStack.push(image);
139 | }
140 |
141 | void PopExecutingImage()
142 | {
143 | _executingImageStack.pop();
144 | }
145 |
146 | const Il2CppImage* GetTopExecutingImage() const
147 | {
148 | if (_executingImageStack.empty())
149 | {
150 | return nullptr;
151 | }
152 | else
153 | {
154 | return _executingImageStack.top();
155 | }
156 | }
157 |
158 | void CollectFrames(il2cpp::vm::StackFrames* stackFrames)
159 | {
160 | for (uint32_t i = 0; i < _frameTopIdx; i++)
161 | {
162 | InterpFrame* frame = _frameBase + i;
163 | const MethodInfo* method = frame->method->method;
164 | Il2CppStackFrameInfo stackFrameInfo = { method, (uintptr_t)method->methodPointer };
165 | stackFrames->push_back(stackFrameInfo);
166 | }
167 | }
168 |
169 | private:
170 |
171 | StackObject* _stackBase;
172 | ptrdiff_t _stackSize;
173 | ptrdiff_t _stackTopIdx;
174 |
175 | InterpFrame* _frameBase;
176 | uint32_t _frameTopIdx;
177 | uint32_t _frameCount;
178 |
179 | std::stack _executingImageStack;
180 | };
181 |
182 | class ExecutingInterpImageScope
183 | {
184 | public:
185 | ExecutingInterpImageScope(MachineState& state, const Il2CppImage* image) : _state(state)
186 | {
187 | _state.PushExecutingImage(image);
188 | }
189 |
190 | ~ExecutingInterpImageScope()
191 | {
192 | _state.PopExecutingImage();
193 | }
194 |
195 | private:
196 | MachineState& _state;
197 | };
198 |
199 | //class NativeInterpFrameGroup
200 | //{
201 | //public:
202 | // NativeInterpFrameGroup(MachineState& state, const MethodInfo* method) : _state(state), _interMethod({})
203 | // {
204 | //
205 | // InterpFrame* frame = state.PushFrame();
206 | // *frame = {};
207 | // _interMethod.method = method;
208 | // frame->method = &_interMethod;
209 | // }
210 |
211 | // ~NativeInterpFrameGroup()
212 | // {
213 | // _state.PopFrame();
214 | // }
215 |
216 | //private:
217 | // MachineState _state;
218 | // InterpMethodInfo _interMethod;
219 | //};
220 |
221 | class InterpFrameGroup
222 | {
223 | public:
224 | InterpFrameGroup(MachineState& ms) : _machineState(ms), _stackBaseIdx(ms.GetStackTop()), _frameBaseIdx(ms.GetFrameTopIdx())
225 | {
226 |
227 | }
228 |
229 | void CleanUpFrames()
230 | {
231 | IL2CPP_ASSERT(_machineState.GetFrameTopIdx() >= _frameBaseIdx);
232 | uint32_t n = _machineState.GetFrameTopIdx() - _frameBaseIdx;
233 | if (n > 0)
234 | {
235 | for (uint32_t i = 0; i < n; i++)
236 | {
237 | LeaveFrame();
238 | }
239 | }
240 | }
241 |
242 | InterpFrame* EnterFrame(const InterpMethodInfo* imi, StackObject* argBase, bool withArgStack);
243 |
244 | InterpFrame* LeaveFrame()
245 | {
246 | IL2CPP_ASSERT(_machineState.GetFrameTopIdx() > _frameBaseIdx);
247 | POP_STACK_FRAME();
248 | InterpFrame* frame = _machineState.GetTopFrame();
249 | if (frame->exHandleStack)
250 | {
251 | frame->exHandleStack->~vector();
252 | IL2CPP_FREE(frame->exHandleStack);
253 | frame->exHandleStack = nullptr;
254 | }
255 | _machineState.PopFrame();
256 | _machineState.SetStackTop(frame->oldStackTop);
257 | return _machineState.GetFrameTopIdx() > _frameBaseIdx ? _machineState.GetTopFrame() : nullptr;
258 | }
259 |
260 | void* AllocLoc(size_t size)
261 | {
262 | uint32_t soNum = (uint32_t)((size + sizeof(StackObject) - 1) / sizeof(StackObject));
263 | //void* data = _machineState.AllocStackSlot(soNum);
264 | //std::memset(data, 0, soNum * 8);
265 | void* data = IL2CPP_MALLOC_ZERO(size);
266 | return data;
267 | }
268 |
269 | size_t GetFrameCount() const { return _machineState.GetFrameTopIdx() - _frameBaseIdx; }
270 | private:
271 | MachineState& _machineState;
272 | ptrdiff_t _stackBaseIdx;
273 | uint32_t _frameBaseIdx;
274 | };
275 | }
276 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/InstrinctDef.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "../CommonDef.h"
3 |
4 | namespace huatuo
5 | {
6 | namespace interpreter
7 | {
8 |
9 | struct HtVector2f
10 | {
11 | float x;
12 | float y;
13 | };
14 | static_assert(sizeof(HtVector2f) == 8, "Vector2f");
15 |
16 | struct HtVector3f
17 | {
18 | float x;
19 | float y;
20 | float z;
21 | };
22 | static_assert(sizeof(HtVector3f) == 12, "Vector3f");
23 |
24 | struct HtVector4f
25 | {
26 | float x;
27 | float y;
28 | float z;
29 | float w;
30 | };
31 | static_assert(sizeof(HtVector4f) == 16, "Vector4f");
32 |
33 | struct HtVector2d
34 | {
35 | double x;
36 | double y;
37 | };
38 | static_assert(sizeof(HtVector2d) == 16, "Vector2d");
39 |
40 | struct HtVector3d
41 | {
42 | double x;
43 | double y;
44 | double z;
45 | };
46 | static_assert(sizeof(HtVector3d) == 24, "Vector3d");
47 |
48 | struct HtVector4d
49 | {
50 | double x;
51 | double y;
52 | double z;
53 | double w;
54 | };
55 | static_assert(sizeof(HtVector4d) == 32, "Vector4d");
56 |
57 | struct HtVector2i
58 | {
59 | int32_t x;
60 | int32_t y;
61 | };
62 | static_assert(sizeof(HtVector2i) == 8, "IntVector2i");
63 |
64 | struct HtVector3i
65 | {
66 | int32_t x;
67 | int32_t y;
68 | int32_t z;
69 | };
70 | static_assert(sizeof(HtVector3i) == 12, "IntVector3i");
71 |
72 | struct HtVector4i
73 | {
74 | int32_t x;
75 | int32_t y;
76 | int32_t z;
77 | int32_t w;
78 | };
79 | static_assert(sizeof(HtVector4i) == 16, "IntVector4i");
80 |
81 | #pragma endregion
82 |
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/huatuo/interpreter/Instruction.cpp:
--------------------------------------------------------------------------------
1 | #include "Instruction.h"
2 |
3 | namespace huatuo
4 | {
5 | namespace interpreter
6 | {
7 | uint16_t g_instructionSizes[] =
8 | {
9 | //!!!{{INST_SIZE
10 | 4,
11 | 6,
12 | 6,
13 | 6,
14 | 6,
15 | 6,
16 | 6,
17 | 8,
18 | 6,
19 | 6,
20 | 6,
21 | 8,
22 | 12,
23 | 4,
24 | 6,
25 | 6,
26 | 6,
27 | 6,
28 | 6,
29 | 6,
30 | 6,
31 | 6,
32 | 6,
33 | 6,
34 | 6,
35 | 6,
36 | 6,
37 | 6,
38 | 6,
39 | 6,
40 | 6,
41 | 8,
42 | 8,
43 | 2,
44 | 6,
45 | 6,
46 | 6,
47 | 6,
48 | 6,
49 | 6,
50 | 6,
51 | 6,
52 | 6,
53 | 6,
54 | 6,
55 | 6,
56 | 6,
57 | 6,
58 | 6,
59 | 6,
60 | 6,
61 | 6,
62 | 6,
63 | 6,
64 | 6,
65 | 6,
66 | 6,
67 | 6,
68 | 6,
69 | 6,
70 | 6,
71 | 6,
72 | 6,
73 | 6,
74 | 6,
75 | 6,
76 | 6,
77 | 6,
78 | 6,
79 | 6,
80 | 6,
81 | 6,
82 | 6,
83 | 6,
84 | 6,
85 | 6,
86 | 6,
87 | 6,
88 | 6,
89 | 6,
90 | 6,
91 | 6,
92 | 6,
93 | 6,
94 | 6,
95 | 6,
96 | 6,
97 | 6,
98 | 6,
99 | 6,
100 | 6,
101 | 6,
102 | 6,
103 | 6,
104 | 6,
105 | 6,
106 | 6,
107 | 6,
108 | 6,
109 | 6,
110 | 6,
111 | 6,
112 | 6,
113 | 6,
114 | 6,
115 | 6,
116 | 6,
117 | 6,
118 | 6,
119 | 6,
120 | 6,
121 | 6,
122 | 6,
123 | 6,
124 | 6,
125 | 6,
126 | 6,
127 | 6,
128 | 6,
129 | 6,
130 | 6,
131 | 6,
132 | 6,
133 | 6,
134 | 6,
135 | 6,
136 | 6,
137 | 6,
138 | 6,
139 | 6,
140 | 6,
141 | 6,
142 | 6,
143 | 6,
144 | 6,
145 | 6,
146 | 6,
147 | 6,
148 | 6,
149 | 6,
150 | 6,
151 | 6,
152 | 6,
153 | 6,
154 | 6,
155 | 6,
156 | 6,
157 | 6,
158 | 6,
159 | 6,
160 | 6,
161 | 6,
162 | 6,
163 | 6,
164 | 6,
165 | 6,
166 | 6,
167 | 6,
168 | 6,
169 | 6,
170 | 6,
171 | 6,
172 | 6,
173 | 6,
174 | 6,
175 | 6,
176 | 6,
177 | 6,
178 | 6,
179 | 6,
180 | 6,
181 | 6,
182 | 6,
183 | 6,
184 | 6,
185 | 6,
186 | 6,
187 | 6,
188 | 6,
189 | 6,
190 | 6,
191 | 6,
192 | 6,
193 | 6,
194 | 6,
195 | 6,
196 | 6,
197 | 6,
198 | 6,
199 | 6,
200 | 6,
201 | 6,
202 | 6,
203 | 6,
204 | 6,
205 | 6,
206 | 6,
207 | 6,
208 | 6,
209 | 6,
210 | 6,
211 | 6,
212 | 6,
213 | 6,
214 | 6,
215 | 6,
216 | 6,
217 | 6,
218 | 6,
219 | 6,
220 | 6,
221 | 6,
222 | 6,
223 | 6,
224 | 6,
225 | 6,
226 | 6,
227 | 6,
228 | 6,
229 | 6,
230 | 6,
231 | 6,
232 | 6,
233 | 6,
234 | 6,
235 | 6,
236 | 6,
237 | 6,
238 | 6,
239 | 6,
240 | 6,
241 | 6,
242 | 6,
243 | 6,
244 | 8,
245 | 8,
246 | 8,
247 | 8,
248 | 8,
249 | 8,
250 | 8,
251 | 8,
252 | 8,
253 | 8,
254 | 8,
255 | 8,
256 | 8,
257 | 8,
258 | 8,
259 | 8,
260 | 8,
261 | 8,
262 | 8,
263 | 8,
264 | 8,
265 | 8,
266 | 8,
267 | 8,
268 | 8,
269 | 8,
270 | 8,
271 | 8,
272 | 8,
273 | 8,
274 | 8,
275 | 8,
276 | 8,
277 | 8,
278 | 8,
279 | 8,
280 | 8,
281 | 8,
282 | 8,
283 | 8,
284 | 8,
285 | 8,
286 | 8,
287 | 8,
288 | 8,
289 | 8,
290 | 8,
291 | 8,
292 | 8,
293 | 8,
294 | 8,
295 | 8,
296 | 8,
297 | 8,
298 | 8,
299 | 8,
300 | 6,
301 | 6,
302 | 6,
303 | 6,
304 | 6,
305 | 6,
306 | 4,
307 | 4,
308 | 8,
309 | 8,
310 | 8,
311 | 8,
312 | 8,
313 | 8,
314 | 8,
315 | 8,
316 | 8,
317 | 8,
318 | 8,
319 | 8,
320 | 8,
321 | 8,
322 | 8,
323 | 8,
324 | 8,
325 | 8,
326 | 8,
327 | 8,
328 | 6,
329 | 8,
330 | 8,
331 | 8,
332 | 8,
333 | 10,
334 | 10,
335 | 10,
336 | 10,
337 | 10,
338 | 10,
339 | 10,
340 | 10,
341 | 10,
342 | 10,
343 | 10,
344 | 10,
345 | 10,
346 | 10,
347 | 10,
348 | 10,
349 | 10,
350 | 10,
351 | 10,
352 | 10,
353 | 10,
354 | 10,
355 | 10,
356 | 10,
357 | 10,
358 | 10,
359 | 10,
360 | 10,
361 | 10,
362 | 10,
363 | 10,
364 | 10,
365 | 10,
366 | 10,
367 | 10,
368 | 10,
369 | 10,
370 | 10,
371 | 10,
372 | 10,
373 | 6,
374 | 12,
375 | 24,
376 | 12,
377 | 12,
378 | 24,
379 | 18,
380 | 14,
381 | 18,
382 | 4,
383 | 14,
384 | 14,
385 | 4,
386 | 4,
387 | 4,
388 | 4,
389 | 4,
390 | 4,
391 | 4,
392 | 4,
393 | 4,
394 | 4,
395 | 8,
396 | 2,
397 | 14,
398 | 16,
399 | 18,
400 | 12,
401 | 14,
402 | 14,
403 | 16,
404 | 18,
405 | 12,
406 | 14,
407 | 14,
408 | 16,
409 | 18,
410 | 16,
411 | 18,
412 | 20,
413 | 16,
414 | 14,
415 | 14,
416 | 14,
417 | 8,
418 | 8,
419 | 12,
420 | 14,
421 | 6,
422 | 14,
423 | 6,
424 | 6,
425 | 6,
426 | 6,
427 | 6,
428 | 6,
429 | 6,
430 | 6,
431 | 6,
432 | 6,
433 | 8,
434 | 8,
435 | 6,
436 | 6,
437 | 6,
438 | 6,
439 | 6,
440 | 6,
441 | 6,
442 | 6,
443 | 6,
444 | 6,
445 | 8,
446 | 6,
447 | 6,
448 | 6,
449 | 6,
450 | 6,
451 | 6,
452 | 6,
453 | 6,
454 | 6,
455 | 6,
456 | 8,
457 | 4,
458 | 4,
459 | 4,
460 | 4,
461 | 4,
462 | 4,
463 | 4,
464 | 4,
465 | 4,
466 | 4,
467 | 6,
468 | 8,
469 | 8,
470 | 8,
471 | 8,
472 | 8,
473 | 8,
474 | 8,
475 | 8,
476 | 8,
477 | 8,
478 | 8,
479 | 8,
480 | 8,
481 | 8,
482 | 8,
483 | 8,
484 | 8,
485 | 10,
486 | 12,
487 | 8,
488 | 8,
489 | 8,
490 | 8,
491 | 8,
492 | 8,
493 | 8,
494 | 8,
495 | 8,
496 | 8,
497 | 8,
498 | 8,
499 | 8,
500 | 8,
501 | 8,
502 | 10,
503 | 12,
504 | 8,
505 | 8,
506 | 8,
507 | 8,
508 | 8,
509 | 8,
510 | 8,
511 | 8,
512 | 8,
513 | 8,
514 | 8,
515 | 8,
516 | 8,
517 | 8,
518 | 8,
519 | 8,
520 | 10,
521 | 12,
522 | 14,
523 | 14,
524 | 14,
525 | 14,
526 | 14,
527 | 14,
528 | 14,
529 | 14,
530 | 14,
531 | 14,
532 | 14,
533 | 14,
534 | 14,
535 | 14,
536 | 14,
537 | 16,
538 | 18,
539 | 14,
540 | 14,
541 | 14,
542 | 14,
543 | 14,
544 | 14,
545 | 14,
546 | 14,
547 | 14,
548 | 14,
549 | 14,
550 | 14,
551 | 14,
552 | 14,
553 | 14,
554 | 16,
555 | 18,
556 | 14,
557 | 12,
558 | 16,
559 | 16,
560 | 16,
561 | 16,
562 | 16,
563 | 16,
564 | 16,
565 | 16,
566 | 16,
567 | 16,
568 | 16,
569 | 16,
570 | 16,
571 | 16,
572 | 16,
573 | 16,
574 | 18,
575 | 20,
576 | 14,
577 | 14,
578 | 14,
579 | 14,
580 | 14,
581 | 14,
582 | 14,
583 | 14,
584 | 14,
585 | 14,
586 | 14,
587 | 14,
588 | 14,
589 | 14,
590 | 14,
591 | 16,
592 | 18,
593 | 14,
594 | 14,
595 | 6,
596 | 6,
597 | 8,
598 | 8,
599 | 16,
600 | 16,
601 | 8,
602 | 8,
603 | 8,
604 | 8,
605 | 8,
606 | 8,
607 | 8,
608 | 8,
609 | 8,
610 | 8,
611 | 8,
612 | 8,
613 | 8,
614 | 8,
615 | 8,
616 | 8,
617 | 8,
618 | 8,
619 | 8,
620 | 8,
621 | 8,
622 | 8,
623 | 8,
624 | 8,
625 | 8,
626 | 8,
627 | 8,
628 | 8,
629 | 8,
630 | 8,
631 | 8,
632 | 8,
633 | 8,
634 | 8,
635 | 8,
636 | 8,
637 | 8,
638 | 8,
639 | 8,
640 | 8,
641 | 8,
642 | 8,
643 | 8,
644 | 8,
645 | 8,
646 | 8,
647 | 14,
648 | 16,
649 | 8,
650 | 8,
651 | 8,
652 | 8,
653 | 8,
654 | 8,
655 | 8,
656 | 8,
657 | 8,
658 | 8,
659 | 8,
660 | 4,
661 | 2,
662 | 6,
663 | 4,
664 | 2,
665 | 14,
666 | 14,
667 | 14,
668 | 14,
669 | 16,
670 | 14,
671 | 10,
672 | 10,
673 | 10,
674 | 8,
675 | 8,
676 | 8,
677 | 4,
678 | 8,
679 | 8,
680 | 10,
681 | 8,
682 | 10,
683 | 12,
684 |
685 | //!!!}}INST_SIZE
686 | };
687 | }
688 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/Interpreter.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Interpreter.h"
3 |
4 | #include
5 |
6 | #include "vm/GlobalMetadata.h"
7 | #include "vm/MetadataLock.h"
8 | #include "vm/Class.h"
9 |
10 | #include "MethodBridge.h"
11 | #include "../metadata/MetadataModule.h"
12 | #include "../metadata/MetadataUtil.h"
13 | #include "../transform/Transform.h"
14 |
15 |
16 |
17 |
18 | namespace huatuo
19 | {
20 | namespace interpreter
21 | {
22 |
23 |
24 | }
25 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/Interpreter.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #include "codegen/il2cpp-codegen-il2cpp.h"
5 | #include "os/ThreadLocalValue.h"
6 |
7 | #include "Engine.h"
8 | #include "MethodBridge.h"
9 | #include "../metadata/MetadataDef.h"
10 | #include "../metadata/Image.h"
11 |
12 | namespace huatuo
13 | {
14 |
15 | namespace interpreter
16 | {
17 |
18 | class Interpreter
19 | {
20 | public:
21 | IL2CPP_FORCE_INLINE static void RuntimeClassCCtorInit(const MethodInfo* method)
22 | {
23 | Il2CppClass* klass = method->klass;
24 | il2cpp::vm::ClassInlines::InitFromCodegen(klass);
25 | if (!IS_CCTOR_FINISH_OR_NO_CCTOR(klass) && huatuo::metadata::IsStaticMethod(method))
26 | {
27 | il2cpp_codegen_runtime_class_init(klass);
28 | }
29 | }
30 |
31 | IL2CPP_FORCE_INLINE static void RuntimeClassCCtorInit(Il2CppClass* klass)
32 | {
33 | il2cpp::vm::ClassInlines::InitFromCodegen(klass);
34 | if (!IS_CCTOR_FINISH_OR_NO_CCTOR(klass))
35 | {
36 | il2cpp_codegen_runtime_class_init(klass);
37 | }
38 | }
39 |
40 | static void Execute(const MethodInfo* methodInfo, StackObject* args, void* ret);
41 |
42 | };
43 |
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/huatuo/interpreter/InterpreterDefs.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "../metadata/MetadataUtil.h"
3 |
4 | #include "MemoryUtil.h"
5 |
6 |
7 | namespace huatuo
8 | {
9 | namespace interpreter
10 | {
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/InterpreterDefs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "../CommonDef.h"
3 | #include "../metadata/MetadataDef.h"
4 |
5 | namespace huatuo
6 | {
7 | namespace interpreter
8 | {
9 |
10 | // from obj or arg
11 | enum class LocationDataType
12 | {
13 | I1,
14 | U1,
15 | I2,
16 | U2,
17 | U8,
18 | U16,
19 | S_12,
20 | S_16, // struct size == 16
21 | S_20,
22 | S_24, // struct size == 24
23 | S_28,
24 | S_32, // struct size == 32
25 | S_N, // struct size = 3,5,6,7, > 8, size is described by stackObjectSize
26 | };
27 |
28 | union StackObject
29 | {
30 | void* ptr; // can't adjust position. will raise native_invoke init args bugs.
31 | bool b;
32 | int8_t i8;
33 | uint8_t u8;
34 | int16_t i16;
35 | uint16_t u16;
36 | int32_t i32;
37 | uint32_t u32;
38 | int64_t i64;
39 | uint64_t u64;
40 | float f4;
41 | double f8;
42 | Il2CppObject* obj;
43 | Il2CppString* str;
44 | Il2CppObject** ptrObj;
45 | };
46 |
47 | static_assert(sizeof(StackObject) == 8, "requrie 64bit");
48 |
49 |
50 | enum class ExceptionFlowType
51 | {
52 | None,
53 | Exception,
54 | Leave,
55 | };
56 |
57 | struct InterpMethodInfo;
58 |
59 | struct ExceptionFlowInfo
60 | {
61 | ExceptionFlowType exFlowType;
62 | int32_t throwOffset;
63 | Il2CppException* ex;
64 | int32_t nextExClauseIndex;
65 | int32_t leaveTarget;
66 | };
67 |
68 | struct InterpFrame
69 | {
70 | const InterpMethodInfo* method;
71 | StackObject* stackBasePtr;
72 | ptrdiff_t oldStackTop;
73 | void* ret;
74 |
75 | byte* ip;
76 |
77 | //Il2CppException* saveException;
78 | std::vector* exHandleStack;
79 | ExceptionFlowInfo prevExFlowInfo;
80 | ExceptionFlowInfo curExFlowInfo;
81 |
82 | //std::vector *bigLocalAllocs;
83 | };
84 |
85 | struct InterpExceptionClause
86 | {
87 | metadata::CorILExceptionClauseType flags;
88 | int32_t tryBeginOffset;
89 | int32_t tryEndOffset;
90 | int32_t handlerBeginOffset;
91 | int32_t handlerEndOffset;
92 | int32_t filterBeginOffset;
93 | Il2CppClass* exKlass;
94 | };
95 |
96 | struct ArgDesc
97 | {
98 | LocationDataType type;
99 | uint32_t stackObjectSize; //
100 | };
101 |
102 | struct InterpMethodInfo
103 | {
104 | const MethodInfo* method;
105 | ArgDesc* args;
106 | uint32_t argCount;
107 | uint32_t argStackObjectSize;
108 | byte* codes;
109 | uint32_t codeLength;
110 | uint32_t maxStackSize; // args + locals + evalstack size
111 | uint32_t localVarBaseOffset;
112 | uint32_t evalStackBaseOffset;
113 | uint32_t localStackSize; // args + locals StackObject size
114 | std::vector resolveDatas;
115 | std::vector exClauses;
116 | uint32_t isTrivialCopyArgs : 1;
117 | };
118 | }
119 | }
--------------------------------------------------------------------------------
/huatuo/interpreter/InterpreterModule.cpp:
--------------------------------------------------------------------------------
1 | #include "InterpreterModule.h"
2 |
3 | #include "Interpreter.h"
4 |
5 | #include
6 |
7 | #include "vm/GlobalMetadata.h"
8 | #include "vm/MetadataLock.h"
9 | #include "vm/Class.h"
10 |
11 | #include "../metadata/MetadataModule.h"
12 | #include "../metadata/MetadataUtil.h"
13 | #include "../transform/Transform.h"
14 |
15 | #include "MethodBridge.h"
16 |
17 | namespace huatuo
18 | {
19 | namespace interpreter
20 | {
21 | il2cpp::os::ThreadLocalValue InterpreterModule::s_machineState;
22 |
23 | static std::unordered_map s_calls;
24 | static std::unordered_map s_invokes;
25 |
26 | MachineState& InterpreterModule::GetCurrentThreadMachineState()
27 | {
28 | MachineState* state = nullptr;
29 | s_machineState.GetValue((void**)&state);
30 | if (!state)
31 | {
32 | state = new MachineState();
33 | s_machineState.SetValue(state);
34 | }
35 | return *state;
36 | }
37 |
38 | void InterpreterModule::Initialize()
39 | {
40 | for (size_t i = 0; ; i++)
41 | {
42 | NativeCallMethod& method = g_callStub[i];
43 | if (!method.signature)
44 | {
45 | break;
46 | }
47 | s_calls.insert({ method.signature, method });
48 | }
49 |
50 | for (size_t i = 0; ; i++)
51 | {
52 | NativeInvokeMethod& method = g_invokeStub[i];
53 | if (!method.signature)
54 | {
55 | break;
56 | }
57 | s_invokes.insert({ method.signature, method });
58 | }
59 | }
60 |
61 | template
62 | const NativeCallMethod* GetNativeCallMethod(const T* method, bool forceStatic)
63 | {
64 | char sigName[1000];
65 | ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
66 | auto it = s_calls.find(sigName);
67 | return (it != s_calls.end()) ? &it->second : nullptr;
68 | }
69 |
70 | template
71 | const NativeInvokeMethod* GetNativeInvokeMethod(const T* method)
72 | {
73 | char sigName[1000];
74 | ComputeSignature(method, false, sigName, sizeof(sigName) - 1);
75 | auto it = s_invokes.find(sigName);
76 | return (it != s_invokes.end()) ? &it->second : nullptr;
77 | }
78 |
79 | static void RaiseMethodNotSupportException(const MethodInfo* method, const char* desc)
80 | {
81 | TEMP_FORMAT(errMsg, "%s. %s.%s::%s", desc, method->klass->namespaze, method->klass->name, method->name);
82 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
83 | }
84 |
85 | static void RaiseMethodNotSupportException(const Il2CppMethodDefinition* method, const char* desc)
86 | {
87 | Il2CppClass* klass = il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeDefinitionIndex(method->declaringType);
88 | TEMP_FORMAT(errMsg, "%s. %s.%s::%s", desc, klass->namespaze, klass->name, il2cpp::vm::GlobalMetadata::GetStringFromIndex(method->nameIndex));
89 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
90 | }
91 |
92 | static void NotSupportNative2Managed()
93 | {
94 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException("NotSupportNative2Managed"));
95 | }
96 |
97 | static void* NotSupportInvoke(Il2CppMethodPointer, const MethodInfo* method, void*, void**)
98 | {
99 | TEMP_FORMAT(errMsg, "Invoke method missing. %s.%s::%s", method->klass->namespaze, method->klass->name, method->name);
100 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
101 | return nullptr;
102 | }
103 |
104 | Il2CppMethodPointer InterpreterModule::GetMethodPointer(const Il2CppMethodDefinition* method)
105 | {
106 | const NativeCallMethod* ncm = GetNativeCallMethod(method, false);
107 | if (ncm)
108 | {
109 | return ncm->method;
110 | }
111 | //RaiseMethodNotSupportException(method, "GetMethodPointer");
112 | return (Il2CppMethodPointer)NotSupportNative2Managed;
113 | }
114 |
115 | Il2CppMethodPointer InterpreterModule::GetMethodPointer(const MethodInfo* method)
116 | {
117 | const NativeCallMethod* ncm = GetNativeCallMethod(method, false);
118 | if (ncm)
119 | {
120 | return ncm->method;
121 | }
122 | //RaiseMethodNotSupportException(method, "GetMethodPointer");
123 | return (Il2CppMethodPointer)NotSupportNative2Managed;
124 | }
125 |
126 | Il2CppMethodPointer InterpreterModule::GetAdjustThunkMethodPointer(const Il2CppMethodDefinition* method)
127 | {
128 | if (!huatuo::metadata::IsInstanceMethod(method))
129 | {
130 | return nullptr;
131 | }
132 | const NativeCallMethod* ncm = GetNativeCallMethod(method, false);
133 | if (ncm)
134 | {
135 | return ncm->adjustThunkMethod;
136 | }
137 | //RaiseMethodNotSupportException(method, "GetAdjustThunkMethodPointer");
138 | return (Il2CppMethodPointer)NotSupportNative2Managed;
139 | }
140 |
141 | Il2CppMethodPointer InterpreterModule::GetAdjustThunkMethodPointer(const MethodInfo* method)
142 | {
143 | if (!huatuo::metadata::IsInstanceMethod(method))
144 | {
145 | return nullptr;
146 | }
147 | const NativeCallMethod* ncm = GetNativeCallMethod(method, false);
148 | if (ncm)
149 | {
150 | return ncm->adjustThunkMethod;
151 | }
152 | //RaiseMethodNotSupportException(method, "GetAdjustThunkMethodPointer");
153 | return (Il2CppMethodPointer)NotSupportNative2Managed;
154 | }
155 |
156 | Managed2NativeCallMethod InterpreterModule::GetManaged2NativeMethodPointer(const MethodInfo* method, bool forceStatic)
157 | {
158 | const NativeCallMethod* ncm = GetNativeCallMethod(method, forceStatic);
159 | if (ncm)
160 | {
161 | return ncm->managed2NativeMethod;
162 | }
163 | char sigName[1000];
164 | ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
165 |
166 | TEMP_FORMAT(errMsg, "GetManaged2NativeMethodPointer. sinature:%s not support.", sigName);
167 | RaiseMethodNotSupportException(method, errMsg);
168 | return nullptr;
169 | }
170 |
171 | Managed2NativeCallMethod InterpreterModule::GetManaged2NativeMethodPointer(const metadata::ResolveStandAloneMethodSig& method)
172 | {
173 | char sigName[1000];
174 | ComputeSignature(&method.returnType, method.params, method.paramCount, false, sigName, sizeof(sigName) - 1);
175 | auto it = s_calls.find(sigName);
176 | if (it != s_calls.end())
177 | {
178 | return it->second.managed2NativeMethod;
179 | }
180 | TEMP_FORMAT(errMsg, "GetManaged2NativeMethodPointer. sinature:%s not support.", sigName);
181 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
182 | return nullptr;
183 | }
184 |
185 | InvokerMethod InterpreterModule::GetMethodInvoker(const Il2CppMethodDefinition* method)
186 | {
187 | const NativeInvokeMethod* nim = GetNativeInvokeMethod(method);
188 | if (nim)
189 | {
190 | return huatuo::metadata::IsInstanceMethod(method) ? nim->instanceMethod : nim->staticMethod;
191 | }
192 | //RaiseMethodNotSupportException(method, "GetMethodInvoker");
193 | return (InvokerMethod)NotSupportInvoke;
194 | }
195 |
196 | InvokerMethod InterpreterModule::GetMethodInvoker(const MethodInfo* method)
197 | {
198 | const NativeInvokeMethod* nim = GetNativeInvokeMethod(method);
199 | if (nim)
200 | {
201 | return huatuo::metadata::IsInstanceMethod(method) ? nim->instanceMethod : nim->staticMethod;
202 | }
203 | //RaiseMethodNotSupportException(method, "GetMethodInvoker");
204 | return (InvokerMethod)NotSupportInvoke;
205 | }
206 |
207 | InterpMethodInfo* InterpreterModule::GetInterpMethodInfo(const MethodInfo* methodInfo)
208 | {
209 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
210 |
211 | if (methodInfo->huatuoData)
212 | {
213 | return (InterpMethodInfo*)methodInfo->huatuoData;
214 | }
215 |
216 | metadata::Image* image = metadata::IsInterpreterMethod(methodInfo) ? huatuo::metadata::MetadataModule::GetImage(methodInfo->klass)
217 | : (metadata::Image*)huatuo::metadata::AOTHomologousImage::FindImageByAssembly(methodInfo->klass->image->assembly);
218 | IL2CPP_ASSERT(image);
219 |
220 | metadata::MethodBody* methodBody = image->GetMethodBody(methodInfo);
221 | if (methodBody == nullptr || methodBody->ilcodes == nullptr)
222 | {
223 | TEMP_FORMAT(errMsg, "%s.%s::%s method body is null. not support external method currently.", methodInfo->klass->namespaze, methodInfo->klass->name, methodInfo->name);
224 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
225 | }
226 | InterpMethodInfo* imi = new (IL2CPP_MALLOC_ZERO(sizeof(InterpMethodInfo))) InterpMethodInfo;
227 | transform::HiTransform::Transform(image, methodInfo, *methodBody, *imi);
228 | il2cpp::os::Atomic::FullMemoryBarrier();
229 | const_cast(methodInfo)->huatuoData = imi;
230 | return imi;
231 | }
232 | }
233 | }
234 |
235 |
--------------------------------------------------------------------------------
/huatuo/interpreter/InterpreterModule.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "os/ThreadLocalValue.h"
4 |
5 | #include "../CommonDef.h"
6 | #include "MethodBridge.h"
7 | #include "Engine.h"
8 | #include "../metadata/Image.h"
9 |
10 | namespace huatuo
11 | {
12 | namespace interpreter
13 | {
14 |
15 | class InterpreterModule
16 | {
17 | public:
18 | static void Initialize();
19 |
20 |
21 | static MachineState& GetCurrentThreadMachineState();
22 |
23 | static InterpMethodInfo* GetInterpMethodInfo(const MethodInfo* methodInfo);
24 |
25 | static Il2CppMethodPointer GetMethodPointer(const Il2CppMethodDefinition* method);
26 | static Il2CppMethodPointer GetMethodPointer(const MethodInfo* method);
27 | static Il2CppMethodPointer GetAdjustThunkMethodPointer(const Il2CppMethodDefinition* method);
28 | static Il2CppMethodPointer GetAdjustThunkMethodPointer(const MethodInfo* method);
29 | static Managed2NativeCallMethod GetManaged2NativeMethodPointer(const MethodInfo* method, bool forceStatic);
30 | static Managed2NativeCallMethod GetManaged2NativeMethodPointer(const metadata::ResolveStandAloneMethodSig& methodSig);
31 |
32 | static InvokerMethod GetMethodInvoker(const Il2CppMethodDefinition* method);
33 | static InvokerMethod GetMethodInvoker(const MethodInfo* method);
34 |
35 | private:
36 |
37 | static il2cpp::os::ThreadLocalValue s_machineState;
38 | };
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/huatuo/interpreter/MemoryUtil.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "InterpreterDefs.h"
3 |
4 | namespace huatuo
5 | {
6 | namespace interpreter
7 | {
8 |
9 | inline void Copy1(void* dst, void* src)
10 | {
11 | *(uint8_t*)dst = *(uint8_t*)src;
12 | }
13 |
14 | inline void Copy2(void* dst, void* src)
15 | {
16 | *(uint16_t*)dst = *(uint16_t*)src;
17 | }
18 |
19 | inline void Copy4(void* dst, void* src)
20 | {
21 | *(uint32_t*)dst = *(uint32_t*)src;
22 | }
23 |
24 | inline void Copy8(void* dst, void* src)
25 | {
26 | *(uint64_t*)dst = *(uint64_t*)src;
27 | }
28 |
29 | inline void Copy12(void* dst, void* src)
30 | {
31 | if (dst <= src)
32 | {
33 | *(uint64_t*)dst = *(uint64_t*)src;
34 | *(uint32_t*)((byte*)dst + 8) = *(uint32_t*)((byte*)src + 8);
35 | }
36 | else
37 | {
38 | *(uint32_t*)((byte*)dst + 8) = *(uint32_t*)((byte*)src + 8);
39 | *(uint64_t*)dst = *(uint64_t*)src;
40 | }
41 | }
42 |
43 | inline void Copy16(void* dst, void* src)
44 | {
45 | if (dst <= src)
46 | {
47 | *(uint64_t*)dst = *(uint64_t*)src;
48 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
49 | }
50 | else
51 | {
52 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
53 | *(uint64_t*)dst = *(uint64_t*)src;
54 | }
55 | }
56 |
57 | inline void Copy20(void* dst, void* src)
58 | {
59 | if (dst <= src)
60 | {
61 | *(uint64_t*)dst = *(uint64_t*)src;
62 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
63 | *(uint32_t*)((byte*)dst + 16) = *(uint32_t*)((byte*)src + 16);
64 | }
65 | else
66 | {
67 | *(uint32_t*)((byte*)dst + 16) = *(uint32_t*)((byte*)src + 16);
68 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
69 | *(uint64_t*)dst = *(uint64_t*)src;
70 | }
71 | }
72 |
73 | inline void Copy24(void* dst, void* src)
74 | {
75 | if (dst <= src)
76 | {
77 | *(uint64_t*)dst = *(uint64_t*)src;
78 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
79 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
80 | }
81 | else
82 | {
83 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
84 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
85 | *(uint64_t*)dst = *(uint64_t*)src;
86 | }
87 | }
88 |
89 | inline void Copy28(void* dst, void* src)
90 | {
91 | if (dst <= src)
92 | {
93 | *(uint64_t*)dst = *(uint64_t*)src;
94 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
95 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
96 | *(uint32_t*)((byte*)dst + 24) = *(uint32_t*)((byte*)src + 24);
97 | }
98 | else
99 | {
100 | *(uint32_t*)((byte*)dst + 24) = *(uint32_t*)((byte*)src + 24);
101 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
102 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
103 | *(uint64_t*)dst = *(uint64_t*)src;
104 | }
105 | }
106 |
107 | inline void Copy32(void* dst, void* src)
108 | {
109 | if (dst <= src)
110 | {
111 | *(uint64_t*)dst = *(uint64_t*)src;
112 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
113 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
114 | *(uint64_t*)((byte*)dst + 24) = *(uint64_t*)((byte*)src + 24);
115 | }
116 | else
117 | {
118 | *(uint64_t*)((byte*)dst + 24) = *(uint64_t*)((byte*)src + 24);
119 | *(uint64_t*)((byte*)dst + 16) = *(uint64_t*)((byte*)src + 16);
120 | *(uint64_t*)((byte*)dst + 8) = *(uint64_t*)((byte*)src + 8);
121 | *(uint64_t*)dst = *(uint64_t*)src;
122 | }
123 | }
124 |
125 | inline void CopyBySize(void* dst, void* src, uint32_t size)
126 | {
127 | switch (size)
128 | {
129 | case 1: Copy1(dst, src); break;
130 | case 2: Copy2(dst, src); break;
131 | case 4: Copy4(dst, src); break;
132 | case 8: Copy8(dst, src); break;
133 | case 12: Copy12(dst, src); break;
134 | case 16: Copy16(dst, src); break;
135 | default: std::memmove(dst, src, size); break;
136 | }
137 | }
138 |
139 | inline void InitDefault1(void* dst)
140 | {
141 | *(uint8_t*)dst = 0;
142 | }
143 |
144 | inline void InitDefault2(void* dst)
145 | {
146 | *(uint16_t*)dst = 0;
147 | }
148 |
149 | inline void InitDefault4(void* dst)
150 | {
151 | *(uint32_t*)dst = 0;
152 | }
153 |
154 | inline void InitDefault8(void* dst)
155 | {
156 | *(uint64_t*)dst = 0;
157 | }
158 |
159 | inline void InitDefault12(void* dst)
160 | {
161 | *(uint64_t*)dst = 0;
162 | *(uint32_t*)((byte*)dst + 8) = 0;
163 | }
164 |
165 | inline void InitDefault16(void* dst)
166 | {
167 | *(uint64_t*)dst = 0;
168 | *(uint64_t*)((byte*)dst + 8) = 0;
169 | }
170 |
171 | inline void InitDefault20(void* dst)
172 | {
173 | *(uint64_t*)dst = 0;
174 | *(uint64_t*)((byte*)dst + 8) = 0;
175 | *(uint32_t*)((byte*)dst + 16) = 0;
176 | }
177 |
178 | inline void InitDefault24(void* dst)
179 | {
180 | *(uint64_t*)dst = 0;
181 | *(uint64_t*)((byte*)dst + 8) = 0;
182 | *(uint64_t*)((byte*)dst + 16) = 0;
183 | }
184 |
185 | inline void InitDefault28(void* dst)
186 | {
187 | *(uint64_t*)dst = 0;
188 | *(uint64_t*)((byte*)dst + 8) = 0;
189 | *(uint64_t*)((byte*)dst + 16) = 0;
190 | *(uint32_t*)((byte*)dst + 24) = 0;
191 | }
192 |
193 | inline void InitDefault32(void* dst)
194 | {
195 | *(uint64_t*)dst = 0;
196 | *(uint64_t*)((byte*)dst + 8) = 0;
197 | *(uint64_t*)((byte*)dst + 16) = 0;
198 | *(uint64_t*)((byte*)dst + 24) = 0;
199 | }
200 |
201 | inline void InitDefaultN(void* dst, size_t size)
202 | {
203 | std::memset(dst, 0, size);
204 | }
205 |
206 | inline void SetConst1(void* dst, int8_t value)
207 | {
208 | *(int8_t*)dst = value;
209 | }
210 |
211 | inline void SetConst2(void* dst, int16_t value)
212 | {
213 | *(int16_t*)dst = value;
214 | }
215 |
216 | inline void SetConst4(void* dst, int32_t value)
217 | {
218 | *(int32_t*)dst = value;
219 | }
220 |
221 | inline void SetConst8(void* dst, int64_t value)
222 | {
223 | *(int64_t*)dst = value;
224 | }
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/huatuo/interpreter/MethodBridge.cpp:
--------------------------------------------------------------------------------
1 | #include "MethodBridge.h"
2 |
3 | #include
4 | #include "vm/ClassInlines.h"
5 | #include "vm/Object.h"
6 | #include "vm/Class.h"
7 |
8 | #include "../metadata/MetadataModule.h"
9 | #include "../metadata/MetadataUtil.h"
10 |
11 | #include "Interpreter.h"
12 | #include "MemoryUtil.h"
13 |
14 | namespace huatuo
15 | {
16 | namespace interpreter
17 | {
18 | ArgDesc GetValueTypeArgDescBySize(uint32_t size)
19 | {
20 | #if HUATUO_TARGET_ARM
21 | if (size <= 8)
22 | {
23 | return { LocationDataType::U8, 1 };
24 | }
25 | else if (size <= 16)
26 | {
27 | return { LocationDataType::U16, 2 };
28 | }
29 | else
30 | {
31 | return { LocationDataType::S_N, (uint32_t)metadata::GetStackSizeByByteSize(size) };
32 | }
33 | #else
34 | switch (size)
35 | {
36 | case 1:
37 | case 2:
38 | case 4:
39 | case 8: return { LocationDataType::U8, 1 };
40 | case 12: return { LocationDataType::S_12, 2 };
41 | case 16: return { LocationDataType::S_16, 2 };
42 | case 20: return { LocationDataType::S_20, 3 };
43 | case 24: return { LocationDataType::S_24, 3 };
44 | case 28: return { LocationDataType::S_28, 4 };
45 | case 32: return { LocationDataType::S_32, 4 };
46 | default: return { LocationDataType::S_N, (uint32_t)metadata::GetStackSizeByByteSize(size) };
47 | }
48 | #endif
49 | }
50 |
51 | ArgDesc GetTypeArgDesc(const Il2CppType* type)
52 | {
53 | if (type->byref)
54 | {
55 | return { LocationDataType::U8, 1 };
56 | }
57 | switch (type->type)
58 | {
59 | case IL2CPP_TYPE_BOOLEAN:
60 | case IL2CPP_TYPE_U1:
61 | return{ LocationDataType::U1, 1 };
62 | case IL2CPP_TYPE_I1:
63 | return{ LocationDataType::I1, 1 };
64 | case IL2CPP_TYPE_I2:
65 | return{ LocationDataType::I2, 1 };
66 | case IL2CPP_TYPE_CHAR:
67 | case IL2CPP_TYPE_U2:
68 | return{ LocationDataType::U2, 1 };
69 | case IL2CPP_TYPE_I4:
70 | case IL2CPP_TYPE_U4:
71 | case IL2CPP_TYPE_R4:
72 | case IL2CPP_TYPE_I8:
73 | case IL2CPP_TYPE_U8:
74 | case IL2CPP_TYPE_R8:
75 | case IL2CPP_TYPE_I:
76 | case IL2CPP_TYPE_U:
77 | case IL2CPP_TYPE_FNPTR:
78 | case IL2CPP_TYPE_PTR:
79 | case IL2CPP_TYPE_BYREF:
80 | case IL2CPP_TYPE_STRING:
81 | case IL2CPP_TYPE_ARRAY:
82 | case IL2CPP_TYPE_SZARRAY:
83 | case IL2CPP_TYPE_OBJECT:
84 | case IL2CPP_TYPE_CLASS:
85 | return{ LocationDataType::U8, 1 };
86 | case IL2CPP_TYPE_TYPEDBYREF:
87 | return GetValueTypeArgDescBySize(sizeof(Il2CppTypedRef));
88 | case IL2CPP_TYPE_VALUETYPE:
89 | {
90 | Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
91 | IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
92 | if (klass->enumtype)
93 | {
94 | return GetTypeArgDesc(&klass->castClass->byval_arg);
95 | }
96 | return GetValueTypeArgDescBySize(il2cpp::vm::Class::GetValueSize(klass, nullptr));
97 | }
98 | case IL2CPP_TYPE_GENERICINST:
99 | {
100 | Il2CppGenericClass* genericClass = type->data.generic_class;
101 | if (genericClass->type->type == IL2CPP_TYPE_CLASS)
102 | {
103 | IL2CPP_ASSERT(!IS_CLASS_VALUE_TYPE(il2cpp::vm::Class::FromIl2CppType(type)));
104 | return{ LocationDataType::U8, 1 };
105 | }
106 | else
107 | {
108 | Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
109 | IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
110 | return GetValueTypeArgDescBySize(il2cpp::vm::Class::GetValueSize(klass, nullptr));
111 | }
112 | }
113 | default:
114 | {
115 | RaiseHuatuoExecutionEngineException("not support arg type");
116 | return{ LocationDataType::U8, 1 };
117 | }
118 | }
119 | }
120 |
121 | void CopyArgs(StackObject* dstBase, StackObject* argBase, ArgDesc* args, uint32_t paramCount, uint32_t totalParamStackObjectSize)
122 | {
123 | uint32_t dstOffset = 0;
124 | for (uint32_t i = 0, n = paramCount; i < n; i++)
125 | {
126 | ArgDesc& arg = args[i];
127 | StackObject* dst = dstBase + dstOffset;
128 | StackObject* src = argBase + i;
129 | switch (arg.type)
130 | {
131 | case LocationDataType::I1:
132 | //{
133 | // dst->i64 = *(int8_t*)src;
134 | // ++dstOffset;
135 | // break;
136 | //}
137 | case LocationDataType::U1:
138 | //{
139 | // dst->i64 = *(uint8_t*)src;
140 | // ++dstOffset;
141 | // break;
142 | //}
143 | case LocationDataType::I2:
144 | //{
145 | // dst->i64 = *(int16_t*)src;
146 | // ++dstOffset;
147 | // break;
148 | //}
149 | case LocationDataType::U2:
150 | //{
151 | // dst->i64 = *(uint16_t*)src;
152 | // ++dstOffset;
153 | // break;
154 | //}
155 | case LocationDataType::U8:
156 | {
157 | dst->i64 = *(int64_t*)src;
158 | ++dstOffset;
159 | break;
160 | }
161 | case LocationDataType::U16:
162 | {
163 | Copy16(dst, *(void**)src);
164 | dstOffset += 2;
165 | break;
166 | }
167 | case LocationDataType::S_12:
168 | {
169 | // when size > 8, arg is ref to struct
170 | Copy12(dst, src->ptr);
171 | dstOffset += 2;
172 | break;
173 | }
174 | case LocationDataType::S_16:
175 | {
176 | // when size > 8, arg is ref to struct
177 | Copy16(dst, src->ptr);
178 | dstOffset += 2;
179 | break;
180 | }
181 | case LocationDataType::S_20:
182 | {
183 | Copy20(dst, src->ptr);
184 | dstOffset += 3;
185 | break;
186 | }
187 | case LocationDataType::S_24:
188 | {
189 | Copy24(dst, src->ptr);
190 | dstOffset += 3;
191 | break;
192 | }
193 | case LocationDataType::S_28:
194 | {
195 | Copy28(dst, src->ptr);
196 | dstOffset += 4;
197 | break;
198 | }
199 | case LocationDataType::S_32:
200 | {
201 | Copy32(dst, src->ptr);
202 | dstOffset += 4;
203 | break;
204 | }
205 | case LocationDataType::S_N:
206 | {
207 | std::memcpy(dst, src->ptr, arg.stackObjectSize * sizeof(StackObject));
208 | dstOffset += arg.stackObjectSize;
209 | break;
210 | }
211 | default:
212 | {
213 | RaiseHuatuoExecutionEngineException("CopyArgs not support data type");
214 | }
215 | }
216 | }
217 | IL2CPP_ASSERT(dstOffset == totalParamStackObjectSize);
218 | }
219 |
220 | bool IsPassArgAsValue(const Il2CppType* type, LocationDataType* locType)
221 | {
222 | ArgDesc argDesc = interpreter::GetTypeArgDesc(type);
223 | if (locType)
224 | {
225 | *locType = argDesc.type;
226 | }
227 | return argDesc.type <= LocationDataType::U8;
228 | }
229 |
230 | Il2CppObject* TranslateNativeValueToBoxValue(const Il2CppType* type, void* value)
231 | {
232 | if (type->byref)
233 | {
234 | IL2CPP_ASSERT(false);
235 | return nullptr;
236 | }
237 | Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
238 | return il2cpp::vm::Object::Box(klass, value);
239 | }
240 |
241 | const uint32_t kMaxByValueSize = 8;
242 |
243 | void ConvertInvokeArgs(StackObject* resultArgs, const MethodInfo* method, void** __args)
244 | {
245 | for (uint8_t i = 0; i < method->parameters_count; i++)
246 | {
247 | const Il2CppType* argType = GET_METHOD_PARAMETER_TYPE(method->parameters[i]);
248 | StackObject* dst = resultArgs + i;
249 |
250 | if (argType->byref)
251 | {
252 | dst->ptr = __args[i];
253 | }
254 | else if (huatuo::metadata::IsValueType(argType))
255 | {
256 | if (IsPassArgAsValue(argType))
257 | {
258 | dst->i64 = *(uint64_t*)__args[i];
259 | }
260 | else
261 | {
262 | dst->ptr = __args[i];
263 | }
264 | }
265 | //else if (argType->type == IL2CPP_TYPE_PTR)
266 | //{
267 | // dst->ptr = __args[i];
268 | //}
269 | else
270 | {
271 | dst->ptr = __args[i];
272 | }
273 | }
274 | }
275 |
276 | struct HFATypeInfo
277 | {
278 | const Il2CppType* eleType;
279 | int32_t count;
280 | };
281 |
282 |
283 | static bool ComputeHFATypeInfo0(Il2CppClass* klass, HFATypeInfo& typeInfo)
284 | {
285 | il2cpp::vm::Class::SetupFields(klass);
286 | for (uint16_t i = 0; i < klass->field_count; i++)
287 | {
288 | FieldInfo* field = klass->fields + i;
289 | const Il2CppType* ftype = field->type;
290 | if (!metadata::IsInstanceField(ftype))
291 | {
292 | continue;
293 | }
294 | if (ftype->byref)
295 | {
296 | return false;
297 | }
298 | if ((ftype->type != IL2CPP_TYPE_R4 && ftype->type != IL2CPP_TYPE_R8))
299 | {
300 | if (ftype->type == IL2CPP_TYPE_VALUETYPE || (ftype->type == IL2CPP_TYPE_GENERICINST && ftype->data.generic_class->type->type == IL2CPP_TYPE_VALUETYPE))
301 | {
302 | Il2CppClass* fieldKlass = il2cpp::vm::Class::FromIl2CppType(ftype);
303 | if (!ComputeHFATypeInfo0(fieldKlass, typeInfo))
304 | {
305 | return false;
306 | }
307 | }
308 | else
309 | {
310 | return false;
311 | }
312 | }
313 | else if (typeInfo.eleType == nullptr || metadata::IsTypeEqual(ftype, typeInfo.eleType))
314 | {
315 | typeInfo.eleType = ftype;
316 | ++typeInfo.count;
317 | }
318 | else
319 | {
320 | return false;
321 | }
322 | }
323 | return typeInfo.count <= 4;
324 | }
325 |
326 | static bool ComputeHFATypeInfo(Il2CppClass* klass, HFATypeInfo& typeInfo)
327 | {
328 | typeInfo = {};
329 | int32_t size = metadata::GetTypeValueSize(klass);
330 | switch (size)
331 | {
332 | case 8:
333 | case 12:
334 | case 16:
335 | case 24:
336 | case 32: break;
337 | default: return false;
338 | }
339 |
340 | bool isHFA = ComputeHFATypeInfo0(klass, typeInfo);
341 | if (isHFA && typeInfo.count >= 2 && typeInfo.count <= 4)
342 | {
343 | int32_t fieldSize = typeInfo.eleType->type == IL2CPP_TYPE_R4 ? 4 : 8;
344 | return size == fieldSize * typeInfo.count;
345 | }
346 | return false;
347 | }
348 |
349 | static void AppendString(char* sigBuf, size_t bufSize, size_t& pos, const char* str)
350 | {
351 | size_t len = std::strlen(str);
352 | if (pos + len < bufSize)
353 | {
354 | std::strcpy(sigBuf + pos, str);
355 | pos += len;
356 | }
357 | else
358 | {
359 | IL2CPP_ASSERT(false);
360 | }
361 | }
362 |
363 | static void AppendValueTypeSignature(Il2CppClass* klass, bool returnType, char* sigBuf, size_t bufferSize, size_t& pos)
364 | {
365 | int typeSize = il2cpp::vm::Class::GetValueSize(klass, nullptr);
366 | #if HUATUO_TARGET_ARM
367 | HFATypeInfo typeInfo = {};
368 | if (ComputeHFATypeInfo(klass, typeInfo))
369 | {
370 | if (typeInfo.eleType->type == IL2CPP_TYPE_R4)
371 | {
372 | switch (typeInfo.count)
373 | {
374 | case 2:
375 | {
376 | AppendString(sigBuf, bufferSize, pos, "vf2");
377 | return;
378 | }
379 | case 3:
380 | {
381 | AppendString(sigBuf, bufferSize, pos, "vf3");
382 | return;
383 | }
384 | case 4:
385 | {
386 | AppendString(sigBuf, bufferSize, pos, "vf4");
387 | return;
388 | }
389 | }
390 | }
391 | else
392 | {
393 | IL2CPP_ASSERT(typeInfo.eleType->type == IL2CPP_TYPE_R8);
394 | switch (typeInfo.count)
395 | {
396 | case 2:
397 | {
398 | AppendString(sigBuf, bufferSize, pos, "vd2");
399 | return;
400 | }
401 | case 3:
402 | {
403 | AppendString(sigBuf, bufferSize, pos, "vd3");
404 | return;
405 | }
406 | case 4:
407 | {
408 | AppendString(sigBuf, bufferSize, pos, "vd4");
409 | return;
410 | }
411 | }
412 | }
413 | }
414 | // FIXME HSV
415 |
416 | if (typeSize <= 8)
417 | {
418 | AppendString(sigBuf, bufferSize, pos, "i8");
419 | }
420 | else if (typeSize <= 16)
421 | {
422 | AppendString(sigBuf, bufferSize, pos, "s2");
423 | }
424 | else
425 | {
426 | if (returnType)
427 | {
428 | pos += std::sprintf(sigBuf + pos, "S%d", typeSize);
429 | }
430 | else
431 | {
432 | AppendString(sigBuf, bufferSize, pos, "sr");
433 | }
434 | }
435 | #else
436 | switch (typeSize)
437 | {
438 | case 1:
439 | case 2:
440 | case 4:
441 | case 8:
442 | {
443 | AppendString(sigBuf, bufferSize, pos, "i8");
444 | break;
445 | }
446 | default:
447 | {
448 | if (returnType)
449 | {
450 | pos += std::sprintf(sigBuf + pos, "S%d", typeSize);
451 | }
452 | else
453 | {
454 | AppendString(sigBuf, bufferSize, pos, "sr");
455 | }
456 | }
457 | }
458 | #endif
459 | }
460 |
461 | static bool IsGenericFullInstantiate(const Il2CppType* type)
462 | {
463 | switch (type->type)
464 | {
465 | case IL2CPP_TYPE_VAR:
466 | case IL2CPP_TYPE_MVAR: return false;
467 | case IL2CPP_TYPE_GENERICINST:
468 | {
469 | Il2CppGenericContext& gctx = type->data.generic_class->context;
470 | const Il2CppGenericInst* gis[] = { gctx.class_inst, gctx.method_inst };
471 |
472 | for (const Il2CppGenericInst* gi : gis)
473 | {
474 | if (!gi)
475 | {
476 | continue;
477 | }
478 | for (uint8_t i = 0; i < gi->type_argc; i++)
479 | {
480 | const Il2CppType* gtype = gi->type_argv[i];
481 | if (!IsGenericFullInstantiate(gtype))
482 | {
483 | return false;
484 | }
485 | }
486 | }
487 | return true;
488 | }
489 | default: return true;
490 |
491 | }
492 | }
493 |
494 | static void AppendSignature(const Il2CppType* type, bool returnType, char* sigBuf, size_t bufferSize, size_t& pos)
495 | {
496 | if (type->byref)
497 | {
498 | AppendString(sigBuf, bufferSize, pos, "i8");
499 | return;
500 | }
501 | switch (type->type)
502 | {
503 | case IL2CPP_TYPE_VOID: AppendString(sigBuf, bufferSize, pos, "v"); break;
504 | #if HUATUO_TARGET_ARM
505 | case IL2CPP_TYPE_BOOLEAN:
506 | case IL2CPP_TYPE_I1:
507 | case IL2CPP_TYPE_U1: AppendString(sigBuf, bufferSize, pos, "i1"); break;
508 | case IL2CPP_TYPE_I2:
509 | case IL2CPP_TYPE_U2:
510 | case IL2CPP_TYPE_CHAR: AppendString(sigBuf, bufferSize, pos, "i2"); break;
511 | case IL2CPP_TYPE_I4:
512 | case IL2CPP_TYPE_U4: AppendString(sigBuf, bufferSize, pos, "i4"); break;
513 | case IL2CPP_TYPE_R4: AppendString(sigBuf, bufferSize, pos, "r4"); break;
514 | #else
515 | case IL2CPP_TYPE_R4:
516 | #endif
517 | case IL2CPP_TYPE_R8: AppendString(sigBuf, bufferSize, pos, "r8"); break;
518 | case IL2CPP_TYPE_TYPEDBYREF:
519 | {
520 | IL2CPP_ASSERT(sizeof(Il2CppTypedRef) == sizeof(void*) * 3);
521 | AppendValueTypeSignature(il2cpp_defaults.typed_reference_class, returnType, sigBuf, bufferSize, pos);
522 | break;
523 | }
524 | case IL2CPP_TYPE_VALUETYPE:
525 | {
526 | Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
527 | IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
528 | AppendValueTypeSignature(klass, returnType, sigBuf, bufferSize, pos);
529 | break;
530 | }
531 | case IL2CPP_TYPE_GENERICINST:
532 | {
533 | const Il2CppType* underlyingGenericType = type->data.generic_class->type;
534 | if (underlyingGenericType->type == IL2CPP_TYPE_CLASS)
535 | {
536 | AppendString(sigBuf, bufferSize, pos, "i8");
537 | }
538 | else
539 | {
540 | IL2CPP_ASSERT(underlyingGenericType->type == IL2CPP_TYPE_VALUETYPE);
541 | if (!IsGenericFullInstantiate(type))
542 | {
543 | AppendString(sigBuf, bufferSize, pos, "#not_full_generic#");
544 | return;
545 | }
546 | Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
547 | IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
548 | AppendValueTypeSignature(klass, returnType, sigBuf, bufferSize, pos);
549 | }
550 | break;
551 | }
552 | default: AppendString(sigBuf, bufferSize, pos, "i8"); break;
553 | }
554 | }
555 |
556 | bool ComputeSignature(const Il2CppType* ret, const Il2CppType* params, uint32_t paramCount, bool instanceCall, char* sigBuf, size_t bufferSize)
557 | {
558 | size_t pos = 0;
559 | AppendSignature(ret, true, sigBuf, bufferSize, pos);
560 |
561 | if (instanceCall)
562 | {
563 | AppendString(sigBuf, bufferSize, pos, "i8");
564 | }
565 |
566 | for (uint8_t i = 0; i < paramCount; i++)
567 | {
568 | AppendSignature(params + i, false, sigBuf, bufferSize, pos);
569 | }
570 | sigBuf[pos] = 0;
571 | return true;
572 | }
573 |
574 | bool ComputeSignature(const Il2CppMethodDefinition* method, bool call, char* sigBuf, size_t bufferSize)
575 | {
576 | size_t pos = 0;
577 |
578 | const Il2CppImage* image = huatuo::metadata::MetadataModule::GetImage(method)->GetIl2CppImage();
579 |
580 | AppendSignature(huatuo::metadata::MetadataModule::GetIl2CppTypeFromEncodeIndex(method->returnType), true, sigBuf, bufferSize, pos);
581 |
582 | if (call && metadata::IsInstanceMethod(method))
583 | {
584 | AppendString(sigBuf, bufferSize, pos, "i8");
585 | }
586 |
587 | for (uint8_t i = 0; i < method->parameterCount; i++)
588 | {
589 | TypeIndex paramTypeIndex = huatuo::metadata::MetadataModule::GetParameterDefinitionFromIndex(image, method->parameterStart + i)->typeIndex;
590 | AppendSignature(huatuo::metadata::MetadataModule::GetIl2CppTypeFromEncodeIndex(paramTypeIndex), false, sigBuf, bufferSize, pos);
591 | }
592 | sigBuf[pos] = 0;
593 | return true;
594 | }
595 |
596 | bool ComputeSignature(const MethodInfo* method, bool call, char* sigBuf, size_t bufferSize)
597 | {
598 | size_t pos = 0;
599 |
600 | AppendSignature(method->return_type, true, sigBuf, bufferSize, pos);
601 |
602 | if (call && metadata::IsInstanceMethod(method))
603 | {
604 | AppendString(sigBuf, bufferSize, pos, "i8");
605 | }
606 |
607 | for (uint8_t i = 0; i < method->parameters_count; i++)
608 | {
609 | AppendSignature(GET_METHOD_PARAMETER_TYPE(method->parameters[i]), false, sigBuf, bufferSize, pos);
610 | }
611 | sigBuf[pos] = 0;
612 | return true;
613 | }
614 |
615 | }
616 | }
617 |
--------------------------------------------------------------------------------
/huatuo/interpreter/MethodBridge.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../CommonDef.h"
4 | #include "InterpreterDefs.h"
5 |
6 | namespace huatuo
7 | {
8 | namespace interpreter
9 | {
10 | union StackObject;
11 |
12 | typedef void (*Managed2NativeCallMethod)(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret);
13 | typedef void (*NativeClassCtor0)(Il2CppObject* obj, const MethodInfo* method);
14 |
15 | struct NativeCallMethod
16 | {
17 | const char* signature;
18 | Il2CppMethodPointer method;
19 | Il2CppMethodPointer adjustThunkMethod;
20 | Managed2NativeCallMethod managed2NativeMethod;
21 | };
22 |
23 | struct NativeInvokeMethod
24 | {
25 | const char* signature;
26 | InvokerMethod instanceMethod;
27 | InvokerMethod staticMethod;
28 | };
29 |
30 | extern NativeCallMethod g_callStub[];
31 | extern NativeInvokeMethod g_invokeStub[];
32 |
33 |
34 | template
35 | struct ValueTypeSize
36 | {
37 | uint8_t __value[N];
38 | };
39 |
40 | struct ValueTypeSize16
41 | {
42 | uint64_t low;
43 | uint64_t high;
44 | };
45 |
46 | inline bool IsNeedExpandLocationType(LocationDataType type)
47 | {
48 | return type < LocationDataType::U8;
49 | }
50 |
51 | ArgDesc GetTypeArgDesc(const Il2CppType* type);
52 |
53 | inline LocationDataType GetLocationDataTypeByType(const Il2CppType* type)
54 | {
55 | return GetTypeArgDesc(type).type;
56 | }
57 |
58 | inline void ExpandLocationData2StackDataByType(void* retValue, LocationDataType type)
59 | {
60 | switch (type)
61 | {
62 | case huatuo::interpreter::LocationDataType::I1:
63 | *(int32_t*)retValue = *(int8_t*)retValue;
64 | break;
65 | case huatuo::interpreter::LocationDataType::U1:
66 | *(int32_t*)retValue = *(uint8_t*)retValue;
67 | break;
68 | case huatuo::interpreter::LocationDataType::I2:
69 | *(int32_t*)retValue = *(int16_t*)retValue;
70 | break;
71 | case huatuo::interpreter::LocationDataType::U2:
72 | *(int32_t*)retValue = *(uint16_t*)retValue;
73 | break;
74 | default:
75 | break;
76 | }
77 | }
78 |
79 | inline void ExpandLocationData2StackDataByType(void* retValue, Il2CppTypeEnum type)
80 | {
81 | switch (type)
82 | {
83 | case IL2CPP_TYPE_BOOLEAN:
84 | case IL2CPP_TYPE_I1:
85 | *(int32_t*)retValue = *(int8_t*)retValue;
86 | break;
87 | case IL2CPP_TYPE_U1:
88 | *(int32_t*)retValue = *(uint8_t*)retValue;
89 | break;
90 | case IL2CPP_TYPE_I2:
91 | *(int32_t*)retValue = *(int16_t*)retValue;
92 | break;
93 | case IL2CPP_TYPE_U2:
94 | case IL2CPP_TYPE_CHAR:
95 | *(int32_t*)retValue = *(uint16_t*)retValue;
96 | break;
97 | default:
98 | break;
99 | }
100 | }
101 |
102 | ArgDesc GetValueTypeArgDescBySize(uint32_t size);
103 |
104 | inline bool IsSimpleStackObjectCopyArg(LocationDataType type)
105 | {
106 | return type <= LocationDataType::U8;
107 | }
108 |
109 | void CopyArgs(StackObject* dstBase, StackObject* argBase, ArgDesc* args, uint32_t paramCount, uint32_t totalParamStackObjectSize);
110 |
111 | inline void* AdjustValueTypeSelfPointer(Il2CppObject* __this, const MethodInfo* method)
112 | {
113 | return __this + IS_CLASS_VALUE_TYPE(__this->klass);
114 | }
115 |
116 | bool IsPassArgAsValue(const Il2CppType* type, LocationDataType* locType = nullptr);
117 | Il2CppObject* TranslateNativeValueToBoxValue(const Il2CppType* type, void* value);
118 | void ConvertInvokeArgs(StackObject* resultArgs, const MethodInfo* method, void** __args);
119 |
120 | bool ComputeSignature(const MethodInfo* method, bool call, char* sigBuf, size_t bufferSize);
121 | bool ComputeSignature(const Il2CppMethodDefinition* method, bool call, char* sigBuf, size_t bufferSize);
122 | bool ComputeSignature(const Il2CppType* ret, const Il2CppType* params, uint32_t paramCount, bool instanceCall, char* sigBuf, size_t bufferSize);
123 |
124 | }
125 | }
--------------------------------------------------------------------------------
/huatuo/metadata/AOTHomologousImage.cpp:
--------------------------------------------------------------------------------
1 | #include "AOTHomologousImage.h"
2 |
3 | #include "vm/MetadataLock.h"
4 | #include "vm/GlobalMetadata.h"
5 | #include "vm/Class.h"
6 | #include "vm/Image.h"
7 | #include "vm/Exception.h"
8 | #include "vm/MetadataCache.h"
9 | #include "metadata/GenericMetadata.h"
10 |
11 | namespace huatuo
12 | {
13 | namespace metadata
14 | {
15 | std::vector s_images;
16 |
17 |
18 | int32_t AOTHomologousImage::LoadMetadataForAOTAssembly(void* dllBytes, uint32_t dllSize)
19 | {
20 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
21 |
22 | AOTHomologousImage* image = new AOTHomologousImage();
23 | LoadImageErrorCode err = image->Load((byte*)CopyBytes(dllBytes, dllSize), dllSize);
24 | if (err != LoadImageErrorCode::OK)
25 | {
26 | return (int32_t)err;
27 | }
28 | if (FindImageByAssembly(image->GetAOTAssembly()))
29 | {
30 | return (int32_t)LoadImageErrorCode::HOMOLOGOUS_ASSEMBLY_HAS_LOADED;
31 | }
32 | image->InitRuntimeMetadatas();
33 | s_images.push_back(image);
34 | return 0;
35 | }
36 |
37 | AOTHomologousImage* AOTHomologousImage::FindImageByAssembly(const Il2CppAssembly* ass)
38 | {
39 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
40 | for (AOTHomologousImage* image : s_images)
41 | {
42 | if (image->_aotAssembly == ass)
43 | {
44 | return image;
45 | }
46 | }
47 | return nullptr;
48 | }
49 |
50 | void AOTHomologousImage::InitRuntimeMetadatas()
51 | {
52 | InitTypes();
53 | InitMethods();
54 | InitFields();
55 | }
56 |
57 | void AOTHomologousImage::InitTypes()
58 | {
59 | const Table& typeDefTb = _rawImage.GetTable(TableType::TYPEDEF);
60 | uint32_t typeCount = typeDefTb.rowNum;
61 | _il2cppTypeForTypeDefs.resize(typeCount);
62 | _typeDefs.resize(typeCount);
63 |
64 | Il2CppImage* image = _aotAssembly->image;
65 | //if (image->typeCount != typeCount)
66 | //{
67 | // RaiseHuatuoExecutionEngineException("image metadata not match");
68 | //}
69 | for (uint32_t index = 0; index < image->typeCount; index++)
70 | {
71 | Il2CppTypeDefinition* typeDef = (Il2CppTypeDefinition*)il2cpp::vm::MetadataCache::GetAssemblyTypeHandle(image, index);
72 | uint32_t rowIndex = DecodeTokenRowIndex(typeDef->token);
73 | IL2CPP_ASSERT(rowIndex > 0);
74 | if (rowIndex > typeCount)
75 | {
76 | continue;
77 | }
78 | TbTypeDef data = _rawImage.ReadTypeDef(rowIndex);
79 | uint32_t typeIndex = rowIndex - 1;
80 | _typeDefs[typeIndex] = typeDef;
81 | const Il2CppType* il2cppType = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDef->byvalTypeIndex);
82 | _il2cppTypeForTypeDefs[typeIndex] = il2cppType;
83 |
84 | const char* name1 = _rawImage.GetStringFromRawIndex(data.typeName);
85 | const char* name2 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(typeDef->nameIndex);
86 | if (std::strcmp(name1, name2))
87 | {
88 | RaiseHuatuoExecutionEngineException("metadata type not match");
89 | }
90 | const char* namespaze1 = _rawImage.GetStringFromRawIndex(data.typeNamespace);
91 | const char* namespaze2 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(typeDef->namespaceIndex);
92 | if (std::strcmp(namespaze1, namespaze2))
93 | {
94 | RaiseHuatuoExecutionEngineException("metadata type not match");
95 | }
96 | }
97 | }
98 |
99 | void AOTHomologousImage::InitMethods()
100 | {
101 | const Table& methodTb = _rawImage.GetTable(TableType::METHOD);
102 | _methodDefs.resize(methodTb.rowNum);
103 |
104 | for (Il2CppTypeDefinition* type : _typeDefs)
105 | {
106 | for (uint16_t i = 0; i < type->method_count; i++)
107 | {
108 | const Il2CppMethodDefinition* methodDef = il2cpp::vm::GlobalMetadata::GetMethodDefinitionFromIndex(type->methodStart + i);
109 | uint32_t rowIndex = DecodeTokenRowIndex(methodDef->token);
110 | IL2CPP_ASSERT(rowIndex > 0 && rowIndex <= methodTb.rowNum);
111 | uint32_t methodIndex = rowIndex - 1;
112 | IL2CPP_ASSERT(_methodDefs[methodIndex] == nullptr);
113 | _methodDefs[methodIndex] = methodDef;
114 |
115 | TbMethod methodData = _rawImage.ReadMethod(rowIndex);
116 | const char* name1 = _rawImage.GetStringFromRawIndex(methodData.name);
117 | const char* name2 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef->nameIndex);
118 | if (std::strcmp(name1, name2))
119 | {
120 | RaiseHuatuoExecutionEngineException("metadata method not match");
121 | }
122 | }
123 | }
124 | }
125 |
126 | void AOTHomologousImage::InitFields()
127 | {
128 | const Table& fieldTb = _rawImage.GetTable(TableType::FIELD);
129 | _fields.resize(fieldTb.rowNum);
130 |
131 | for (size_t i = 0; i < _typeDefs.size() ; i++)
132 | {
133 | Il2CppTypeDefinition* type = _typeDefs[i];
134 | for (uint16_t j = 0; j < type->field_count; j++)
135 | {
136 | const Il2CppFieldDefinition* fieldDef = il2cpp::vm::GlobalMetadata::GetFieldDefinitionFromTypeDefAndFieldIndex(type, j);
137 | uint32_t rowIndex = DecodeTokenRowIndex(fieldDef->token);
138 | IL2CPP_ASSERT(rowIndex > 0);
139 | uint32_t fieldIndex = rowIndex - 1;
140 | IL2CPP_ASSERT(_fields[fieldIndex].fieldDef == nullptr);
141 | if (rowIndex >= fieldTb.rowNum)
142 | {
143 | continue;
144 | }
145 | _fields[fieldIndex] = {(uint32_t)i, fieldDef};
146 |
147 | TbField fieldData = _rawImage.ReadField(rowIndex);
148 | const char* name1 = _rawImage.GetStringFromRawIndex(fieldData.name);
149 | const char* name2 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(fieldDef->nameIndex);
150 | if (std::strcmp(name1, name2))
151 | {
152 | RaiseHuatuoExecutionEngineException("metadata field not match");
153 | }
154 | }
155 | }
156 | }
157 |
158 | MethodBody* AOTHomologousImage::GetMethodBody(const MethodInfo* method)
159 | {
160 | uint32_t token = method->token;
161 | auto it = _token2MethodBodies.find(token);
162 | if (it != _token2MethodBodies.end())
163 | {
164 | return it->second;
165 | }
166 | TbMethod methodData = _rawImage.ReadMethod(DecodeTokenRowIndex(token));
167 | MethodBody* body = new (IL2CPP_MALLOC_ZERO(sizeof(MethodBody))) MethodBody();
168 | ReadMethodBody(*(Il2CppMethodDefinition*)GetUnderlyingMethodInfo(method)->methodMetadataHandle, methodData, *body);
169 | _token2MethodBodies.insert({ token, body });
170 | return body;
171 | }
172 |
173 | const Il2CppType* AOTHomologousImage::GetIl2CppTypeFromRawTypeDefIndex(uint32_t index)
174 | {
175 | IL2CPP_ASSERT((size_t)index < _il2cppTypeForTypeDefs.size());
176 | return _il2cppTypeForTypeDefs[index];
177 | }
178 |
179 | const Il2CppType* AOTHomologousImage::GetIl2CppTypeFromRawIndex(uint32_t index) const
180 | {
181 | return il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(index);
182 | }
183 |
184 | Il2CppGenericContainer* AOTHomologousImage::GetGenericContainerByRawIndex(uint32_t index)
185 | {
186 | return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(index);
187 | }
188 |
189 | const Il2CppMethodDefinition* AOTHomologousImage::GetMethodDefinitionFromRawIndex(uint32_t index)
190 | {
191 | IL2CPP_ASSERT((size_t)index < _methodDefs.size());
192 | return _methodDefs[index];
193 | }
194 |
195 | const Il2CppTypeDefinition* AOTHomologousImage::GetTypeFromRawIndex(uint32_t index) const
196 | {
197 | IL2CPP_ASSERT((size_t)index < _typeDefs.size());
198 | return _typeDefs[index];
199 | }
200 |
201 | Il2CppGenericContainer* AOTHomologousImage::GetGenericContainerByTypeDefIndex(int32_t typeDefIndex)
202 | {
203 | Il2CppTypeDefinition* type = (Il2CppTypeDefinition*)il2cpp::vm::GlobalMetadata::GetTypeHandleFromIndex(typeDefIndex);
204 | return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(type->genericContainerIndex);
205 | }
206 |
207 | const MethodInfo* AOTHomologousImage::GetMethodInfo(const Il2CppType* containerType, const Il2CppMethodDefinition* methodDef, const Il2CppGenericInst* instantiation, const Il2CppGenericContext* genericContext)
208 | {
209 | const Il2CppType* finalContainerType = TryInflateIfNeed(containerType, genericContext, true);
210 | const MethodInfo* method = GetMethodInfoFromMethodDef(containerType, methodDef);
211 | IL2CPP_ASSERT(method);
212 | // final genericContext = finalContainerType.class_inst + mri.instantiation
213 | if (instantiation)
214 | {
215 | const Il2CppGenericInst* finalClassIns = finalContainerType->type == IL2CPP_TYPE_GENERICINST ? finalContainerType->data.generic_class->context.class_inst : nullptr;
216 | const Il2CppGenericInst* finalMethodIns = instantiation;
217 | Il2CppGenericContext finalGenericContext = { finalClassIns, finalMethodIns };
218 | method = method->is_inflated ? method->genericMethod->methodDefinition : method;
219 | method = il2cpp::metadata::GenericMetadata::Inflate(method, &finalGenericContext);
220 | IL2CPP_ASSERT(method);
221 | }
222 | return method;
223 | }
224 |
225 | const MethodInfo* AOTHomologousImage::ResolveMethodInfo(const Il2CppType* type, const char* resolveMethodName, const MethodRefSig& resolveSig, const Il2CppGenericInst* genericInstantiation, const Il2CppGenericContext* genericContext)
226 | {
227 | if (type->type != IL2CPP_TYPE_ARRAY)
228 | {
229 | const Il2CppTypeDefinition* typeDef = GetUnderlyingTypeDefinition(type);
230 | const Il2CppGenericContainer* klassGenericContainer = GetGenericContainerFromIl2CppType(type);
231 | const char* typeName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(typeDef->nameIndex);
232 | for (uint32_t i = 0; i < typeDef->method_count; i++)
233 | {
234 | const Il2CppMethodDefinition* methodDef = il2cpp::vm::GlobalMetadata::GetMethodDefinitionFromIndex(typeDef->methodStart + i);
235 | const char* methodName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef->nameIndex);
236 | if (std::strcmp(resolveMethodName, methodName) == 0 && IsMatchMethodSig(methodDef, resolveSig, klassGenericContainer, genericInstantiation ? genericInstantiation->type_argc : 0))
237 | {
238 | return GetMethodInfo(type, methodDef, genericInstantiation, genericContext);
239 | }
240 | }
241 | }
242 | else
243 | {
244 | IL2CPP_ASSERT(genericInstantiation == nullptr);
245 | Il2CppClass* arrayKlass = il2cpp::vm::Class::FromIl2CppType(type);
246 | il2cpp::vm::Class::SetupMethods(arrayKlass);
247 | //const Il2CppType* genericClassInstArgv[] = { &arrayKlass->element_class->byval_arg };
248 | const Il2CppType** genericClassInstArgv = genericContext && genericContext->class_inst ? genericContext->class_inst->type_argv : nullptr;
249 | const Il2CppType** genericMethodInstArgv = genericContext && genericContext->method_inst ? genericContext->method_inst->type_argv : nullptr;
250 |
251 | // FIXME MEMORY LEAK
252 | for (uint16_t i = 0; i < arrayKlass->method_count; i++)
253 | {
254 | const MethodInfo* method = arrayKlass->methods[i];
255 | if (std::strcmp(resolveMethodName, method->name) == 0 && IsMatchMethodSig(method, resolveSig, genericClassInstArgv, genericMethodInstArgv))
256 | {
257 | return method;
258 | }
259 | }
260 | }
261 | RaiseMethodNotFindException(type, resolveMethodName);
262 | return nullptr;
263 | }
264 |
265 | const MethodInfo* AOTHomologousImage::ReadMethodInfoFromToken(const Il2CppGenericContainer* klassGenericContainer,
266 | const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext, Il2CppGenericInst* genericInst, TableType tableType, uint32_t rowIndex)
267 | {
268 | IL2CPP_ASSERT(rowIndex > 0);
269 | switch (tableType)
270 | {
271 | case TableType::METHOD:
272 | {
273 | const Il2CppMethodDefinition* methodDef = GetMethodDefinitionFromRawIndex(rowIndex - 1);
274 | const Il2CppTypeDefinition* declareType = (Il2CppTypeDefinition*)il2cpp::vm::GlobalMetadata::GetTypeHandleFromIndex(methodDef->declaringType);
275 | const Il2CppType* type = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(declareType->byvalTypeIndex);
276 | return GetMethodInfo(type, methodDef, genericInst, genericContext);
277 | }
278 | case TableType::MEMBERREF:
279 | {
280 | ResolveMemberRef rmr = {};
281 | ReadResolveMemberRefFromMemberRef(klassGenericContainer, methodGenericContainer, rowIndex, rmr);
282 | IL2CPP_ASSERT(rmr.parent.parentType == TableType::TYPEDEF || rmr.parent.parentType == TableType::TYPEREF || rmr.parent.parentType == TableType::TYPESPEC);
283 | IL2CPP_ASSERT(rmr.signature.memberType == TableType::METHOD_POINTER);
284 | if (genericContext)
285 | {
286 | rmr.parent.type = *TryInflateIfNeed(&rmr.parent.type, genericContext, true);
287 | }
288 | return ResolveMethodInfo(&rmr.parent.type, rmr.name, rmr.signature.method, genericInst, genericContext);
289 | }
290 | case TableType::METHODSPEC:
291 | {
292 | TbMethodSpec methodSpec = _rawImage.ReadMethodSpec(rowIndex);
293 | Il2CppGenericInst* genericInstantiation = nullptr;
294 | // FIXME! genericInstantiation memory leak
295 | ReadMethodSpecInstantiation(methodSpec.instantiation, klassGenericContainer, methodGenericContainer, genericInstantiation);
296 | // FIXME memory leak
297 | genericInstantiation = TryInflateGenericInst(genericInstantiation, genericContext);
298 |
299 | TableType methodTableType = DecodeMethodDefOrRefCodedIndexTableType(methodSpec.method);
300 | uint32_t methodRowIndex = DecodeMethodDefOrRefCodedIndexRowIndex(methodSpec.method);
301 | switch (methodTableType)
302 | {
303 | case TableType::METHOD:
304 | {
305 | return ReadMethodInfoFromToken(klassGenericContainer, methodGenericContainer, genericContext, genericInstantiation, methodTableType, methodRowIndex);
306 | }
307 | case TableType::MEMBERREF:
308 | {
309 | return ReadMethodInfoFromToken(klassGenericContainer, methodGenericContainer, genericContext, genericInstantiation, methodTableType, methodRowIndex);
310 | }
311 | default:
312 | {
313 | RaiseBadImageException("ReadMethodSpec invaild TableType");
314 | return nullptr;
315 | }
316 | }
317 | break;
318 | }
319 | default:
320 | {
321 | RaiseBadImageException("ReadMethodInfoFromToken invaild TableType");
322 | return nullptr;
323 | }
324 | }
325 | }
326 |
327 | const MethodInfo* AOTHomologousImage::GetMethodInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext)
328 | {
329 | auto key = std::tuple(token, genericContext);
330 | {
331 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
332 | auto it = _token2ResolvedDataCache.find(key);
333 | if (it != _token2ResolvedDataCache.end())
334 | {
335 | return (const MethodInfo*)it->second;
336 | }
337 | }
338 |
339 | const MethodInfo* method = ReadMethodInfoFromToken(klassGenericContainer, methodGenericContainer, genericContext,
340 | nullptr, DecodeTokenTableType(token), DecodeTokenRowIndex(token));
341 |
342 | IL2CPP_ASSERT(method);
343 | {
344 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
345 | _token2ResolvedDataCache.insert({ key, (void*)method });
346 | }
347 | return method;
348 | }
349 |
350 | void AOTHomologousImage::ReadFieldRefInfoFromToken(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, FieldRefInfo& ret)
351 | {
352 | IL2CPP_ASSERT(rowIndex > 0);
353 | if (tableType == TableType::FIELD)
354 | {
355 | AOTFieldData& fd = _fields[rowIndex - 1];
356 | ret.containerType = *_il2cppTypeForTypeDefs[fd.typeDefIndex];
357 | ret.field = fd.fieldDef;
358 | //ret.classType = *image.GetIl2CppTypeFromRawTypeDefIndex(DecodeMetadataIndex(ret.field->typeIndex));
359 | }
360 | else
361 | {
362 | IL2CPP_ASSERT(tableType == TableType::MEMBERREF);
363 | ReadFieldRefInfoFromMemberRef(klassGenericContainer, methodGenericContainer, rowIndex, ret);
364 | }
365 | }
366 |
367 | const FieldInfo* AOTHomologousImage::GetFieldInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext)
368 | {
369 | auto key = std::tuple(token, genericContext);
370 | {
371 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
372 | auto it = _token2ResolvedDataCache.find(key);
373 | if (it != _token2ResolvedDataCache.end())
374 | {
375 | return (const FieldInfo*)it->second;
376 | }
377 | }
378 |
379 | FieldRefInfo fri;
380 | ReadFieldRefInfoFromToken(klassGenericContainer, methodGenericContainer, DecodeTokenTableType(token), DecodeTokenRowIndex(token), fri);
381 | const Il2CppType* resultType = genericContext != nullptr ? il2cpp::metadata::GenericMetadata::InflateIfNeeded(&fri.containerType, genericContext, true) : &fri.containerType;
382 | const FieldInfo* fieldInfo = GetFieldInfoFromFieldRef(*resultType, fri.field);
383 | {
384 | il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
385 | _token2ResolvedDataCache.insert({ key, (void*)fieldInfo });
386 | }
387 | return fieldInfo;
388 | }
389 |
390 | void AOTHomologousImage::GetStandAloneMethodSigFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext, ResolveStandAloneMethodSig& methodSig)
391 | {
392 | RaiseHuatuoNotSupportedException("GetStandAloneMethodSigFromToken");
393 | }
394 |
395 | }
396 | }
397 |
398 |
--------------------------------------------------------------------------------
/huatuo/metadata/AOTHomologousImage.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Image.h"
3 |
4 | namespace huatuo
5 | {
6 | namespace metadata
7 | {
8 | struct AOTFieldData
9 | {
10 | uint32_t typeDefIndex; // rowIndex - 1
11 | const Il2CppFieldDefinition* fieldDef;
12 | };
13 |
14 | class AOTHomologousImage : public Image
15 | {
16 | public:
17 |
18 | static int32_t LoadMetadataForAOTAssembly(void* dllBytes, uint32_t dllSize);
19 |
20 | static AOTHomologousImage* FindImageByAssembly(const Il2CppAssembly* ass);
21 |
22 | AOTHomologousImage() : _aotAssembly(nullptr)
23 | {
24 |
25 | }
26 |
27 | const Il2CppAssembly* GetAOTAssembly() const
28 | {
29 | return _aotAssembly;
30 | }
31 |
32 | LoadImageErrorCode Load(const byte* imageData, size_t length)
33 | {
34 | LoadImageErrorCode err = _rawImage.Load(imageData, length);
35 | if (err != LoadImageErrorCode::OK)
36 | {
37 | return err;
38 | }
39 |
40 | TbAssembly data = _rawImage.ReadAssembly(1);
41 | const char* assName = _rawImage.GetStringFromRawIndex(data.name);
42 | const Il2CppAssembly* aotAss = il2cpp::vm::Assembly::GetLoadedAssembly(assName);
43 | // FIXME. not free memory.
44 | if (!aotAss)
45 | {
46 | return LoadImageErrorCode::AOT_ASSEMBLY_NOT_FIND;
47 | }
48 | if(huatuo::metadata::IsInterpreterImage(aotAss->image))
49 | {
50 | return LoadImageErrorCode::HOMOLOGOUS_ONLY_SUPPORT_AOT_ASSEMBLY;
51 | }
52 | _aotAssembly = aotAss;
53 |
54 | return LoadImageErrorCode::OK;
55 | }
56 |
57 | void InitRuntimeMetadatas();
58 |
59 | void InitTypes();
60 | void InitMethods();
61 | void InitFields();
62 |
63 | MethodBody* GetMethodBody(const MethodInfo* method) override;
64 |
65 | const Il2CppType* GetIl2CppTypeFromRawTypeDefIndex(uint32_t index) override;
66 | Il2CppGenericContainer* GetGenericContainerByRawIndex(uint32_t index) override;
67 | const Il2CppMethodDefinition* GetMethodDefinitionFromRawIndex(uint32_t index) override;
68 | const Il2CppType* GetIl2CppTypeFromRawIndex(uint32_t index) const override;
69 | const Il2CppTypeDefinition* GetTypeFromRawIndex(uint32_t index) const override;
70 | Il2CppGenericContainer* GetGenericContainerByTypeDefIndex(int32_t typeDefIndex) override;
71 | void ReadFieldRefInfoFromToken(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, FieldRefInfo& ret);
72 | const MethodInfo* ReadMethodInfoFromToken(const Il2CppGenericContainer* klassGenericContainer,
73 | const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext, Il2CppGenericInst* genericInst, TableType tableType, uint32_t rowIndex);
74 | const MethodInfo* GetMethodInfo(const Il2CppType* containerType, const Il2CppMethodDefinition* methodDef, const Il2CppGenericInst* instantiation, const Il2CppGenericContext* genericContext);
75 | const MethodInfo* ResolveMethodInfo(const Il2CppType* type, const char* resolveMethodName, const MethodRefSig& resolveSig, const Il2CppGenericInst* genericInstantiation, const Il2CppGenericContext* genericContext);
76 |
77 | const MethodInfo* GetMethodInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext) override;
78 | const FieldInfo* GetFieldInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext) override;
79 | void GetStandAloneMethodSigFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext, ResolveStandAloneMethodSig& methodSig) override;
80 |
81 | private:
82 | const Il2CppAssembly* _aotAssembly;
83 |
84 | std::vector _il2cppTypeForTypeDefs;
85 | std::vector _typeDefs;
86 |
87 | std::unordered_map _token2MethodBodies;
88 | std::vector< const Il2CppMethodDefinition*> _methodDefs;
89 |
90 | std::vector _fields;
91 | };
92 | }
93 | }
--------------------------------------------------------------------------------
/huatuo/metadata/Assembly.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Assembly.h"
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "os/File.h"
9 | #include "utils/MemoryMappedFile.h"
10 | #include "vm/Assembly.h"
11 | #include "vm/Image.h"
12 | #include "vm/Class.h"
13 | #include "vm/String.h"
14 |
15 | #include "Image.h"
16 | #include "MetadataModule.h"
17 | #include "MetadataUtil.h"
18 |
19 | namespace huatuo
20 | {
21 | namespace metadata
22 | {
23 |
24 | std::vector s_placeHolderAssembies;
25 |
26 |
27 |
28 | bool GetMappedFileBuffer(const char* assemblyFile, void*& buf, uint64_t& fileLength)
29 | {
30 | int err = 0;
31 | il2cpp::os::FileHandle* fh = il2cpp::os::File::Open(assemblyFile, FileMode::kFileModeOpen, FileAccess::kFileAccessRead, FileShare::kFileShareReadWrite, 0, &err);
32 |
33 | if (err != 0)
34 | {
35 | return false;
36 | }
37 |
38 | fileLength = il2cpp::os::File::GetLength(fh, &err);
39 | if (err != 0)
40 | {
41 | il2cpp::os::File::Close(fh, &err);
42 | return false;
43 | }
44 |
45 | buf = il2cpp::utils::MemoryMappedFile::Map(fh);
46 |
47 | il2cpp::os::File::Close(fh, &err);
48 | if (err != 0)
49 | {
50 | il2cpp::utils::MemoryMappedFile::Unmap(buf);
51 | buf = NULL;
52 | return false;
53 | }
54 | return true;
55 | }
56 |
57 | #if ENABLE_PLACEHOLDER_DLL == 1
58 | static const char* s_ignorePlaceHolderDlls[] =
59 | {
60 | "UnityEngine.",
61 | "Unity.",
62 | "WindowsRuntimeMetadata.dll",
63 | nullptr,
64 | };
65 |
66 | static bool NeedCreatePlaceHolderDll(const char* assemblyName)
67 | {
68 | // if assemblyName is path
69 | if (std::strstr(assemblyName, "/") || std::strstr(assemblyName, "\\"))
70 | {
71 | return false;
72 | }
73 | for (const char** ignoreDll = s_ignorePlaceHolderDlls; *ignoreDll; ignoreDll++)
74 | {
75 | if (std::strstr(assemblyName, *ignoreDll))
76 | {
77 | return false;
78 | }
79 | }
80 | return true;
81 | }
82 |
83 | static const char* CreateAssemblyNameWithoutExt(const char* assemblyName)
84 | {
85 | const char* extStr = std::strstr(assemblyName, ".dll");
86 | if (extStr)
87 | {
88 | size_t nameLen = extStr - assemblyName;
89 | char* name = (char*)IL2CPP_MALLOC(nameLen + 1);
90 | std::strncpy(name, assemblyName, nameLen);
91 | name[nameLen] = '\0';
92 | return name;
93 | }
94 | else
95 | {
96 | return CopyString(assemblyName);
97 | }
98 | }
99 |
100 | static Il2CppAssembly* CreatePlaceHolderAssembly(const char* assemblyName)
101 | {
102 | auto ass = new (IL2CPP_MALLOC_ZERO(sizeof(Il2CppAssembly))) Il2CppAssembly;
103 | auto image2 = new (IL2CPP_MALLOC_ZERO(sizeof(Il2CppImage))) Il2CppImage;
104 | ass->image = image2;
105 | ass->image->name = CopyString(assemblyName);
106 | ass->image->nameNoExt = ass->aname.name = CreateAssemblyNameWithoutExt(assemblyName);
107 | image2->assembly = ass;
108 | s_placeHolderAssembies.push_back(ass);
109 | return ass;
110 | }
111 |
112 | static Il2CppAssembly* FindPlaceHolderAssembly(const char* assemblyNameNoExt)
113 | {
114 | for (Il2CppAssembly* ass : s_placeHolderAssembies)
115 | {
116 | if (std::strcmp(ass->image->nameNoExt, assemblyNameNoExt) == 0)
117 | {
118 | return ass;
119 | }
120 | }
121 | return nullptr;
122 | }
123 | #endif
124 |
125 | Il2CppAssembly* Assembly::LoadFromFile(const char* assemblyFile)
126 | {
127 | void* fileBuffer;
128 | uint64_t fileLength;
129 | if (!GetMappedFileBuffer(assemblyFile, fileBuffer, fileLength))
130 | {
131 |
132 | #if ENABLE_PLACEHOLDER_DLL == 1
133 | if (!NeedCreatePlaceHolderDll(assemblyFile))
134 | {
135 | return nullptr;
136 | }
137 | return CreatePlaceHolderAssembly(assemblyFile);
138 | #else
139 | return nullptr;
140 | #endif
141 | }
142 |
143 | return LoadFromBytes((const byte*)fileBuffer, fileLength, false);
144 | }
145 |
146 | Il2CppAssembly* Assembly::LoadFromBytes(const void* assemblyData, uint64_t length, bool copyData)
147 | {
148 | return Create((const byte*)assemblyData, length, copyData);
149 | }
150 |
151 | Il2CppAssembly* Assembly::Create(const byte* assemblyData, uint64_t length, bool copyData)
152 | {
153 | if (!assemblyData)
154 | {
155 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentNullException("rawAssembly is null"));
156 | }
157 |
158 | uint32_t imageId = InterpreterImage::AllocImageIndex();
159 | if (imageId > kMaxLoadImageCount)
160 | {
161 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("exceed max image index", ""));
162 | }
163 | InterpreterImage* image = new InterpreterImage(imageId);
164 |
165 | if (copyData)
166 | {
167 | assemblyData = (const byte*)CopyBytes(assemblyData, length);
168 | }
169 | LoadImageErrorCode err = image->Load(assemblyData, (size_t)length);
170 |
171 |
172 | if (err != LoadImageErrorCode::OK)
173 | {
174 | if (copyData)
175 | {
176 | IL2CPP_FREE((void*)assemblyData);
177 | }
178 | TEMP_FORMAT(errMsg, "LoadImageErrorCode:%d", (int)err);
179 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetBadImageFormatException(errMsg));
180 | // when load a bad image, mean a fatal error. we don't clean image on purpose.
181 | }
182 |
183 | TbAssembly data = image->GetRawImage().ReadAssembly(1);
184 | const char* nameNoExt = image->GetStringFromRawIndex(data.name);
185 |
186 | Il2CppAssembly* ass;
187 | Il2CppImage* image2;
188 | if ((ass = FindPlaceHolderAssembly(nameNoExt)) != nullptr)
189 | {
190 | image2 = ass->image;
191 | IL2CPP_FREE((void*)ass->image->name);
192 | IL2CPP_FREE((void*)ass->image->nameNoExt);
193 | }
194 | else
195 | {
196 | ass = new (IL2CPP_MALLOC_ZERO(sizeof(Il2CppAssembly))) Il2CppAssembly;
197 | image2 = new (IL2CPP_MALLOC_ZERO(sizeof(Il2CppImage))) Il2CppImage;
198 | }
199 |
200 | image->InitBasic(image2);
201 | image->BuildIl2CppAssembly(ass);
202 | ass->image = image2;
203 |
204 | image->BuildIl2CppImage(image2);
205 | image2->name = ConcatNewString(ass->aname.name, ".dll");
206 | image2->nameNoExt = ass->aname.name;
207 | image2->assembly = ass;
208 |
209 | image->InitRuntimeMetadatas();
210 |
211 | return ass;
212 | }
213 | }
214 | }
215 |
216 |
--------------------------------------------------------------------------------
/huatuo/metadata/Assembly.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../CommonDef.h"
4 |
5 | namespace huatuo
6 | {
7 | namespace metadata
8 | {
9 |
10 | class Assembly
11 | {
12 | public:
13 | static Il2CppAssembly* LoadFromFile(const char* assemblyFile);
14 | static Il2CppAssembly* LoadFromBytes(const void* assemblyData, uint64_t length, bool copyData);
15 | private:
16 | static Il2CppAssembly* Create(const byte* assemblyData, uint64_t length, bool copyData);
17 | };
18 | }
19 | }
--------------------------------------------------------------------------------
/huatuo/metadata/BlobReader.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../CommonDef.h"
4 |
5 | namespace huatuo
6 | {
7 | namespace metadata
8 | {
9 |
10 | class BlobReader
11 | {
12 | public:
13 | BlobReader(const byte* buf, uint32_t length) : _buf(buf), _length(length), _readPos(0)
14 | {
15 |
16 | }
17 |
18 | const byte* GetData() const
19 | {
20 | return _buf;
21 | }
22 |
23 | uint32_t GetLength() const
24 | {
25 | return _length;
26 | }
27 |
28 | uint32_t GetReadPosition() const
29 | {
30 | return _readPos;
31 | }
32 |
33 | bool IsEmpty() const
34 | {
35 | return _readPos >= _length;
36 | }
37 |
38 | bool NonEmpty() const
39 | {
40 | return _readPos < _length;
41 | }
42 |
43 | int32_t ReadCompressedInt32()
44 | {
45 | uint32_t unsignedValue = ReadCompressedUint32();
46 | uint32_t value = unsignedValue >> 1;
47 | if (!(unsignedValue & 0x1))
48 | {
49 | return value;
50 | }
51 | if (value < 0x40)
52 | {
53 | return value - 0x40;
54 | }
55 | if (value < 0x2000)
56 | {
57 | return value - 0x2000;
58 | }
59 | if (value < 0x10000000)
60 | {
61 | return value - 0x10000000;
62 | }
63 | IL2CPP_ASSERT(value < 0x20000000);
64 | return value - 0x20000000;
65 | }
66 |
67 | static uint32_t ReadCompressedUint32(const byte* buf, uint32_t& lengthSize)
68 | {
69 | uint32_t firstByte = buf[0];
70 | if (firstByte < 128)
71 | {
72 | lengthSize = 1;
73 | return firstByte;
74 | }
75 | else if (firstByte < 192)
76 | {
77 | lengthSize = 2;
78 | return ((firstByte & 0x3f) << 8) | buf[1];
79 | }
80 | else if (firstByte < 224)
81 | {
82 | lengthSize = 4;
83 | return ((firstByte & 0x1f) << 24) | (((uint32_t)buf[1]) << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
84 | }
85 | else
86 | {
87 | RaiseHuatuoExecutionEngineException("bad metadata data. ReadEncodeLength fail");
88 | return 0;
89 | }
90 | }
91 |
92 | uint32_t ReadCompressedUint32()
93 | {
94 | uint32_t lengthSize;
95 | uint32_t value = ReadCompressedUint32(_buf + _readPos, lengthSize);
96 | _readPos += lengthSize;
97 | return value;
98 | }
99 |
100 | uint8_t ReadByte()
101 | {
102 | IL2CPP_ASSERT(_readPos < _length);
103 | return _buf[_readPos++];
104 | }
105 |
106 | uint16_t ReadUshort()
107 | {
108 | IL2CPP_ASSERT(_readPos + 2 <= _length);
109 | uint16_t value = *(uint16_t*)(_buf + _readPos);
110 | _readPos += 2;
111 | return value;
112 | }
113 |
114 | template
115 | T Read()
116 | {
117 | IL2CPP_ASSERT(_readPos + sizeof(T) <= _length);
118 | T value = *(T*)(_buf + _readPos);
119 | _readPos += sizeof(T);
120 | return value;
121 | }
122 |
123 | uint8_t PeekByte()
124 | {
125 | IL2CPP_ASSERT(_readPos < _length);
126 | return _buf[_readPos];
127 | }
128 |
129 | void SkipByte()
130 | {
131 | IL2CPP_ASSERT(_readPos < _length);
132 | ++_readPos;
133 | }
134 |
135 | const byte* GetAndSkipCurBytes(uint32_t len)
136 | {
137 | IL2CPP_ASSERT(_readPos + len <= _length);
138 | const byte* data = _buf + _readPos;
139 | _readPos += len;
140 | return data;
141 | }
142 |
143 | private:
144 | const byte* const _buf;
145 | const uint32_t _length;
146 | uint32_t _readPos;
147 | };
148 |
149 | }
150 | }
--------------------------------------------------------------------------------
/huatuo/metadata/Coff.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "../CommonDef.h"
3 |
4 |
5 | namespace huatuo
6 | {
7 | namespace metadata
8 | {
9 | struct PEHeader
10 | {
11 | uint16_t matchine;
12 | uint16_t sections;
13 | uint32_t timestamp;
14 | uint32_t ptrSymbolTable;
15 | uint32_t numSymbols;
16 | uint16_t optionalHeadersize;
17 | uint16_t characteristics;
18 | };
19 |
20 | struct PEDirEntry
21 | {
22 | uint32_t rva;
23 | uint32_t size;
24 | };
25 |
26 | struct CLIHeader
27 | {
28 | uint32_t cb;
29 | uint16_t majorRuntimeVersion;
30 | uint16_t minorRuntimeVersion;
31 | PEDirEntry metaData;
32 | uint32_t flags;
33 | uint32_t entryPointToken;
34 | PEDirEntry resources;
35 | uint64_t strongNameSignature;
36 | uint64_t codeManagerTable;
37 | uint64_t vTableFixups;
38 | uint64_t exportAddressTableJumps;
39 | uint64_t managedNativeHeader;
40 | };
41 |
42 |
43 | struct PESectionHeader
44 | {
45 | char name[8];
46 | uint32_t virtualSize;
47 | uint32_t virtualAddress;
48 | uint32_t sizeOfRawData;
49 | uint32_t ptrRawData;
50 | uint32_t ptrRelocations;
51 | uint32_t ptrLineNumbers;
52 | uint16_t numRelocation;
53 | uint16_t numLineNumber;
54 | uint32_t characteristics;
55 | };
56 |
57 | struct MetadataRootPartial
58 | {
59 | uint32_t signature;
60 | uint16_t majorVersion;
61 | uint16_t minorVersion;
62 | uint32_t reserved;
63 | uint32_t length;
64 | byte versionFirstByte;
65 | };
66 |
67 | struct StreamHeader
68 | {
69 | uint32_t offset;
70 | uint32_t size;
71 | char name[1];
72 | };
73 |
74 | struct TableStreamHeader
75 | {
76 | uint32_t reserved;
77 | uint8_t majorVersion;
78 | uint8_t minorVersion;
79 | uint8_t heapSizes;
80 | uint8_t reserved2;
81 | uint64_t valid;
82 | uint64_t sorted;
83 | uint32_t rows[1];
84 | // tables;
85 | };
86 |
87 | struct CliStream
88 | {
89 | const char* name;
90 | const byte* data;
91 | uint32_t size;
92 | };
93 |
94 | struct UserString
95 | {
96 | const char* data;
97 | uint32_t size;
98 | uint8_t flags;
99 | };
100 |
101 | struct Blob
102 | {
103 | const byte* data;
104 | uint32_t size;
105 | };
106 |
107 | struct Table
108 | {
109 | const byte* data;
110 | uint32_t rowMetaDataSize;
111 | uint32_t rowNum;
112 | bool vaild;
113 | bool sorted;
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/huatuo/metadata/Image.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "vm/GlobalMetadataFileInternals.h"
8 | #include "gc/GarbageCollector.h"
9 | #include "gc/Allocator.h"
10 | #include "gc/AppendOnlyGCHashMap.h"
11 |
12 | #include "RawImage.h"
13 | #include "VTableSetup.h"
14 | #include "MetadataUtil.h"
15 |
16 |
17 | namespace huatuo
18 | {
19 | namespace metadata
20 | {
21 |
22 | typedef std::tuple TokenGenericContextType;
23 |
24 | struct TokenGenericContextTypeHash {
25 | size_t operator()(const TokenGenericContextType x) const noexcept {
26 | return std::get<0>(x) * 0x9e3779b9 + (size_t)std::get<1>(x);
27 | }
28 | };
29 |
30 | struct TokenGenericContextTypeEqual
31 | {
32 | bool operator()(const TokenGenericContextType a, const TokenGenericContextType b) const {
33 | return std::get<0>(a) == std::get<0>(b) && std::get<1>(a) == std::get<1>(b);
34 | }
35 | };
36 |
37 | class Image
38 | {
39 | public:
40 |
41 | const RawImage& GetRawImage() const
42 | {
43 | return _rawImage;
44 | }
45 |
46 | // misc
47 | bool IsValueTypeFromToken(TableType tableType, uint32_t rowIndex);
48 | bool IsThreadStaticCtorToken(TableType tableType, uint32_t rowIndex);
49 | void ReadMemberRefParentFromToken(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, ResolveMemberRefParent& ret);
50 | void ReadTypeFromMemberRefParent(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, Il2CppType& type);
51 |
52 | const Il2CppTypeDefinition* GetTypeDefinition(uint32_t assemblyRefIndex, uint32_t typeNamespace, uint32_t typeName);
53 | // type
54 | void ReadType(BlobReader& reader, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppType& type);
55 |
56 | void ReadTypeFromTypeDef(uint32_t rowIndex, Il2CppType& type);
57 | void ReadTypeFromTypeRef(uint32_t rowIndex, Il2CppType& type);
58 | void ReadTypeFromTypeSpec(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, uint32_t rowIndex, Il2CppType& type);
59 | void ReadTypeFromToken(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, Il2CppType& type);
60 |
61 | void ReadTypeFromResolutionScope(uint32_t scope, uint32_t typeNamespace, uint32_t typeName, Il2CppType& type);
62 |
63 | void ReadArrayType(BlobReader& reader, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppArrayType& type);
64 | void ReadGenericClass(BlobReader& reader, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppGenericClass& type);
65 |
66 | // signature
67 | void ReadMemberRefSig(const Il2CppGenericContainer* klassGenericContainer, TbMemberRef& data, ResolveMemberRefSig& signature);
68 | void ReadFieldRefSig(BlobReader& reader, const Il2CppGenericContainer* klassGenericContainer, FieldRefSig& field);
69 | void ReadMethodRefSig(TbMemberRef& rowData, MethodRefSig& method);
70 | void ReadMethodSpecInstantiation(uint32_t signatureIdx, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppGenericInst*& genericInstantiation);
71 | void ReadLocalVarSig(BlobReader& reader, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppType*& vars, uint32_t& varCount);
72 | void ReadStandAloneSig(uint32_t signatureIdx, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, ResolveStandAloneMethodSig& sig);
73 |
74 | // resolve from token
75 | void ReadResolveMemberRefFromMemberRef(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, uint32_t rowIndex, ResolveMemberRef& ret);
76 | void ReadMethodRefInfoFromToken(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, TableType tableType, uint32_t rowIndex, MethodRefInfo& ret);
77 | void ReadMethodRefInfoFromMemberRef(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, Il2CppGenericInst* genericInstantiation, uint32_t rowIndex, MethodRefInfo& ret);
78 |
79 | void ReadFieldRefInfoFromMemberRef(const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, uint32_t rowIndex, FieldRefInfo& ret);
80 | void ReadMethodBody(const Il2CppMethodDefinition& methodDef, const TbMethod& methodData, MethodBody& body);
81 |
82 | Il2CppString* GetIl2CppUserStringFromRawIndex(StringIndex index);
83 | Il2CppClass* GetClassFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext);
84 | const FieldInfo* GetFieldInfoFromFieldRef(const Il2CppType& type, const Il2CppFieldDefinition* fieldDef);
85 | const void* GetRuntimeHandleFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext);
86 | const MethodInfo* FindImplMethod(Il2CppClass* klass, const MethodInfo* matchMethod);
87 |
88 | virtual const Il2CppType* GetIl2CppTypeFromRawTypeDefIndex(uint32_t index) = 0;
89 | virtual Il2CppGenericContainer* GetGenericContainerByRawIndex(uint32_t index) = 0;
90 | virtual const Il2CppMethodDefinition* GetMethodDefinitionFromRawIndex(uint32_t index) = 0;
91 | virtual const Il2CppType* GetIl2CppTypeFromRawIndex(uint32_t index) const = 0;
92 | virtual const Il2CppTypeDefinition* GetTypeFromRawIndex(uint32_t index) const = 0;
93 | virtual Il2CppGenericContainer* GetGenericContainerByTypeDefIndex(int32_t typeDefIndex) = 0;
94 |
95 | virtual MethodBody* GetMethodBody(const MethodInfo* method) = 0;
96 | virtual const MethodInfo* GetMethodInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext) = 0;
97 | virtual const FieldInfo* GetFieldInfoFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext) = 0;
98 | virtual void GetStandAloneMethodSigFromToken(uint32_t token, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer, const Il2CppGenericContext* genericContext, ResolveStandAloneMethodSig& methodSig) = 0;
99 |
100 | protected:
101 | RawImage _rawImage;
102 | il2cpp::gc::AppendOnlyGCHashMap> _il2cppStringCache;
103 |
104 | std::unordered_map, void*, TokenGenericContextTypeHash, TokenGenericContextTypeEqual> _token2ResolvedDataCache;
105 | };
106 | }
107 | }
--------------------------------------------------------------------------------
/huatuo/metadata/MetadataDef.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "il2cpp-config.h"
4 |
5 | #include "Coff.h"
6 | #include "Tables.h"
7 |
8 | namespace huatuo
9 | {
10 | namespace metadata
11 | {
12 |
13 | enum class CorILMethodFormat : uint8_t
14 | {
15 | Tiny = 0x2,
16 | Fat = 0x3,
17 | MoreSects = 0x8,
18 | InitLocals = 0x10,
19 | };
20 |
21 | enum class CorILSecion : uint8_t
22 | {
23 | EHTable = 0x1,
24 | OptILTable = 0x2,
25 | FatFormat = 0x40,
26 | MoreSects = 0x80,
27 | };
28 |
29 | enum class CorILExceptionClauseType
30 | {
31 | Exception = 0,
32 | Filter = 1,
33 | Finally = 2,
34 | Fault = 4,
35 | };
36 |
37 | struct CorILMethodFatHeader
38 | {
39 | uint16_t flags : 12;
40 | uint16_t size : 4;
41 | uint16_t maxStack;
42 | uint32_t codeSize;
43 | uint32_t localVarSigToken;
44 | };
45 |
46 | struct CorILEHSmall
47 | {
48 | uint16_t flags;
49 | uint16_t tryOffset;
50 | uint8_t tryLength;
51 | uint8_t handlerOffset0;
52 | uint8_t handlerOffset1;
53 | uint8_t handlerLength;
54 | uint32_t classTokenOrFilterOffset;
55 | };
56 |
57 | static_assert(sizeof(CorILEHSmall) == 12, "sizeof(CorILEHSmall) != 12");
58 |
59 | struct CorILEHFat
60 | {
61 | uint32_t flags;
62 | uint32_t tryOffset;
63 | uint32_t tryLength;
64 | uint32_t handlerOffset;
65 | uint32_t handlerLength;
66 | uint32_t classTokenOrFilterOffset;
67 | };
68 |
69 | static_assert(sizeof(CorILEHFat) == 24, "sizeof(CorILEHFat) != 24");
70 |
71 | struct CorILEHSectionHeaderSmall
72 | {
73 | uint8_t kind;
74 | uint8_t dataSize;
75 | uint16_t reserved;
76 | CorILEHSmall clauses[0];
77 | };
78 |
79 | #pragma pack(push, 1)
80 | struct CorILEHSectionHeaderFat
81 | {
82 | uint8_t kind;
83 | uint8_t dataSize0;
84 | uint8_t dataSize1;
85 | uint8_t dataSize2;
86 | CorILEHFat clauses[0];
87 | };
88 | #pragma pack(pop)
89 |
90 | const int MAX_TABLE_INDEX = 0x2C;
91 | const int TABLE_NUM = MAX_TABLE_INDEX + 1;
92 |
93 | class TagBits
94 | {
95 | public:
96 | static const uint32_t TypeDefOrRef = 2;
97 | static const uint32_t HasConstant = 2;
98 | static const uint32_t HasCustomAttribute = 5;
99 | static const uint32_t HasFieldMarshal = 1;
100 | static const uint32_t HasDeclSecurity = 2;
101 | static const uint32_t MemberRefParent = 3;
102 | static const uint32_t HasSemantics = 1;
103 | static const uint32_t MethodDefOrRef = 1;
104 | static const uint32_t MemberForwarded = 1;
105 | static const uint32_t Implementation = 2;
106 | static const uint32_t CustomAttributeType = 3;
107 | static const uint32_t ResoulutionScope = 2;
108 | static const uint32_t TypeOrMethodDef = 1;
109 |
110 | };
111 |
112 |
113 | const TableType HasCustomAttributeAssociateTables[] = {
114 | TableType::METHOD,
115 | TableType::FIELD,
116 | TableType::TYPEREF,
117 | TableType::TYPEDEF,
118 | TableType::PARAM,
119 | TableType::INTERFACEIMPL,
120 | TableType::MEMBERREF,
121 | TableType::MODULE,
122 | TableType::DECLSECURITY,
123 | TableType::PROPERTY,
124 | TableType::EVENT,
125 | TableType::STANDALONESIG,
126 | TableType::MODULEREF,
127 | TableType::TYPESPEC,
128 | TableType::ASSEMBLY,
129 | TableType::ASSEMBLYREF,
130 | TableType::FILE,
131 | TableType::EXPORTEDTYPE,
132 | TableType::MANIFESTRESOURCE,
133 | TableType::GENERICPARAM,
134 | TableType::GENERICPARAMCONSTRAINT,
135 | TableType::METHODSPEC,
136 | };
137 |
138 | inline TableType DecodeTokenTableType(uint32_t index)
139 | {
140 | return TableType(index >> 24);
141 | }
142 |
143 | inline uint32_t DecodeTokenRowIndex(uint32_t index)
144 | {
145 | return index & 0xFFFFFF;
146 | }
147 |
148 | struct ColumnOffsetSize
149 | {
150 | uint32_t size;
151 | uint16_t offset;
152 | };
153 |
154 | enum class SigType
155 | {
156 | DEFAULT = 0,
157 | C = 1,
158 | ST_STDCALL = 2,
159 | ST_THISCALL = 3,
160 | ST_FASTCALL = 4,
161 | VARARG = 5,
162 | FIELD = 6,
163 | LOCAL_VAR = 7,
164 | PROPERTY_NOT_THIS = 8,
165 | GENERIC = 0x10,
166 | SENTINEL = 0x41,
167 | };
168 |
169 | const uint32_t kSigMask = 0x0F;
170 |
171 | inline SigType DecodeSigType(uint8_t rawSigType)
172 | {
173 | return (SigType)(rawSigType & kSigMask);
174 | }
175 |
176 | inline uint8_t DecodeSigFlags(uint8_t rawSigType)
177 | {
178 | return (uint8_t)(rawSigType & 0xF0);
179 | }
180 |
181 | inline uint32_t EncodeToken(TableType type, uint32_t index)
182 | {
183 | return ((uint32_t)type << 24) | index;
184 | }
185 |
186 | inline void DecodeToken(uint32_t token, TableType& type, uint32_t& rowIndex)
187 | {
188 | type = (TableType)(token >> 24);
189 | rowIndex = token & 0xFFFFFF;
190 | }
191 |
192 | enum class MethodSigFlags
193 | {
194 | HAS_THIS = 0x20,
195 | EXPLICITTHIS = 0x40,
196 | DEFAULT = 0x0,
197 | VARARG = 0x5,
198 | GENERIC = 0x10,
199 | };
200 |
201 | inline Il2CppTypeEnum GetElementType(Il2CppTypeEnum encodeType)
202 | {
203 | return (Il2CppTypeEnum)((uint8_t)encodeType & 0x3f);
204 | }
205 |
206 | inline TableType DecodeTypeDefOrRefOrSpecCodedIndexTableType(uint32_t encodedToken)
207 | {
208 | switch (encodedToken & 0x3)
209 | {
210 | case 0: return TableType::TYPEDEF;
211 | case 1: return TableType::TYPEREF;
212 | case 2: return TableType::TYPESPEC;
213 | default: IL2CPP_ASSERT(false); return (TableType)-1;
214 | }
215 | }
216 |
217 | inline uint32_t DecodeTypeDefOrRefOrSpecCodedIndexRowIndex(uint32_t encodedToken)
218 | {
219 | return encodedToken >> 2;
220 | }
221 |
222 | inline uint32_t EncodeTypeDefOrRefOrSpecCodedIndex(TableType type, uint32_t rowIndex)
223 | {
224 | uint32_t tableBits;
225 | switch (type)
226 | {
227 | case TableType::TYPEDEF: tableBits = 0; break;
228 | case TableType::TYPEREF: tableBits = 1; break;
229 | case TableType::TYPESPEC: tableBits = 2; break;
230 | default: IL2CPP_ASSERT(0); tableBits = 0; break;
231 | }
232 | return (rowIndex << 2) | tableBits;
233 | }
234 |
235 | inline uint32_t ConvertTypeDefOrRefOrSpecToken2CodedIndex(uint32_t token)
236 | {
237 | TableType type;
238 | uint32_t rowIndex;
239 | DecodeToken(token, type, rowIndex);
240 |
241 | uint32_t tableBits;
242 | switch (type)
243 | {
244 | case TableType::TYPEDEF: tableBits = 0; break;
245 | case TableType::TYPEREF: tableBits = 1; break;
246 | case TableType::TYPESPEC: tableBits = 2; break;
247 | default: IL2CPP_ASSERT(0); tableBits = 0; break;
248 | }
249 | return (rowIndex << 2) | tableBits;
250 | }
251 |
252 | inline void DecodeResolutionScopeCodedIndex(uint32_t encodedToken, TableType& tokenType, uint32_t& rawIndex)
253 | {
254 | switch (encodedToken & 0x3)
255 | {
256 | case 0: tokenType = TableType::MODULE; break;
257 | case 1: tokenType = TableType::MODULEREF; break;
258 | case 2: tokenType = TableType::ASSEMBLYREF; break;
259 | case 3: tokenType = TableType::TYPEREF; break;
260 | }
261 | rawIndex = encodedToken >> 2;
262 | }
263 |
264 | inline TableType DecodeTypeOrMethodDefCodedIndexTableType(uint32_t encodeIndex)
265 | {
266 | switch (encodeIndex & 0x1)
267 | {
268 | case 0: return TableType::TYPEDEF;
269 | case 1: return TableType::METHOD;
270 | }
271 | IL2CPP_ASSERT(false);
272 | return (TableType)-1;
273 | }
274 |
275 | inline uint32_t DecodeTypeOrMethodDefCodedIndexRowIndex(uint32_t encodeIndex)
276 | {
277 | return encodeIndex >> 1;
278 | }
279 |
280 | inline TableType DecodeMethodDefOrRefCodedIndexTableType(uint32_t token)
281 | {
282 | switch (token & 0x1)
283 | {
284 | case 0: return TableType::METHOD;
285 | case 1: return TableType::MEMBERREF;
286 | }
287 | return (TableType)-1;
288 | }
289 |
290 | inline uint32_t DecodeMethodDefOrRefCodedIndexRowIndex(uint32_t token)
291 | {
292 | return token >> 1;
293 | }
294 |
295 | inline uint32_t EncodeMethodDefOrRefCodedIndex(TableType type, uint32_t rowIndex)
296 | {
297 | IL2CPP_ASSERT(type == TableType::METHOD || type == TableType::MEMBERREF);
298 | return (rowIndex << 1) | (type != TableType::METHOD);
299 | }
300 |
301 | inline uint32_t ConvertMethodDefOrRefToken2CodedIndex(uint32_t token)
302 | {
303 | TableType type;
304 | uint32_t rowIndex;
305 | DecodeToken(token, type, rowIndex);
306 | return EncodeMethodDefOrRefCodedIndex(type, rowIndex);
307 | }
308 |
309 | inline TableType DecodeMemberRefParentType(uint32_t token)
310 | {
311 | switch (token & 0x7)
312 | {
313 | case 0: return TableType::TYPEDEF;
314 | case 1: return TableType::TYPEREF;
315 | case 2: return TableType::MODULEREF;
316 | case 3: return TableType::METHOD;
317 | case 4: return TableType::TYPESPEC;
318 | default: IL2CPP_ASSERT(false); return (TableType)-1;
319 | }
320 | }
321 |
322 | inline uint32_t DecodeMemberRefParentRowIndex(uint32_t token)
323 | {
324 | return token >> 3;
325 | }
326 |
327 | inline TableType DecodeFieldDefOrDefType(uint32_t encodeIndex)
328 | {
329 | switch (encodeIndex & 0x1)
330 | {
331 | case 0: return TableType::FIELD;
332 | case 1: return TableType::MEMBERREF;
333 | }
334 | return (TableType)-1;
335 | }
336 |
337 | inline uint32_t DecodeFieldDefOrDefTypeRowIndex(uint32_t encodeIndex)
338 | {
339 | return encodeIndex >> 1;
340 | }
341 |
342 | inline uint32_t EncodeFieldDefOrRefCodedIndex(TableType type, uint32_t rowIndex)
343 | {
344 | IL2CPP_ASSERT(type == TableType::FIELD || type == TableType::MEMBERREF);
345 | return (rowIndex << 1) | (type != TableType::FIELD);
346 | }
347 |
348 | inline uint32_t ConvertFieldDefOrRefToken2CodedIndex(uint32_t token)
349 | {
350 | TableType type;
351 | uint32_t rowIndex;
352 | DecodeToken(token, type, rowIndex);
353 | return EncodeFieldDefOrRefCodedIndex(type, rowIndex);
354 | }
355 |
356 | inline TableType DecodeMemberRefParentCodedIndexTableType(uint32_t encodeIndex)
357 | {
358 | switch ((encodeIndex & 0x7))
359 | {
360 | case 0: return TableType::TYPEDEF;
361 | case 1: return TableType::TYPEREF;
362 | case 2: return TableType::MODULEREF;
363 | case 3: return TableType::METHOD;
364 | case 4: return TableType::TYPESPEC;
365 | default: IL2CPP_ASSERT(false); return (TableType)-1;
366 | }
367 | }
368 |
369 | inline uint32_t DecodeMemberRefParentCodedIndexRowIndex(uint32_t encodeIndex)
370 | {
371 | return encodeIndex >> 3;
372 | }
373 |
374 | inline TableType DecodeHasCustomAttributeCodedIndexTableType(uint32_t codedIndex)
375 | {
376 | switch (codedIndex & 0x1f)
377 | {
378 | case 0: return TableType::METHOD;
379 | case 1: return TableType::FIELD;
380 | case 2: return TableType::TYPEREF;
381 | case 3: return TableType::TYPEDEF;
382 | case 4: return TableType::PARAM;
383 | case 5: return TableType::INTERFACEIMPL;
384 | case 6: return TableType::MEMBERREF;
385 | case 7: return TableType::MODULE;
386 | case 8: return TableType::DECLSECURITY;
387 | case 9: return TableType::PROPERTY;
388 | case 10: return TableType::EVENT;
389 | case 11: return TableType::STANDALONESIG;
390 | case 12: return TableType::MODULEREF;
391 | case 13: return TableType::TYPESPEC;
392 | case 14: return TableType::ASSEMBLY;
393 | case 15: return TableType::ASSEMBLYREF;
394 | case 16: return TableType::FILE;
395 | case 17: return TableType::EXPORTEDTYPE;
396 | case 18: return TableType::MANIFESTRESOURCE;
397 | case 19: return TableType::GENERICPARAM;
398 | case 20: return TableType::GENERICPARAMCONSTRAINT;
399 | case 21: return TableType::METHODSPEC;
400 | default: IL2CPP_ASSERT(false); return (TableType)-1;
401 | }
402 | }
403 |
404 | inline uint32_t DecodeHasCustomAttributeCodedIndexRowIndex(uint32_t codedIndex)
405 | {
406 | return codedIndex >> 5;
407 | }
408 |
409 | inline TableType DecodeCustomAttributeTypeCodedIndexTableType(uint32_t codeIndex)
410 | {
411 | switch (codeIndex & 0x7)
412 | {
413 | case 2: return TableType::METHOD;
414 | case 3: return TableType::MEMBERREF;
415 | default: IL2CPP_ASSERT(false); return (TableType)-1;
416 | }
417 | }
418 |
419 | inline uint32_t DecodeCustomAttributeTypeCodedIndexRowIndex(uint32_t codedIndex)
420 | {
421 | return codedIndex >> 3;
422 | }
423 |
424 | enum class UserStringEncoding
425 | {
426 | ASCII = 0,
427 | Unicode = 1,
428 | };
429 |
430 | struct ExceptionClause
431 | {
432 | CorILExceptionClauseType flags;
433 | uint32_t tryOffset;
434 | uint32_t tryLength;
435 | uint32_t handlerOffsets;
436 | uint32_t handlerLength;
437 | uint32_t classTokenOrFilterOffset;
438 | };
439 |
440 | struct MethodBody
441 | {
442 | uint32_t flags;
443 | uint32_t codeSize;
444 | const uint8_t* ilcodes;
445 | Il2CppType* localVars;
446 | uint32_t localVarCount;
447 | uint32_t maxStack;
448 | std::vector exceptionClauses;
449 | // optional data sections
450 | };
451 |
452 |
453 |
454 | struct MethodRefInfo
455 | {
456 | Il2CppType containerType; // maybe generic
457 | const Il2CppMethodDefinition* methodDef;
458 | Il2CppGenericInst* instantiation;
459 | };
460 |
461 | struct MethodImpl
462 | {
463 | MethodRefInfo body;
464 | MethodRefInfo declaration;
465 | };
466 |
467 | struct MethodDefSig
468 | {
469 | Il2CppType classType;
470 | const char* name;
471 | uint32_t flags;
472 | uint32_t genericParamCount;
473 | Il2CppType returnType;
474 | std::vector params;
475 | };
476 |
477 | struct MethodRefSig
478 | {
479 | uint32_t flags;
480 | uint32_t genericParamCount;
481 | Il2CppType returnType;
482 | std::vector params;
483 | };
484 |
485 | struct FieldRefSig
486 | {
487 | Il2CppType type;
488 | };
489 |
490 | struct FieldRefInfo
491 | {
492 | Il2CppType containerType; // maybe generic
493 | const Il2CppFieldDefinition* field;
494 | };
495 |
496 | struct ResolveModuleRef
497 | {
498 |
499 | };
500 |
501 | struct ResolveMethodDef
502 | {
503 | const Il2CppMethodDefinition* methodDef;
504 | };
505 |
506 | struct ResolveMemberRefParent
507 | {
508 | TableType parentType;
509 | Il2CppType type; // TYPEREF, TYPEDEF,TYPESPEC
510 | ResolveModuleRef moduleRef;
511 | ResolveMethodDef methodDef;
512 | };
513 |
514 | struct ResolveMemberRefSig
515 | {
516 | TableType memberType; // FIELD_POINTER OR METHOD_POINTER
517 | MethodRefSig method;
518 | FieldRefSig field;
519 | };
520 |
521 | struct ResolveMemberRef
522 | {
523 | ResolveMemberRefParent parent;
524 | const char* name;
525 | ResolveMemberRefSig signature;
526 | };
527 |
528 | struct MemberRefInfo
529 | {
530 | TableType memberType;
531 | MethodRefInfo method;
532 | FieldRefInfo field;
533 | };
534 |
535 | struct ResolveStandAloneMethodSig
536 | {
537 | int32_t flags;
538 | uint32_t paramCount;
539 | Il2CppType returnType;
540 | Il2CppType* params;
541 | };
542 |
543 | inline TableType DecodeHasConstantType(uint32_t token)
544 | {
545 | switch (token & 0x3)
546 | {
547 | case 0: return TableType::FIELD;
548 | case 1: return TableType::PARAM;
549 | case 2: return TableType::PROPERTY;
550 | default: IL2CPP_ASSERT(false); return (TableType)-1;
551 | break;
552 | }
553 | }
554 |
555 | inline uint32_t DecodeHashConstantIndex(uint32_t token)
556 | {
557 | return token >> 2;
558 | }
559 |
560 | enum class MethodSemanticsAttributes
561 | {
562 | Setter = 0x1,
563 | Getter = 0x2,
564 | Other = 0x4,
565 | AddOn = 0x8,
566 | RemoveOn = 0x10,
567 | Fire = 0x20,
568 | };
569 |
570 | inline TableType DecodeHasSemanticsCodedIndexTableType(uint32_t codedIndex)
571 | {
572 | switch (codedIndex & 0x1)
573 | {
574 | case 0: return TableType::EVENT;
575 | case 1: return TableType::PROPERTY;
576 | }
577 | return (TableType)-1;
578 | }
579 |
580 | inline uint32_t DecodeHasSemanticsCodedIndexRowIndex(uint32_t codedIndex)
581 | {
582 | return codedIndex >> 1;
583 | }
584 | }
585 | }
--------------------------------------------------------------------------------
/huatuo/metadata/MetadataModule.cpp:
--------------------------------------------------------------------------------
1 | #include "MetadataModule.h"
2 |
3 | #include "Baselib.h"
4 | #include "Cpp/ReentrantLock.h"
5 | #include "os/Atomic.h"
6 | #include "os/Mutex.h"
7 | #include "os/File.h"
8 | #include "vm/Exception.h"
9 | #include "vm/String.h"
10 | #include "vm/Assembly.h"
11 | #include "vm/Class.h"
12 | #include "vm/Object.h"
13 | #include "vm/Image.h"
14 | #include "vm/MetadataLock.h"
15 | #include "utils/Logging.h"
16 | #include "utils/MemoryMappedFile.h"
17 | #include "utils/Memory.h"
18 |
19 | #include "InterpreterImage.h"
20 | #include "AOTHomologousImage.h"
21 |
22 | using namespace il2cpp;
23 |
24 | namespace huatuo
25 | {
26 |
27 | namespace metadata
28 | {
29 |
30 | void MetadataModule::Initialize()
31 | {
32 | InterpreterImage::Initialize();
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/huatuo/metadata/MetadataModule.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "InterpreterImage.h"
4 | #include "AOTHomologousImage.h"
5 | #include "Assembly.h"
6 |
7 | namespace huatuo
8 | {
9 |
10 | namespace metadata
11 | {
12 |
13 | class MetadataModule
14 | {
15 | public:
16 |
17 | static void Initialize();
18 |
19 | static InterpreterImage* GetImage(uint32_t imageIndex)
20 | {
21 | return InterpreterImage::GetImage(imageIndex);
22 | }
23 |
24 | static InterpreterImage* GetImage(const Il2CppImage* image)
25 | {
26 | return GetImage(DecodeImageIndex(image->token));
27 | }
28 |
29 | static InterpreterImage* GetImage(const Il2CppClass* klass)
30 | {
31 | return GetImage(klass->image);
32 | }
33 |
34 | static InterpreterImage* GetImage(const Il2CppTypeDefinition* typeDef)
35 | {
36 | return GetImage(DecodeImageIndex(typeDef->byvalTypeIndex));
37 | }
38 |
39 | static InterpreterImage* GetImage(const Il2CppMethodDefinition* typeDef)
40 | {
41 | return GetImage(DecodeImageIndex(typeDef->nameIndex));
42 | }
43 |
44 | static InterpreterImage* GetImageByEncodedIndex(uint32_t encodedIndex)
45 | {
46 | return GetImage(DecodeImageIndex(encodedIndex));
47 | }
48 |
49 | static const char* GetStringFromEncodeIndex(StringIndex index)
50 | {
51 | uint32_t imageIndex = DecodeImageIndex(index);
52 | return GetImage(imageIndex)->GetStringFromRawIndex(DecodeMetadataIndex(index));
53 | }
54 |
55 | static uint32_t GetTypeEncodeIndex(const Il2CppTypeDefinition* typeDef)
56 | {
57 | InterpreterImage* image = GetImage(typeDef);
58 | return huatuo::metadata::EncodeImageAndMetadataIndex(image->GetIndex(), image->GetTypeRawIndex(typeDef));
59 | }
60 |
61 | static Il2CppMetadataTypeHandle GetAssemblyTypeHandleFromRawIndex(const Il2CppImage* image, AssemblyTypeIndex index)
62 | {
63 | return GetImage(image)->GetAssemblyTypeHandleFromRawIndex(index);
64 | }
65 |
66 | static Il2CppMetadataTypeHandle GetAssemblyTypeHandleFromEncodeIndex(AssemblyTypeIndex index)
67 | {
68 | uint32_t imageIndex = DecodeImageIndex(index);
69 | return GetImage(imageIndex)->GetAssemblyTypeHandleFromRawIndex(DecodeMetadataIndex(index));
70 | }
71 |
72 | static Il2CppMetadataTypeHandle GetAssemblyExportedTypeHandleFromEncodeIndex(AssemblyTypeIndex index)
73 | {
74 | uint32_t imageIndex = DecodeImageIndex(index);
75 | return GetImage(imageIndex)->GetAssemblyExportedTypeHandleFromRawIndex(DecodeMetadataIndex(index));
76 | }
77 |
78 | static const Il2CppTypeDefinitionSizes* GetTypeDefinitionSizesFromEncodeIndex(TypeDefinitionIndex index)
79 | {
80 | uint32_t imageIndex = DecodeImageIndex(index);
81 | return GetImage(imageIndex)->GetTypeDefinitionSizesFromRawIndex(DecodeMetadataIndex(index));
82 | }
83 |
84 | static const Il2CppType* GetIl2CppTypeFromEncodeIndex(uint32_t index)
85 | {
86 | uint32_t imageIndex = DecodeImageIndex(index);
87 | IL2CPP_ASSERT(imageIndex > 0);
88 |
89 | uint32_t rawIndex = DecodeMetadataIndex(index);
90 | return GetImage(imageIndex)->GetIl2CppTypeFromRawIndex(rawIndex);
91 | }
92 |
93 | static Il2CppClass* GetTypeInfoFromTypeDefinitionEncodeIndex(TypeDefinitionIndex index)
94 | {
95 | uint32_t imageIndex = DecodeImageIndex(index);
96 | IL2CPP_ASSERT(imageIndex > 0);
97 |
98 | uint32_t rawIndex = DecodeMetadataIndex(index);
99 | return GetImage(imageIndex)->GetTypeInfoFromTypeDefinitionRawIndex(rawIndex);
100 | }
101 |
102 | static const Il2CppFieldDefinition* GetFieldDefinitionFromEncodeIndex(uint32_t index)
103 | {
104 | uint32_t imageIndex = DecodeImageIndex(index);
105 | return GetImage(imageIndex)->GetFieldDefinitionFromRawIndex(DecodeMetadataIndex(index));
106 | }
107 |
108 | static const Il2CppMethodDefinition* GetMethodDefinitionFromIndex(MethodIndex index)
109 | {
110 | uint32_t imageIndex = DecodeImageIndex(index);
111 | return GetImage(imageIndex)->GetMethodDefinitionFromRawIndex(DecodeMetadataIndex(index));
112 | }
113 |
114 | static uint32_t GetFieldOffset(const Il2CppClass* klass, int32_t fieldIndexInType, FieldInfo* field)
115 | {
116 | return GetImage(klass)->GetFieldOffset(klass, fieldIndexInType, field);
117 | }
118 |
119 | static const MethodInfo* GetMethodInfoFromMethodDefinitionIndex(uint32_t index)
120 | {
121 | uint32_t imageIndex = DecodeImageIndex(index);
122 | return GetImage(imageIndex)->GetMethodInfoFromMethodDefinitionRawIndex(DecodeMetadataIndex(index));
123 | }
124 |
125 | static const MethodInfo* GetMethodInfoFromMethodDefinition(const Il2CppMethodDefinition* methodDef)
126 | {
127 | uint32_t imageIndex = DecodeImageIndex(methodDef->nameIndex);
128 | return GetImage(imageIndex)->GetMethodInfoFromMethodDefinition(methodDef);
129 | }
130 |
131 | static const MethodInfo* GetMethodInfoFromVTableSlot(const Il2CppClass* klass, int32_t vTableSlot)
132 | {
133 | return GetImage(klass)->GetMethodInfoFromVTableSlot(klass, vTableSlot);
134 | }
135 |
136 | static const Il2CppMethodDefinition* GetMethodDefinitionFromVTableSlot(const Il2CppTypeDefinition* typeDefine, int32_t vTableSlot)
137 | {
138 | return GetImage(typeDefine)->GetMethodDefinitionFromVTableSlot(typeDefine, vTableSlot);
139 | }
140 |
141 | static Il2CppMethodPointer GetAdjustorThunk(const Il2CppImage* image, uint32_t token)
142 | {
143 | uint32_t imageIndex = DecodeImageIndex(image->token);
144 | return GetImage(imageIndex)->GetAdjustorThunk(token);
145 | }
146 |
147 | static Il2CppMethodPointer GetMethodPointer(const Il2CppImage* image, uint32_t token)
148 | {
149 | uint32_t imageIndex = DecodeImageIndex(image->token);
150 | return GetImage(imageIndex)->GetMethodPointer(token);
151 | }
152 |
153 | static InvokerMethod GetMethodInvoker(const Il2CppImage* image, uint32_t token)
154 | {
155 | uint32_t imageIndex = DecodeImageIndex(image->token);
156 | return GetImage(imageIndex)->GetMethodInvoker(token);
157 | }
158 |
159 | static const Il2CppParameterDefinition* GetParameterDefinitionFromIndex(const Il2CppImage* image, ParameterIndex index)
160 | {
161 | uint32_t imageIndex = DecodeImageIndex(image->token);
162 | return GetImage(imageIndex)->GetParameterDefinitionFromIndex(index);
163 | }
164 |
165 | static const Il2CppType* GetInterfaceFromOffset(const Il2CppClass* klass, TypeInterfaceIndex offset)
166 | {
167 | return GetImage(klass)->GetInterfaceFromOffset(klass, offset);
168 | }
169 |
170 | static const Il2CppType* GetInterfaceFromOffset(const Il2CppTypeDefinition* typeDefine, TypeInterfaceIndex offset)
171 | {
172 | return GetImage(typeDefine)->GetInterfaceFromOffset(typeDefine, offset);
173 | }
174 |
175 | static Il2CppInterfaceOffsetInfo GetInterfaceOffsetInfo(const Il2CppTypeDefinition* typeDefine, TypeInterfaceOffsetIndex index)
176 | {
177 | return GetImage(typeDefine)->GetInterfaceOffsetInfo(typeDefine, index);
178 | }
179 |
180 | static Il2CppClass* GetNestedTypeFromOffset(const Il2CppClass* klass, TypeNestedTypeIndex offset)
181 | {
182 | return GetImage(klass)->GetNestedTypeFromOffset(klass, offset);
183 | }
184 |
185 | static Il2CppMetadataTypeHandle GetNestedTypes(Il2CppMetadataTypeHandle handle, void** iter)
186 | {
187 | Il2CppTypeDefinition* typeDef = (Il2CppTypeDefinition*)handle;
188 | return (Il2CppMetadataTypeHandle)(GetImage(typeDef)->GetNestedTypes(typeDef, iter));
189 | }
190 |
191 | static const Il2CppGenericContainer* GetGenericContainerFromEncodeIndex(uint32_t index)
192 | {
193 | return GetImage(DecodeImageIndex(index))->GetGenericContainerByRawIndex(DecodeMetadataIndex(index));
194 |
195 | }
196 |
197 | static const Il2CppFieldDefaultValue* GetFieldDefaultValueEntry(uint32_t index)
198 | {
199 | return GetImage(DecodeImageIndex(index))->GetFieldDefaultValueEntryByRawIndex(DecodeMetadataIndex(index));
200 | }
201 |
202 | static const uint8_t* GetFieldOrParameterDefalutValue(uint32_t index)
203 | {
204 | return GetImage(DecodeImageIndex(index))->GetFieldOrParameterDefalutValueByRawIndex(DecodeMetadataIndex(index));
205 | }
206 |
207 | static bool HasAttribute(const Il2CppImage* image, uint32_t token, Il2CppClass* attribute)
208 | {
209 | return GetImage(image)->HasAttribute(token, attribute);
210 | }
211 |
212 | static std::tuple GetCustomAttributeDataRange(const Il2CppImage* image, uint32_t token)
213 | {
214 | return GetImage(image)->GetCustomAttributeDataRange(token);
215 | }
216 |
217 | static bool IsImplementedByInterpreter(MethodInfo* method)
218 | {
219 | Il2CppClass* klass = method->klass;
220 | Il2CppClass* parent = klass->parent;
221 | return parent != il2cpp_defaults.multicastdelegate_class && parent != il2cpp_defaults.delegate_class && AOTHomologousImage::FindImageByAssembly(klass->image->assembly);
222 | }
223 | private:
224 | };
225 | }
226 |
227 | }
--------------------------------------------------------------------------------
/huatuo/metadata/MetadataUtil.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #include "vm/GlobalMetadata.h"
5 | #include "vm/Exception.h"
6 |
7 | #include "../CommonDef.h"
8 | #include "MetadataDef.h"
9 |
10 | namespace huatuo
11 | {
12 | namespace metadata
13 | {
14 | class Image;
15 |
16 | #pragma region byteorder
17 |
18 | template
19 | inline void* GetAlignBorder(const void* pointer)
20 | {
21 | uint64_t p = (uint64_t)pointer;
22 | if (p % N == 0)
23 | {
24 | return (void*)pointer;
25 | }
26 | else
27 | {
28 | return (void*)((p + N - 1) / N * N);
29 | }
30 | }
31 |
32 | inline int32_t GetI1(const byte* data)
33 | {
34 | return *(int8_t*)data;
35 | }
36 |
37 | inline uint16_t GetU2LittleEndian(const byte* data)
38 | {
39 | return *(uint16_t*)data;
40 | }
41 |
42 | inline int16_t GetI2LittleEndian(const byte* data)
43 | {
44 | return *(int16_t*)data;
45 | }
46 |
47 | inline int32_t GetI4LittleEndian(const byte* data)
48 | {
49 | return *(int32_t*)data;
50 | }
51 |
52 | inline int64_t GetI8LittleEndian(const byte* data)
53 | {
54 | return *(int64_t*)data;
55 | }
56 |
57 | uint32_t GetNotZeroBitCount(uint64_t x);
58 |
59 | #pragma endregion
60 |
61 |
62 | #pragma region interpreter metadtata index
63 |
64 | const uint32_t kMetadataIndexBits = 26;
65 |
66 | const uint32_t kMetadataIndexMask = (1 << kMetadataIndexBits) - 1;
67 |
68 | const uint32_t kLoadImageIndexBits = 32 - kMetadataIndexBits;
69 |
70 | const uint32_t kMaxLoadImageCount = (1 << kLoadImageIndexBits) - 1;
71 |
72 | const int32_t kInvalidIndex = -1;
73 |
74 | inline uint32_t DecodeImageIndex(int32_t index)
75 | {
76 | return index != kInvalidIndex ? ((uint32_t)index) >> kMetadataIndexBits : 0;
77 | }
78 |
79 | inline uint32_t DecodeMetadataIndex(int32_t index)
80 | {
81 | return index != kInvalidIndex ? ((uint32_t)index) & kMetadataIndexMask : kInvalidIndex;
82 | }
83 |
84 | inline int32_t EncodeImageAndMetadataIndex(uint32_t imageIndex, int32_t rawIndex)
85 | {
86 | IL2CPP_ASSERT(rawIndex <= kMetadataIndexMask);
87 | return rawIndex != kInvalidIndex ? (imageIndex << kMetadataIndexBits) | rawIndex : kInvalidIndex;
88 | }
89 |
90 | inline bool IsInterpreterIndex(int32_t index)
91 | {
92 | return DecodeImageIndex(index) != 0;
93 | }
94 |
95 | inline bool IsInterpreterType(const Il2CppTypeDefinition* typeDefinition)
96 | {
97 | return IsInterpreterIndex(typeDefinition->byvalTypeIndex);
98 | }
99 |
100 | inline bool IsInterpreterType(const Il2CppClass* klass)
101 | {
102 | return IsInterpreterIndex(klass->image->token) && klass->rank == 0;
103 | }
104 |
105 | inline bool IsInterpreterImage(const Il2CppImage* image)
106 | {
107 | return IsInterpreterIndex(image->token);
108 | }
109 |
110 | #pragma endregion
111 |
112 |
113 | #pragma region method and klass
114 |
115 | inline bool IsInstanceField(const Il2CppType* type)
116 | {
117 | return (type->attrs & FIELD_ATTRIBUTE_STATIC) == 0;
118 | }
119 |
120 | inline bool IsInterpreterMethod(const MethodInfo* method)
121 | {
122 | return IsInterpreterType(method->klass);
123 | }
124 |
125 | inline bool IsInstanceMethod(const MethodInfo* method)
126 | {
127 | return !(method->flags & METHOD_ATTRIBUTE_STATIC);
128 | }
129 |
130 | inline bool IsInstanceMethod(const Il2CppMethodDefinition* method)
131 | {
132 | return !(method->flags & METHOD_ATTRIBUTE_STATIC);
133 | }
134 |
135 | inline bool IsStaticMethod(const MethodInfo* method)
136 | {
137 | return (method->flags & METHOD_ATTRIBUTE_STATIC);
138 | }
139 |
140 | inline bool IsPrivateMethod(uint32_t flags)
141 | {
142 | return (flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE;
143 | }
144 |
145 | inline bool IsGenericIns(const Il2CppType* type)
146 | {
147 | return type->type == IL2CPP_TYPE_GENERICINST;
148 | }
149 |
150 | inline bool IsVirtualMethod(uint32_t flags)
151 | {
152 | return flags & METHOD_ATTRIBUTE_VIRTUAL;
153 | }
154 |
155 | inline bool IsNewSlot(uint32_t flags)
156 | {
157 | return flags & METHOD_ATTRIBUTE_NEW_SLOT;
158 | }
159 |
160 | inline bool IsSealed(uint32_t flags)
161 | {
162 | return flags & METHOD_ATTRIBUTE_FINAL;
163 | }
164 |
165 | inline bool IsInterface(uint32_t flags)
166 | {
167 | return flags & TYPE_ATTRIBUTE_INTERFACE;
168 | }
169 |
170 | bool IsValueType(const Il2CppType* type);
171 |
172 | inline const Il2CppTypeDefinition* GetUnderlyingTypeDefinition(const Il2CppType* type)
173 | {
174 | if (IsGenericIns(type))
175 | {
176 | return (Il2CppTypeDefinition*)type->data.generic_class->type->data.typeHandle;
177 | }
178 | else
179 | {
180 | return (Il2CppTypeDefinition*)type->data.typeHandle;
181 | }
182 | }
183 |
184 | inline void GetIl2CppTypeFromTypeDefinition(const Il2CppTypeDefinition* typeDef, Il2CppType& type)
185 | {
186 | type.type = typeDef->bitfield & (1 << (il2cpp::vm::kBitIsValueType - 1)) ? IL2CPP_TYPE_VALUETYPE : IL2CPP_TYPE_CLASS;
187 | type.data.typeHandle = (Il2CppMetadataTypeHandle)typeDef;
188 | }
189 |
190 | inline uint32_t GetActualArgumentNum(const MethodInfo* method)
191 | {
192 | return (uint32_t)method->parameters_count + (!(method->flags & METHOD_ATTRIBUTE_STATIC));
193 | }
194 |
195 | inline bool IsReturnVoidMethod(const MethodInfo* method)
196 | {
197 | return method->return_type->type == IL2CPP_TYPE_VOID;
198 | }
199 |
200 | inline bool IsVoidType(const Il2CppType* type)
201 | {
202 | return type->type == IL2CPP_TYPE_VOID;
203 | }
204 |
205 | inline const MethodInfo* GetUnderlyingMethodInfo(const MethodInfo* method)
206 | {
207 | return !method->genericMethod || method->is_generic ? method : method->genericMethod->methodDefinition;
208 | }
209 |
210 |
211 | const Il2CppType* TryInflateIfNeed(const Il2CppType* selfType, const Il2CppGenericContext* genericContext, bool inflateMethodVars);
212 | const Il2CppType* TryInflateIfNeed(const Il2CppType* containerType, const Il2CppType* selfType);
213 |
214 | bool IsTypeSameByTypeIndex(TypeIndex t1, TypeIndex t2);
215 |
216 | bool IsTypeEqual(const Il2CppType* t1, const Il2CppType* t2);
217 |
218 | bool IsTypeGenericCompatible(const Il2CppType* t1, const Il2CppType* t2);
219 |
220 | bool IsExactlyMatch(const Il2CppMethodDefinition* src, const Il2CppMethodDefinition* dst);
221 |
222 | bool IsOverrideMethod(const Il2CppType* type1, const Il2CppMethodDefinition* method1, const Il2CppType* type2, const Il2CppMethodDefinition* method2);
223 | bool IsOverrideMethodIgnoreName(const Il2CppType* type1, const Il2CppMethodDefinition* methodDef1, const Il2CppType* type2, const Il2CppMethodDefinition* methodDef2);
224 |
225 | const Il2CppMethodDefinition* ResolveMethodDefinition(const Il2CppType* type, const char* resolveMethodName, const MethodRefSig& resolveSig, const Il2CppGenericInst* genericInstantiation);
226 |
227 | const MethodInfo* GetMethodInfoFromMethodDef(const Il2CppType* type, const Il2CppMethodDefinition* methodDef);
228 |
229 | bool ResolveField(const Il2CppType* type, const char* resolveFieldName, Il2CppType* resolveFieldType, const Il2CppFieldDefinition*& retFieldDef);
230 |
231 | const Il2CppGenericContainer* GetGenericContainerFromIl2CppType(const Il2CppType* type);
232 |
233 | bool IsMatchSigType(const Il2CppType* dstType, const Il2CppType* sigType, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer);
234 |
235 | bool IsMatchMethodSig(const Il2CppMethodDefinition* methodDef, const MethodRefSig& resolveSig, const Il2CppGenericContainer* klassGenericContainer, uint32_t genericArgCount);
236 | bool IsMatchMethodSig(const MethodInfo* methodDef, const MethodRefSig& resolveSig, const Il2CppGenericContainer* klassGenericContainer, uint32_t genericArgCount);
237 | bool IsMatchMethodSig(const MethodInfo* methodDef, const MethodRefSig& resolveSig, const Il2CppType** klassInstArgv, const Il2CppType** methodInstArgv);
238 |
239 | inline Il2CppType* CloneIl2CppType(const Il2CppType* type)
240 | {
241 | Il2CppType* newType = (Il2CppType*)IL2CPP_MALLOC(sizeof(Il2CppType));
242 | *newType = *type;
243 | return newType;
244 | }
245 |
246 | Il2CppGenericInst* TryInflateGenericInst(Il2CppGenericInst* inst, const Il2CppGenericContext* genericContext);
247 |
248 | #pragma endregion
249 |
250 |
251 | #pragma region misc
252 |
253 | int32_t GetTypeValueSize(const Il2CppType* type);
254 |
255 | inline int32_t GetTypeValueSize(const Il2CppClass* klass)
256 | {
257 | if (IS_CLASS_VALUE_TYPE(klass))
258 | {
259 | return il2cpp::vm::Class::GetValueSize((Il2CppClass*)klass, nullptr);
260 | }
261 | else
262 | {
263 | return sizeof(Il2CppObject*);
264 | }
265 | }
266 |
267 | inline int32_t GetStackSizeByByteSize(int32_t size)
268 | {
269 | return (size + 7) / 8;
270 | }
271 |
272 | inline int32_t GetTypeValueStackObjectCount(const Il2CppType* type)
273 | {
274 | return (GetTypeValueSize(type) + 7) / 8;
275 | }
276 |
277 | inline void RaiseBadImageException(const char* msg = nullptr)
278 | {
279 | il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetBadImageFormatException(msg));
280 | }
281 | #pragma endregion
282 |
283 | }
284 | }
--------------------------------------------------------------------------------
/huatuo/metadata/Opcodes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../CommonDef.h"
4 |
5 | namespace huatuo
6 | {
7 | namespace metadata
8 | {
9 | enum class OpcodeValue : uint8_t
10 | {
11 | //!!!{{OPCODE_VALUE
12 | NOP = 0,
13 | BREAK = 1,
14 | LDARG_0 = 2,
15 | LDARG_1 = 3,
16 | LDARG_2 = 4,
17 | LDARG_3 = 5,
18 | LDLOC_0 = 6,
19 | LDLOC_1 = 7,
20 | LDLOC_2 = 8,
21 | LDLOC_3 = 9,
22 | STLOC_0 = 10,
23 | STLOC_1 = 11,
24 | STLOC_2 = 12,
25 | STLOC_3 = 13,
26 | LDARG_S = 14,
27 | LDARGA_S = 15,
28 | STARG_S = 16,
29 | LDLOC_S = 17,
30 | LDLOCA_S = 18,
31 | STLOC_S = 19,
32 | LDNULL = 20,
33 | LDC_I4_M1 = 21,
34 | LDC_I4_0 = 22,
35 | LDC_I4_1 = 23,
36 | LDC_I4_2 = 24,
37 | LDC_I4_3 = 25,
38 | LDC_I4_4 = 26,
39 | LDC_I4_5 = 27,
40 | LDC_I4_6 = 28,
41 | LDC_I4_7 = 29,
42 | LDC_I4_8 = 30,
43 | LDC_I4_S = 31,
44 | LDC_I4 = 32,
45 | LDC_I8 = 33,
46 | LDC_R4 = 34,
47 | LDC_R8 = 35,
48 | UNUSED99 = 36,
49 | DUP = 37,
50 | POP = 38,
51 | JMP = 39,
52 | CALL = 40,
53 | CALLI = 41,
54 | RET = 42,
55 | BR_S = 43,
56 | BRFALSE_S = 44,
57 | BRTRUE_S = 45,
58 | BEQ_S = 46,
59 | BGE_S = 47,
60 | BGT_S = 48,
61 | BLE_S = 49,
62 | BLT_S = 50,
63 | BNE_UN_S = 51,
64 | BGE_UN_S = 52,
65 | BGT_UN_S = 53,
66 | BLE_UN_S = 54,
67 | BLT_UN_S = 55,
68 | BR = 56,
69 | BRFALSE = 57,
70 | BRTRUE = 58,
71 | BEQ = 59,
72 | BGE = 60,
73 | BGT = 61,
74 | BLE = 62,
75 | BLT = 63,
76 | BNE_UN = 64,
77 | BGE_UN = 65,
78 | BGT_UN = 66,
79 | BLE_UN = 67,
80 | BLT_UN = 68,
81 | SWITCH = 69,
82 | LDIND_I1 = 70,
83 | LDIND_U1 = 71,
84 | LDIND_I2 = 72,
85 | LDIND_U2 = 73,
86 | LDIND_I4 = 74,
87 | LDIND_U4 = 75,
88 | LDIND_I8 = 76,
89 | LDIND_I = 77,
90 | LDIND_R4 = 78,
91 | LDIND_R8 = 79,
92 | LDIND_REF = 80,
93 | STIND_REF = 81,
94 | STIND_I1 = 82,
95 | STIND_I2 = 83,
96 | STIND_I4 = 84,
97 | STIND_I8 = 85,
98 | STIND_R4 = 86,
99 | STIND_R8 = 87,
100 | ADD = 88,
101 | SUB = 89,
102 | MUL = 90,
103 | DIV = 91,
104 | DIV_UN = 92,
105 | REM = 93,
106 | REM_UN = 94,
107 | AND = 95,
108 | OR = 96,
109 | XOR = 97,
110 | SHL = 98,
111 | SHR = 99,
112 | SHR_UN = 100,
113 | NEG = 101,
114 | NOT = 102,
115 | CONV_I1 = 103,
116 | CONV_I2 = 104,
117 | CONV_I4 = 105,
118 | CONV_I8 = 106,
119 | CONV_R4 = 107,
120 | CONV_R8 = 108,
121 | CONV_U4 = 109,
122 | CONV_U8 = 110,
123 | CALLVIRT = 111,
124 | CPOBJ = 112,
125 | LDOBJ = 113,
126 | LDSTR = 114,
127 | NEWOBJ = 115,
128 | CASTCLASS = 116,
129 | ISINST = 117,
130 | CONV_R_UN = 118,
131 | UNUSED58 = 119,
132 | UNUSED1 = 120,
133 | UNBOX = 121,
134 | THROW = 122,
135 | LDFLD = 123,
136 | LDFLDA = 124,
137 | STFLD = 125,
138 | LDSFLD = 126,
139 | LDSFLDA = 127,
140 | STSFLD = 128,
141 | STOBJ = 129,
142 | CONV_OVF_I1_UN = 130,
143 | CONV_OVF_I2_UN = 131,
144 | CONV_OVF_I4_UN = 132,
145 | CONV_OVF_I8_UN = 133,
146 | CONV_OVF_U1_UN = 134,
147 | CONV_OVF_U2_UN = 135,
148 | CONV_OVF_U4_UN = 136,
149 | CONV_OVF_U8_UN = 137,
150 | CONV_OVF_I_UN = 138,
151 | CONV_OVF_U_UN = 139,
152 | BOX = 140,
153 | NEWARR = 141,
154 | LDLEN = 142,
155 | LDELEMA = 143,
156 | LDELEM_I1 = 144,
157 | LDELEM_U1 = 145,
158 | LDELEM_I2 = 146,
159 | LDELEM_U2 = 147,
160 | LDELEM_I4 = 148,
161 | LDELEM_U4 = 149,
162 | LDELEM_I8 = 150,
163 | LDELEM_I = 151,
164 | LDELEM_R4 = 152,
165 | LDELEM_R8 = 153,
166 | LDELEM_REF = 154,
167 | STELEM_I = 155,
168 | STELEM_I1 = 156,
169 | STELEM_I2 = 157,
170 | STELEM_I4 = 158,
171 | STELEM_I8 = 159,
172 | STELEM_R4 = 160,
173 | STELEM_R8 = 161,
174 | STELEM_REF = 162,
175 | LDELEM = 163,
176 | STELEM = 164,
177 | UNBOX_ANY = 165,
178 | UNUSED5 = 166,
179 | UNUSED6 = 167,
180 | UNUSED7 = 168,
181 | UNUSED8 = 169,
182 | UNUSED9 = 170,
183 | UNUSED10 = 171,
184 | UNUSED11 = 172,
185 | UNUSED12 = 173,
186 | UNUSED13 = 174,
187 | UNUSED14 = 175,
188 | UNUSED15 = 176,
189 | UNUSED16 = 177,
190 | UNUSED17 = 178,
191 | CONV_OVF_I1 = 179,
192 | CONV_OVF_U1 = 180,
193 | CONV_OVF_I2 = 181,
194 | CONV_OVF_U2 = 182,
195 | CONV_OVF_I4 = 183,
196 | CONV_OVF_U4 = 184,
197 | CONV_OVF_I8 = 185,
198 | CONV_OVF_U8 = 186,
199 | UNUSED50 = 187,
200 | UNUSED18 = 188,
201 | UNUSED19 = 189,
202 | UNUSED20 = 190,
203 | UNUSED21 = 191,
204 | UNUSED22 = 192,
205 | UNUSED23 = 193,
206 | REFANYVAL = 194,
207 | CKFINITE = 195,
208 | UNUSED24 = 196,
209 | UNUSED25 = 197,
210 | MKREFANY = 198,
211 | UNUSED59 = 199,
212 | UNUSED60 = 200,
213 | UNUSED61 = 201,
214 | UNUSED62 = 202,
215 | UNUSED63 = 203,
216 | UNUSED64 = 204,
217 | UNUSED65 = 205,
218 | UNUSED66 = 206,
219 | UNUSED67 = 207,
220 | LDTOKEN = 208,
221 | CONV_U2 = 209,
222 | CONV_U1 = 210,
223 | CONV_I = 211,
224 | CONV_OVF_I = 212,
225 | CONV_OVF_U = 213,
226 | ADD_OVF = 214,
227 | ADD_OVF_UN = 215,
228 | MUL_OVF = 216,
229 | MUL_OVF_UN = 217,
230 | SUB_OVF = 218,
231 | SUB_OVF_UN = 219,
232 | ENDFINALLY = 220,
233 | LEAVE = 221,
234 | LEAVE_S = 222,
235 | STIND_I = 223,
236 | CONV_U = 224,
237 | UNUSED26 = 225,
238 | UNUSED27 = 226,
239 | UNUSED28 = 227,
240 | UNUSED29 = 228,
241 | UNUSED30 = 229,
242 | UNUSED31 = 230,
243 | UNUSED32 = 231,
244 | UNUSED33 = 232,
245 | UNUSED34 = 233,
246 | UNUSED35 = 234,
247 | UNUSED36 = 235,
248 | UNUSED37 = 236,
249 | UNUSED38 = 237,
250 | UNUSED39 = 238,
251 | UNUSED40 = 239,
252 | UNUSED41 = 240,
253 | UNUSED42 = 241,
254 | UNUSED43 = 242,
255 | UNUSED44 = 243,
256 | UNUSED45 = 244,
257 | UNUSED46 = 245,
258 | UNUSED47 = 246,
259 | UNUSED48 = 247,
260 | PREFIX7 = 248,
261 | PREFIX6 = 249,
262 | PREFIX5 = 250,
263 | PREFIX4 = 251,
264 | PREFIX3 = 252,
265 | PREFIX2 = 253,
266 | PREFIX1 = 254,
267 | PREFIXREF = 255,
268 | ARGLIST = 0,
269 | CEQ = 1,
270 | CGT = 2,
271 | CGT_UN = 3,
272 | CLT = 4,
273 | CLT_UN = 5,
274 | LDFTN = 6,
275 | LDVIRTFTN = 7,
276 | UNUSED56 = 8,
277 | LDARG = 9,
278 | LDARGA = 10,
279 | STARG = 11,
280 | LDLOC = 12,
281 | LDLOCA = 13,
282 | STLOC = 14,
283 | LOCALLOC = 15,
284 | UNUSED57 = 16,
285 | ENDFILTER = 17,
286 | UNALIGNED_ = 18,
287 | VOLATILE_ = 19,
288 | TAIL_ = 20,
289 | INITOBJ = 21,
290 | CONSTRAINED_ = 22,
291 | CPBLK = 23,
292 | INITBLK = 24,
293 | NO_ = 25,
294 | RETHROW = 26,
295 | UNUSED = 27,
296 | SIZEOF = 28,
297 | REFANYTYPE = 29,
298 | READONLY_ = 30,
299 | UNUSED53 = 31,
300 | UNUSED54 = 32,
301 | UNUSED55 = 33,
302 | UNUSED70 = 34,
303 | ILLEGAL = 0,
304 | ENDMAC = 0,
305 |
306 | //!!!}}OPCODE_VALUE
307 | };
308 |
309 | enum class OpcodeEnum
310 | {
311 | //!!!{{OPCODE_ENUM
312 | NOP,
313 | BREAK,
314 | LDARG_0,
315 | LDARG_1,
316 | LDARG_2,
317 | LDARG_3,
318 | LDLOC_0,
319 | LDLOC_1,
320 | LDLOC_2,
321 | LDLOC_3,
322 | STLOC_0,
323 | STLOC_1,
324 | STLOC_2,
325 | STLOC_3,
326 | LDARG_S,
327 | LDARGA_S,
328 | STARG_S,
329 | LDLOC_S,
330 | LDLOCA_S,
331 | STLOC_S,
332 | LDNULL,
333 | LDC_I4_M1,
334 | LDC_I4_0,
335 | LDC_I4_1,
336 | LDC_I4_2,
337 | LDC_I4_3,
338 | LDC_I4_4,
339 | LDC_I4_5,
340 | LDC_I4_6,
341 | LDC_I4_7,
342 | LDC_I4_8,
343 | LDC_I4_S,
344 | LDC_I4,
345 | LDC_I8,
346 | LDC_R4,
347 | LDC_R8,
348 | UNUSED99,
349 | DUP,
350 | POP,
351 | JMP,
352 | CALL,
353 | CALLI,
354 | RET,
355 | BR_S,
356 | BRFALSE_S,
357 | BRTRUE_S,
358 | BEQ_S,
359 | BGE_S,
360 | BGT_S,
361 | BLE_S,
362 | BLT_S,
363 | BNE_UN_S,
364 | BGE_UN_S,
365 | BGT_UN_S,
366 | BLE_UN_S,
367 | BLT_UN_S,
368 | BR,
369 | BRFALSE,
370 | BRTRUE,
371 | BEQ,
372 | BGE,
373 | BGT,
374 | BLE,
375 | BLT,
376 | BNE_UN,
377 | BGE_UN,
378 | BGT_UN,
379 | BLE_UN,
380 | BLT_UN,
381 | SWITCH,
382 | LDIND_I1,
383 | LDIND_U1,
384 | LDIND_I2,
385 | LDIND_U2,
386 | LDIND_I4,
387 | LDIND_U4,
388 | LDIND_I8,
389 | LDIND_I,
390 | LDIND_R4,
391 | LDIND_R8,
392 | LDIND_REF,
393 | STIND_REF,
394 | STIND_I1,
395 | STIND_I2,
396 | STIND_I4,
397 | STIND_I8,
398 | STIND_R4,
399 | STIND_R8,
400 | ADD,
401 | SUB,
402 | MUL,
403 | DIV,
404 | DIV_UN,
405 | REM,
406 | REM_UN,
407 | AND,
408 | OR,
409 | XOR,
410 | SHL,
411 | SHR,
412 | SHR_UN,
413 | NEG,
414 | NOT,
415 | CONV_I1,
416 | CONV_I2,
417 | CONV_I4,
418 | CONV_I8,
419 | CONV_R4,
420 | CONV_R8,
421 | CONV_U4,
422 | CONV_U8,
423 | CALLVIRT,
424 | CPOBJ,
425 | LDOBJ,
426 | LDSTR,
427 | NEWOBJ,
428 | CASTCLASS,
429 | ISINST,
430 | CONV_R_UN,
431 | UNUSED58,
432 | UNUSED1,
433 | UNBOX,
434 | THROW,
435 | LDFLD,
436 | LDFLDA,
437 | STFLD,
438 | LDSFLD,
439 | LDSFLDA,
440 | STSFLD,
441 | STOBJ,
442 | CONV_OVF_I1_UN,
443 | CONV_OVF_I2_UN,
444 | CONV_OVF_I4_UN,
445 | CONV_OVF_I8_UN,
446 | CONV_OVF_U1_UN,
447 | CONV_OVF_U2_UN,
448 | CONV_OVF_U4_UN,
449 | CONV_OVF_U8_UN,
450 | CONV_OVF_I_UN,
451 | CONV_OVF_U_UN,
452 | BOX,
453 | NEWARR,
454 | LDLEN,
455 | LDELEMA,
456 | LDELEM_I1,
457 | LDELEM_U1,
458 | LDELEM_I2,
459 | LDELEM_U2,
460 | LDELEM_I4,
461 | LDELEM_U4,
462 | LDELEM_I8,
463 | LDELEM_I,
464 | LDELEM_R4,
465 | LDELEM_R8,
466 | LDELEM_REF,
467 | STELEM_I,
468 | STELEM_I1,
469 | STELEM_I2,
470 | STELEM_I4,
471 | STELEM_I8,
472 | STELEM_R4,
473 | STELEM_R8,
474 | STELEM_REF,
475 | LDELEM,
476 | STELEM,
477 | UNBOX_ANY,
478 | UNUSED5,
479 | UNUSED6,
480 | UNUSED7,
481 | UNUSED8,
482 | UNUSED9,
483 | UNUSED10,
484 | UNUSED11,
485 | UNUSED12,
486 | UNUSED13,
487 | UNUSED14,
488 | UNUSED15,
489 | UNUSED16,
490 | UNUSED17,
491 | CONV_OVF_I1,
492 | CONV_OVF_U1,
493 | CONV_OVF_I2,
494 | CONV_OVF_U2,
495 | CONV_OVF_I4,
496 | CONV_OVF_U4,
497 | CONV_OVF_I8,
498 | CONV_OVF_U8,
499 | UNUSED50,
500 | UNUSED18,
501 | UNUSED19,
502 | UNUSED20,
503 | UNUSED21,
504 | UNUSED22,
505 | UNUSED23,
506 | REFANYVAL,
507 | CKFINITE,
508 | UNUSED24,
509 | UNUSED25,
510 | MKREFANY,
511 | UNUSED59,
512 | UNUSED60,
513 | UNUSED61,
514 | UNUSED62,
515 | UNUSED63,
516 | UNUSED64,
517 | UNUSED65,
518 | UNUSED66,
519 | UNUSED67,
520 | LDTOKEN,
521 | CONV_U2,
522 | CONV_U1,
523 | CONV_I,
524 | CONV_OVF_I,
525 | CONV_OVF_U,
526 | ADD_OVF,
527 | ADD_OVF_UN,
528 | MUL_OVF,
529 | MUL_OVF_UN,
530 | SUB_OVF,
531 | SUB_OVF_UN,
532 | ENDFINALLY,
533 | LEAVE,
534 | LEAVE_S,
535 | STIND_I,
536 | CONV_U,
537 | UNUSED26,
538 | UNUSED27,
539 | UNUSED28,
540 | UNUSED29,
541 | UNUSED30,
542 | UNUSED31,
543 | UNUSED32,
544 | UNUSED33,
545 | UNUSED34,
546 | UNUSED35,
547 | UNUSED36,
548 | UNUSED37,
549 | UNUSED38,
550 | UNUSED39,
551 | UNUSED40,
552 | UNUSED41,
553 | UNUSED42,
554 | UNUSED43,
555 | UNUSED44,
556 | UNUSED45,
557 | UNUSED46,
558 | UNUSED47,
559 | UNUSED48,
560 | PREFIX7,
561 | PREFIX6,
562 | PREFIX5,
563 | PREFIX4,
564 | PREFIX3,
565 | PREFIX2,
566 | PREFIX1,
567 | PREFIXREF,
568 | ARGLIST,
569 | CEQ,
570 | CGT,
571 | CGT_UN,
572 | CLT,
573 | CLT_UN,
574 | LDFTN,
575 | LDVIRTFTN,
576 | UNUSED56,
577 | LDARG,
578 | LDARGA,
579 | STARG,
580 | LDLOC,
581 | LDLOCA,
582 | STLOC,
583 | LOCALLOC,
584 | UNUSED57,
585 | ENDFILTER,
586 | UNALIGNED_,
587 | VOLATILE_,
588 | TAIL_,
589 | INITOBJ,
590 | CONSTRAINED_,
591 | CPBLK,
592 | INITBLK,
593 | NO_,
594 | RETHROW,
595 | UNUSED,
596 | SIZEOF,
597 | REFANYTYPE,
598 | READONLY_,
599 | UNUSED53,
600 | UNUSED54,
601 | UNUSED55,
602 | UNUSED70,
603 | ILLEGAL,
604 | ENDMAC,
605 |
606 | //!!!}}OPCODE_ENUM
607 | __Count,
608 | };
609 |
610 |
611 | enum class FlowType
612 | {
613 | Next,
614 | Branch,
615 | CondBranch,
616 | Call,
617 | Return,
618 | Meta,
619 | Throw,
620 | Break,
621 | };
622 |
623 | enum class ArgType
624 | {
625 | None,
626 | Data,
627 | StaticBranch,
628 | BranchTarget,
629 | Switch,
630 | };
631 |
632 | enum class InputType
633 | {
634 | None,
635 | };
636 |
637 | enum class OutputType
638 | {
639 | None,
640 | };
641 |
642 | enum class OpCodeKind
643 | {
644 | Primitive,
645 | ObjModel,
646 | Macro,
647 | Prefix,
648 | Nternal,
649 | };
650 |
651 | struct OpCodeInfo
652 | {
653 | OpcodeEnum id;
654 | const char name[16];
655 | InputType intput[3];
656 | OutputType output;
657 | ArgType inlineType;
658 | int32_t inlineParam;
659 | uint8_t flag;
660 | OpcodeValue baseOpValue;
661 | FlowType flow;
662 | int32_t constValue;
663 | };
664 |
665 | extern OpCodeInfo g_opcodeInfos[(int)OpcodeEnum::__Count];
666 |
667 | const OpCodeInfo* DecodeOpCodeInfo(const byte*& ip, const byte* end);
668 |
669 | uint32_t GetOpCodeSize(const byte*& ip, const OpCodeInfo* opCodeInfo);
670 | }
671 | }
672 |
673 |
--------------------------------------------------------------------------------
/huatuo/metadata/RawImage.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "MetadataDef.h"
3 | #include "BlobReader.h"
4 | #include "MetadataUtil.h"
5 |
6 | namespace huatuo
7 | {
8 | namespace metadata
9 | {
10 | enum class LoadImageErrorCode
11 | {
12 | OK = 0,
13 | BAD_IMAGE,
14 | NOT_IMPLEMENT,
15 | AOT_ASSEMBLY_NOT_FIND,
16 | HOMOLOGOUS_ONLY_SUPPORT_AOT_ASSEMBLY,
17 | HOMOLOGOUS_ASSEMBLY_HAS_LOADED,
18 | };
19 |
20 | class RawImage
21 | {
22 | public:
23 | RawImage(): _ptrRawData(nullptr), _imageLength(0), _ptrRawDataEnd(nullptr),
24 | _isDll(false), _PEHeader(nullptr), _PESectionHeaders(nullptr), _ptrMetaData(nullptr), _ptrMetaRoot(nullptr),
25 | _streamStringHeap{}, _streamUS{}, _streamBlobHeap{}, _streamGuidHeap{}, _streamTables{},
26 | _stringHeapStrNum(0), _userStringStrNum(0), _blobNum(0),
27 | _4byteStringIndex(false), _4byteGUIDIndex(false), _4byteBlobIndex(false)
28 | {
29 |
30 | }
31 |
32 |
33 | LoadImageErrorCode Load(const byte* imageData, size_t length);
34 |
35 | uint32_t GetTypeCount() const
36 | {
37 | return _tables[(int)TableType::TYPEDEF].rowNum;
38 | }
39 |
40 | uint32_t GetExportedTypeCount() const
41 | {
42 | return _tables[(int)TableType::EXPORTEDTYPE].rowNum;
43 | }
44 |
45 | const char* GetStringFromRawIndex(StringIndex index) const
46 | {
47 | IL2CPP_ASSERT(DecodeImageIndex(index) == 0);
48 | IL2CPP_ASSERT(index >= 0 && (uint32_t)index < _streamStringHeap.size);
49 | return (const char*)(_streamStringHeap.data + index);
50 | }
51 |
52 | const byte* GetBlobFromRawIndex(StringIndex index) const
53 | {
54 | IL2CPP_ASSERT(DecodeImageIndex(index) == 0);
55 | IL2CPP_ASSERT(index >= 0 && (size_t)index < _streamBlobHeap.size);
56 | return _streamBlobHeap.data + index;
57 | }
58 |
59 | const uint8_t* GetFieldOrParameterDefalutValueByRawIndex(uint32_t index) const
60 | {
61 | return _ptrRawData + index;
62 | }
63 |
64 | BlobReader DecodeBlob(const byte* buf) const
65 | {
66 | uint32_t sizeLength;
67 | uint32_t length = BlobReader::ReadCompressedUint32(buf, sizeLength);
68 | return BlobReader(buf + sizeLength, length);
69 | }
70 |
71 | BlobReader GetBlobReaderByRawIndex(uint32_t rawIndex) const
72 | {
73 | IL2CPP_ASSERT(DecodeImageIndex(rawIndex) == 0);
74 | const byte* buf = _streamBlobHeap.data + rawIndex;
75 | return DecodeBlob(buf);
76 | }
77 |
78 | uint32_t GetImageOffsetOfBlob(uint32_t index) const
79 | {
80 | return (uint32_t)(GetBlobReaderByRawIndex(index).GetData() - _ptrRawData);
81 | }
82 |
83 | const byte* GetDataPtrByImageOffset(uint32_t imageOffset) const
84 | {
85 | IL2CPP_ASSERT(imageOffset < _imageLength);
86 | return _ptrRawData + imageOffset;
87 | }
88 |
89 | const byte* GetTableRowPtr(TableType type, uint32_t rawIndex) const
90 | {
91 | auto& tb = _tables[(int)type];
92 | IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= tb.rowNum);
93 | return tb.data + tb.rowMetaDataSize * (rawIndex - 1);
94 | }
95 |
96 | const Table& GetTable(TableType type) const
97 | {
98 | return _tables[(int)type];
99 | }
100 |
101 | const std::vector& GetRowSchema(TableType type) const
102 | {
103 | return _tableRowMetas[(int)type];
104 | }
105 |
106 | bool TranslateRVAToImageOffset(uint32_t rvaOffset, uint32_t& imageOffset);
107 |
108 | LoadImageErrorCode LoadStreams();
109 |
110 | LoadImageErrorCode LoadTables();
111 |
112 | void BuildTableRowMetas();
113 |
114 | uint32_t ComputTableRowMetaDataSize(TableType tableIndex) const;
115 |
116 | uint32_t ComputStringIndexByte() const
117 | {
118 | return _4byteStringIndex ? 4 : 2;
119 | }
120 |
121 | uint32_t ComputGUIDIndexByte() const
122 | {
123 | return _4byteGUIDIndex ? 4 : 2;
124 | }
125 |
126 | uint32_t ComputBlobIndexByte() const
127 | {
128 | return _4byteBlobIndex ? 4 : 2;
129 | }
130 |
131 | uint32_t ComputTableIndexByte(TableType tableIndex) const
132 | {
133 | return _tables[(int)tableIndex].rowNum < 65536 ? 2 : 4;
134 | }
135 |
136 | uint32_t ComputIndexByte(uint32_t maxRowNum, uint32_t tagBitNum) const
137 | {
138 | return (maxRowNum << tagBitNum) < 65536 ? 2 : 4;
139 | }
140 |
141 | uint32_t GetTableRowNum(TableType tableIndex) const
142 | {
143 | return _tables[(int)tableIndex].rowNum;
144 | }
145 |
146 | uint32_t ComputTableIndexByte(TableType t1, TableType t2, uint32_t tagBitNum) const
147 | {
148 | uint32_t n = GetTableRowNum(t1);
149 | n = std::max(n, GetTableRowNum(t2));
150 | return ComputIndexByte(n, tagBitNum);
151 | }
152 |
153 | uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, uint32_t tagBitNum) const
154 | {
155 | uint32_t n = GetTableRowNum(t1);
156 | n = std::max(n, GetTableRowNum(t2));
157 | n = std::max(n, GetTableRowNum(t3));
158 | return ComputIndexByte(n, tagBitNum);
159 | }
160 |
161 | uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, TableType t4, uint32_t tagBitNum) const
162 | {
163 | uint32_t n = GetTableRowNum(t1);
164 | n = std::max(n, GetTableRowNum(t2));
165 | n = std::max(n, GetTableRowNum(t3));
166 | n = std::max(n, GetTableRowNum(t4));
167 | return ComputIndexByte(n, tagBitNum);
168 | }
169 |
170 | uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, TableType t4, TableType t5, uint32_t tagBitNum) const
171 | {
172 | uint32_t n = GetTableRowNum(t1);
173 | n = std::max(n, GetTableRowNum(t2));
174 | n = std::max(n, GetTableRowNum(t3));
175 | n = std::max(n, GetTableRowNum(t4));
176 | n = std::max(n, GetTableRowNum(t5));
177 | return ComputIndexByte(n, tagBitNum);
178 | }
179 |
180 | uint32_t ComputTableIndexByte(const TableType* ts, int num, uint32_t tagBitNum) const
181 | {
182 | uint32_t n = 0;
183 | for (int i = 0; i < num; i++)
184 | {
185 | n = std::max(n, GetTableRowNum(ts[i]));
186 | }
187 | return ComputIndexByte(n, tagBitNum);
188 | }
189 |
190 | uint32_t GetEntryPointToken() const
191 | {
192 | return _CLIHeader->entryPointToken;
193 | }
194 |
195 | const byte* GetUserStringBlogByIndex(uint32_t index) const
196 | {
197 | IL2CPP_ASSERT(index >= 0 && (uint32_t)index < _streamUS.size);
198 | return _streamUS.data + index;
199 | }
200 | private:
201 | uint32_t ReadColumn(const byte* rowPtr, const ColumnOffsetSize& columnMt) const
202 | {
203 | return ReadColumn(rowPtr, columnMt.offset, columnMt.size);
204 | }
205 |
206 | uint32_t ReadColumn(const byte* data, uint32_t offset, uint32_t size) const
207 | {
208 | IL2CPP_ASSERT(size == 2 || size == 4);
209 | return (size == 2 ? *(uint16_t*)(data + offset) : *(uint32_t*)(data + offset));
210 | }
211 |
212 | public:
213 |
214 |
215 | #define TABLE_BEGIN(name, tableType) Tb##name Read##name(uint32_t rawIndex) const \
216 | { \
217 | IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(tableType).rowNum); \
218 | const byte* rowPtr = GetTableRowPtr(tableType, rawIndex); \
219 | auto& rowSchema = GetRowSchema(tableType); \
220 | uint32_t __fieldIndex = 0; \
221 | Tb##name __r = {};
222 |
223 | #define __F(fieldName) const ColumnOffsetSize& col_##fieldName = rowSchema[__fieldIndex++]; \
224 | __r.fieldName = ReadColumn(rowPtr, col_##fieldName);
225 |
226 | #define TABLE_END return __r; \
227 | }
228 |
229 | #define TABLE1(name, tableType, f1) TABLE_BEGIN(name, tableType) \
230 | __F(f1) \
231 | TABLE_END
232 |
233 | #define TABLE2(name, tableType, f1, f2) TABLE_BEGIN(name, tableType) \
234 | __F(f1) \
235 | __F(f2) \
236 | TABLE_END
237 |
238 | #define TABLE3(name, tableType, f1, f2, f3) TABLE_BEGIN(name, tableType) \
239 | __F(f1) \
240 | __F(f2) \
241 | __F(f3) \
242 | TABLE_END
243 |
244 | #define TABLE4(name, tableType, f1, f2, f3, f4) TABLE_BEGIN(name, tableType) \
245 | __F(f1) \
246 | __F(f2) \
247 | __F(f3) \
248 | __F(f4) \
249 | TABLE_END
250 |
251 | #define TABLE5(name, tableType, f1, f2, f3, f4, f5) TABLE_BEGIN(name, tableType) \
252 | __F(f1) \
253 | __F(f2) \
254 | __F(f3) \
255 | __F(f4) \
256 | __F(f5) \
257 | TABLE_END
258 |
259 | #define TABLE6(name, tableType, f1, f2, f3, f4, f5, f6) TABLE_BEGIN(name, tableType) \
260 | __F(f1) \
261 | __F(f2) \
262 | __F(f3) \
263 | __F(f4) \
264 | __F(f5) \
265 | __F(f6) \
266 | TABLE_END
267 |
268 | TABLE5(Module, TableType::MODULE, generation, name, mvid, encid, encBaseId);
269 | TABLE3(TypeRef, TableType::TYPEREF, resolutionScope, typeName, typeNamespace)
270 | TABLE6(TypeDef, TableType::TYPEDEF, flags, typeName, typeNamespace, extends, fieldList, methodList)
271 | TABLE1(TypeSpec, TableType::TYPESPEC, signature);
272 | TABLE3(Field, TableType::FIELD, flags, name, signature)
273 | TABLE4(GenericParam, TableType::GENERICPARAM, number, flags, owner, name)
274 | TABLE2(GenericParamConstraint, TableType::GENERICPARAMCONSTRAINT, owner, constraint)
275 | TABLE3(MemberRef, TableType::MEMBERREF, classIdx, name, signature)
276 | TABLE1(StandAloneSig, TableType::STANDALONESIG, signature)
277 | TABLE3(MethodImpl, TableType::METHODIMPL, classIdx, methodBody, methodDeclaration)
278 | TABLE2(FieldRVA, TableType::FIELDRVA, rva, field)
279 | TABLE2(FieldLayout, TableType::FIELDLAYOUT, offset, field)
280 | TABLE3(Constant, TableType::CONSTANT, type, parent, value)
281 | TABLE2(MethodSpec, TableType::METHODSPEC, method, instantiation)
282 | TABLE3(CustomAttribute, TableType::CUSTOMATTRIBUTE, parent, type, value)
283 | TABLE2(PropertyMap, TableType::PROPERTYMAP, parent, propertyList)
284 | TABLE3(Property, TableType::PROPERTY, flags, name, type)
285 | TABLE2(EventMap, TableType::EVENTMAP, parent, eventList)
286 | TABLE3(Event, TableType::EVENT, eventFlags, name, eventType)
287 | TABLE3(MethodSemantics, TableType::METHODSEMANTICS, semantics, method, association)
288 |
289 | TABLE2(NestedClass, TableType::NESTEDCLASS, nestedClass, enclosingClass)
290 | TABLE6(Method, TableType::METHOD, rva, implFlags, flags, name, signature, paramList)
291 | TABLE3(Param, TableType::PARAM, flags, sequence, name)
292 |
293 | TABLE3(ClassLayout, TableType::CLASSLAYOUT, packingSize, classSize, parent)
294 | TABLE2(InterfaceImpl, TableType::INTERFACEIMPL, classIdx, interfaceIdx)
295 |
296 | TABLE_BEGIN(Assembly, TableType::ASSEMBLY)
297 | __F(hashAlgId)
298 | __F(majorVersion)
299 | __F(minorVersion)
300 | __F(buildNumber)
301 | __F(revisionNumber)
302 | __F(flags)
303 | __F(publicKey)
304 | __F(name)
305 | __F(culture)
306 | TABLE_END
307 |
308 |
309 | TABLE_BEGIN(AssemblyRef, TableType::ASSEMBLYREF)
310 | __F(majorVersion)
311 | __F(minorVersion)
312 | __F(buildNumber)
313 | __F(revisionNumber)
314 | __F(flags)
315 | __F(publicKeyOrToken)
316 | __F(name)
317 | __F(culture)
318 | __F(hashValue)
319 | TABLE_END
320 |
321 | private:
322 | const byte* _ptrRawData;
323 | uint32_t _imageLength;
324 | const byte* _ptrRawDataEnd;
325 |
326 | bool _isDll;
327 | const PEHeader* _PEHeader;
328 | const CLIHeader* _CLIHeader;
329 | const PESectionHeader* _PESectionHeaders;
330 | const MetadataRootPartial* _ptrMetaRoot;
331 |
332 | const byte* _ptrMetaData;
333 |
334 | CliStream _streamStringHeap;
335 | CliStream _streamUS;
336 | CliStream _streamBlobHeap;
337 | CliStream _streamGuidHeap;
338 | CliStream _streamTables;
339 |
340 | uint32_t _stringHeapStrNum;
341 |
342 | uint32_t _userStringStrNum;
343 | uint32_t _blobNum;
344 |
345 |
346 | bool _4byteStringIndex;
347 | bool _4byteGUIDIndex;
348 | bool _4byteBlobIndex;
349 |
350 | Table _tables[TABLE_NUM];
351 | std::vector _tableRowMetas[TABLE_NUM];
352 | };
353 | }
354 | }
--------------------------------------------------------------------------------
/huatuo/metadata/Tables.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace huatuo
5 | {
6 | namespace metadata
7 | {
8 |
9 | enum class TableType
10 | {
11 | MODULE,
12 | TYPEREF,
13 | TYPEDEF,
14 | FIELD_POINTER,
15 | FIELD,
16 | METHOD_POINTER,
17 | METHOD,
18 | PARAM_POINTER,
19 | PARAM,
20 | INTERFACEIMPL,
21 | MEMBERREF, /* 0xa */
22 | CONSTANT,
23 | CUSTOMATTRIBUTE,
24 | FIELDMARSHAL,
25 | DECLSECURITY,
26 | CLASSLAYOUT,
27 | FIELDLAYOUT, /* 0x10 */
28 | STANDALONESIG,
29 | EVENTMAP,
30 | EVENT_POINTER,
31 | EVENT,
32 | PROPERTYMAP,
33 | PROPERTY_POINTER,
34 | PROPERTY,
35 | METHODSEMANTICS,
36 | METHODIMPL,
37 | MODULEREF, /* 0x1a */
38 | TYPESPEC,
39 | IMPLMAP,
40 | FIELDRVA,
41 | UNUSED6,
42 | UNUSED7,
43 | ASSEMBLY, /* 0x20 */
44 | ASSEMBLYPROCESSOR,
45 | ASSEMBLYOS,
46 | ASSEMBLYREF,
47 | ASSEMBLYREFPROCESSOR,
48 | ASSEMBLYREFOS,
49 | FILE,
50 | EXPORTEDTYPE,
51 | MANIFESTRESOURCE,
52 | NESTEDCLASS,
53 | GENERICPARAM, /* 0x2a */
54 | METHODSPEC,
55 | GENERICPARAMCONSTRAINT,
56 | UNUSED8,
57 | UNUSED9,
58 | UNUSED10,
59 | /* Portable PDB tables */
60 | DOCUMENT, /* 0x30 */
61 | METHODBODY,
62 | LOCALSCOPE,
63 | LOCALVARIABLE,
64 | LOCALCONSTANT,
65 | IMPORTSCOPE,
66 | STATEMACHINEMETHOD,
67 | CUSTOMDEBUGINFORMATION
68 | };
69 |
70 |
71 | // 0
72 | struct TbModule
73 | {
74 | uint16_t generation;
75 | uint32_t name;
76 | uint32_t mvid;
77 | uint32_t encid;
78 | uint32_t encBaseId;
79 | };
80 |
81 | // 1
82 | struct TbTypeRef
83 | {
84 | uint32_t resolutionScope;
85 | uint32_t typeName;
86 | uint32_t typeNamespace;
87 | };
88 |
89 | // 2
90 | struct TbTypeDef
91 | {
92 | uint32_t flags;
93 | uint32_t typeName;
94 | uint32_t typeNamespace;
95 | uint32_t extends;
96 | uint32_t fieldList;
97 | uint32_t methodList;
98 | };
99 |
100 | // 3 FIELD_POINTER
101 |
102 | // 4
103 | struct TbField
104 | {
105 | uint32_t flags;
106 | uint32_t name;
107 | uint32_t signature;
108 | };
109 |
110 | // 5 METHOD_POINTER
111 |
112 | // 6
113 | struct TbMethod
114 | {
115 | uint32_t rva;
116 | uint16_t implFlags;
117 | uint16_t flags;
118 | uint32_t name;
119 | uint32_t signature;
120 | uint32_t paramList;
121 | };
122 |
123 | // 7 PARAM_POINTER
124 |
125 | // 8
126 | struct TbParam
127 | {
128 | uint16_t flags;
129 | uint16_t sequence;
130 | uint32_t name;
131 | };
132 |
133 | // 9
134 | struct TbInterfaceImpl
135 | {
136 | uint32_t classIdx;
137 | uint32_t interfaceIdx;
138 | };
139 |
140 | // 0xa
141 | struct TbMemberRef
142 | {
143 | uint32_t classIdx;
144 | uint32_t name;
145 | uint32_t signature;
146 | };
147 |
148 | struct TbConstant
149 | {
150 | uint8_t type; // 实际上占2字节
151 | uint32_t parent;
152 | uint32_t value;
153 | };
154 |
155 | struct TbCustomAttribute
156 | {
157 | uint32_t parent;
158 | uint32_t type;
159 | uint32_t value;
160 | };
161 |
162 | struct TbFieldMarshal
163 | {
164 | uint32_t parent;
165 | uint32_t nativeType;
166 | };
167 |
168 | struct TbDeclSecurity
169 | {
170 | uint16_t action;
171 | uint32_t parent;
172 | uint32_t permissionSet;
173 | };
174 |
175 | struct TbClassLayout
176 | {
177 | uint16_t packingSize;
178 | uint32_t classSize;
179 | uint32_t parent;
180 | };
181 |
182 | // 0x10
183 | struct TbFieldLayout
184 | {
185 | uint32_t offset;
186 | uint32_t field;
187 | };
188 |
189 | struct TbStandAloneSig
190 | {
191 | uint32_t signature; // 指向 blob heap的位置
192 | };
193 |
194 | struct TbEventMap
195 | {
196 | uint32_t parent;
197 | uint32_t eventList;
198 | };
199 |
200 | // 0x13 EVENT_POINTER
201 |
202 | // 0x14
203 | struct TbEvent
204 | {
205 | uint16_t eventFlags;
206 | uint32_t name;
207 | uint32_t eventType;
208 | };
209 |
210 | struct TbPropertyMap
211 | {
212 | uint32_t parent;
213 | uint32_t propertyList;
214 | };
215 |
216 | // PROPERTY_POINTER
217 |
218 | struct TbProperty
219 | {
220 | uint16_t flags;
221 | uint32_t name;
222 | uint32_t type;
223 | };
224 |
225 | struct TbMethodSemantics
226 | {
227 | uint16_t semantics;
228 | uint32_t method;
229 | uint32_t association;
230 | };
231 |
232 | struct TbMethodImpl
233 | {
234 | uint32_t classIdx;
235 | uint32_t methodBody;
236 | uint32_t methodDeclaration;
237 | };
238 |
239 | struct TbModuleRef
240 | {
241 | uint32_t name;
242 | };
243 |
244 | struct TbTypeSpec
245 | {
246 | uint32_t signature;
247 | };
248 |
249 | struct TbImplMap
250 | {
251 | uint16_t mappingFlags;
252 | uint32_t memberForwarded;
253 | uint32_t importName;
254 | uint32_t importScope;
255 | };
256 |
257 | struct TbFieldRVA
258 | {
259 | uint32_t rva;
260 | uint32_t field;
261 | };
262 |
263 | // UNUSED 6
264 | // UNUSED 7
265 |
266 | struct TbAssembly
267 | {
268 | uint32_t hashAlgId;
269 | uint16_t majorVersion;
270 | uint16_t minorVersion;
271 | uint16_t buildNumber;
272 | uint16_t revisionNumber;
273 | uint32_t flags;
274 | uint32_t publicKey;
275 | uint32_t name;
276 | uint32_t culture;
277 | };
278 |
279 | struct TbAssemblyProcessor
280 | {
281 | uint32_t processor;
282 | };
283 |
284 | struct TbAssemblyOS
285 | {
286 | uint32_t osPlatformID;
287 | uint32_t osMajorVersion;
288 | uint32_t osMinorVersion;
289 | };
290 |
291 | struct TbAssemblyRef
292 | {
293 | uint16_t majorVersion;
294 | uint16_t minorVersion;
295 | uint16_t buildNumber;
296 | uint16_t revisionNumber;
297 | uint32_t flags;
298 | uint32_t publicKeyOrToken;
299 | uint32_t name;
300 | uint32_t culture;
301 | uint32_t hashValue;
302 | };
303 |
304 | struct TbAssemblyRefProcessor
305 | {
306 | uint32_t processor;
307 | uint32_t assemblyRef;
308 | };
309 |
310 | struct TbAssemblyRefOS
311 | {
312 | uint32_t osPlatformID;
313 | uint32_t osMajorVersion;
314 | uint32_t osMinorVersion;
315 | uint32_t assemblyRef;
316 | };
317 |
318 | struct TbFile
319 | {
320 | uint32_t flags;
321 | uint32_t name;
322 | uint32_t hashValue;
323 | };
324 |
325 | struct TbExportedType
326 | {
327 | uint32_t flags;
328 | uint32_t typeDefId;
329 | uint32_t typeName;
330 | uint32_t typeNamespace;
331 | uint32_t implementation;
332 | };
333 |
334 | struct TbManifestResource
335 | {
336 | uint32_t offset;
337 | uint32_t flags;
338 | uint32_t name;
339 | uint32_t implementation;
340 | };
341 |
342 | struct TbNestedClass
343 | {
344 | uint32_t nestedClass;
345 | uint32_t enclosingClass;
346 | };
347 |
348 | struct TbGenericParam
349 | {
350 | uint16_t number;
351 | uint16_t flags;
352 | uint32_t owner;
353 | uint32_t name;
354 | };
355 |
356 | struct TbMethodSpec
357 | {
358 | uint32_t method;
359 | uint32_t instantiation;
360 | };
361 |
362 | struct TbGenericParamConstraint
363 | {
364 | uint32_t owner;
365 | uint32_t constraint;
366 | };
367 |
368 | // 以下这些都不是tables的类型
369 | // 但mono特殊处理一下,额外也加到这个表中
370 |
371 | // size 84
372 | struct TbSymbolDocument
373 | {
374 |
375 | };
376 |
377 | // size 52
378 | struct TbSymbolMethodBody
379 | {
380 |
381 | };
382 |
383 | // size 20
384 | struct TbSymbolLocalScope
385 | {
386 |
387 | };
388 |
389 | // size 56
390 | struct TbSymbolLocalVariable
391 | {
392 |
393 | };
394 |
395 | // size 24
396 | struct TbSymbolConstant
397 | {
398 |
399 | };
400 |
401 | // SymUsing. size 8
402 | struct TbSymbolImportScope
403 | {
404 |
405 | };
406 |
407 |
408 | struct TbSymbolMisc
409 | {
410 |
411 | };
412 |
413 | struct TbSymbolString
414 | {
415 |
416 | };
417 |
418 | }
419 |
420 | }
--------------------------------------------------------------------------------
/huatuo/metadata/VTableSetup.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "../CommonDef.h"
7 | #include "MetadataUtil.h"
8 |
9 | namespace huatuo
10 | {
11 | namespace metadata
12 | {
13 | struct GenericClassMethod
14 | {
15 | const Il2CppType* type;
16 | const Il2CppMethodDefinition* method;
17 | const char* name; // TODO remove
18 | };
19 |
20 | struct VirtualMethodImpl
21 | {
22 | const Il2CppMethodDefinition* method;
23 | const Il2CppType* type;
24 | uint16_t slot;
25 | const char* name; // TODO for debug
26 | };
27 |
28 | class VTableSetUp;
29 |
30 | struct RawInterfaceOffsetInfo
31 | {
32 | const Il2CppType* type;
33 | VTableSetUp* tree;
34 | uint32_t offset;
35 | };
36 |
37 | struct Il2CppTypeHash {
38 | size_t operator()(const Il2CppType* x) const noexcept {
39 | return il2cpp::metadata::Il2CppTypeHash::Hash(x);
40 | }
41 | };
42 |
43 | struct Il2CppTypeEqualTo
44 | {
45 | bool operator()(const Il2CppType* a, const Il2CppType* b) const {
46 | return il2cpp::metadata::Il2CppTypeEqualityComparer::AreEqual(a, b);
47 | }
48 | };
49 |
50 | typedef std::unordered_map Il2CppType2TypeDeclaringTreeMap;
51 |
52 | class VTableSetUp
53 | {
54 | public:
55 | static VTableSetUp* BuildByType(Il2CppType2TypeDeclaringTreeMap& cache, const Il2CppType* type);
56 | static VTableSetUp* InflateVts(Il2CppType2TypeDeclaringTreeMap& cache, VTableSetUp* genericType, const Il2CppType* type);
57 |
58 | VTableSetUp()
59 | {
60 |
61 | }
62 |
63 | const VTableSetUp* GetParent() const { return _parent; }
64 |
65 | void ComputVtables(Il2CppType2TypeDeclaringTreeMap& cache);
66 | void ComputAotTypeVtables(Il2CppType2TypeDeclaringTreeMap& cache);
67 | void ComputInterpTypeVtables(Il2CppType2TypeDeclaringTreeMap& cache);
68 | void ComputInterfaceVtables(Il2CppType2TypeDeclaringTreeMap& cache);
69 |
70 | const Il2CppType* FindImplType(const Il2CppMethodDefinition* methodDef);
71 | const GenericClassMethod* FindImplMethod(const Il2CppType* containerType, const Il2CppMethodDefinition* methodDef);
72 | const std::vector& GetInterfaceOffsetInfos() const { return _interfaceOffsetInfos; }
73 | const std::vector& GetVirtualMethodImpls() const { return _methodImpls; }
74 | const Il2CppType* GetType() const { return _type; }
75 | uint32_t GetTypeIndex() const { return _typeDef->byvalTypeIndex; }
76 | bool IsInterType() const { return huatuo::metadata::IsInterpreterType(_typeDef); }
77 | private:
78 | VTableSetUp* _parent;
79 | std::vector _interfaces;
80 | std::vector _interfaceOffsetInfos;
81 |
82 | const Il2CppType* _type;
83 | const Il2CppTypeDefinition* _typeDef;
84 | const char* _name; // TODO remove
85 | std::vector _methods;
86 |
87 | std::vector _virtualMethods;
88 | std::vector _methodImpls;
89 | };
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/huatuo/transform/BasicBlockSpliter.cpp:
--------------------------------------------------------------------------------
1 | #include "BasicBlockSpliter.h"
2 |
3 | #include "../metadata/Opcodes.h"
4 | #include "../metadata/MetadataUtil.h"
5 |
6 | using namespace huatuo::metadata;
7 |
8 | namespace huatuo
9 | {
10 | namespace transform
11 | {
12 |
13 | void BasicBlockSpliter::SplitNormal(const byte* ilcodeStart, uint32_t codeSize, std::unordered_set& ilOffsets)
14 | {
15 | const byte* codeEnd = ilcodeStart + codeSize;
16 | const byte* ip = ilcodeStart;
17 |
18 | while (ip < codeEnd)
19 | {
20 | ilOffsets.insert((uint32_t)(ip - ilcodeStart));
21 | const OpCodeInfo* oc = DecodeOpCodeInfo(ip, codeEnd);
22 | IL2CPP_ASSERT(oc);
23 | int32_t opCodeSize = GetOpCodeSize(ip, oc);
24 | const byte* nextIp = ip + opCodeSize;
25 | int32_t nextOffset = (int32_t)(nextIp - ilcodeStart);
26 | IL2CPP_ASSERT(nextOffset >= 0 && nextOffset <= (int32_t)codeSize);
27 |
28 | switch (oc->inlineType)
29 | {
30 | case ArgType::None:
31 | case ArgType::Data:
32 | {
33 | break;
34 | }
35 | case ArgType::StaticBranch:
36 | {
37 | _splitOffsets.insert(nextOffset);
38 | break;
39 | }
40 | case ArgType::BranchTarget:
41 | {
42 | int32_t offset;
43 | switch (oc->inlineParam)
44 | {
45 | case 1:
46 | {
47 | offset = GetI1(ip + 1);
48 | break;
49 | }
50 | case 4:
51 | {
52 | offset = GetI4LittleEndian(ip + 1);
53 | break;
54 | }
55 | default:
56 | {
57 | IL2CPP_ASSERT(false);
58 | }
59 | }
60 | // don't split 0 offset br
61 | if (offset != 0 || (oc->baseOpValue == OpcodeValue::LEAVE || oc->baseOpValue == OpcodeValue::LEAVE_S))
62 | {
63 | _splitOffsets.insert(nextOffset);
64 | _splitOffsets.insert(nextOffset + offset);
65 | }
66 | break;
67 | }
68 | case ArgType::Switch:
69 | {
70 | uint32_t caseNum = GetI4LittleEndian(ip + 1);
71 | bool splitAny = false;
72 | for (uint32_t caseIdx = 0; caseIdx < caseNum; caseIdx++)
73 | {
74 | int32_t caseOffset = GetI4LittleEndian(ip + 5 + caseIdx * 4);
75 | if (caseOffset != 0)
76 | {
77 | _splitOffsets.insert(nextOffset + caseOffset);
78 | splitAny = true;
79 | }
80 | }
81 | if (splitAny)
82 | {
83 | _splitOffsets.insert(nextOffset);
84 | }
85 | break;
86 | }
87 | default:
88 | {
89 | IL2CPP_ASSERT(false && "unknown inline type");
90 | }
91 | }
92 | ip = nextIp;
93 | }
94 | IL2CPP_ASSERT(ip == codeEnd);
95 | }
96 |
97 | void BasicBlockSpliter::SplitExceptionHandles(const byte* ilcodeStart, uint32_t codeSize, const std::vector& exceptionClauses)
98 | {
99 | for (auto& eh : exceptionClauses)
100 | {
101 | _splitOffsets.insert(eh.tryOffset);
102 | _splitOffsets.insert(eh.tryOffset + eh.tryLength);
103 | _splitOffsets.insert(eh.handlerOffsets);
104 | _splitOffsets.insert(eh.handlerOffsets + eh.handlerLength);
105 | if (eh.flags == CorILExceptionClauseType::Filter)
106 | {
107 | _splitOffsets.insert(eh.classTokenOrFilterOffset);
108 | }
109 | }
110 | }
111 |
112 | void BasicBlockSpliter::SplitBasicBlocks()
113 | {
114 | const byte* ilcodeStart = _body.ilcodes;
115 |
116 | std::unordered_set ilOffsets;
117 | ilOffsets.insert(_body.codeSize);
118 |
119 | SplitNormal(ilcodeStart, _body.codeSize, ilOffsets);
120 | SplitExceptionHandles(ilcodeStart, _body.codeSize, _body.exceptionClauses);
121 |
122 | /*if (_splitOffsets.find(0) != _splitOffsets.end())
123 | {
124 | _splitOffsets.erase(0);
125 | }*/
126 | #if DEBUG
127 | for (uint32_t offset : _splitOffsets)
128 | {
129 | IL2CPP_ASSERT(ilOffsets.find(offset) != ilOffsets.end());
130 | }
131 | IL2CPP_ASSERT(_splitOffsets.find(_body.codeSize) != _splitOffsets.end());
132 | #endif
133 | }
134 | }
135 | }
--------------------------------------------------------------------------------
/huatuo/transform/BasicBlockSpliter.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../CommonDef.h"
8 | #include "../metadata/MetadataDef.h"
9 |
10 | namespace huatuo
11 | {
12 | namespace transform
13 | {
14 | class BasicBlockSpliter
15 | {
16 | public:
17 | BasicBlockSpliter(const metadata::MethodBody& body) : _body(body) { }
18 |
19 | void SplitBasicBlocks();
20 |
21 | const std::set& GetSplitOffsets() const { return _splitOffsets; }
22 | private:
23 | const metadata::MethodBody& _body;
24 | std::set _splitOffsets;
25 |
26 | void SplitNormal(const byte* ilcodeStart, uint32_t codeSize, std::unordered_set& ilOffsets);
27 | void SplitExceptionHandles(const byte* ilcodeStart, uint32_t codeSize, const std::vector& exceptionClauses);
28 | };
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/huatuo/transform/TemporaryMemoryArena.cpp:
--------------------------------------------------------------------------------
1 | #include "TemporaryMemoryArena.h"
2 |
3 | namespace huatuo
4 | {
5 | namespace transform
6 | {
7 |
8 | TemporaryMemoryArena::Block TemporaryMemoryArena::AllocBlock(size_t size)
9 | {
10 | void* data = IL2CPP_MALLOC(size);
11 | return { data, size };
12 | }
13 |
14 | void TemporaryMemoryArena::Begin()
15 | {
16 | IL2CPP_ASSERT(_buf == nullptr);
17 | IL2CPP_ASSERT(_size == 0);
18 | IL2CPP_ASSERT(_pos == 0);
19 | RequireSize(kMinBlockSize);
20 | }
21 |
22 | void TemporaryMemoryArena::End()
23 | {
24 | if (_buf)
25 | {
26 | IL2CPP_FREE(_buf);
27 | //_buf = nullptr;
28 | //_size = _pos = 0;
29 | }
30 | for (auto& block : _useOuts)
31 | {
32 | IL2CPP_FREE(block.data);
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/huatuo/transform/TemporaryMemoryArena.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../CommonDef.h"
8 |
9 | namespace huatuo
10 | {
11 | namespace transform
12 | {
13 | const size_t kMinBlockSize = 1024 * 1024;
14 |
15 | class TemporaryMemoryArena
16 | {
17 | public:
18 |
19 | TemporaryMemoryArena() : _buf(nullptr), _size(0), _pos(0)
20 | {
21 | Begin();
22 | }
23 | ~TemporaryMemoryArena()
24 | {
25 | End();
26 | }
27 |
28 | static size_t AligndSize(size_t size)
29 | {
30 | return (size + 7) & ~7;
31 | }
32 |
33 | template
34 | T* AllocIR()
35 | {
36 | const size_t aligndSize = AligndSize(sizeof(T));
37 | if (_pos + aligndSize <= _size)
38 | {
39 | T* ir = (T*)(_buf + _pos);
40 | *ir = {};
41 | _pos += aligndSize;
42 | return ir;
43 | }
44 |
45 | RequireSize(aligndSize);
46 |
47 | T* ir = (T*)(_buf + _pos);
48 | *ir = {};
49 | _pos += aligndSize;
50 | return ir;
51 | }
52 |
53 | template
54 | T* NewAny()
55 | {
56 | const size_t needSize = AligndSize(sizeof(T));
57 | if (_pos + needSize <= _size)
58 | {
59 | T* ir = new (_buf + _pos) T();
60 | *ir = {};
61 | _pos += needSize;
62 | return ir;
63 | }
64 |
65 | RequireSize(needSize);
66 |
67 | T* ir = new (_buf + _pos) T();
68 | *ir = {};
69 | _pos += needSize;
70 | return ir;
71 | }
72 |
73 | template
74 | T* NewNAny(int n)
75 | {
76 | if (n > 0)
77 | {
78 | size_t bytes = AligndSize(sizeof(T) * n);
79 | if (_pos + bytes > _size)
80 | {
81 | RequireSize(bytes);
82 | }
83 | T* ret = new (_buf + _pos) T[n];
84 | _pos += bytes;
85 | return ret;
86 | }
87 | else
88 | {
89 | return nullptr;
90 | }
91 | }
92 |
93 | void Begin();
94 |
95 | void End();
96 |
97 | private:
98 | struct Block
99 | {
100 | void* data;
101 | size_t size;
102 | };
103 |
104 | void RequireSize(size_t size)
105 | {
106 | if (_buf)
107 | {
108 | _useOuts.push_back({ (void*)_buf, _size});
109 | }
110 |
111 | Block newBlock = AllocBlock(std::max(size, kMinBlockSize));
112 | _buf = (byte*)newBlock.data;
113 | _size = newBlock.size;
114 | _pos = 0;
115 | }
116 |
117 | static Block AllocBlock(size_t size);
118 |
119 | std::vector _useOuts;
120 |
121 | byte* _buf;
122 | size_t _size;
123 | size_t _pos;
124 | };
125 | }
126 | }
--------------------------------------------------------------------------------
/huatuo/transform/Transform.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "BasicBlockSpliter.h"
4 |
5 | #include "../metadata/Image.h"
6 | #include "../interpreter/Instruction.h"
7 | #include "../interpreter/Engine.h"
8 |
9 | namespace huatuo
10 | {
11 | namespace transform
12 | {
13 |
14 | struct IRBasicBlock
15 | {
16 | bool visited;
17 | bool inPending;
18 | uint32_t ilOffset;
19 | uint32_t codeOffset;
20 | std::vector insts;
21 | };
22 |
23 | struct ArgVarInfo
24 | {
25 | const Il2CppType* type;
26 | Il2CppClass* klass;
27 | int32_t argOffset; // StackObject index
28 | int32_t argLocOffset;
29 | };
30 |
31 | struct LocVarInfo
32 | {
33 | const Il2CppType* type;
34 | Il2CppClass* klass;
35 | int32_t locOffset;
36 | };
37 |
38 | enum class EvalStackReduceDataType
39 | {
40 | I4,
41 | I8,
42 | I,
43 | R4,
44 | R8,
45 | Ref,
46 | Obj,
47 | Other,
48 | };
49 |
50 | struct EvalStackVarInfo
51 | {
52 | EvalStackReduceDataType reduceType;
53 | int32_t byteSize;
54 | int32_t locOffset;
55 | };
56 |
57 | class HiTransform
58 | {
59 | public:
60 | static void Transform(metadata::Image* image, const MethodInfo* methodInfo, metadata::MethodBody& body, interpreter::InterpMethodInfo& result);
61 | };
62 | }
63 | }
--------------------------------------------------------------------------------
/scripts/iOSBuild/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # file: CMakeList.txt
2 | cmake_minimum_required(VERSION 3.0)
3 | set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
4 |
5 | set(TMP $ENV{HUATUO_IL2CPP_SOURCE_DIR})
6 | if ( NOT TMP )
7 | message(FATAL_ERROR "需要设置环境变量: HUATUO_IL2CPP_SOURCE_DIR")
8 | else()
9 | message(STATUS "unity il2cpp 路径为: ${TMP}")
10 | endif()
11 |
12 | set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
13 | if ( SDK_VERSION )
14 | message(STATUS "使用iPhoneSimulator版本:" ${SDK_VERSION})
15 | else()
16 | message(STATUS "当前使用默认版本的iPhoneSimulator,可以通过设置环境变量IPHONESIMULATOR_VERSION,指定版本")
17 | endif()
18 |
19 | project(il2cpp)
20 | execute_process(COMMAND sh gen_lump.sh ${PROJECT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
21 |
22 | add_subdirectory(external)
23 | add_subdirectory(objective)
24 |
25 |
26 | set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
27 |
28 | message(STATUS "il2cpp project, binary dir: " ${CMAKE_BINARY_DIR})
29 | message(STATUS "il2cpp project, build dir: " ${PROJECT_BINARY_DIR})
30 | message(STATUS "il2cpp project, il2cpp source dir: " ${IL2CPP_SOURCE_DIR})
31 |
32 |
33 | SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
34 | find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
35 | if (NOT CLANG_EXECUTABLE)
36 | message(FATAL_ERROR "Cannot find any clang executable.")
37 | endif()
38 |
39 |
40 | set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
41 |
42 | #set(CMAKE_VERBOSE_MAKEFILE ON)
43 | set(CMAKE_CXX_COMPILER clang++)
44 | set(CMAKE_C_COMPILER clang)
45 | #add_compile_options(-x objective-c++)
46 |
47 | # 以下命令为复制的Xcode生成中的命令
48 | set(CMAKE_CXX_FLAGS "-target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu++1z -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wunguarded-availability ")
49 |
50 |
51 | add_definitions(-DIL2CPP_TARGET_IOS=1)
52 | add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
53 | add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
54 | add_definitions(-DAARCH64)
55 | add_definitions(-D__aarch64__)
56 | add_definitions(-DIL2CPP_SUPPORT_THREADS)
57 | add_definitions(-DIL2CPP_THREADS_PTHREAD)
58 | #add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
59 | #add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
60 | #add_definitions(-DIL2CPP_TARGET_DARWIN)
61 | add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO)
62 |
63 | add_definitions(-MMD)
64 | add_definitions(-MT dependencies)
65 |
66 |
67 | include_directories(${IL2CPP_SOURCE_DIR}/libil2cpp/)
68 | include_directories(${IL2CPP_SOURCE_DIR}/external/)
69 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
70 | include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
71 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
72 |
73 | # 修改为本机对应SDK路径
74 | include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/v1)
75 | include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include)
76 |
77 | aux_source_directory(${PROJECT_BINARY_DIR}/lump_cpp LUMP_SOURCE_LIST)
78 | aux_source_directory(${IL2CPP_SOURCE_DIR}/libil2cpp LIBIL2CPP_SOURCE_LIST)
79 |
80 | #find_library(zlib ${PROJECT_SOURCE_DIR}/external)
81 | add_library(il2cpp_original STATIC ${LIBIL2CPP_SOURCE_LIST} ${LUMP_SOURCE_LIST})
82 | add_dependencies(il2cpp_original external objective)
83 |
84 | add_custom_command(TARGET il2cpp_original
85 | POST_BUILD
86 | COMMAND xcrun -r libtool -static -o libil2cpp.a libil2cpp_original.a external/libexternal.a objective/libobjective.a
87 | COMMENT "post build this is command combine libil2cpp_original.a, libojjective.a and libzlib.a into libil2cpp"
88 | )
89 |
--------------------------------------------------------------------------------
/scripts/iOSBuild/external/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # file: external/CMakeList.txt
2 | cmake_minimum_required(VERSION 3.0)
3 | set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
4 |
5 | set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
6 | set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
7 |
8 | message(STATUS "external project, external source dir: " ${IL2CPP_SOURCE_DIR})
9 |
10 | SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
11 |
12 | find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
13 | if (NOT CLANG_EXECUTABLE)
14 | message(FATAL_ERROR "Cannot find any clang executable.")
15 | endif()
16 |
17 | set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
18 | set(CMAKE_VERBOSE_MAKEFILE ON)
19 | set(CMAKE_C_COMPILER clang)
20 |
21 | set(CMAKE_C_FLAGS "-x c -target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu11 -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fstrict-aliasing -Wdeprecated-declarations -g -Wno-sign-conversion -Winfinite-recursion -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wno-semicolon-before-method-body -Wunguarded-availability")
22 |
23 |
24 | add_definitions(-DIL2CPP_TARGET_IOS=1)
25 | add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
26 | add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
27 | add_definitions(-DAARCH64)
28 | add_definitions(-D__aarch64__)
29 | #add_definitions(-D__arm64__)
30 | add_definitions(-DIL2CPP_SUPPORT_THREADS)
31 | add_definitions(-DIL2CPP_THREADS_PTHREAD)
32 | #add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
33 | #add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
34 | #add_definitions(-DIL2CPP_TARGET_DARWIN)
35 | add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO=0)
36 |
37 | add_definitions(-MMD)
38 | add_definitions(-MT dependencies)
39 |
40 | include_directories(${IL2CPP_SOURCE_DIR}/external/)
41 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
42 | include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
43 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
44 |
45 | aux_source_directory(${IL2CPP_SOURCE_DIR}/external/zlib/ ZLIB_C_SOURCE_LIST)
46 | add_library(external STATIC ${ZLIB_C_SOURCE_LIST})
47 |
48 |
--------------------------------------------------------------------------------
/scripts/iOSBuild/gen_lump.sh:
--------------------------------------------------------------------------------
1 | echo '====================================================================='
2 | echo 'gen lump'
3 | echo '$HUATUO_IL2CPP_SOURCE_DIR='${HUATUO_IL2CPP_SOURCE_DIR} #/Applications/Unity/Unity.app/Contents/il2cpp/
4 |
5 | GEN_SOURCE_DIR=$1
6 | BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
7 | echo base dir: ${BASE_DIR}
8 | echo " "
9 | #BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
10 | function SearchCppFile()
11 | {
12 | for f in $(ls $1)
13 | do
14 | SUB_DIR=$1/$f
15 | if [ -d ${SUB_DIR} ]; then
16 | SearchCppFile ${SUB_DIR}
17 | fi
18 | done
19 |
20 | CPP_FILE_NUM=`ls -l $1/ | grep "\.cpp$"|wc -l`
21 | if (( ${CPP_FILE_NUM} > 0 ))
22 | then
23 | for f in $1/*.cpp
24 | do
25 | echo "#include \""$f"\"" >> ${OUTPUT_FILE_NAME}
26 | done
27 | fi
28 |
29 | MM_FILE_NUM=`ls -l $1/ | grep "\.mm$"|wc -l`
30 | if (( ${MM_FILE_NUM} > 0 ))
31 | then
32 | for f in $1/*.mm
33 | do
34 | echo "#include \""$f"\"" >> ${OBJECTIVE_FILE_NAME}
35 | done
36 | fi
37 | }
38 |
39 | rm -rf ${GEN_SOURCE_DIR}/lump_cpp
40 | rm -rf ${GEN_SOURCE_DIR}/lump_mm
41 | mkdir ${GEN_SOURCE_DIR}/lump_cpp
42 | mkdir ${GEN_SOURCE_DIR}/lump_mm
43 |
44 | OBJECTIVE_FILE_NAME=${GEN_SOURCE_DIR}/lump_mm/lump_libil2cpp_ojective.mm
45 | echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OBJECTIVE_FILE_NAME}
46 | echo gen file: ${OBJECTIVE_FILE_NAME}
47 |
48 | for FOLDER in huatuo vm pch utils vm-utils codegen metadata os debugger mono gc icalls
49 | do
50 | OUTPUT_FILE_NAME=${GEN_SOURCE_DIR}/lump_cpp/lump_libil2cpp_${FOLDER}.cpp
51 | echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OUTPUT_FILE_NAME}
52 | if [ $FOLDER = huatuo ] || [ $FOLDER = vm ]
53 | then
54 | echo "#include \"${BASE_DIR}/codegen/il2cpp-codegen.h\"" >> ${OUTPUT_FILE_NAME}
55 | fi
56 | SearchCppFile ${BASE_DIR}/${FOLDER}
57 | echo gen file: ${OUTPUT_FILE_NAME}
58 | done
59 |
60 | echo gen done.
61 | echo '====================================================================='
62 | echo " "
63 |
64 |
65 |
--------------------------------------------------------------------------------
/scripts/iOSBuild/objective/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # file: CMakeList.txt
2 | cmake_minimum_required(VERSION 3.0)
3 | set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
4 | project(il2cpp)
5 |
6 | set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
7 | set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
8 |
9 | message(STATUS "objective project, binary dir: " ${PROJECT_BINARY_DIR})
10 | message(STATUS "objective project, il2cpp source dir: " ${PROJECT_SOURCE_DIR})
11 |
12 |
13 | SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
14 | find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
15 | if (NOT CLANG_EXECUTABLE)
16 | message(FATAL_ERROR "Cannot find any clang executable.")
17 | endif()
18 |
19 |
20 | set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
21 |
22 | set(CMAKE_VERBOSE_MAKEFILE ON)
23 | set(CMAKE_CXX_COMPILER clang++)
24 | set(CMAKE_C_COMPILER clang)
25 | #add_compile_options(-x objective-c++)
26 |
27 | # 以下命令为复制的Xcode生成中的命令
28 | set(CMAKE_CXX_FLAGS "-target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu++1z -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -DIL2CPP_TARGET_IOS=1 -isysroot ${SDK_VERSION} -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wunguarded-availability ")
29 |
30 |
31 | add_definitions(-DIL2CPP_TARGET_IOS=1)
32 | add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
33 | add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
34 | add_definitions(-DAARCH64)
35 | add_definitions(-D__aarch64__)
36 | add_definitions(-DIL2CPP_SUPPORT_THREADS)
37 | add_definitions(-DIL2CPP_THREADS_PTHREAD)
38 | #add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
39 | #add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
40 | #add_definitions(-DIL2CPP_TARGET_DARWIN)
41 | add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO)
42 |
43 | add_definitions(-MMD)
44 | add_definitions(-MT dependencies)
45 |
46 |
47 | include_directories(${IL2CPP_SOURCE_DIR}/libil2cpp)
48 | include_directories(${IL2CPP_SOURCE_DIR}/external)
49 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
50 | include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
51 | include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
52 |
53 | # 修改为本机对应SDK路径
54 | include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/v1)
55 | include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include)
56 |
57 | get_filename_component(PARENT_PATH ${PROJECT_BINARY_DIR} PATH)
58 | aux_source_directory(${PARENT_PATH}/lump_mm LUMP_SOURCE_LIST)
59 |
60 | #find_library(zlib ${PROJECT_SOURCE_DIR}/external)
61 | add_library(objective STATIC ${LUMP_SOURCE_LIST})
62 |
63 |
--------------------------------------------------------------------------------