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

如何在LLVM中定义可在链接脚本中访问的链接器符号

实现方案

方案1:模块内联汇编(全版本兼容,实现最简单)

直接通过llvm::Module提供的appendModuleInlineAsm方法注入你需要的汇编符号定义即可,效果和手动写汇编文件完全一致:

#include "llvm/IR/Module.h"

bool YourPass::runOnModule(Module &M) {
  // 直接注入汇编符号定义,和手写sym.s的逻辑完全相同
  M.appendModuleInlineAsm(R"(
    .global asdf
    asdf = 0x1234
  )");
  return true;
}

编译后生成的目标文件符号和你示例中的sym.o完全一致,符号asdf为ABS类型,值为0x1234,不占用任何段空间。

方案2:原生IR API实现(LLVM 13+支持)

如果你希望用纯LLVM IR API实现,不需要依赖汇编语法,可以按以下逻辑创建全局绝对符号:

#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Type.h"
#include "llvm/ADT/APInt.h"

bool YourPass::runOnModule(Module &M) {
  auto &Ctx = M.getContext();
  // 创建全局变量实例,不需要初始值
  auto *AbsSym = new llvm::GlobalVariable(
    M,
    llvm::Type::getInt8Ty(Ctx),
    true, // 标记为常量
    llvm::GlobalValue::ExternalLinkage,
    nullptr, // 初始值设空,不分配数据段空间
    "asdf" // 符号名
  );
  // 关键:设置为绝对符号,值固定为0x1234
  AbsSym->setAbsoluteSymbolRange(llvm::APInt(64, 0x1234), llvm::APInt(64, 0x1234));
  AbsSym->setSize(0); // 标记符号大小为0
  return true;
}

对应正确的IR写法如下,你之前的尝试错误是因为给全局变量指定了初始值,导致LLVM将其识别为普通数据变量:

target triple = "x86_64-pc-linux-gnu"
@asdf = external global i8, !absolute_symbol !0
!0 = !{i64 0x1234, i64 0x1234}
注意事项
  • 方案1兼容所有LLVM版本,实现更简单,不容易出错,优先推荐使用
  • 方案2需要LLVM 13及以上版本才支持setAbsoluteSymbolRange接口

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:27:05