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

如何在LLVM IR程序中查找address-taken变量和top-level变量

在LLVM IR中识别top-level变量与address-taken变量

定义回顾

  • top-level变量:无法通过指针间接访问的变量,其地址从未通过取址操作暴露,也不是动态内存分配返回的变量。
  • address-taken变量:地址已被暴露(如被取址后存储到其他指针、作为函数参数传递),可通过指针间接访问的变量。

示例说明

以下LLVM IR代码中,a是top-level变量,b、c是address-taken变量:

a = alloca i8**
b = alloca i8*
c = alloca i8

store b a
store c b
store 0 c

原因:b的地址被存储到a中,c的地址被存储到b中,二者地址均已暴露;而a的地址从未被任何操作暴露,只能直接对其进行加载/存储操作,无法通过其他指针间接访问。


识别方法

1. 手动分析LLVM IR

对于小规模IR代码,可通过逐行检查变量的使用场景判断:

  • 遍历所有alloca指令(栈上变量):
    • 若变量仅被用于直接加载/存储其值(如store 0 c中的c是作为存储目标,而非被存储的地址),且从未被取址后存储到其他指针、传递给函数,则为top-level变量。
    • 若变量的地址被存储到其他指针(如store b a中的b)、作为函数参数传递,或被取址后用于其他指针操作,则为address-taken变量。
  • 动态内存分配(如malloc)返回的指针:这类变量的地址天然是暴露的,属于address-taken变量。
  • 全局变量:所有全局变量的地址默认可被访问,均为address-taken变量(除非是private属性且从未被取址使用,这类情况极少)。

2. 用LLVM Pass自动化分析

对于大规模IR程序,手动分析效率极低,可编写LLVM Pass自动识别:

以下是一个简单的FunctionPass实现,用于分析函数内的栈上变量:

#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
struct VarAnalysisPass : public FunctionPass {
  static char ID;
  VarAnalysisPass() : FunctionPass(ID) {}

  bool runOnFunction(Function &F) override {
    errs() << "Analyzing function: " << F.getName() << "\n";
    
    for (auto &BB : F) {
      for (auto &I : BB) {
        if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
          bool isAddressTaken = false;
          // 遍历当前alloca的所有使用场景
          for (auto &Use : AI->uses()) {
            User *U = Use.getUser();
            // 排除直接加载/存储变量值的情况
            if (!isa<LoadInst>(U) && !isa<StoreInst>(U, Use.getOperandNo())) {
              isAddressTaken = true;
              break;
            }
            // 检查是否存在存储该变量地址的操作
            if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
              if (SI->getValueOperand() == AI) {
                isAddressTaken = true;
                break;
              }
            }
          }
          
          if (isAddressTaken) {
            errs() << "  Address-taken variable: " << *AI << "\n";
          } else {
            errs() << "  Top-level variable: " << *AI << "\n";
          }
        }
      }
    }
    return false;
  }
};
}

char VarAnalysisPass::ID = 0;
static RegisterPass<VarAnalysisPass> X("var-analysis", "Analyze top-level and address-taken variables");

逻辑说明

该Pass遍历函数内的每个基本块与指令,对每个alloca指令:

  • 检查其所有使用场景,若存在存储变量地址、作为非加载/存储类指令的操作数(如传递给函数),则标记为address-taken变量。
  • 若仅被用于直接加载或存储其值,则标记为top-level变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:50:00