I am new to LLVM. I am trying to write a basic Pass that will check printf invocation arguments when it is presented with an intermediate view.
If the format string is not a string literal, then of course I cannot check it. But this is often the case.
The sample IR I'm trying to verify 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 a pre-existing 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 identifier is 14, which means it is PointerTyID .
But now, how do I get the contents of a string literal that is passed as an argument, so I can check the number of expected arguments against the number that is actually specified?
source share