6

LLVMは初めてです。printf中間表現が与えられたときに、呼び出しの引数を検査する基本的なパスを作成しようとしています。
フォーマット文字列が文字列リテラルでない場合は、もちろん検査できません。しかし、かなり頻繁にそうです。

私が調べようとしているサンプルIRは次のとおりです。

@.str = private unnamed_addr constant [7 x i8] c"Hi %u\0A\00", 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ます。

しかし、今、引数として渡されている文字列リテラルの内容を取得するにはどうすればよいので、実際に与えられた数に対して期待される引数の数を検証できますか?

4

1 に答える 1

7
CS.getArgument(0)  

GetElementPtrConstantExpr を表します

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

、それは User オブジェクトです。必要な文字列 (つまり @.str) は、この GetElementPtrConstantExpr の最初のオペランドです。

したがって、文字列リテラルを取得できます

CS.getArgument(0).getOperand(0)

ただし、このコードはテストしていません。間違いがあれば教えてください。

于 2012-08-26T14:57:17.130 に答える