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

GCC中-pie选项如何影响文件作用域变量的地址?

GCC中-pie选项对文件作用域变量地址的影响机制

问题示例代码

#include <stdio.h>
int gprs[32];
int main(void)
{
   printf("%p\n", (void*)&gprs);
}

不同编译选项的输出

  • 使用-pie编译(GCC当前默认):
    0x55c183951040
    
  • 使用-no-pie编译:
    0x404060
    

注:Clang默认使用-no-pie选项。


核心机制解释

1. PIE的本质

PIE(Position-Independent Executable)是位置无关可执行文件,核心设计目标是配合操作系统的地址空间随机化(ASLR),让程序每次运行时都被加载到内存的随机地址,以此降低内存攻击的成功率。

2. -no-pie:固定地址的传统可执行文件

用-no-pie编译出的是普通ELF可执行文件(类型标记为EXEC):

  • 链接阶段会直接给全局/静态变量分配固定虚拟地址(通常落在0x400000起始的地址段,比如示例中的0x404060属于数据段)。
  • 程序运行时,内核会严格按照链接器指定的固定地址加载程序,因此全局变量的运行时地址始终固定。

3. -pie:随机基址的位置无关可执行文件

用-pie编译出的是类共享库的可执行文件(ELF类型标记为DYN,和动态库一致):

  • 链接阶段仅计算全局变量相对于程序加载基址的偏移量,不会分配固定绝对地址。
  • 程序启动时,内核会随机选择一个基址(通常落在0x550000000000附近,比如示例中的0x55c183951040)加载整个程序。全局变量的实际运行时地址 = 随机加载基址 + 编译链接时确定的偏移量。
  • 由于每次加载的基址是随机的,全局变量的实际地址每次运行都会变化。

4. 底层访问方式差异

  • 非PIE程序:直接使用编译时确定的绝对地址访问全局变量。
  • PIE程序:在64位系统下通常用RIP相对寻址获取变量地址,32位系统则依赖**GOT(全局偏移表)**间接寻址,确保无论程序加载到哪个基址,都能正确定位全局变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:35:19