我正在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

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

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

  • 编辑:

    这是我正在谈论的方法的字节码的转储。 https://gist.github.com/kmicinski/c8382f0521b19643bb24379d91c47d36如您所见,0x570并不是指令的开始,并且(据我所知)在任何地方r5与应该作为对象的String冲突都没有。

    最佳答案

    如果您仔细查看该错误,则表明您正在传递Object,该位置应包含String。无论如何,除非您发布导致问题的实际字节码,否则没有更多的可说的了。

    您确定0x570指向指令的中间吗?不应该这样无论如何,调试的方法是查看相关指令,弄清楚为什么r5应该是String时为什么r5是Object。或者,您可以发布字节码,以便我看看。

    编辑:现在,您已经发布了代码,实际上存在一个导致v5为Object的路径,但这有点微妙。

    异常处理程序.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
    
    :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
    
    :A28是代码块的开头,该代码块假定v5为String。特别是,在指令:AE0上,v5传递给采用String的函数。
    00000AE0  invoke-virtual      StringBuilder->append(String)StringBuilder, v7, v5
    

    0xAE0正好是0x570的两倍,一旦您按照JesusFreke的建议调整了代码单位,它就会说明错误中显示的偏移量。

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

    关于android - Dalvik Verifier中的引用与精确引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43554462/

    10-10 09:09