【问题标题】:How to extract information from the llvm metadata如何从 llvm 元数据中提取信息
【发布时间】:2013-04-15 14:35:33
【问题描述】:

我有以下代码:

 int main(int argc, char *argv[])
    {
        int a = 2;
        int b = 5;
        int soma = a + b;
   //...}

得到的 llvm 位码是:

       define i32 @main(i32 %argc, i8** %argv) #0 {
        entry:
          ...
          %a = alloca i32, align 4
          %b = alloca i32, align 4
          %soma = alloca i32, align 4
          ...
          call void @llvm.dbg.declare(metadata !{i32* %a}, metadata !15), !dbg !16
          store i32 2, i32* %a, align 4, !dbg !16
          call void @llvm.dbg.declare(metadata !{i32* %b}, metadata !17), !dbg !18
          store i32 5, i32* %b, align 4, !dbg !18
          call void @llvm.dbg.declare(metadata !{i32* %soma}, metadata !19), !dbg !20
          %0 = load i32* %a, align 4, !dbg !20
          %1 = load i32* %b, align 4, !dbg !20
          %add = add nsw i32 %0, %1, !dbg !20
          store i32 %add, i32* %soma, align 4, !dbg !20
          ...       
          !1 = metadata !{i32 0}
          !2 = metadata !{metadata !3}
          ...
          !15 = metadata !{i32 786688, metadata !3, metadata !"a", metadata !4, i32 6, metadata !7, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [a] [line 6]
!16 = metadata !{i32 6, i32 0, metadata !3, null}
!17 = metadata !{i32 786688, metadata !3, metadata !"b", metadata !4, i32 7, metadata !7, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [b] [line 7]
!18 = metadata !{i32 7, i32 0, metadata !3, null}
!19 = metadata !{i32 786688, metadata !3, metadata !"soma", metadata !4, i32 8, metadata !7, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [soma] [line 8]
!20 = metadata !{i32 8, i32 0, metadata !3, null}

从位码我需要得到以下文本:

a = 2
b = 5
soma = a + b

我的疑问是如何从元数据(dgb)中提取我需要的信息?? 现在我只有指令名称I-> getName () 和操作数名称valueOp Value * = I-> getOperand (i); valueOp-> getName (). Str (); 元数据非常广泛。如何从元数据中获取这些信息?

【问题讨论】:

    标签: metadata llvm instructions


    【解决方案1】:

    依靠I->getName() 来查找变量名不是一个好主意——你有调试信息。找出所有 C/C++ 局部变量名称的正确方法是遍历 IR 并查找对 @llvm.dbg.declare 的所有调用,然后转到它们的第二个操作数(调试元数据),并从那里检索变量名称.

    使用source-level debugging guide 了解调试元数据的布局方式。特别是for local variables, the 3rd argument will be a metadata string with the variable name in the C/C++ source

    所以剩下的就是找出变量被初始化为什么。为此,请按照 @llvm.dbg.declare 的第一个参数获取实际使用的 LLVM 值,然后将第一个 store 指令定位到其中,并检查其中使用了哪些数据。

    如果它是一个常量,那么您现在拥有输出a = 5 样式信息所需的一切。如果它是另一条指令,您必须自己遵循并“解码”它 - 例如,如果它是“添加”,那么您需要打印它的两个操作数,中间带有“+”等。当然还有打印必须是递归的……不简单。但它会为您提供准确的初始化值。

    如果您正在寻找更粗略的东西并且您可以访问原始源代码,您只需获取声明变量的行号(调试元数据中的第 5 个操作数,假设标签(第 1 个)操作数)确实是DW_TAG_auto_variable 而不是DW_TAG_arg_variable,它表示一个参数)。然后从原始来源打印出该行。但这不会打印所有相关信息(如果初始化值是由多行构造的),并且可以打印不相关信息(例如,如果该行中有多个语句)。

    最后,请记住优化会严重影响调试信息。如果获取这些打印输出很重要,请注意您的-O 选项,也许坚持使用-O0

    【讨论】:

    • 当提到“...查找所有对@llvm.dbg.declare ...的调用”时,哪些方法允许我这样做?
    • @user2084755 iterate over each instruction in the function,以及每次检查CallInst* Call = dyn_cast<CallInst>(I) && Call->getCalledFunction()->getName().equals("llvm.dbg.declare")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 2023-04-01
    • 2017-02-17
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多