0

除了执行以下操作之外,是否还必须执行其他操作才能将 String 常量加载到寄存器中,然后在方法调用中使用它:

const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I

?

以下指令块

iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0

invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1

给了我以下 logcat 错误消息:

10-29 23:37:37.191: W/dalvikvm(515): VFY: register1 v6 type 2, wanted ref
10-29 23:37:37.241: W/dalvikvm(515): VFY: bad arg 0 (into Ljava/lang/String;)
10-29 23:37:37.241: W/dalvikvm(515): VFY:  rejecting call to Landroid/util/Log;.wtf (Ljava/lang/String;Ljava/lang/String;)I
10-29 23:37:37.241: W/dalvikvm(515): VFY:  rejecting opcode 0x71 at 0x0028
4

2 回答 2

1

在这种情况下,您的怀疑是正确的。问题是因为在第二个 Log->wtf 实例中,不一定要设置 v6。

至于为什么会发生这种情况,重要的是要注意在重新组装字节码时进行的验证很少。在许多情况下,汇编器根本没有足够的信息来进行此级别的验证 - 这将要求汇编器了解应用程序运行时将出现的完整类集,类似于 deodexing (-o ) 或生成寄存器信息 (-r)。

dalvik在验证字节码时发现了这些类型的问题,这正是您提到的错误所在。

此外,您提到“我用于 p1 和 p2 的值在 if-eqz 测试中都失败了”。这与 dalvik 的字节码验证器无关。验证者确保所有代码路径都有效。它不能知道或假定传递给方法的参数的任何特定值。

如果您想查看与寄存器类型如何在整个方法中传播相关的其他信息,您可以尝试使用 baksmali 的 -r 选项。

# grab the full framework directory from your device
adb pull /system/framework framework
# run baksmali with the -r command
baksmali -r ARGS,DEST,FULLMERGE -d framework <apk_or_dex_file>

这将在每条指令之前/之后添加注释,其中包含有关该位置寄存器类型的详细信息。

于 2012-10-31T18:18:37.373 回答
0

我改变了一些东西并让它工作,但我不知道为什么......

我所做的改变是将常量加载(const-string v6, "TEST CONSTANT")移到“if-block”之外,导致

const-string v6, "TEST CONSTANT"
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;

invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0

invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1

我怀疑最初问题的原因是如果流程绕过了第一个“if-block”但进入了第二个“if-block”,那么在v6使用之前还没有加载寄存器。

我不太确定的原因是,当我运行重新组装的程序时,我使用的值p1并且p2会通过两个if-eqz测试(即流程将进入两个“if-blocks”)。

所以看起来, 1.在实际控制流之前先检查要在使用之前加载
的寄存器吗? 2. 我认为这种检查只在编译时进行?v6

我将其发布为答案,因为我需要更多空间来解释我的所作所为。但是,我仍然很好奇为什么这样的改变让它起作用,所以如果有人能给出解释,我会把它标记为答案,谢谢!

于 2012-10-30T14:12:54.543 回答