一、分析背景 Unity引擎开发游戏采用了C#语言,Unity采用了Mono的Jit机制实现C#逻辑代码动态编译和执行,Mono属于开源的工程,可通过查看Mono源码了解其中的处理。本文针对Mono的Jit动态编译和执行的机制进行分析,更好的了解Unity引擎在Android平台所采用的处理方式。 二、Mono Jit相关处理机制 1、MONO主要框架 Mono针对C#代码编译和执行主要框架涉及函数调用过程如下: mini/main.c: main() mono_main_with_options() mono_main() mini_init() mono_assembly_open() main_thread_handler() // assembly(也就是bytecode)的编译执行 mini_cleanup() main_thread_handler() mono_jit_exec() mono_assembly_get_image() // 得到image信息,如"test.exe" mono_image_get_entry_point() // 得到类,方法信息 mono_runtime_run_main(method, argc, argv, NULL) mono_thread_set_main(mono_thread_current()) // 将当前线程设为主线程 mono_assembly_set_main() mono_runtime_exec_main() // 编译及调用目标方法 mono_runtime_exec_main() mono_runtime_invoke(method, NULL, pa, exc) // 要调用的方法,如"ClassName::Main()" default_mono_runtime_invoke() // 实际上是调用了mono_jit_runtime_invoke() info->compiled_method = mono_jit_compile_method_with_opt(method) // 编译目标函数 info->runtime_invoke = mono_jit_compile_method() // 编译目标函数的runtime wrapper mono_jit_compile_method_with_opt(method, default_opt, &ex) runtime_invoke = info->runtime_invoke runtime_invoke(obj, params, exc, info->compiled_method) // 调用wrapper,wrapper会调用目标方法 mono_jit_compile_method_with_opt() mono_jit_compile_method_inner() mini_method_compile(method, opt, target_domain, TRUE, FALSE, 0) // 通过JIT编译给定方法 mono_runtime_class_init_full() // 初始化方法所在对象 method = mono_class_get_cctor() // 得到类的构造函数 if (do_initialization) // 对象需要初始化 mono_runtime_invoke() // 调用相应构造函数来构造对象,如"System.console:.cctor()" mono_jit_runtime_invoke() 2、编译并执行过程 其中mono_runtime_invoke函数在mono源代码object.c中,而其实际调用的mono_jit_runtime_invoke则在mini.c代码中。查看mini.c代码:
可以看到,在该函数中,会先通过查找列表,看是否已创建对应的info信息,若不存在,则先进行编译得到info信息:
编译完成(或之前已编译相同的info信息)后,则调用info自身的runtime_invoke实现对真正函数的调用。 以上是基于对mono的源代码进行的分析,下面将基于以上的分析设想,对实际的android unity游戏进行逆向推定。
而 compiled_method即为实际的代码。而根据入口参数method也可获取到compile_method的函数名,通过结构分析可以看到,在整个编译和调用的过程中,结构MonoMethod函数都是相当关键的结构,其结构在class_internal.h定义中:
而在该结构中的name属性,应就是对应的函数名,如:
以上是对一般模式下的mono进行的分析。而实际上,mono还支持动态调用的方式: 在mono_jit_runtime_invoke中,还存在代码:
而android unity的编译代码正是支持该功能。 在核心代码中,对真正的c#函数进行了编译与调用:
三 、总结 以上针对Unity引擎采用的Mono Jit动态编辑机制进行详细分析和阐述。Unity采用Mono的C#动态编译处理机制更好的实现了跨平台功能,Mono的Jit将C#代码编译为IL指令,在运行过程中动态编译为机制识别指令,了解整个处理机制便于更好的分析Android平台Unity引擎开发的游戏。
*转载请注明来自游戏安全实验室(GSLAB.QQ.COM)
|
最新评论
发表评论