smali:字符串常量

时间:2012-10-29 15:41:09

标签: android smali

除了执行以下操作之外,还有什么必须要做的事情才能将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

2 个答案:

答案 0 :(得分: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>

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

答案 1 :(得分: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在它之前尚未加载用了。

我之所以不确定的原因是,当我运行重新组装的程序时,我用于p1p2的值将失败if-eqz次测试(即流程将进入“if-blocks”)。

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

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