在LLVM传递中标识带注释的变量

时间:2017-09-13 21:00:44

标签: llvm llvm-ir

如何在LLVM传递中识别带注释的变量?

#include <stdio.h>

int main (){
int x __attribute__((annotate("my_var")))= 0;
int a,b;
x = x + 1;
a = 5;
b = 6;
x = x + a;

return x;
}

例如,我想识别带有注释变量的指令(在本例中为x)并将其打印出来(x = x + 1; x = x + a) 我怎样才能做到这一点?

这是使用LLVM生成的.ll文件

    ; ModuleID = 'test.c'
source_filename = "test.c"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64"

@.str = private unnamed_addr constant [7 x i8] c"my_var\00", section "llvm.metadata"
@.str.1 = private unnamed_addr constant [7 x i8] c"test.c\00", section "llvm.metadata"

; Function Attrs: noinline nounwind optnone
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  %5 = bitcast i32* %2 to i8*
  call void @llvm.var.annotation(i8* %5, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.s$
  store i32 0, i32* %2, align 4
  %6 = load i32, i32* %2, align 4
  %7 = add nsw i32 %6, 1
  store i32 %7, i32* %2, align 4
  store i32 5, i32* %3, align 4
  store i32 6, i32* %4, align 4
  %8 = load i32, i32* %2, align 4
  %9 = load i32, i32* %3, align 4
  %10 = add nsw i32 %8, %9
  store i32 %10, i32* %2, align 4
  %11 = load i32, i32* %2, align 4
  ret i32 %11
}

; Function Attrs: nounwind
declare void @llvm.var.annotation(i8*, i8*, i8*, i32) #1

attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" $
attributes #1 = { nounwind }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}

2 个答案:

答案 0 :(得分:0)

您必须循环说明并识别对llvm.var.annotation

的来电

第一个参数是指向带注释的变量(i8 *)的指针。

要获取实际的带注释变量,您需要找到此指针指向的内容。

在您的情况下,这是bitcast指令的源操作数。

答案 1 :(得分:0)

我最近遇到了类似问题,因为我搜索Google仍未找到解决方案。    但是最后,我找到了“ ollvm”项目的Utils.cpp,它解决了我的问题。

就您而言,

    %5 = bitcast i32* %2 to i8*
  call void @llvm.var.annotation(i8* %5, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.s$

如我们所见,在我们的密码中,有一个@ llvm.var.annotation的调用, 我们可以遍历函数上的指令,并搜索“调用”指令。 然后获取被调用函数的名称:

Function *fn = callInst->getCalledFunction();

            StringRef fn_name = fn->getName();

并将调用的函数名称与“ llvm.var.annotation” 进行比较。 如果它们匹配,那么在您的情况下,我们找到了“ int x”的位置。 函数“ llvm.var.annotation”记录在llvm的doc中: http://llvm.org/docs/LangRef.html#llvm-var-annotation-intrinsic

如果您已经学习了函数“ llvm.var.annotation”的原型, 那么您知道它的第二个参数是一个指针 在您的情况下,指向“ my_var \ 00”。如果您认为可以 将其转换为 GlobalVariable ,那么您将无法获得 你自找的 。实际的第二个参数传递给“ llvm.var.annotation” 是

i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.s$
在你的情况下。 这是一个表达,但一个GlobalVariable!通过了解这一点,我们可以 最终通过以下方式获取目标变量的注释:

ConstantExpr *ce =
                  cast<ConstantExpr>(callInst->getOperand(1));
              if (ce) {
                if (ce->getOpcode() == Instruction::GetElementPtr) {
                  if (GlobalVariable *annoteStr =
                          dyn_cast<GlobalVariable>(ce->getOperand(0))) {
                    if (ConstantDataSequential *data =
                            dyn_cast<ConstantDataSequential>(
                                annoteStr->getInitializer())) {
                      if (data->isString()) {
                        errs() << "Found data " << data->getAsString();
                      }
                    }
                  }
                }

希望您已经解决了这个问题。 祝你今天愉快 。