use*_*840 32 linux memory x86-64 elf abi
在本文件中.27它说文本段从0x400000开始.为什么选择这个特定的地址?有什么理由吗?相同的地址被选择在GNU ld上Linux:
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)
这是令人惊讶的,因为这个地址在32位x86可执行文件中更大:
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)
我读了这个问题,讨论为什么为i386选择了0x080xxxxx地址,但它没有解释x86_64的变化.在这个问题上很难找到任何解释.有人有线索吗?
iva*_*eev 31
结论:使用大地址时的一些技术限制amd64建议将较低2GiB的地址空间专用于代码和数据以提高效率.因此,堆栈已经重新定位在此范围之外.
在i386ABI 1
0x8048000向下增长.它提供了"堆栈略高于128 MB,文本和数据约为2 GB"(第3-22页).0x80000000(2GiB),1GiB,至少从0xC0000000(第3-21页)开始(这是它通常做的).128MiB(即288KiB)将被保留用于此目的.amd64(其ABI被公式化为对其的修正i386(第9页))具有更大的(48位)地址空间,但大多数指令只接受32位立即操作数(包括跳转指令中的直接地址和偏移),需要更多的工作和效率更低的代码(特别是在考虑指令相互依赖性时)来处理更大的值.作者总结了一些解决这些限制的措施,他们建议使用一些"代码模型"来"让编译器生成更好的代码".(第33页)
0x00000000到0x7effffff" 的范围内的地址",这允许一些非常有效的相对引用和数组迭代.这1.98GiB对于许多程序来说已经足够了.movabs指令,就像在中间代码模型中一样,甚至用于处理文本部分内的地址.此外,当分支到其地址时需要间接分支.当前指令指针的偏移量是未知的." 他们继续建议将代码库拆分为多个共享库,因为这些度量不适用于具有已知在边界内的偏移的相对引用(如"小位置无关代码模型"中所述).因此,堆栈被移动到共享库空间(0x80000000000,128GiB)下,因为它的地址永远不是立即操作数,总是间接引用或与lea/ mov从另一个引用引用,因此只应用相对偏移限制.
以上解释了为什么加载地址被移动到较低的地址.现在,为什么它移动到完全0x400000(4MiB)?在这里,我空洞如此,总结了我在ABI规范中所读到的内容,我只能猜测它感觉"恰到好处":
amd64运行,但小到足以不浪费大量有价值2GiB的地址空间启动.1 注意实际的X32 Linux版本已经从这个布局偏离更多的和更随着时间的推移.但是我们在这里讨论的是ABI规范,因为amd64它正式基于它而不是任何派生的布局(参见其引用的段落).
| 归档时间: |
|
| 查看次数: |
2259 次 |
| 最近记录: |