修改 Dalvik 虚拟机以拦截应用程序代码的方法

Modifying Dalvik Virtual Machine to intercept methods of Application code

在我目前的实现中,我只能拦截一些Class初始化方法的Method_Entry事件,包括:

*.<init> or *.<cinit>
* stands for any Class

Java 应用程序中编写的所有方法都丢失了。

目前,我在以下地方插入了"fprintf()":

stack.cpp: dvmCallMethod() 
stack.cpp: dvmCallMethodV() 
stack.cpp: dvmCallMethodA()
stack.cpp: dvmInvokeMethod()
Interp.cpp: dvmInterpret()
Mterp.cpp: dvmMterpStd()

当DVM的这些地方被执行时,我会在我的日志文件中打印一条信息。但是,只有 Class 初始化函数触发了我的 println() 代码。换句话说,应用程序方法的执行看起来并没有经过DVM的上述地方。我不知道 DVM 的哪一部分负责应用程序的方法执行。谁能给我一个线索?

弄清楚事情是如何工作的最简单的方法是查看方法分析的工作原理。每次调用方法时,分析都会在日志文件中添加一个条目。密钥文件是 dalvik/vm/Profile.h,它定义了像 TRACE_METHOD_ENTER 这样的宏。 (在 gingerbread 中,这就是您需要查找的全部内容。在 ICS 中,情况发生了很大变化,当调试、分析和 JIT 编译之间的交互被重新处理时。KitKat 添加了 "sampling" 分析器。所以现在有点曲折,还有一些其他的函数需要注意,比如dvmFastMethodTraceEnter().)

您在问题中确定的入口点用于反映和调用本机代码的进出。解释代码之间的调用通过更新堆栈和程序计数器来处理,并继续循环遍历解释器。你可以在 line 3928 in the portable interpreter.

看到这个

不明显的部分是第 415 行定义的 FINISH() 宏。这会调用 dvmCheckBefore(),第 1692 in Interp.cpp. This function checks the subMode field to see if there is anything interesting to do; you can find the various meanings in the definition, line 50 in InterpState.h 行。简而言之,标志用于各种分析、调试和 JIT 编译功能。

您可以在 line 3916 in the portable interpreter, in the method invocation handling. It calls into dvmReportInvoke(), over in Interp.cpp 上看到 subMode 检查,它会调用 TRACE_METHOD_ENTER 宏。

如果您只是想在每次调用任何方法时都发生一些事情,您可能应该将它连接到分析系统中,因为这已经在做您想要的事情了。如果您不需要方法分析功能,只需将其替换为您的代码即可。