Jestem nowy w LLVM. Próbuję napisać podstawowe hasło, które będzie sprawdzać argumenty wywołania printf
, gdy otrzyma reprezentację pośrednią.
Jeśli ciąg formatu nie jest literałem ciągłym, to oczywiście nie mogę go sprawdzić. Ale dość często tak jest.Jak uzyskać wartość literału ciągu w LLVM IR?
IR próbki Próbuję sprawdzić to:
@.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*, ...)
znalazłem wcześniej istniejących Przełęcz nazywa ExternalFunctionsPassedConstants
, co wydawało się istotne:
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;
...
Więc dodałem kod:
if (I->getName() == "printf") {
errs() << "printf() arg0 type: "
<< CS.getArgument(0)->getType()->getTypeID() << "\n";
}
Jak dotąd, tak dobrze - widzę, że identyfikator typu to 14, co oznacza, że jest to PointerTyID
.
Ale teraz, jak mogę uzyskać zawartość z literału ciągu, który jest przekazywany jako argument, więc mogę sprawdzić poprawność liczby oczekiwanych argumentów w stosunku do faktycznie podanej liczby?
Och, super! 'getOperand' wskazał mi właściwy kierunek! Wydaje mi się, że potrzebuję 'cast (cast (cast (CS.getArgument (0)) -> getOperand (0)) -> getInitializer()) -> getAsCString()', co daje mi ciąg znaków. :) Dziękuję bardzo! –
Mehrdad