LLVM FunctionPass开发:实现目标函数存在性检查
刚好做过类似的LLVM Pass开发,给你整理个简洁清晰的实现方案,完全贴合你已经准备好的信息提取逻辑:
实现LLVM FunctionPass检查目标函数的具体方案
1. 核心逻辑梳理
你已经拿到了待检查函数和目标函数的名称、返回类型、参数数量+类型,核心就是在FunctionPass遍历每个函数的过程中,对这几项信息逐一比对——全匹配就判定找到了目标函数,逻辑非常直接。
2. 具体代码实现步骤
第一步:定义你的FunctionPass类
继承llvm::FunctionPass,重写runOnFunction方法(这是遍历每个函数的核心入口)。你可以把目标函数的信息作为类的成员变量,要么硬编码(适合固定目标的场景),要么通过构造函数传入(动态目标更灵活)。
第二步:实现精准的信息比对逻辑
在runOnFunction里,对当前遍历到的函数,按以下顺序比对(从快到慢,提前过滤不匹配的函数,提升效率):
- 先比函数名称:用
func.getName().str()拿到函数名的字符串,和目标名称快速对比,不匹配直接跳过。 - 再比返回类型:LLVM的
Type对象是全局单例,直接用func.getReturnType()和目标返回类型用==判断就行,不用自己解析类型字符串。 - 最后比参数:先看参数数量是否一致(
func.arg_size()),然后逐个遍历参数的类型,和目标参数类型逐一比对,顺序也要对应上(毕竟foo(int, float)和foo(float, int)是完全不同的函数)。
第三步:完整代码模板
给你一个可直接复用的简洁模板,你可以根据自己的需求调整:
#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct TargetFuncChecker : public FunctionPass { static char ID; // 目标函数信息,这里示例用硬编码,你可以改成构造函数传入 std::string TargetName = "my_target_func"; Type* TargetRetTy; std::vector<Type*> TargetParamTys; TargetFuncChecker() : FunctionPass(ID) {} // 用于动态设置目标函数类型信息的方法 void setTargetInfo(Type* RetTy, std::vector<Type*> ParamTys) { TargetRetTy = RetTy; TargetParamTys = ParamTys; } bool runOnFunction(Function &F) override { // 1. 快速过滤名称不匹配的函数 if (F.getName().str() != TargetName) { return false; // 返回false表示没修改IR,继续遍历 } // 2. 比对返回类型 if (F.getReturnType() != TargetRetTy) { errs() << "Name matches but return type mismatch: " << F.getName() << "\n"; return false; } // 3. 比对参数数量和类型 if (F.arg_size() != TargetParamTys.size()) { errs() << "Name matches but param count mismatch: " << F.getName() << "\n"; return false; } unsigned idx = 0; for (Argument &Arg : F.args()) { if (Arg.getType() != TargetParamTys[idx]) { errs() << "Name matches but param " << idx << " type mismatch: " << F.getName() << "\n"; return false; } idx++; } // 所有信息匹配,输出结果 errs() << "✅ Found target function: " << F.getName() << "\n"; return false; } }; } // namespace char TargetFuncChecker::ID = 0; static RegisterPass<TargetFuncChecker> X("check-target", "Check for existence of target function", false /* Doesn't modify CFG */, false /* Not an analysis pass */);
3. 关键细节提示
- Type对象的可靠性:LLVM的
Type是全局唯一实例,直接用==对比完全准确,比解析类型字符串靠谱得多,还能避免字符串解析的各种坑。 - 参数顺序不能忽略:函数签名的参数顺序是匹配的核心,一定要按顺序比对每个参数的类型。
- Pass注册:最后通过
RegisterPass把你的Pass注册到LLVM系统,这样才能用opt工具加载运行。 - 动态传参优化:如果你的目标函数信息是从外部获取的(比如配置文件或者命令行参数),可以给Pass添加带参数的构造函数,或者在初始化阶段读取配置,不用硬编码目标信息。
4. 运行方式
把代码编译成LLVM Pass的动态库后,用opt工具运行:
opt -load ./libTargetFuncChecker.so -check-target < input.bc > /dev/null
运行后就能在控制台看到是否找到目标函数的提示了。
内容的提问来源于stack exchange,提问作者mikasa
相关产品推荐
相关产品推荐

