【发布时间】:2016-10-21 18:11:53
【问题描述】:
如果我查看 Linux (x86_64) 上 64 位进程的内存映射,我发现 a.out 映射在相当低的内存中:
$ cat /proc/1160/maps
00400000-004dd000 r-xp 00000000 103:03 536876177 /usr/bin/bash
006dc000-006dd000 r--p 000dc000 103:03 536876177 /usr/bin/bash
006dd000-006e6000 rw-p 000dd000 103:03 536876177 /usr/bin/bash
006e6000-006ec000 rw-p 00000000 00:00 0
00e07000-00e6a000 rw-p 00000000 00:00 0 [heap]
7fbeac11c000-7fbeac128000 r-xp 00000000 103:03 1074688839 /usr/lib64/libnss_files-2.17.so
7fbeac128000-7fbeac327000 ---p 0000c000 103:03 1074688839 /usr/lib64/libnss_files-2.17.so
我想在内存的最低部分映射一个 2G 内存区域,但必须将其放在这些 a.out 映射之后的区域中,进入第二个 2G 区域。
在此处映射的 a.out 是否是 x86_64 ABI 的一部分,或者是否可以将此加载地址移动到不同的区域,使用以下之一:
- 运行时加载程序标志
- 创建可执行文件时的链接器标志
?
【问题讨论】:
-
您确实意识到,我希望这些都是虚拟地址,它们与实际使用的物理内存地址之间没有特别的关联?没有连续的虚拟内存页在物理内存中一定是有序的,甚至相互靠近,甚至在同一个NUMA节点上或在同一个内存区域中……
-
默认代码模型将静态数据和代码放在低 2G 中,因此它们的地址可以用符号扩展的 32 位常量表示,用作立即操作数。您绝对需要重新编译一个典型的可执行文件才能使其正常工作,因为默认情况下它们不是位置独立的(并且会执行
mov edi, .LC0 / call puts之类的操作,在链接时将字符串地址硬编码为 32 位常量) .请参阅 ABI 文档(链接自 x86 tag wiki。