8

私はスマリ語を学ぼうとしていますが、グーグルで検索しても見つからない質問がいくつかあります。

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

.catch ステートメント: 2 つの引数は、そのラベルからそのラベルまで取得してキャッチすることを意味しますか (2 つのラベルの間のコード)、それとも :try_start_0 から :try_end_0 に到達するまで試行の実行を開始することを意味しますか (goto ジャンプを許可します) 2 つのラベル内にないコードを実行するには)?

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

switch ステートメント: switch ステートメントが switch データと switch 呼び出しの間にある必要がありますか? また、ラベルの命名は固定されていますか、それとも便宜上のものですか?

3) ラベルが異なる可能性がある場合、baksmali は異なるラベルで smali コードを生成しますか?

4) dex を逆コンパイルするときに常に表示されるとは限らないオプションの行は何ですか?

.parameter と .line がオプションであることは知っていますが、存在しないものは何ですか?

前もって感謝します。

4

1 に答える 1

6

1)

最初の 2 つのラベル (この例では try_start_0 と try_end_0) は、try ブロックがカバーするコードの範囲を定義します。カバーされたコード内で例外が発生した場合、実行はすぐに 3 番目のラベル (catchall_0) にジャンプします。ラベルの名前は重要ではありません。有効な識別子であれば何でもかまいません。

.catch ディレクティブもありますが、特定の種類の例外のみを処理することを除いて同じです (Java の catch ステートメントに似ています)。

コードのブロックは複数の catch ステートメントでカバーでき、最大で 1 つの catch all ステートメントでカバーできます。.catch ステートメントの場所は重要ではありませんが、同じコードをカバーする catch ステートメントの相対的な順序は重要です。たとえば、

.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :handler1
.catch Ljava/lang/RuntimeException; {:try_start_0 .. :try_end_0} :handler2

2 番目の catch ステートメントは使用されません。対象となるコードで RuntimeException がスローされた場合、RuntimeException は例外であるため、最初のキャッチが常に使用されます。

ただし、それらが逆の順序である場合は、期待どおりに動作します。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

このようなかなり奇妙な構造を持つこともできます。

.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

上記の例はどちらも、コンパイルされた Java コードから生成されることはありませんが、バイトコード自体はそれを可能にします。

2) switch ステートメントは、switch ステートメントまたは switch データに関連する任意の場所にある可能性があります。ここでのラベル名も任意です。

3) Baksmali は、2 つの方法のいずれかでラベルを生成できます。デフォルトの方法は、ラベルの一般的な「タイプ」を使用し、ラベルのバイトコード アドレスを追加することです。-s/--sequential-labels オプションを指定すると、バイトコード アドレスを使用する代わりに、各ラベル タイプのカウンターが保持され、そのタイプのラベルが生成されるたびにインクリメントされます。

4) 通常、デバッグ情報の一部であるすべてのもの。.parameter, .line, .prologue, .epilogue, .source, .local, .restart local, .end local... くらいでいいと思います。

于 2012-12-31T17:57:18.920 に答える