C++ LLVM IR:使用元数据节点标识变量

C++ LLVM IR:使用元数据节点标识变量,c++,llvm,llvm-ir,C++,Llvm,Llvm Ir,目前我正在开发一个工具,它可以识别对任意程序上全局变量和字段变量的加载和存储访问。此外,应通过其源级别名称/标识符来标识访问的变量。 为了实现这一点,我将诊断程序的源代码编译成带有调试信息的LLVM IR。到目前为止,生成的元数据节点包含所需的源级别标识符。但是,我无法连接到某些LLVM IR标识符和元数据中的信息 例如,考虑一个类的SATIC成员: class TestClass { public: static int Number; }; 相应的LLVM IR如下所示:

目前我正在开发一个工具,它可以识别对任意程序上全局变量和字段变量的加载和存储访问。此外,应通过其源级别名称/标识符来标识访问的变量。 为了实现这一点,我将诊断程序的源代码编译成带有调试信息的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”是“Number”的标识符。然而,一般来说,我看不出如何找出哪些IR标识符对应于哪些元数据


有人能帮我吗?

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

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


那么,为什么我不使用clangast来识别变量的存储和加载呢?因为区分AST中的读写不是一项简单的任务。AST可以很容易地告诉您访问了变量,但这取决于访问的变量是读还是写的操作。因此,我必须考虑每一个操作/操作员来确定变量是写/读还是二者。在这方面,LLVM更简单、更低级,因此更不容易出错。此外,与LLVM一样,AST中的实际插装(说代码插入)要困难得多。由于这两个原因,我认为结合使用clang AST和LLVM IR仪器是解决我问题的最佳方法。

感谢您的解释。你能分享你的Solion代码吗?