我的程序正在使用gcc的linux上工作。通过手册页,我发现edata,它代表初始化数据段的第一个地址过去结束。
但我想知道初始化数据段的首地址
我该如何得到它?如何获得初始化数据段的首地址
我试过把etext作为初始化数据段的第一个地址。然后,当我增加地址并访问存储在其中的变量时,我遇到了段错误。我认为etext和edata之间的一些地址空间没有映射到虚拟内存中。是对的吗?
我的程序正在使用gcc的linux上工作。通过手册页,我发现edata,它代表初始化数据段的第一个地址过去结束。
但我想知道初始化数据段的首地址
我该如何得到它?如何获得初始化数据段的首地址
我试过把etext作为初始化数据段的第一个地址。然后,当我增加地址并访问存储在其中的变量时,我遇到了段错误。我认为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
的另一种选择d解析ELF头文件(希望可执行文件被线性映射)
至于_etext
,它是text
部分的结尾(您也可以在链接描述文件中阅读它,但我没有包含它在摘录中),但text
部分后面跟着rodata
,试图写入可能会出现段错误。
您可以使用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
你如何找到'edata'?你不能使用相同的技术来查找数据吗?为什么不简单地阅读二进制文件并找到'data'段?我最感兴趣的是*为什么*你需要它?你试图解决什么是原始问题?(相关阅读:[“什么是XY问题”](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) –
@JoachimPileborg。我搜索这个问题,只找到edata,etext,结束。这就是为什么我在这里寻求帮助。 – fanux
@JoachimPileborg不是我的问题清楚吗?我已阅读相关文件并进行搜索。如果你不能回答,就走开。或者,我会感谢你。不要评价我或者问我为什么想知道它。那是愚蠢的 – fanux