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

如何在新版LLVM中查找特定函数CallSite及替代use_back()

嘿,刚好在LLVM开发中经常跟CallSite打交道,我来帮你解决这两个问题~

如何在LLVM中查找特定函数的CallSite

要定位特定函数的所有调用点,有两种常用的思路:

  • 直接遍历目标函数的用户列表
    每个调用指令(CallInst或InvokeInst)都是目标函数的直接用户,所以我们可以遍历目标函数的users()集合,筛选出调用指令并转换为CallSite:

    // 首先获取目标函数的指针(假设M是当前Module的引用)
    Function* TargetFunc = M.getFunction("your_target_function_name");
    if (!TargetFunc) {
      errs() << "Target function not found!\n";
      return;
    }
    
    // 遍历目标函数的所有用户
    for (User* U : TargetFunc->users()) {
      // 判断该用户是否是调用指令(CallBase是CallInst和InvokeInst的父类)
      if (auto* CB = dyn_cast<CallBase>(U)) {
        CallSite CS(CB);
        // 在这里处理CallSite,比如打印调用位置、获取参数等
        errs() << "Found call site: " << *CB << "\n";
      }
    }
    
  • 遍历整个模块的所有指令(适合间接调用场景)
    如果目标函数存在间接调用(比如通过函数指针调用),上面的方法可能无法覆盖,这时候可以遍历模块内所有函数的基本块和指令,检查每个调用指令的目标是否是我们要找的函数:

    Function* TargetFunc = M.getFunction("your_target_function_name");
    if (!TargetFunc) {
      errs() << "Target function not found!\n";
      return;
    }
    
    for (Function& F : M) {
      for (BasicBlock& BB : F) {
        for (Instruction& I : BB) {
          if (auto* CB = dyn_cast<CallBase>(&I)) {
            // 检查调用的目标函数是否匹配
            if (CB->getCalledFunction() == TargetFunc) {
              CallSite CS(CB);
              // 处理CallSite逻辑
            }
          }
        }
      }
    }
    
新版LLVM中替代use_back()创建CallSite的方法

你说得没错,use_back()方法在新版LLVM中已经被移除了——原因很简单:LLVM内部的use列表是无顺序保证的,依赖use_back()获取"最后一个调用点"的逻辑本身就不可靠,而且这个方法的性能表现也不佳。

现在要实现类似的功能,正确的做法是遍历目标函数的users集合,找到符合要求的调用指令,具体分两种场景:

  • 只想获取任意一个调用点
    如果原来的代码只是随便取一个调用点(比如旧版用use_back()只是为了拿到一个示例),可以遍历users找到第一个匹配的调用指令:

    Function* SomeFunc = ...; // 你的目标函数指针
    CallSite CS;
    
    for (User* U : SomeFunc->users()) {
      if (auto* CB = dyn_cast<CallBase>(U)) {
        CS = CallSite(CB);
        break; // 取第一个找到的调用点
      }
    }
    
    // 记得检查CallSite是否有效
    if (CS) {
      // 执行你的业务逻辑
    }
    
  • 确定目标函数只有一个调用点
    如果能保证目标函数只有一个调用点,可以直接取users集合的第一个元素:

    Function* SomeFunc = ...;
    if (!SomeFunc->users().empty()) {
      User* U = *SomeFunc->users().begin();
      if (auto* CB = dyn_cast<CallBase>(U)) {
        CallSite CS(CB);
        // 处理逻辑
      }
    }
    

总的来说,新版LLVM更鼓励开发者显式遍历use列表,而不是依赖不确定的顺序方法,这样代码会更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:12:51