1

我对 Dalvik 字节码的格式有点陌生,我想知道这些 *-bearing 寄存器是什么意思,例如对象承载、异常承载等。

同时,生成的字节码是使用类型,而不是寄存器?例如,

throws Landroid/database/SQLException是生成的,但是Landroid/database/SQLException是一个类型,那么为什么指令摘要说异常承载寄存器throw vAA在哪里?vAA我错过了什么吗?

4

1 回答 1

0

这只是指指令保存的数据类型。vm 必须能够静态地确定该寄存器在该点包含该类型的数据。换句话说,对于所有传入的代码路径,该寄存器已设置为该类型的数据。

如果您想更详细地研究寄存器类型信息是如何传播的,您可以使用 -r 选项使用 baksmali 反编译您的应用程序,该选项将在每条指令之前/之后输出注释,其中包含与寄存器相关的寄存器类型信息那条指令。此信息应与 vm 在字节码验证器中内部构建的寄存器类型信息相匹配。

例如,假设您有一个仅包含以下内容的方法:

const-string v0, "Hello World!"
throw v0

这是不允许的,因为在 throw 指令处,p0 寄存器不包含对从 Throwable 扩展的对象的引用(即它不是“带有异常的寄存器”)。

如果你在 baksmali 中使用 -r,你会看到:

#v0=(Uninit);
const-string v0, "Hello World!"
#v0=(Reference,Ljava/lang/String;);

#v0=(Reference,Ljava/lang/String;);
throw v0

这清楚地表明 v0 在 throw 指令处不包含异常。

此外,不允许这样的事情:

#v0=(Uninit);
new-instance v0, Ljava/lang/Exception;
#v0=(UninitRef,Ljava/lang/Exception;);

#v0=(UninitRef,Ljava/lang/Exception;);
invoke-direct {v0}, Ljava/lang/Exception;-><init>()V
#v0=(Reference,Ljava/lang/Exception;);

#p0=(Integer);
if-eqz p0, :cond_9

#v0=(Reference,Ljava/lang/Exception;);
const-string v0, "Hello World!"
#v0=(Reference,Ljava/lang/String;);

:cond_9
#v0=(Reference,Ljava/lang/Object;);
throw v0

因为在抛出点,v0 可能包含异常或字符串。在这种情况下,它将 v0 的“类型”报告为Ljava/lang/Object;,因为这是两种类型的公共父类。

于 2012-05-04T22:06:31.003 回答