2017-04-24 58 views
1

我需要在我的LLVM傳遞中識別虛擬函數調用站點,並識別可能在運行時調用的候選函數。在llvm中識別虛擬呼叫站點

class B 
{ 
    virtual void F() { // do something } 
}; 

class D : public B 
{ 
void F() { // do something else } 
}; 

B* d = new D(); 
d->F(); 

例如,對於給定的層次結構和F調用,將B :: F和D :: F都標識爲可能的候選者。

在尋找解決方案時,我遇到了Clang CFI(控制流集成),他們說他們正在通過檢查它是否在一組候選虛擬表指針中來識別虛擬表指針是否有效。因此,我假設有一種方法可以獲得有關繼承層次結構的信息。但是我無法找到如何在llvm中完成這件事。

那麼,有沒有人有一個想法如何做到這一點?

回答

1

在llvm開發人員的幫助下,我找到了一種方法來解決我的問題,並且想在這裏分享它,以防有人需要它。

在llvm中有一個轉換過程-wholeprogramdevirt,它正在做我想做的事情。它識別模塊中的虛擬呼叫站點和候選被呼叫者,然後儘可能虛擬化這些呼叫。例如,如果一個虛擬函數僅在一個層次結構中實現,那麼對此函數的間接調用將被直接調用實現的函數所取代。

class B 
{ 
virtual void F() { // do something } 
}; 

class D : public B {}; 

B* d = new D(); 
d->F(); 

因此,對於這種情況,間接調用F將被直接調用B :: F替換。 WholeProgramDevirt傳遞使用類型元數據和llvm類型檢查內部函數來識別虛擬呼叫站點和候選被調用者。

首先,您需要獲取啓用了clang的-fwhole-program-vtables標誌的位代碼。這將爲虛擬呼叫站點生成相應的固有功能。這些內部函數是llvm.type.test,llvm.checked.load和llvm.assume。然後使用這些內部函數,整個程序devirtualizer找到虛擬呼叫站點,併爲每個候選呼叫者。

對我而言,我不需要做轉換,所以我將它作爲分析過程並收集結果以供進一步使用。