【发布时间】:2018-07-07 00:11:21
【问题描述】:
我试图弄清楚为什么 static uint64_t arr[] 的地址在主可执行文件内的全局范围内定义时会发生变化。
它在运行时从0x201060(由链接器定义?)变为0x555555755060,我不知道为什么。
为什么会发生这种情况,有什么方法可以防止这种行为吗?
我有一个没有表现出这种行为的预编译二进制文件,我正在尝试模拟它。
$ gdb a.out # compiled from test.c
GNU gdb (GDB) 8.0.1...
Reading symbols from a.out...done.
(gdb) x/x arr
0x201060 <arr>: 0x00000024
(gdb) b main
Breakpoint 1 at 0x6e9: file test.c, line 116.
(gdb) run
Starting program: ...
Breakpoint 1, main (argc=1, argv=0x7fffffffdb28) at test.c:116
116 if(argc != 2) {
(gdb) x/x arr
0x555555755060 <arr>: 0x00000024
test.c 使用以下选项编译:-g -fno-stack-protector -z execstack。
我在没有 ASLR (sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space') 的情况下编译并运行了 test.c,但结果是一样的。
test.c的相关部分是:
#include <stdint.h>
extern int func(uint64_t[]);
static uint64_t arr[] = {
0x00000024, 0x00201060,
0x00201080, 0x00000000,
0x00000008, 0x002010e0,
0x002010a0, 0x00000000,
0x00000032, 0x002010c0,
...
0x00201100, 0x00000000
};
int main(int argc, char** argv) {
func(arr);
return 0;
}
【问题讨论】:
-
为什么要阻止这种行为?
-
这可能是地址空间布局随机化。也可能是在运行时映射到虚拟内存空间
-
@chux 是的。虚拟内存会通过将每个进程的地址映射到物理内存中的两个不同区域来处理内存冲突。
-
当您无法理解某些代码的工作原理时,请始终创建Minimal, Complete, and Verifiable Example 向我们展示。例如,是
arr? -
请发布
gcc -###的输出。默认情况下,您的编译器可能是为生成 PIE 可执行文件而构建的。