如何在LLVM Pass中创建指向llvm::Value的指针并传递给函数?
实现LLVM Pass插入
mystore(&file)调用的方案 核心思路
需要完成三个关键操作:定位目标file变量、生成该变量的地址指针、将指针值转换为int类型后调用mystore函数。以下分步骤实现:
1. 搭建Pass基础框架
根据file变量的作用域选择Pass类型:
- 若
file是全局变量,使用ModulePass遍历整个模块 - 若
file是函数内局部变量,使用FunctionPass遍历目标函数
这里以全局变量为例,给出基础框架:
#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct LogVariablePass : public ModulePass { static char ID; LogVariablePass() : ModulePass(ID) {} bool runOnModule(Module &M) override { // 核心逻辑写在这里 return false; } }; } // namespace char LogVariablePass::ID = 0; static RegisterPass<LogVariablePass> X("log-variable", "Insert mystore(&file) call", false, false);
2. 定位目标file变量
遍历模块中的全局变量,找到名为file且类型为FILE*的变量(LLVM中通常以i8*表示不透明指针类型的FILE*):
// 在runOnModule函数内 LLVMContext &Ctx = M.getContext(); GlobalVariable *FileVar = M.getNamedGlobal("file"); if (!FileVar) { errs() << "Global variable 'file' not found!\n"; return false; } // 验证变量类型是否为FILE*(以i8*为例,根据实际IR调整) Type *FileTy = FileVar->getValueType(); if (!FileTy->isPointerTy() || !cast<PointerType>(FileTy)->getElementType()->isIntegerTy(8)) { errs() << "Variable 'file' is not a FILE*\n"; return false; }
如果是局部变量,在FunctionPass的runOnFunction中遍历函数内的AllocaInst:
// FunctionPass的runOnFunction示例 bool runOnFunction(Function &F) override { for (BasicBlock &BB : F) { for (Instruction &I : BB) { if (auto *Alloca = dyn_cast<AllocaInst>(&I)) { if (Alloca->getName() == "file") { // 找到目标局部变量,后续逻辑同全局变量 } } } } return false; }
3. 生成变量地址并转换类型
file本身是指针,&file是指向指针的指针。需要将这个地址转换为int类型以匹配mystore的参数:
// 全局变量的地址可直接用FileVar,局部变量则用找到的AllocaInst Value *FileAddr = FileVar; // 根据目标系统选择int宽度,32位用i32,64位用i64 Type *IntTy = Type::getInt32Ty(Ctx); Value *FileAddrAsInt = CastInst::CreatePointerCast(FileAddr, IntTy, "file_addr_int");
4. 声明/获取mystore函数并插入调用
如果模块中未声明mystore,先创建函数声明;然后在指定位置插入调用指令:
// 定义mystore的函数类型:void(int) FunctionType *MystoreFT = FunctionType::get(Type::getVoidTy(Ctx), {IntTy}, false); // 获取或声明mystore函数 Function *MystoreFunc = M.getFunction("mystore"); if (!MystoreFunc) { MystoreFunc = Function::Create(MystoreFT, Function::ExternalLinkage, "mystore", M); } // 选择插入位置:比如模块第一个函数的入口基本块开头 Function *FirstFunc = &*M.begin(); if (!FirstFunc || FirstFunc->empty()) { errs() << "No valid function to insert call!\n"; return false; } BasicBlock &EntryBB = FirstFunc->getEntryBlock(); Instruction *InsertPt = &*EntryBB.getFirstInsertionPt(); // 创建调用指令 IRBuilder<> Builder(InsertPt); Builder.CreateCall(MystoreFunc, {FileAddrAsInt});
完整代码整合
将上述步骤整合后的完整Pass代码:
#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct LogVariablePass : public ModulePass { static char ID; LogVariablePass() : ModulePass(ID) {} bool runOnModule(Module &M) override { LLVMContext &Ctx = M.getContext(); // 1. 定位全局变量file GlobalVariable *FileVar = M.getNamedGlobal("file"); if (!FileVar) { errs() << "Global variable 'file' not found!\n"; return false; } // 验证file类型为FILE*(i8*) Type *FileTy = FileVar->getValueType(); if (!FileTy->isPointerTy() || !cast<PointerType>(FileTy)->getElementType()->isIntegerTy(8)) { errs() << "Variable 'file' is not a FILE*\n"; return false; } // 2. 生成&file并转换为int类型 Value *FileAddr = FileVar; Type *IntTy = Type::getInt32Ty(Ctx); Value *FileAddrAsInt = CastInst::CreatePointerCast(FileAddr, IntTy, "file_addr_int"); // 3. 获取或声明mystore函数 FunctionType *MystoreFT = FunctionType::get(Type::getVoidTy(Ctx), {IntTy}, false); Function *MystoreFunc = M.getFunction("mystore"); if (!MystoreFunc) { MystoreFunc = Function::Create(MystoreFT, Function::ExternalLinkage, "mystore", M); } // 4. 选择插入位置并插入调用 Function *FirstFunc = &*M.begin(); if (!FirstFunc || FirstFunc->empty()) { errs() << "No valid function to insert call!\n"; return false; } BasicBlock &EntryBB = FirstFunc->getEntryBlock(); Instruction *InsertPt = &*EntryBB.getFirstInsertionPt(); IRBuilder<> Builder(InsertPt); Builder.CreateCall(MystoreFunc, {FileAddrAsInt}); return true; } }; } // namespace char LogVariablePass::ID = 0; static RegisterPass<LogVariablePass> X("log-variable", "Insert mystore(&file) call to log variable", false, false);
注意事项
- 若目标系统是64位,需将
IntTy改为Type::getInt64Ty(Ctx),匹配mystore参数的实际宽度 - 若
file是局部变量,需调整变量定位逻辑,遍历函数内的AllocaInst - 插入位置可根据需求修改(如特定函数、特定基本块)
- 确保
mystore函数的链接属性正确,避免链接错误
内容的提问来源于stack exchange,提问作者user1388672
相关产品推荐
相关产品推荐

