如何让GCC编译的Linux程序获得固定线程栈地址?
解决Linux下GCC编译程序固定局部变量地址的方法
一、编译链接阶段:生成非PIE程序
单独使用-no-pie链接选项可能不够,需要同时指定编译和链接阶段的参数,确保生成非位置无关可执行文件:
gcc -fno-pie -no-pie stkaddr.cpp -o stkaddr
其中-fno-pie用于编译阶段,告诉编译器不要生成位置无关代码;-no-pie用于链接阶段,让链接器生成非PIE格式的可执行文件。这一步能固定程序代码段、全局变量的地址,但栈地址仍受系统ASLR(地址空间布局随机化)控制。
二、调整系统ASLR配置
要让栈上变量(比如&argc)的地址每次运行都固定,必须关闭系统级的栈随机化:
- 临时关闭(重启后失效):
执行以下命令修改内核参数:
sudo sysctl -w kernel.randomize_va_space=0
- 永久关闭:
编辑/etc/sysctl.conf文件,添加或修改一行:
kernel.randomize_va_space=0
执行sudo sysctl -p让配置立即生效。
验证效果
完成上述操作后,多次运行编译好的程序,会发现&argc的地址完全一致:
./stkaddr ./stkaddr
补充说明
- Linux的ASLR有三个级别:0为完全关闭,1为仅随机化栈和堆地址,2为完全随机化所有地址。只有设置为0才能让栈地址固定。
- 非PIE程序搭配关闭系统ASLR后,栈上所有局部变量的地址都会保持固定。
内容的提问来源于stack exchange,提问作者Jimm Chen
相关产品推荐
相关产品推荐

