关于Dalvik字节码中的* -bearing寄存器

时间:2012-05-04 21:23:06

标签: android bytecode dalvik

我对Dalvik字节码的格式有点新,我很想知道这些* -bearing寄存器是什么意思,例如物体承载,异常承载等

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

生成

throws Landroid/database/SQLException,但Landroid/database/SQLException是一种类型,那么为什么instruction summarythrow vAA vAA哪个是异常承载寄存器? 我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

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

如果您想更详细地研究寄存器类型信息的传播方式,可以使用-r选项使用b-malidi对应用程序进行反编译,该选项将在每条指令之前/之后输出注释,并提供有关寄存器寄存器类型的信息。与该指令相关。此信息应与字节码验证程序中内置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

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