[实践] Android5.1.1源码 - 让某个APP以解释执行模式运行
前言
本文的实践修改了Android5.1.1的源码。
本文只简单的讲了一下原理。在“实践”一节讲了具体做法。
本文的内容涉及Art模式下dex加载的知识,想要详细了解这部分知识可以去看老罗的文章:
本文的内容涉及zygote,如果不知道zygote是什么,或者好奇zygote如何启动,可以去看老罗的文章:
Android系统进程Zygote启动过程的源代码分析
老罗的文章分析的是Android2.3的源码,所以下面提到的与zygote有关的函数在老罗的文章里面可能没有,如果想要对下面提到的与zygote有关的函数有一个简单的了解可以看我的文章:Android5.1.1源码 - zygote fork出的子进程如何权限降级
原理简介
怎么才能让方法解释执行
在函数ClassLinker::LinkCode中会链接dex中的方法代码,这个函数的定义在文件”art/runtime/class_linker.cc”中,下面是它的源码(这里只列出了与本文有关的部分):
在这个函数中调用了NeedsInterpreter函数判断当前方法是否要解释执行,如果返回值为true,即局部变量enter_interpreter被赋值为true,那么调用ArtMethod类中的SetEntryPointFromQuickCompiledCode函数并将GetQuickToInterpreterBridge()的返回值传入,GetQuickToInterpreterBridge()函数返回用于解释执行的函数的入口地址,这个入口函数解释执行dex中的方法。
那么现在来看看NeedsInterpreter函数,这个函数的定义在文件”art/runtime/class_linker.cc”中,下面是它的源码:
当”Runtime::Current()->GetInstrumentation()->InterpretOnly()”返回true且不是本地方法和代理方法,那么这个函数就会返回true,否则返回false。
InterpretOnly函数是Instrumentation类的成员函数,它的函数定义在文件”art/runtime/instrumentation.h”中,下面是它的源码:
interpret_only_是类Instrumentation的成员变量,是布尔类型。可以发现InterpretOnly函数仅仅是将”interpret_only_”返回,如果将interpret_only_设置为true,那么根据上文分析,所有“非本地且非代理”方法都将被解释执行。
那么如何将interpret_only_设置为true哪,在Instrumentation类中有一个ForceInterpretOnly函数,下面是这个函数的源码:
这个函数是Instrumentation类的公有成员函数,所以直接调用这个函数即可将interpret_only_设置为true。
这里有一个问题,将interpret_only_设置为true,那么“非本地且非代理”方法在链接代码时都将被设置成解释执行,那么会不会影响到其他的APP进程?不会,因为ClassLinker::LinkCode函数对方法的链接是在APP进程的内存中进行的,所以这个操作并不会影响到其他进程。
这里进行一个小节,当执行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”语句时,会把Instrumentation对象的interpret_only_成员变量设置为true。那么当方法是“非本地且非代理”方法时,NeedsInterpreter函数将返回true,那么在ClassLinker::LinkCode函数中会将这个方法设置为解释执行。
如果要将APP中所有方法都设置为解释执行,那么就需要在链接APP的dex中的方法代码之前执行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”语句。
调用ForceInterpretOnly函数的时机
我的办法是在EnableDebugFeatures函数中调用ForceInterpretOnly函数,在这一节中会先说明Android如何执行到EnableDebugFeatures函数,然后会说明在EnableDebugFeatures函数中调用ForceInterpretOnly函数的好处。
所有的Android应用进程都是zygote fork出来的,fork APP进程时的函数调用路径:
调用完ForkAndSpecializeCommon函数后APP进程就被fork出来了。
ForkAndSpecializeCommon函数定义在文件”frameworks/base/core/jni/com_android_internal_os_Zygote.cpp”中,下面它的源码:
gCallPostForkChildHooks是一个全局变量,它在com_android_internal_os_Zygote.cpp文件的register_com_android_internal_os_Zygote函数中被初始化。
env->CallStaticVoidMethod(…)语句调用了Java方法”Zygote.callPostForkChildHooks”。
下面是Zygote.callPostForkChildHooks方法的源码,这个方法在文件”frameworks/base/core/java/com/android/internal/os/Zygote.java”中:
VM_HOOKS是Zygote类的成员变量,下面是它的定义:
VM_HOOKS.postForkChild调用的就是ZygoteHooks类中的成员方法postForkChild,这个方法在文件”libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java”中,下面是它的源码:
这个方法中调用了native函数nativePostForkChild,nativePostForkChild函数的C层代码在文件”/home/sowuy/android/system/art/runtime/native/dalvik_system_ZygoteHooks.cc”中,下面是它的源码:
我将在EnableDebugFeatures函数中调用ForceInterpretOnly函数,原因有三点:
- EnableDebugFeatures函数参数接收的是一个标志,我可以设置一个新的标志位用来表示是否需要调用ForceInterpretOnly函数。
- 每次APP启动的时候都会执行EnableDebugFeatures函数。
- EnableDebugFeatures函数被调用的时机好,它运行在fork出的APP进程中,并且在链接APP的dex中的方法前被调用。
实践
修改Zygote.java中的代码
Zygote.java文件的位置是:frameworks/base/core/java/com/android/internal/os/Zygote.java,在Zygote类中添加一个成员变量:
在Zygote类forkAndSpecialize方法的开始部分添加下面的代码:
修改dalvik_system_ZygoteHooks.cc中的代码
dalvik_system_ZygoteHooks.cc文件的位置是:art/runtime/native/dalvik_system_ZygoteHooks.cc,修改这个文件中的EnableDebugFeatures函数的代码。
向这个函数中添加下面的代码:
下面是对这个函数修改后的完整代码:
作者:寻禹@阿里聚安全,更多安全技术文章,请访问阿里聚安全博客
[实践] Android5.1.1源码 - 让某个APP以解释执行模式运行的更多相关文章
- [实践] Android5.1.1源码 - 在Framework中添加自定义系统服务
前言 本文的方法要修改Android源码.但只要将系统服务写出来,也可以注入system_server进程将系统服务加载到system_server中. 步骤 1. 添加一个aidl文件,我将aidl ...
- 【JVM源码解析】模板解释器解释执行Java字节码指令(上)
本文由HeapDump性能社区首席讲师鸠摩(马智)授权整理发布 第17章-x86-64寄存器 不同的CPU都能够解释的机器语言的体系称为指令集架构(ISA,Instruction Set Archit ...
- python编程从入门到实践 alien invasion 项目源码
现在上传一个 python编程从入门到实践 alien invasion 项目源码 以供大家学习参考 跟官方版本可能不太一样,因为是自己写的 也算是给新手一个参考 我用的环境是pycharm 可能需要 ...
- 关于android源码中的APP编译时引用隐藏的API出现的问题
今天在编译android源码中的计算器APP时发现,竟然无法使用系统隐藏的API,比如android.os.ServiceManager中的API,引用这个类时提示错误,记忆中在android源码中的 ...
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
- 导入android源码中的APP源码到eclipse
导入android源码中的APP源码到eclipse 一般最简单的办法就是创建新的android工程,选择create project from existing source选项,直接导入源码就OK ...
- [源码解析]Oozie来龙去脉之内部执行
[源码解析]Oozie来龙去脉之内部执行 目录 [源码解析]Oozie来龙去脉之内部执行 0x00 摘要 0x01 Oozie阶段 1.1 ActionStartXCommand 1.2 HiveAc ...
- 从源码角度理解Java设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
- [源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎
[源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎 目录 [源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎 0x00 摘要 0x01 前言 1.1 ...
随机推荐
- jQuery中的Ajax - Codeigniter版本
发送(view中): $.ajax({ type : 'post', url : 'add', data : { 'nickname':nickname, 'mobile':mobile, 'sex' ...
- 怎样用conda安装opencv
首先用Anaconda是因为方便(管理方便,包安装真心不方便).下面是我的安装过程: 首先使用如下命令安装opencv conda install -c https://conda.binstar.o ...
- 继承映射关系 TPH、TPT、TPC<EntityFramework6.0>
每个类型一张表[TPT] 声明方式 public class Business { [Key] public int BusinessId { get; protected set; } public ...
- NetMQ(四): 推拉模式 Push-Pull
ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...
- 关于Solr的使用总结的心得体会
摘要:在项目中使用Solr作为搜索引擎对大数据量创建索引,提供服务,本文是作者对Solr的使用总结的一点心得体会, 具体包括使用DataImportHandler从数据库中近实时同步数据.测试Solr ...
- Android获取ImageView上的图片,和一个有可能遇到的问题!
1.在获取图片前先调用setDrawingCacheEnabled(true)这个方法: 举例:mImageView.setDrawingCacheEnabled(true); 2.之后可以通过get ...
- 浩瀚PDA开单器-结束手工开单模式【百货、商超】PDA安卓智能手持POS 进销存管理系统移动收银管理软件
移动销售终端:先进的跨平台技术,支持智能PDA等移动终端提供移动销售开单.移动POS.移动查询货品.移动盘点等功能. 移动开单器的操作说明 第一步:选客户 Ø 用户在空白开单主页左划屏幕 ...
- Redis——学习之路三(初识redis config配置)
我们先看看config 默认情况下系统是怎么配置的.在命令行中输入 config get *(如图) 默认情况下有61配置信息,每一个命令占两行,第一行为配置名称信息,第二行为配置的具体信息. ...
- DelphiXE10.1获取Administrator所有权的方法
操作: 菜单选择Proceject->Options->Application->把Enable Admonistrator Privileges打勾(manifest file - ...
- 递推+高精度 UVA 10497 Sweet Child Makes Trouble(可爱的孩子惹麻烦)
题目链接 题意: n个物品全部乱序排列(都不在原来的位置)的方案数. 思路: dp[i]表示i个物品都乱序排序的方案数,所以状态转移方程.考虑i-1个物品乱序,放入第i个物品一定要和i-1个的其中一个 ...