DalvikVM如何处理切换并尝试smali代码

Xon*_*nar 8 dalvik smali

我正在努力学习smali,我有一些问题,我用谷歌搜索他们找不到.

1)我创建了一个简单的测试用例来更好地解释自己

const-string v1, "Start"
:try_start_0
const-string v1, "Try Block"
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
:try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0
Run Code Online (Sandbox Code Playgroud)

.catch语句:两个参数是否意味着从该标签到该标签并捕获它(两个标签之间的代码)或者它是否意味着开始执行try:try_start_0直到达到:try_end_0(允许goto跳转)执行不在两个标签内的代码)?

try标签总是采用try_start_%d格式,还是可以是任何标签?

2)另一个案例

packed-switch v0, :pswitch_data_0

const-string v1, "Default Case"

invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V

:goto_0

const-string v1, "The End"

invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V

return-void

:pswitch_0
const-string v1, "Case 1"

invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V

goto :goto_0

:pswitch_data_0
.packed-switch 0x1
:pswitch_0
.end packed-switch
Run Code Online (Sandbox Code Playgroud)

switch语句:是否要求switch语句位于交换机数据和交换机调用之间?还有标签的命名固定或只是为了方便?

3)如果标签可能不同,baksmali会不会产生带有不同标签的小码?

4)在反编译dex时,哪些可选行并不总是显示?

我知道.parameter和.line是可选的,但是那些可能不存在的是什么?

先感谢您.

Jes*_*eke 6

1)

前两个标签(示例中为try_start_0和try_end_0)定义了try块所涵盖的代码范围.如果在覆盖的代码中发生异常,则执行会立即跳转到第三个标签(catchall_0).标签的名称并不重要,它可以是任何有效的标识符.

除了它只处理特定类型的异常(类似于java的catch语句)之外,还有.catch指令,它是相同的.

一个代码块可以被多个catch语句覆盖,并且最多可以捕获所有语句..catch语句的位置并不重要,但是,导入包含相同代码的catch语句的相对顺序.例如,如果你有

.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :handler1
.catch Ljava/lang/RuntimeException; {:try_start_0 .. :try_end_0} :handler2
Run Code Online (Sandbox Code Playgroud)

永远不会使用第二个catch语句.如果在覆盖的代码中抛出RuntimeException,则始终会使用第一个catch,因为RuntimeException是Exception.

但是,如果它们的顺序相反,它将按预期工作 - RuntimeException处理程序用于RuntimeExceptions,并且Exception处理程序用于任何其他类型的异常.

最后,与java不同,.catch语句中的代码范围不需要严格嵌套.例如,拥有类似的东西是完全合法的

:a
const-string v1, "Start"
:b
const-string v1, "Try Block"
:c
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
:d
.catch Ljava/lang/RuntimeException; {:a .. :c} :d
.catch Ljava/lang/Exception; {:b .. :d} :d
Run Code Online (Sandbox Code Playgroud)

你也可以有一些非常奇怪的结构,像这样.

.method public static main([Ljava/lang/String;)V
    .registers 3

    :second_handler
    :first_try_start
        new-instance v0, Ljava/lang/RuntimeException;
        invoke-direct {v0}, Ljava/lang/RuntimeException;-><init>()V
        throw v0
    :first_try_end
    .catch Ljava/lang/Exception; {:first_try_start .. :first_try_end} :first_handler
    :first_handler
    :second_try_start
        new-instance v0, Ljava/lang/RuntimeException;
        invoke-direct {v0}, Ljava/lang/RuntimeException;-><init>()V
        throw v0
    :second_try_end
    .catch Ljava/lang/Exception; {:second_try_start .. :second_try_end} :second_handler
.end method
Run Code Online (Sandbox Code Playgroud)

以上示例都不会从编译的java代码生成,但字节码本身允许它.

2)switch语句可以是与switch语句或switch数据有关的任何地方.这里的标签名称也是任意的.

3)Baksmali可以通过两种方式之一生成标签.默认方式是使用标签的一般"类型",并附加标签的字节码地址.如果指定-s/ - 顺序标签选项,而不是使用字节码地址,它会为每种标签类型保留一个计数器,并在每次生成该类型的标签时递增它.

4)通常是调试信息的一部分..parameter,.line,.prologue,.epilogue,.source,.local,.restart local,.end local ...我认为这涵盖了它.