Android安全交流群:478084054
接上篇笔记。
在ClassLinker的LoadClass方法中,先调用DexFile的GetClassData方法从对应的DEX文件中得到class数据。
然后不管是否具有对应的oat_class,都是调用LoadClassMembers加载类的成员。前面笔记中做过一种假设,就是DEX加固壳阻止了指定DEX生成OAT文件的过程,这种情况下传给LoadClassMembers方法的oat_class参数为nullptr。
LoadClassMembers方法的前半部分用于加载class的静态域和实例域,主要看后面加载方法的部分。
先加载direct方法,再加载virtual方法。先调用LoadMethod方法初始化ArtMethod对象。
回到LoadClassMembers,再继续调用LinkCode链接类方法。先来看LinkCode的前半部分。
如果oat_class不为空,则调用其GetOatMethod方法得到相应的oat_method,再调用LinkMethod方法对method进行设置。
实际上就是设置ArtMethod对象的entry_point_from_quick_compiled_code_成员,作为编译代码入口点。
继续看LinkCode,调用NeedsInterpreter,看看是否需要解释执行。
第2个参数quick_code传入的是method->GetEntryPointFromQuickCompiledCode(),也就是LinkMethod里面设置的entry_point_from_quick_compiled_code_。如果前面oat_class为空,没有设置entry_point_from_quick_compiled_code_,那我觉得NeedsInterpreter传入的参数quick_code应该为空,不管ART是否运行在解释模式中,NeedsInterpreter都会返回true。
之所以说这些,是因为我发现有些DEX壳代码,在运行时想方设法的强制将ART设置为interpret-only,但单从加载类方法这块代码来看,如果壳代码之前阻止了指定DEX生成OAT的过程,这块在找不到方法对应的机器代码入口点的情况下,即使不设置interpret-only,也会以解释运行的方式设置各个Entry Point。(我对ART的了解还太少,后面随着学习的不断深入,再回过头来想想这个问题)
贴出LinkCode的后半部分代码。
主要就是根据各种情况,设置method的解释执行入口点,或者执行编译代码的入口点。