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

Linux Ubuntu可执行文件中GOT是“指针的指针”吗?是否由加载器处理?

关于Linux(Ubuntu)中GOT与PIE的寻址疑问解答

先明确GOT的核心作用

在Linux(Ubuntu)的位置无关代码(PIC/PIE)可执行文件中,文本段是只读的,静态链接阶段无法确定全局数据/函数的实际加载地址——因为PIE程序每次启动都会被加载到随机内存地址。这时候GOT(全局偏移表)就作为一个可修改的间接层存在:加载时,操作系统的动态链接器会自动修改GOT中的条目,把它们指向对应数据/函数的真实内存地址。

解答你的核心疑问

结论先行:不需要手动做两次解引用,加载器会自动处理GOT条目,也不会让PIE中的指针变成“指针的指针”。具体拆解:

无GOT的场景(非PIE静态链接)

此时全局数据的地址在编译时就已经确定,指令mov fun_data(%rip), %rax的逻辑是:

  • 通过RIP相对偏移计算出fun_data的直接内存地址
  • 读取该地址上存储的数据值,放到rax中
    等价于代码层面的 rax = *fun_data

有GOT的场景(PIE/动态链接)

编译器会自动调整对fun_data的访问逻辑,把它重定向到GOT条目,而非直接访问数据地址:

  1. 指令会变成类似 lea fun_data@GOTPCREL(%rip), %rax —— 通过RIP相对偏移找到GOT条目的内存地址,存入rax
  2. 接着执行 mov (%rax), %rax —— 读取GOT条目中存储的内容(也就是fun_data的真实加载地址),更新rax
  3. 如果要获取数据值,再执行 mov (%rax), %rbx —— 此时rbx就是fun_data的值

但这并不是你担心的“两次解引用fun_data”,因为在PIE编译模式下,原fun_data符号已经不再对应数据的直接地址,而是编译器生成的指向GOT条目的偏移。动态链接器会在加载时自动把GOT条目填充为数据的真实地址,所以代码层面不需要你手动处理指针的指针,编译器和动态链接器已经帮你完成了所有间接层的处理。

简单说:GOT是编译器和动态链接器共同实现PIE的底层机制,对开发者透明——你写代码访问fun_data时,不需要关心GOT的存在,最终的执行效果和非PIE下直接访问数据是一致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:45:38