C 文本部分从哪个地址开始?

C 文本部分从哪个地址开始?,c,C,我在一本书中读到(记不起名字),32位系统的文本部分总是从0x0848000开始。但是当我执行readelf-S example\u executable时,它并不反映相同的信息。为什么呢?其他部分(bss、数据、rodata等)是否也从固定地址开始?如何找到这些部分的对齐边界?对于文本部分或任何其他部分,操作系统和体系结构之间没有一致的地址。此外,位置无关的代码和地址空间布局随机性使得某些系统在同一台机器上的这些值甚至不一致。这里有一个很好的解释,说明了Linux虚拟内存在为特定程序分配存储时

我在一本书中读到(记不起名字),32位系统的文本部分总是从0x0848000开始。但是当我执行
readelf-S example\u executable
时,它并不反映相同的信息。为什么呢?其他部分(bss、数据、rodata等)是否也从固定地址开始?如何找到这些部分的对齐边界?

对于文本部分或任何其他部分,操作系统和体系结构之间没有一致的地址。此外,位置无关的代码和地址空间布局随机性使得某些系统在同一台机器上的这些值甚至不一致。

这里有一个很好的解释,说明了Linux虚拟内存在为特定程序分配存储时是如何工作的。

编译器/链接器工具链的设计者需要为特定内存块分配一个任意地址。为了使调试器和分析器等工具链的其他组件更容易使用,它们总是将相同的块分配给相同的地址。选择的实际地址完全是任意的


当程序加载时,虚拟地址将映射到某个随机的空闲内存块(这主要是在硬件中完成的)。此映射是在每个进程的基础上完成的,几个程序可以寻址虚拟地址x'0848000',但指向不同的“真实”内存地址。

这一切都取决于特定计算机上的实现。对于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

由于地址空间布局随机化(ASLR),在现代操作系统上,这些边界中的许多是随机化的。您可能指的是0x08048000,而不是0x0848000。地址的选择并非完全是任意的;有些选择比其他的好。特别是,将文本段设置为
0x60000000
左右将使应用程序可能使用的最大
mmap
大小大约减半。。。