【问题标题】:Identify virtual call sites in llvm识别 llvm 中的虚拟呼叫站点
【发布时间】:2017-04-24 20:00:45
【问题描述】:

我需要在我的 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 中完成此操作。

那么有人知道如何做到这一点吗?

【问题讨论】:

    标签: c++ llvm llvm-clang llvm-ir


    【解决方案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 pass 使用类型元数据和 llvm 类型检查内在函数来识别虚拟调用站点和候选被调用者。

    首先,您需要获取启用了 clang 的 -fwhole-program-vtables 标志的位码。这将为虚拟呼叫站点生成相应的内在函数。这些内在函数是 llvm.type.test、llvm.checked.load 和 llvm.assume。然后使用这些内在函数,整个程序去虚拟化器找到虚拟调用站点,并为它们中的每一个候选被调用者。

    就我而言,我不需要进行转换,因此我将其实现为分析过程并收集结果以供进一步使用。

    【讨论】:

      猜你喜欢
      • 2010-09-18
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多