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

LLVM代码求助:获取CallInst返回值并传参时运行崩溃

解决LLVM Pass中获取CallInst返回值并传递时的崩溃问题

看起来你在编写LLVM函数Pass时遇到了段错误,从错误栈能直接定位到问题出在DebugLoc::getLine()的调用上。我来帮你拆解问题原因,再给出修复方案:

崩溃的直接原因

你的代码里直接调用I.getDebugLoc().getLine(),但不是所有LLVM指令都携带调试信息。当某个CallInst没有调试信息时,getDebugLoc()会返回一个"Unknown"状态的DebugLoc对象,这时调用getLine()或getCol()会访问内部空指针,直接触发段错误——这就是错误栈指向_ZNK4llvm8DebugLoc7getLineEv的原因。

除此之外,代码还有几个潜在问题,也可能引发运行时错误:

  1. 直接把CallInst*作为参数传给hook1:如果原调用是返回void的函数,ci本身没有返回值;如果返回类型不是i32,还会出现类型不匹配的问题。
  2. IRBuilder的插入点设置冗余,可能导致插入位置不符合预期。

修复后的代码

下面是调整后的代码,解决了上述所有问题:

if (auto* ci = dyn_cast<CallInst>(&I)) { // 合并isa和dyn_cast,写法更简洁高效
    // 先检查调试信息是否有效,避免空指针访问
    DebugLoc debugLoc = ci->getDebugLoc();
    int line = 0, col = 0;
    if (!debugLoc.isUnknown()) {
        line = debugLoc.getLine();
        col = debugLoc.getCol();
    } else {
        // 没有调试信息时,可设置默认值,也可根据需求直接跳过该指令
        line = -1;
        col = -1;
    }

    LLVMContext& ctx = F.getContext();
    Type* i32Ty = Type::getInt32Ty(ctx);
    Value* lineVal = ConstantInt::get(i32Ty, line, true);
    Value* colVal = ConstantInt::get(i32Ty, col, true);

    // 处理CallInst的返回值,确保和hook1的int参数类型匹配
    Value* callRetVal = ci;
    if (ci->getType()->isVoidTy()) {
        // 如果原函数返回void,用默认i32值替代返回值
        callRetVal = ConstantInt::get(i32Ty, 0, true);
    } else {
        // 如果返回类型不是i32,执行整数类型转换
        if (callRetVal->getType() != i32Ty) {
            callRetVal = CastInst::CreateIntegerCast(
                callRetVal, i32Ty, true, "cast_to_i32", ci
            );
        }
    }

    // 构造参数并插入hook调用
    ArrayRef<Value*> hookArgs = {lineVal, colVal, callRetVal};
    IRBuilder<> builder(ci->getNextNode()); // 明确将调用插入在原CallInst之后
    builder.CreateCall(hook1, hookArgs);
}

关键修复点说明

  1. DebugLoc有效性检查:通过!debugLoc.isUnknown()判断调试信息是否存在,仅在有效时才调用getLine()和getCol()。
  2. 返回值类型适配:
    • 针对返回void的函数,用默认i32值替代返回值;
    • 针对非i32的返回类型,通过CreateIntegerCast转换为i32,确保和hook1的参数类型匹配(hook1接受int类型,对应LLVM的i32类型)。
  3. 简化IRBuilder使用:直接将插入点设为原CallInst的下一个节点,避免冗余的插入点设置。
  4. 使用ArrayRef:用LLVM原生的ArrayRef替代C风格数组,更符合LLVM API的使用习惯,也更安全。

额外建议

如果你的场景中,没有调试信息的指令不需要处理,可以直接在debugLoc.isUnknown()时continue跳过,这样能避免不必要的默认值处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 21:18:12