簡體   English   中英

使用ASM跟蹤字節碼中的方法調用參數

[英]Tracing method invocation arguments in bytecode using ASM

如何檢查類的字節碼(使用諸如ASM之類的東西)來了解哪些初始值傳遞給方法?

例如:給定一些將值互相傳遞的方法:

void m1(Object o) {
  Object v = o;
  m2(v);
  m2("box");
}

void m2(Object o) {
  Object v = o;
  m3(x);
}  

void m3(Object o) {
}

還有一些方法調用,都在同一個類中定義:

{
  Object foo = "foo";
  m1(foo);
  m2("bar");
  m3("baz");
}

我如何檢查類的字節碼,以了解m3將被調用4次,值為"foo""box""bar""baz"

使用ASM,理論上可以跟蹤每個方法,如果從其中調用同一個類的另一個方法。 訪問者API負責定義方法調用的方法是visitMethodIns 假設您的類名為bar.Foo ,您需要跟蹤:

visitMethodIns(<any>, "bar.Foo", <any>, <any>)

然后,您需要構建一個彼此調用的方法的傳遞關系,其中最后兩個參數允許您構建這樣的關系層次結構。 另外,您需要跟蹤這些方法調用的參數,更棘手但也不是不可能。

它更復雜的原因是參數可以加載到操作數堆棧的可能方式的數量。 對於您的示例,您只需要關注visitInsvisitLCDIns回調。

在常量池值(LCD)上調用方法時,參數的分辨率相當微不足道。 但是,在調用方法學習局部變量賦值之前,您需要跟蹤整個指令鏈,以便知道您正在調用方法參數上的方法。 因此,你可以找到答案

ALOAD_0 / ASTORE_1 / ALOAD_1 => ALOAD_0

從方法局部變量數組中讀取/寫入序列的有效結果。

有了這一切,通過解析字節代碼,您將了解以下調用轉換:

m1(Ljava/lang/Object)V -> m2(Ljava/lang/Object)V [ALOAD 0]
                       -> m2(Ljava/lang/Object)V [LCD "box"] 
m2(Ljava/lang/Object)V -> m3(Ljava/lang/Object)V [ALOAD 0]

然后,您可以使用這些結果來解析塊,在那里您可以找到這些方法調用及其含義。 然而,你會創建一個非常脆弱的解決方案,其中的間接如下:

{
  Foo foo = this;
  foo.m1("bar");
}

不會被發現。 正如評論中所指出的,您基本上需要模擬Java虛擬機以“運行”您的代碼。

即使您實施了一個復雜的解決方案來追蹤所有這些,您仍然無法確定您的結果。 當我從實現中調用接口方法時會發生什么。 還是一個子類的方法? 由於動態調度方法,您永遠無法確定被調用的目標。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM