You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:35:14