Dalvik Verifier中的参考与精确参考

Kri*_*ski 6 android bytecode dalvik bytecode-manipulation smali

我正在Dalvik字节码上编写工具,该代码对各种方法调用条目执行一些日志记录。具体来说,在各种方法调用站点,我将插入一组指令,这些指令收集参数,将其放入Object[]数组中,然后将其传递给日志记录函数。

这一切都很好,很好,我已经实现并克服了大多数应用程序的所有麻烦。但是我遇到了一个特别难以理解的Dalvik验证程序错误:

java.lang.VerifyError: Verifier rejected class io.a.a.g: void io.a.a.g.r() 
failed to verify: void io.a.a.g.r(): [0x570] register v5 has type Reference: 
java.lang.Object but expected Precise Reference: java.lang.String
Run Code Online (Sandbox Code Playgroud)

我查看了仪器生成的代码,我所做的只是将寄存器v5放入对象数组中。

我在这里有几个问题:

  • 什么是精确参考,为什么它与参考不兼容?
  • 这里的偏移量是什么意思?[0x570]指向字节码指令的中间,因此不会清楚地映射到任何指令:那里的指令不涉及v5
  • 我将如何调试呢?理想情况下,我想知道验证者认为应该发生的情况并加以解决。

编辑:

这是我正在谈论的方法的字节码的转储。https://gist.github.com/kmicinski/c8382f0521b19643bb24379d91c47d36正如你所看到的,0x570不是指令的开始,(据我可以告诉)没有任何地方有一个字符串,其中R5冲突它应该是一个对象。

Ant*_*ony 4

如果你仔细观察这个错误,它会告诉你你正在传递一个Object,而 aString是应该传递的。无论如何,除非您发布导致问题的实际字节码,否则没有什么可说的。

你确定0x570指向指令的中间吗?不应该。无论如何,调试它的方法是查看相关指令并找出为什么 r5 是一个对象,而它应该是一个字符串。或者你可以发布字节码,以便我看一下。

编辑:现在您已经发布了代码,实际上有一条路径导致 v5 成为对象,但它有点微妙

异常处理程序 .catch JSONException {:5D8 .. :938} :BDE跳转到:BDE

异常处理程序的代码将捕获的异常存储在 v5 中,这意味着 v5 此时不再是 String。然后它跳转到:162

:BDE
00000BDE  move-exception      v5
00000BE0  const               v0, 0x00488B36
00000BE6  invoke-static       Logger->logBasicBlockEntry(I)V, v0
00000BEC  goto/16             :162
Run Code Online (Sandbox Code Playgroud)

:162在另一个异常处理程序的范围内:.catch ClassNotFoundException {:2E .. :594} :BF0

:Bf0保持 v5 不变并跳转到:A28

:BF0
00000BF0  move-exception      v6
00000BF2  const               v0, 0x00488B3E
00000BF8  invoke-static       Logger->logBasicBlockEntry(I)V, v0
00000BFE  goto/16             :A28
Run Code Online (Sandbox Code Playgroud)

:A28是代码块的开头,假设 v5 是字符串。特别是,在指令 上:AE0,v5 被传递给采用字符串的函数。

00000AE0  invoke-virtual      StringBuilder->append(String)StringBuilder, v7, v5
Run Code Online (Sandbox Code Playgroud)

0xAE0 恰好是 0x570 的两倍,这解释了错误中显示的偏移量,一旦您按照 JesusFreke 建议调整代码单元。

请注意,这不一定是唯一损坏的代码路径,它只是我在查看代码时发现的第一个路径。然而,一条糟糕的路径足以将 v5 的类型与 JSONException 统一起来,从而将其转换为 Object。