我使用dexlib2以编程方式检测dex文件中的某些方法,例如,如果我找到这样的指令:
invoke-virtual {v8, v9, v10}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
我想在它之前插入一条指令,因此在运行时我可以知道Class.getMethod()的确切参数。
但是,现在我遇到一些关于如何分配在插入的监控指令中使用的寄存器的问题?
我知道两种方法,但无论哪种方式都有问题:
我可以使用DexRewriter来增加此方法的registerCount(例如从.register 6到.register 9),这样我就可以使用额外的(3)寄存器。但首先这受到16个寄存器的限制;第二,当我增加registerCount时,参数将被传递到最后一个,因此我必须重写此方法中使用参数的所有指令,这很累人。
或者我可以重用寄存器。这种方式我必须分析每个寄存器的活跃性,而dexlib2似乎没有现有的API来构建CFG和def-use链,这意味着我必须自己编写它。 此外,我怀疑通过这种方式我是否可以获得足够的可用寄存器。
我理解这个问题对吗?有没有现成的工具/算法呢?或者我能以更好的方式做任何建议?
感谢。
答案 0 :(得分:0)
几点:
您不限于此方法中的16个寄存器。大多数指令只能处理前16个寄存器,但有一些mov指令可用于将值与更高的寄存器交换出来
如果你可以通过而不是分配任何新的寄存器,那么你的生活会更容易。一种方法是使用检测逻辑创建一个新的静态方法,然后使用目标方法中的适当值添加对该静态方法的调用。
我所看到的一种方法是增加寄存器计数,然后在方法开头添加一系列移动指令,将所有参数寄存器移回到相同的寄存器中在您递增寄存器计数之前。这使得您不必重写所有现有指令,并保证未使用范围末尾的新寄存器。这种方法的主要烦恼是当新的寄存器是v16或更高时,你必须在它们被用来将值恢复到低寄存器的点之前和之后进行一些交换,然后恢复该寄存器中的任何内容。