如何使用 IRBuilder 更新 LLVM IR 中的全局变量值?

Emm*_*ano 5 c++ llvm llvm-ir

我想更新 LLVM IR 中全局变量的值。我在 ModulePass 中创建了新的全局变量:

bool runOnModule(llvm::Module &M) {
    IRBuilder<> Builder(M.getContext());
    Instruction *I = &*inst_begin(M.getFunction("main"));
    Builder.SetInsertPoint(I);
    M.getOrInsertGlobal("globalKey", Builder.getInt64Ty());
    GlobalVariable* gVar = M.getNamedGlobal("globalKey");
    gVar->setLinkage(GlobalValue::InternalLinkage);
    gVar->setAlignment(Align(8));
    gVar->setInitializer(Builder.getInt64(0));
    gVar->setConstant(false);

    for (Function &F : M.functions()) {
        InstructionVisitor visitor(DL, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F));
        for (Instruction &I : instructions(F)) {
            visitor.visit(I);
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

后来在InstructionVisitor中,我尝试在每次分配时增加globalKey并使用printf函数打印它:

Instruction* InstructionVisitor::print(Instruction* I, const char* text, Value* arg1, Value* arg2, Value* arg3, Value* arg4) {
    Function* printfFn = I->getModule()->getFunction("printf");
    if (printfFn) {
        IRBuilder<> Builder(I->getContext());
        Builder.SetInsertPoint(I->getNextNode());
        Value* convertedText = Builder.CreateGlobalStringPtr(text);
        std::vector <Value *> params;
        params.push_back(convertedText);
        if (arg1)
            params.push_back(arg1);
        if (arg2)
            params.push_back(arg2);
        if (arg3)
            params.push_back(arg3);
        if (arg4)
            params.push_back(arg4);
        return Builder.CreateCall(printfFn, params);
    }
    return I;
}

Instruction* InstructionVisitor::incrementGlobalKey(Instruction* I) {
    IRBuilder<> Builder(I->getContext());
    Builder.SetInsertPoint(I->getNextNode());
    GlobalVariable* key = I->getModule()->getNamedGlobal("globalKey");
    if (key) {
        LoadInst* load = Builder.CreateLoad(key);
        Value* inc = Builder.CreateAdd(load, Builder.getInt64(1));
        StoreInst* store = Builder.CreateStore(inc, key);
        return store;
    }
    return I;
}

void InstructionVisitor::visitCallInst(CallInst &CI) {
    if (isAllocationFn(&CI, &TLI)) {
        Value* allocatedAddress = &CI;
        Instruction* I = &CI;
        Value* allocatedSize = I->getOperand(0);
        Instruction* next = incrementGlobalKey(I);
        GlobalVariable* key = I->getModule()->getNamedGlobal("globalKey");
        const char* message = "Allocated address: 0x%p, size: %d, key: 0x%x\n";
        print(next, message, allocatedAddress, allocatedSize, key->getOperand(0));

    }
}
Run Code Online (Sandbox Code Playgroud)

我在执行检测代码期间打印该全局变量(使用注入的 printf 调用)。我通过 key->getOperand(0) 访问它的值(如上所示),但它没有改变。我根据本教程使用 ORC JIT: https: //llvm.org/docs/tutorial/BuildingAJIT2.html,并从本教程中的 optimizationModule 函数运行 ModulePass。

IR、我正在检测的源代码和程序输出可以在这里找到: https: //pastebin.com/JbDR2Wug

有谁知道如何让它发挥作用?我将不胜感激的帮助!

Emm*_*ano 3

在 @droptop 有用的评论之后,我更改了代码以使用加载指令实际加载全局变量的值。现在效果很好。如果有人需要的话,更新后的代码如下所示:

Instruction* InstructionVisitor::getGlobalValue(Instruction* I, StringRef Name) {
    IRBuilder<> Builder(I->getContext());
    Builder.SetInsertPoint(I->getNextNode());
    GlobalVariable* key = I->getModule()->getNamedGlobal(Name);
    if (key) {
        LoadInst* load = Builder.CreateLoad(key);
        return load;
    }
    return nullptr;
}

void InstructionVisitor::visitCallInst(CallInst &CI) {
    if (isAllocationFn(&CI, &TLI)) {
        Value* allocatedAddress = &CI;
        Instruction* I = &CI;
        Value* allocatedSize = I->getOperand(0);
        Instruction* next = incrementGlobalKey(I, allocatedAddress, allocatedSize);
        Instruction* loadKey = getGlobalValue(next, "globalKey"); //here

        const char* message = "Allocated address: 0x%p, size: %d, key: %lld\n";
        next = print(loadKey, message, allocatedAddress, allocatedSize, loadKey);
    }
}
Run Code Online (Sandbox Code Playgroud)