在llvm中识别虚拟呼叫站点

问题描述:

我需要在我的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中完成这件事。

那么,有没有人有一个想法如何做到这一点?

在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找到虚拟呼叫站点,并为每个候选呼叫者。

对我而言,我不需要做转换,所以我将它作为分析过程并收集结果以供进一步使用。