2

我一直在学习如何编写 smali 文件,并且我创建了一个特定的方法,它接受一个字符串参数并将其放入日志中。它的 java 等价物是这样的:

public void log(String param){
        Log.d(param, param);
    }

当我再次对其进行修改并签署 apk 时,我在 logCat 中收到以下错误:

10-05 21:52:42.081: W/dalvikvm(32021): VFY: register1 v2 type 0, wanted ref
10-05 21:52:42.081: W/dalvikvm(32021): VFY: bad arg 0 (into Ljava/lang/String;)
10-05 21:52:42.081: W/dalvikvm(32021): VFY:  rejecting call to Landroid/util/Log;.d (Ljava/lang/String;Ljava/lang/String;)I
10-05 21:52:42.081: W/dalvikvm(32021): VFY:  rejecting opcode 0x71 at 0x0000
10-05 21:52:42.081: W/dalvikvm(32021): VFY:  rejected Lcom/shqipe/worthstream/utils/Utils;.log (Ljava/lang/String;)V
10-05 21:52:42.081: W/dalvikvm(32021): Verifier rejected class Lcom/shqipe/worthstream/utils/Utils;
10-05 21:52:42.081: D/AndroidRuntime(32021): Shutting down VM

这是smali文件中的方法:

.method public static log(Ljava/lang/String;)V
    .registers 2
    .parameter "paramString"
    .prologue


    invoke-static {p1, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 63
    return-void
.end method

谁能向我解释如何调试此错误?

4

2 回答 2

3

p1 在该上下文中是无效寄存器。事实上,baksmali 应该抓住这一点!:)

使用 .registers 2 和一个参数,您就有了寄存器 v0 和 v1,其中 p0 被别名为 v1。根据您的 .registers 指令,p1 实际上是 v2,这是不允许的。

你想要的是

invoke-static {p0, p0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

或等效地

invoke-static {v1, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

关于如何调试此类错误,您可以做的最好的事情是查看您看到的 VFY 错误字符串的 dalvik 源代码,并准确识别错误消息的含义(即错误条件是什么)它触发),以及在字节码中发生错误的位置。

要确定错误发生的字节码位置,请查看错误行

10-05 21:52:42.081: W/dalvikvm(32021): VFY:  rejecting opcode 0x71 at 0x0000
10-05 21:52:42.081: W/dalvikvm(32021): VFY:  rejected Lcom/shqipe/worthstream/utils/Utils;.log (Ljava/lang/String;)V

这表明错误发生在Lcom/shqipe/worthstream/utils/Utils;.log (Ljava/lang/String;)V方法中,在字节码偏移量 0 处(即第一条指令)。但是,如果不清楚它指的是哪条指令,您可以对 baksmali 使用 -f 选项,这将导致它在每条指令之前添加字节码偏移量作为注释。

于 2013-10-05T17:27:24.757 回答
1

只是对 JesusFreke 的回答的补充, p0 在示例中没有引用 Java this,因为该函数是静态的。因此,正如 JesusFreke 所说,争论从 p0 开始。

于 2013-10-19T13:11:15.337 回答