【问题标题】:LLVM IR: Identifying Variables with Metadata NodesLLVM IR:使用元数据节点识别变量
【发布时间】:2016-01-03 15:49:08
【问题描述】:

目前我正在开发一种工具,该工具可以识别任意程序上全局变量和字段变量的加载和存储访问。此外,访问的变量应该由它们的源级名称/标识符来标识。 为了做到这一点,我将诊断程序的源代码编译到带有调试信息的 LLVM IR 中。到目前为止一切顺利,生成的元数据节点包含所需的源级别标识符。但是,我无法与某些 LLVM IR 标识符和元数据中的信息建立联系。

例如,考虑一个类的 satic 成员:

 class TestClass {
   public:
    static int Number;
};

对应的 LLVM IR 如下所示:

@_ZN12TestClass6NumberE = external global i32, align 4

...
!15 = !DIDerivedType(tag: DW_TAG_member, name: "Number", scope: !"_ZTS12TestClass", file: !12, line: 5, baseType: !16, flags: DIFlagPublic | DIFlagStaticMember)

在这个受控示例中,我知道“@_ZN12TestClass6NumberE”是“数字”的标识符。但是,总的来说,我看不到如何找出哪些 IR 标识符对应于哪些元数据。

有人可以帮帮我吗?

【问题讨论】:

    标签: c++ llvm llvm-ir


    【解决方案1】:

    由于似乎没有人能很好地解决我的问题,我会告诉我自己处理这个问题的不方便方法。 LLVM 生成的 MetaData 节点包含有关已定义类型和代码变量的信息。但是,没有关于哪些生成的 IR 变量对应于哪些源代码变量的信息。 LLVM 仅将 IR 指令的元数据信息与相应的源位置(行和列)链接起来。这是有道理的,因为 LLVM 元数据的主要任务不是分析而是调试。

    不过,所包含的信息并非毫无用处。我对这个问题的解决方案是使用 clang AST 来分析源代码。在这里,我们获得有关在哪个源位置访问哪个变量的信息。因此,为了在 LLVM IR 检测期间获取有关源变量身份的信息,我们只需在 clang AST 分析期间将源位置映射到源变量身份。作为第二步,我们使用之前收集的信息执行 IR 检测。当我们在 IR 中遇到存储或加载指令时,我们会在该指令的元数据节点中搜索其对应的源位置。由于我们已将源位置映射到源变量标识,我们现在可以轻松访问 IR 指令的源变量标识。

    那么,为什么我不只使用 clang AST 来识别变量的存储和加载呢?因为在 AST 中区分读写并不是一件简单的事情。 AST 可以很容易地告诉您访问了一个变量,但这取决于访问的变量是读取还是写入的操作。因此,我必须考虑每一个操作/运算符来确定变量是写入/读取还是两者兼而有之。 LLVM 在这方面更简单,更底层,因此更不容易出错。此外,与 LLVM 一样,AST 中的实际检测(说话代码插入)要困难得多。由于这两个原因,我相信 clang AST 和 LLVM IR 检测的组合是解决我的问题的最佳解决方案。

    【讨论】:

    • 感谢 NicoKop 的解释。你能分享你的解决方案的代码吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 2014-10-03
    相关资源
    最近更新 更多