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

如何为LLVM Pass传递运行时参数以指定待检测函数?

嘿,这个需求在LLVM Pass开发里太常见了!我给你拆解几个实际可行的方案,都是项目里验证过的靠谱路子:

方法1:通过命令行参数动态传递目标函数名

这是最直接、最符合“动态指定”需求的方案,LLVM原生支持给Pass绑定命令行参数:

  • 第一步,在你的Pass类里,用LLVM的cl::opt工具注册一个命令行选项,用来接收目标函数名:
#include "llvm/Support/CommandLine.h"

static cl::opt<std::string> TargetFunction(
    "target-func",
    cl::desc("Specify the target function to analyze"),
    cl::value_desc("function name")
);
  • 第二步,在Pass的核心逻辑(比如runOnModule或runOnFunction方法)里,直接读取这个参数并匹配模块中的函数:
bool runOnModule(Module &M) override {
  // 根据命令行传入的名字查找目标函数
  Function *TargetFunc = M.getFunction(TargetFunction);
  if (!TargetFunc) {
    errs() << "Warning: Target function '" << TargetFunction << "' not found in module!\n";
    return false;
  }

  // 这里写你的检测逻辑,比如遍历函数的基本块、指令
  errs() << "Analyzing target function: " << TargetFunc->getName() << "\n";
  // ...你的检测代码...

  return true;
}
  • 运行Pass时,直接在命令行指定参数即可:
opt -load ./YourPass.so -your-pass-name -target-func=my_target_function input.ll -o output.ll
方法2:通过IR元数据传递目标函数名

如果不想每次运行都敲命令行参数,也可以把目标函数名嵌入到IR文件的元数据中,让Pass自动读取:

  • 首先,在生成的IR文件里添加模块级元数据(可以手动编辑,也可以通过前端编译时插入):
!llvm.module.flags = !{!0}
!0 = !{i32 4, !"target-function", !"my_target_function"}
  • 然后在Pass里读取这个元数据:
bool runOnModule(Module &M) override {
  MDNode *ModuleFlag = M.getModuleFlag("target-function");
  if (!ModuleFlag) {
    errs() << "Error: No target function specified in module metadata!\n";
    return false;
  }

  // 解析元数据中的函数名
  StringRef TargetFuncName = cast<MDString>(ModuleFlag->getOperand(2))->getString();
  Function *TargetFunc = M.getFunction(TargetFuncName);
  
  // 后续检测逻辑...
  return true;
}

这种方式适合需要把目标函数和IR文件绑定的场景,不用每次运行都指定参数。

方法3:新Pass Manager的构造函数传参(LLVM 13+)

如果你用的是LLVM 13及以后的新Pass Manager(推荐现代LLVM项目使用),可以通过Pass的构造函数直接传递参数:

  • 定义你的Pass类,在构造函数中接收目标函数名:
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassManager.h"

class TargetFuncAnalysisPass : public PassInfoMixin<TargetFuncAnalysisPass> {
private:
  std::string TargetFuncName;

public:
  explicit TargetFuncAnalysisPass(std::string Name) : TargetFuncName(std::move(Name)) {}

  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
    Function *TargetFunc = M.getFunction(TargetFuncName);
    if (!TargetFunc) {
      errs() << "Warning: Target function '" << TargetFuncName << "' not found!\n";
      return PreservedAnalyses::all();
    }

    // 你的检测逻辑...
    return PreservedAnalyses::all();
  }
};
  • 在注册Pass或编写工具时,通过命令行参数获取名字并传入Pass的构造函数:
int main(int argc, char **argv) {
  cl::opt<std::string> TargetFunc("target-func", cl::desc("Target function name"));
  cl::ParseCommandLineOptions(argc, argv);

  PassBuilder PB;
  ModulePassManager MPM;
  // 将命令行参数传入Pass构造函数
  MPM.addPass(TargetFuncAnalysisPass(TargetFunc));

  // 后续模块处理逻辑...
  return 0;
}
几个注意点
  • 一定要处理目标函数不存在的情况,避免Pass崩溃,比如上面例子中的错误提示。
  • 如果是C++函数,IR中的名字会被修饰(比如_ZN3Foo3barEv),你可以传入修饰后的名字,或者在Pass里用llvm::demangle工具把修饰名转成可读名字再匹配。
  • 命令行参数的方式是最灵活的动态指定方案,也是实际开发中用得最多的。

内容的提问来源于stack exchange,提问作者mikasa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:54:24