我读了一本书(不能回忆起名字),在32位系统文本部分总是从0x0848000开始。但是当我readelf -S example_executable
时,它并不反映相同的信息。这是为什么?其他部分(bss,data,rodata等)也是从固定地址开始的吗?如何找到这些部分的对齐边界?
答案 0 :(得分:4)
这里有一个很好的解释,说明在为特定程序分配存储时Linux虚拟内存的工作原理。 ua alberta - linux memory allocation
编译器/链接器工具链的设计者需要为特定的内存块分配一个仲裁地址。为了使工具链的其他组件(如调试器和分析器)更容易,它们总是将相同的块分配给相同的地址。选择的实际地址完全是任意的。
当程序加载时,虚拟地址将被映射到一些随机的可用内存(这主要在硬件中完成)。这种映射是基于每个进程完成的,几个程序可以解决虚拟地址x'0848000',但可以指向不同的“实际”内存地址。
答案 1 :(得分:2)
这一切都取决于特定机器上的实现。对于Linux机器,行为将与Windows机器的行为不同。 但请注意,虚拟内存地址需要从某个固定地址开始,以便使调试器的生活更轻松。但是,根据RAM中可用的页面,实际地址会有所不同。 如果你更仔细地查看readelf -S的输出,你会发现你会注意到从地址中减去偏移确实给你0x0848000。 正如我之前提到的,幻数0x0848000 将取决于可执行格式的类型。 这是我在ubuntu 32位机器上输出的输出:
readelf -S ~/a.out
There are 29 section headers, starting at offset 0x1130:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048168 000168 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0804818c 00018c 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481ac 0001ac 000050 10 A 6 1 4
[ 6] .dynstr STRTAB 080481fc 0001fc 00004c 00 A 0 0 1
[ 7] .gnu.version VERSYM 08048248 000248 00000a 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048254 000254 000020 00 A 6 1 4
[ 9] .rel.dyn REL 08048274 000274 000008 08 A 5 0 4
[10] .rel.plt REL 0804827c 00027c 000018 08 A 5 12 4
[11] .init PROGBITS 08048294 000294 000030 00 AX 0 0 4
[12] .plt PROGBITS 080482c4 0002c4 000040 04 AX 0 0 4
[13] .text PROGBITS 08048310 000310 00018c 00 AX 0 0 16
[14] .fini PROGBITS 0804849c 00049c 00001c 00 AX 0 0 4
答案 2 :(得分:1)
文本部分或任何其他部分的操作系统和体系结构之间没有一致的地址。此外,与位置无关的代码和地址空间布局随机化使得这些值在某些系统的同一台机器上甚至不一致。