如何获取初始化数据段的首地址

我的程序正在使用gcc在linux上工作。 通过手册页,我发现edata,代表了初始化数据段结束后的第一个地址。
但是我想知道初始化数据段的第一个地址
我怎么才能得到它?

我已经尝试将etext作为初始化数据段的第一个地址。 然后当我增加地址并访问存储在其中的variables时,我得到了段错误。 我认为etext和edata之间的一些地址空间没有映射到虚拟内存中。 是对的吗?

这取决于你的链接脚本。 例如,在某些平台上,在BSS开始处有符号__bss_start 。 这是一个没有任何数据关联的符号,你可以通过extern声明一个带有这个名字的变量来获得一个指针(仅仅为了获取变量的地址)。 例如:

 #include <stdio.h> extern char __bss_start; int main() { printf("%p\n", &__bss_start); return 0; } 

您可以通过查看链接描述文件来找到这一点,例如在/usr/lib/ldscripts/elf_x64_64.x

 .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); __bss_start = .; /* <<<<< this is what you're looking for /* .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. */ . = ALIGN(. != 0 ? 64 / 8 : 1); } 

你也可以看到你提到的edata ,但是由于edata没有被保留用于实现( PROVIDE只是在没有使用的时候才创建这个符号),所以你应该使用_edata来代替。

如果你想要地址到data部分的开头,你可以修改链接脚本:

 __data_start = . ; .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); __bss_start = .; /* <<<<< this is what you're looking for /* .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. */ . = ALIGN(. != 0 ? 64 / 8 : 1); } 

您可能需要制作链接器脚本的副本(在/usr/lib/ldscripts查找正确的副本,具体取决于您定位的输出类型),并在编译时提供它:

 gcc -o execfile source.c -Wl,-T ldscript 

如果不想修改链接描述文件,另一个选择是使用__executable_start并解析ELF头(希望可执行文件被线性映射)

至于_etext ,它是text部分的结尾(你也可以在链接描述文件中看到,但是我没有把它包含在摘录中),但text部分后面是rodata ,试图写在那里可能会segfault。

您可以使用Linux工具size (Debian / Ubuntu中的binutils软件包)。

 size -A /usr/bin/gcc 

结果是

 /usr/bin/gcc : section size addr .interp 28 4194928 .note.ABI-tag 32 4194956 .note.gnu.build-id 36 4194988 .gnu.hash 240 4195024 .dynsym 4008 4195264 .dynstr 2093 4199272 .gnu.version 334 4201366 .gnu.version_r 160 4201704 .rela.dyn 720 4201864 .rela.plt 3240 4202584 .init 14 4205824 .plt 2176 4205840 .text 384124 4208016 .fini 9 4592140 .rodata 303556 4592160 .eh_frame_hdr 8540 4895716 .eh_frame 50388 4904256 .gcc_except_table 264 4954644 .tbss 16 7052632 .init_array 16 7052632 .fini_array 8 7052648 .jcr 8 7052656 .data.rel.ro 3992 7052672 .dynamic 480 7056664 .got 216 7057144 .got.plt 1104 7057384 .data 2520 7058496 .bss 80976 7061024 .gnu_debuglink 12 0 Total 849310