2012-12-31 34 views
5

我想學習smali,我有一些問題,我找不到通過搜索他們。DalvikVM如何處理切換和嘗試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 

的.catch聲明:沒有這兩個參數的意思是採取從標籤到標籤和抓住它(代碼兩個標籤之間)或者是否意味着從try_start_0開始執行try,直到它達到try_end_0(允許跳轉來執行不在兩個標籤內的代碼)?

嘗試的標籤始終是格式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語句所在的交換機數據和交換機中的呼叫之間?又是爲了方便而固定標籤的名稱? 3)如果標籤可能不同,baksmali會不會生成不同標籤的小代碼?

4)反編譯dex時不會總是顯示的可選行是什麼?

我知道.parameter和.line是可選的,但那些可能不在那裏的是什麼?

預先感謝您。

回答

4

1)

前兩個標籤(try_start_0和try_end_0在你的例子)定義的代碼try塊覆蓋的範圍內。如果在所涵蓋的代碼中發生異常,則執行立即跳轉到第三個標籤(catchall_0)。標籤的名稱並不重要,它可以是任何有效的標識符。

還有.catch指令,除了只處理特定類型的異常(類似於java的catch語句)之外,它們是一樣的。

一段代碼可以被多個catch語句覆蓋,最多1個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 

第二個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 

你也可以有一些很奇怪的構造,就像這樣。

.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 ...我認爲這是關於它的。

+0

謝謝。這正是我想知道的。我特別喜歡你的第二個「怪異」建築:)。我知道已編譯的java代碼將無法提供該代碼,但是優化程序能夠優化代碼爲無法通過常規java代碼實現的狀態(有點像C/C++轉到允許「怪異」控制流) ? – Xonar

+0

優化器 - 可能不是。但是,它可能更可能來自混淆器 – JesusFreke