如何在LLVM IR中获取字符串文字的值

How to get the value of a string literal in LLVM IR?

本文关键字:字符串 文字 获取 LLVM IR      更新时间:2023-10-16

我是LLVM的新手。我正在尝试编写一个基本的Pass,当它被赋予中间表示时,它将检查printf调用的参数
如果格式字符串不是字符串文字,那么我当然不能检查它。但通常情况下,它是。

我试图检查的样品IR是:

@.str = private unnamed_addr constant [7 x i8] c"Hi %uA0", align 1
define i32 @main() nounwind {
entry:
  %retval = alloca i32, align 4
  store i32 0, i32* %retval
  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), i32 1)
  ret i32 0
}
declare i32 @printf(i8*, ...)

我发现了之前存在的名为ExternalFunctionsPassedConstants的通行证,它似乎很相关:

struct ExternalFunctionsPassedConstants : public ModulePass {
  static char ID; // Pass ID, replacement for typeid
  ExternalFunctionsPassedConstants() : ModulePass(ID) {}
  virtual bool runOnModule(Module &M) {
    for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
      if (!I->isDeclaration()) continue;
      bool PrintedFn = false;
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
           UI != E; ++UI) {
        Instruction *User = dyn_cast<Instruction>(*UI);
        if (!User) continue;
        CallSite CS(cast<Value>(User));
        if (!CS) continue;
        ...

所以我添加了代码:

        if (I->getName() == "printf") {
          errs() << "printf() arg0 type: "
                 << CS.getArgument(0)->getType()->getTypeID() << "n";
        }

到目前为止,很好——我看到类型ID是14,这意味着它是一个PointerTyID

但是现在,我如何获得作为参数传递的字符串文本的内容,以便根据实际给定的数量验证预期参数的数量?

CS.getArgument(0)  

表示GetElementPtrConstantExpr

i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0)

,它是一个User对象。您想要的字符串(即@.str)是GetElementPtrConstantExpr的第一个操作数。

因此,您可以通过获取字符串文字

CS.getArgument(0).getOperand(0)

但是,我还没有测试过这个代码。如果有任何错误,请告诉我。