【问题标题】:Is there a way to have a.out loaded in linux x86_64 "high memory"?有没有办法在linux x86_64“高内存”中加载a.out?
【发布时间】: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。

标签: linux memory x86-64


【解决方案1】:

是的。将 Linux x86-64 应用程序构建为与位置无关的可执行文件将导致它及其堆与 libc 和其他库一起映射到高内存。这应该会留下 2GB 以下的空间供您使用。 (但是,请注意,内核可能会保护前 64KB 左右的内存不被映射,以保护它免受某些攻击;请查看 vm.mmap_min_addr 获取信息。)

要将您的应用程序构建为与位置无关的可执行文件,请将-pie -fPIE 传递给编译器。

【讨论】:

  • 看起来我可以低至 4096 开始(虽然 64K 的起点可能一样好)。
猜你喜欢
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多