2013-04-15 25 views
3

我有下面的代码:如何从LLVM的元数据中提取信息

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(); 操作数的名称元数据非常广泛。我如何从元数据中获取这些信息?

回答

2

依靠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个操作数,假设标记为第一个操作数)确实是DW_TAG_auto_variable而不是DW_TAG_arg_variable,它表示一个参数)。然后从原始来源打印出该行。但是这不会打印所有相关信息(如果初始化值是由多行构成的)并且可以打印不相关的信息(例如,如果该行中有多个语句)。

最后,记住优化可以认真地拧与调试信息。如果打印输出很重要,请注意您的-O选项,可能需要使用-O0

+0

当提到“...寻找所有的电话[email protected] ...”哪些方法允许我这样做? – user2084755

+0

@ user2084755 [迭代函数中的每条指令](http://llvm.org/docs/ProgrammersManual.html#iterating-over-the-instruction-in-a-function),并为每个检查调用CallInst * Call = dyn_cast (I)&& Call-> getCalledFunction() - > getName()。equals(“llvm.dbg.declare”)'。 – Oak