如何获取初始化数据段的第一个地址

时间:2015-11-03 07:29:01

标签: c linux

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

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

2 个答案:

答案 0 :(得分:4)

这取决于您的链接器脚本。例如,在某些平台上,您在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,尝试写入可能会出现段错误。

答案 1 :(得分:0)

您可以使用linux工具'fnDrawCallback': function(oSettings) { $("<tr colspan='2'><td>Press Ctrl+Click To select</td></tr>").prependTo("table > tbody"); } (Debian / Ubuntu中的binutils包)。

实施例

size

结果

size -A /usr/bin/gcc