ngClass旨在把Class从Dex加载到虚拟机中,但不涉及类的使用或执行流程。InitializingClass旨在保证使用类前已经经过了初始化流程,此流程嵌入类的使用或执行过程中。
加载类
DefineClass主要通过SetupClass、InsertClass以及LoadClass将一个类加载到虚拟机中,最后返回mirror:Class对象指针。
-
SetupClass:设置类的访问标志以及ClassLoader。
-
InsertClass:将类插入到对应ClassLoader的ClassTable中,以便查找。
-
LoadClass:将类的属性及方法加载到类中。
类初始化
类的属性或方法在使用前必须经过类的初始化。
提前发现
从上面的分析可以看出,应该尽可能让核查走VerifyClassUsingOatFile流程,即通过Oat文件状态位核查成功。Oat文件中类的状态位是什么以及为什么状态位不等于kStatusVerified是问题的突破点。
通过oatdump命令去dump相应的odex文件,可以查看类的状态位,操作方式如下
-
InitializeClass:核验类、初始化父类、接口方法以及静态属性。
-
VerifyClass:核验类的合法性,在下一节详细分析。
-
erifyClassUsingOatFile:通过Oat文件中的Class状态位去核验Class,当状态位等于kStatusVerified时,核查流程到此为止,直接快速返回。否则需要进入耗时的PerformClassVerification流程。
-
PerformClassVerification:主要核验类中的直接方法和虚方法。
-
ComputeWidthsAndCountOps:判断PC值与dalvik指令数是否相等。
-
ScanTryCatchBlocks:检查Try语句开始地址、结束地址以及try开始操作符的合法性。检查catch中handler语句开始操作符的合法性。
-
VerifyInstructions:检查各种dalvik指令,同时将GC检查点插入到括号、switch、throw指令中。
-
VerifyCodeFlow:检查每条dalvik指令的寄存器以及参数的合法性。
OG默认是不会被打印的,需要动态开启,开启的方式可以通过:art::gLogVerbosity.class_linker = true而打开,因为本项目需要看到dex2oat和其他进程的打印情况,本人是在系统源码中进行编译生成的so,然后,通过ptrace注入so到Zygote的,此方法需要root设备,如果只需要查看本进程,应不需要这么麻烦,具体方法还未探索,但思路应该是一致的。举例如下,本人碰到的问题是AppCompat包中的类不能被核验通过。
决方案
将Runtime对象中的verify_设置成verifier::VerifyMode::kNone。
-
需要通过Runtime对象首地址遍历查找verify_属性,魔改厂商可能带来兼容性问题。
-
缺少VerifyClass过程,可能会后置发现非法指令问题。
-
对zygote中值verify_进行修改将造成cow内存消耗。
-
将多出EnsureSkipAccessChecksMethods一步处理逻辑,将类中每个函数flag进行修改,此处逻辑没有对单个类进行处理,所以,每个类的每个函数的flag都将被无谓修改,如下图所示:
-

(编辑:开发网_开封站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|