Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

llvm

llvm-ir

I'm new to LLVM. I'm trying to write a basic Pass that will inspect the arguments of a printf call, when it is given the Intermediate Representation.
If the format string is not a string literal, then of course I can't inspect it. But quite often, it is.

The sample IR I'm trying to inspect is:

@.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*, ...)

I found the preexisting Pass called ExternalFunctionsPassedConstants, which seemed relevant:

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;

        ...

So I added the code:

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

So far, so good -- I see that the type ID is 14, which means it's a PointerTyID.

But now, how do I get the contents of the string literal that is being passed as an argument, so I can validate the number of expected arguments against the number actually given?

like image 920
user541686 Avatar asked Aug 26 '12 02:08

user541686


1 Answers

CS.getArgument(0)  

represents the GetElementPtrConstantExpr

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

, it is an User object. The string you want (i.e. @.str) is this GetElementPtrConstantExpr's first operand.

So, you can get the string literal through

CS.getArgument(0).getOperand(0)

However, I have not tested this code. If there are any mistakes, please tell me.

like image 98
CharlesZhang Avatar answered Oct 07 '22 11:10

CharlesZhang