为什么 ELF 头和文本段一起加载到内存中?
Why is the ELF header loaded into memory along with the text segment?
我用 -m32 -nostdlib
将这个程序编译成一个 ELF 可执行文件:
void _start() {}
当我这样做时 readelf -l
我惊讶地发现 LOAD 段上的偏移量是 0x000000,因为这意味着可执行文件头将与文本段同时加载到内存中.于是去GDB查了一下,确实是这样:
(gdb) b _start
Breakpoint 1 at 0x8048083
(gdb) r
Starting program: /home/tbodt/ish/build/a.out
Breakpoint 1, 0x08048083 in _start ()
(gdb) x/4c 0x08048000
0x8048000: 127 '7' 69 'E' 76 'L' 70 'F'
为什么这有用?
I was surprised to see that the offset on the LOAD segment was 0x000000
你为什么感到惊讶?
since that would mean that the executable header would get loaded into memory at the same time as the text segment.
正确。为什么这是个问题?
正如 this answer 解释的那样,可执行文件是 mmap
ed 并且 mmap
在 整个 页面上工作;您不能映射从偏移 0x34
.
开始的页面部分
您可以构建一个可执行文件,其中 .text
从偏移量 4096
开始(在 ELF header 和程序之间留下一个大洞headers 和文本),然后这样的可执行文件可以具有偏移量为 4096
的第一个 PT_LOAD
段。这并不常见:文件中浪费的 space 通常不值得节省 52 字节的内存。
我用 -m32 -nostdlib
将这个程序编译成一个 ELF 可执行文件:
void _start() {}
当我这样做时 readelf -l
我惊讶地发现 LOAD 段上的偏移量是 0x000000,因为这意味着可执行文件头将与文本段同时加载到内存中.于是去GDB查了一下,确实是这样:
(gdb) b _start
Breakpoint 1 at 0x8048083
(gdb) r
Starting program: /home/tbodt/ish/build/a.out
Breakpoint 1, 0x08048083 in _start ()
(gdb) x/4c 0x08048000
0x8048000: 127 '7' 69 'E' 76 'L' 70 'F'
为什么这有用?
I was surprised to see that the offset on the LOAD segment was 0x000000
你为什么感到惊讶?
since that would mean that the executable header would get loaded into memory at the same time as the text segment.
正确。为什么这是个问题?
正如 this answer 解释的那样,可执行文件是 mmap
ed 并且 mmap
在 整个 页面上工作;您不能映射从偏移 0x34
.
您可以构建一个可执行文件,其中 .text
从偏移量 4096
开始(在 ELF header 和程序之间留下一个大洞headers 和文本),然后这样的可执行文件可以具有偏移量为 4096
的第一个 PT_LOAD
段。这并不常见:文件中浪费的 space 通常不值得节省 52 字节的内存。