我的程序正在使用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