讲师中心 微信公众号
AI工具推荐 视频效率加速

LLVM后端怎么支持位置无关代码

小瑶小哥_1009

小瑶小哥_1009

发布时间:2026-09-28 22:23:15

|

945人浏览过

|

来源于php中文网

原创

LLVM后端通过目标特定的Lowering逻辑,在Reloc::PIC模式下将GlobalAddressSDNode等节点转为GOT/PLT访问或PC-relative指令序列,如x86-64生成movq foo@GOTPCREL(%rip), %rax,而非绝对地址加载。

llvm后端怎么支持位置无关代码

LLVM后端如何生成 PIC 指令序列

LLVM 后端本身不直接“支持”-fPIC这种编译选项,而是通过目标特定的代码生成逻辑,在指令选择、地址计算和重定位模型中配合前端传递的 PIC 模式(如 TargetMachine::getRelocationModel() == Reloc::PIC)来生成符合位置无关语义的机器指令。

关键在于:后端必须为每个目标架构实现正确的 PC 相对寻址模式、全局偏移表(GOT)访问序列、以及对符号引用的重定位类型标注(如 R_X86_64_GOTPCREL、R_AARCH64_PREL64 等)。

  • 当 Reloc::PIC 被启用时,后端在 lowering GlobalAddressSDNode 或 ExternalSymbolSDNode 时,会避开直接生成绝对地址加载,转而插入 GOT 查找或 PC-relative load 序列
  • 例如在 X86-64 上,movq foo@GOTPCREL(%rip), %rax 这类指令由 SelectionDAG 的 LowerGlobalAddress 方法生成,而非 movq $foo, %rax
  • ARM64 使用 adrp + add 组合实现 PC-relative 地址计算;RISC-V 使用 auipc + addi,这些都需在目标 Lowering 函数中显式支持

SelectionDAG 中的 PIC lowering 必须覆盖哪些节点

不是所有全局引用都会被自动转成 PIC 形式。后端需在 TargetLowering::LowerOperation 或专用 lowering 函数(如 LowerGlobalAddress、LowerConstantPool、LowerBlockAddress)中显式处理以下节点类型:

  • GlobalAddressSDNode:对应全局变量、函数地址取址(如 &printf)——必须生成 GOT 入口访问或 PC-relative load
  • ExternalSymbolSDNode:对应未定义外部符号(如调用 malloc)——需生成 PLT stub 调用或 GOT+call 序列
  • ConstantPoolSDNode:常量池项(如字符串字面量)——在 PIC 模式下不能硬编码地址,需通过 GOT 或 PC-relative offset 访问
  • JumpTableSDNode:跳转表地址——必须使用 PC-relative 加载,否则无法在任意基址运行

漏掉任一节点,就可能导致生成非法的绝对地址引用,链接时报 relocation R_X86_64_32 against <code>xxx can not be used when making a shared object 错误。

寄存器分配与调度对 PIC 正确性的影响

PIC 指令序列往往比普通指令更长(例如多一条 lea 或额外 mov),且依赖特定寄存器(如 x86-64 的 %rip、AArch64 的 x29 常作 frame pointer,但 GOT 访问可能需临时寄存器)。这直接影响寄存器分配和指令调度行为:

  • 某些目标(如 ARM)要求 PIC 序列中不能破坏 lr(link register),否则 PLT 调用返回失败;后端需在 TargetRegisterInfo 中将该寄存器标记为 clobbered 或预留
  • GOT 访问通常引入额外的数据依赖链(load addr → load from addr),若调度器错误地重排,可能造成冒险;需在 SchedPredicate 或 SubtargetInfo::getSchedModel 中为 GOT 相关指令指定正确延迟和资源
  • 寄存器分配器若将 PIC 序列中的临时地址寄存器(如 x86-64 的 %rax 用于 GOT 查找)分配给其他活跃值,会导致地址被覆盖——必须确保 lowering 后的 MachineInstr 显式声明 def 和 use 关系

测试 PIC 生成是否真正生效的实操方法

光看汇编输出不够,必须验证最终产物是否真的不含非法重定位、能否被 dlopen 正确加载:

  • 编译时加 -fPIC -shared,然后用 readelf -d libxxx.so | grep TEXTREL —— 若输出为空,说明无运行时文本重定位(TEXTREL 是 PIC 失败的典型标志)
  • 用 objdump -dr libxxx.so | grep -E "(R_[A-Z0-9_]+_32|R_[A-Z0-9_]+_64)" 检查是否存在非 GOT/PLT 类型的绝对重定位(如 R_X86_64_32)
  • 写一个 minimal C 文件调用该库函数,用 gcc -pie main.c -L. -lxxx -o main 链接,再运行 ./main —— 若 segfault 或报 cannot make segment writable for relocation,说明 PIC 生成有缺陷
  • 对自研后端,可在 SelectionDAGBuilder 中插入断点,检查 GlobalAddressSDNode 是否被 Lower 成 ISD::LOAD + ISD::ADD(GOT)或 ISD::ADD + ISD::Constant(PC-rel),而非直接 ISD::Constant

最易忽略的一点:很多后端只实现了函数调用的 PLT 支持,却忘了全局变量取址的 GOT 支持——这两者在 lowering 层是完全独立的路径,必须分别验证。

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2183

2023.08.11

前端和后端的区别
前端和后端的区别

前端关注的是用户界面的设计和交互,而后端则注重数据处理和逻辑控制。想了解更多前端后端的相关内容,可以阅读本专题下面的文章。

5790

2024.03.19

后端的主要工作内容介绍
后端的主要工作内容介绍

后端是应用程序的服务端部分,负责核心任务,如数据库交互、业务逻辑处理和响应客户端请求。想了解更多后端的相关内容,可以阅读本专题下面的文章。

5106

2024.03.19

PixTV AI视频生成与无限画布创作
PixTV AI视频生成与无限画布创作

PixTV专题整理AI视频与视觉内容创作相关功能使用教程,涵盖AI生图、视频生成、无限画布、多模型创作、素材管理、声音音乐及视频剪辑等功能,帮助用户快速掌握PixTV从创意到成片的完整制作方法。

0

2026.09.29

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

200

2026.09.23

Buffalo框架路由与请求处理实操指南
Buffalo框架路由与请求处理实操指南

本专题讲解Buffalo框架路由与请求处理机制,涵盖路由注册与分组、资源路由、Handler编写规范、Context上下文方法、参数绑定、中间件编写挂载、Session与Cookie读写、Flash消息及错误页面定制方法。

100

2026.09.23

Buffalo框架零基础入门教程
Buffalo框架零基础入门教程

本专题整理Buffalo框架入门内容,涵盖Go环境准备、buffalo CLI安装、新项目生成、目录结构说明、dev热加载启动、数据库连接配置与常见报错排查,帮助新手按约定优于配置的思路跑通第一个Buffalo框架应用。

80

2026.09.23

Conan创建软件包配方指南
Conan创建软件包配方指南

本专题介绍通过conanfile.py创建软件包的方法,讲解包名、版本、依赖和构建设置等基础信息,以及source、build、package、package_info等常用方法的作用及编写思路。

60

2026.09.22

Conan二进制包配置指南
Conan二进制包配置指南

本专题介绍Conan根据操作系统、编译器、架构和构建类型生成二进制包的方法,讲解Profile、Settings、Options及Package ID的作用,帮助管理不同平台和编译环境下的包版本。

60

2026.09.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn