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

如何在LLVM Pass中通过头文件链接外部函数并使用getOrInsertFunction

实现LLVM插桩调用display()的方案

1. 先修正头文件与实现分离

原foo.h直接包含函数实现,会导致链接冲突,建议拆分:

foo.h(仅声明):

#ifndef __FOO_H__
#define __FOO_H__
#include <stdio.h>
void display();
#endif

foo.c(实现):

#include "foo.h"
void display(){
    printf("Hello");
}

2. 编写instrumentation.cpp(LLVM Pass代码)

以下代码实现在main函数开头插入display()调用的插桩逻辑:

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "foo.h" // 引入函数声明以确保签名一致

using namespace llvm;

namespace {
struct InstrumentDisplayPass : public ModulePass {
    static char ID;
    InstrumentDisplayPass() : ModulePass(ID) {}

    bool runOnModule(Module &M) override {
        // 定义display函数的类型:无参数、无返回值
        FunctionType *displayFuncType = FunctionType::get(
            Type::getVoidTy(M.getContext()),
            false
        );

        // 获取或插入display函数到当前模块
        Function *displayFunc = M.getOrInsertFunction("display", displayFuncType).getCallee();

        // 定位main函数
        Function *mainFunc = M.getFunction("main");
        if (!mainFunc) {
            errs() << "未找到main函数!\n";
            return false;
        }

        // 在main函数的入口基本块插入display调用
        IRBuilder<> builder(&*mainFunc->getEntryBlock().getFirstInsertionPt());
        builder.CreateCall(displayFunc);

        return true;
    }
};
} // 匿名命名空间

char InstrumentDisplayPass::ID = 0;
static RegisterPass<InstrumentDisplayPass> X(
    "instrument-display", 
    "在main函数插入display()调用",
    false, 
    false
);

3. 编译与运行步骤

步骤1:生成LLVM中间码

# 编译foo.c为LLVM IR
clang -S -emit-llvm foo.c -o foo.ll
# 编译simple.c为LLVM IR
clang -S -emit-llvm simple.c -o simple.ll

步骤2:编译LLVM Pass为共享库

clang++ -fPIC -shared instrumentation.cpp -o libInstrumentDisplay.so `llvm-config --cxxflags --ldflags --system-libs --libs core passes`

步骤3:应用插桩Pass到simple.ll

opt -load ./libInstrumentDisplay.so -instrument-display < simple.ll > instrumented.ll

步骤4:链接生成可执行文件并运行

clang instrumented.ll foo.ll -o simple_instrumented
./simple_instrumented
# 输出:Hello World

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:48:24