【问题标题】:How to get the first address of initialized data segment如何获取初始化数据段的首地址
【发布时间】:2015-11-03 07:29:01
【问题描述】:

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

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

【问题讨论】:

  • 如何找到edata?你不能用同样的技术找到data吗?为什么不简单地读取二进制文件并找到data 段呢?不过,我最好奇的是,为什么你需要它?您要解决的原始问题是什么? (相关阅读:"What is the XY problem"
  • @JoachimPileborg。我搜索问题,只找到edata、etext、end。这就是我在这里寻求帮助的原因。
  • @JoachimPileborg 我的问题还不清楚吗?我已阅读相关文档并进行了搜索。如果你不能回答,那就走开。或者,我会感谢你。不要评判我或问我为什么想知道它。那是愚蠢的
  • 我猜数据段从etext之后的下一页边界开始,至少根据链接描述文件是这样的。
  • @fanux - 我们很好奇您是否找到了使用该信息的方法。 Joachim 和我显然没有。

标签: c linux


【解决方案1】:

这取决于您的链接器脚本。例如,在某些平台上,您在 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 表示仅在未使用时创建此符号)您可能应该使用@987654329 @ 代替。

如果您希望地址位于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,尝试在那里写可能会出现段错误。

【讨论】:

  • 但是我期望的是函数或变量或宏...谢谢
  • 变量__data_startdata_start可以在程序中直接使用,无需在ldscript中定义。它们都是初始化数据段的首地址,它们的值相同。它们的用法就像 etext 和 edata 一样。这可能只适用于使用 gcc 的 Linux,因为我还没有在其他编译器和平台上测试它。
  • @fanux 看起来这些符号来自链接描述文件以外的其他地方。它实际上依赖于如何组合部分以形成可执行文件中的数据部分,__data_startcrt0.o 部分中的第一个,这使得它位于可执行文件的数据部分中。无论如何,任何此类功能都取决于正在使用的编译器/链接器 - 如果您要使用另一个编译器/链接器,您将不得不研究如何做到这一点。
【解决方案2】:

您可以使用 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

【讨论】:

    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 2017-01-30
    • 2019-09-28
    • 2016-02-03
    • 2018-08-02
    • 1970-01-01
    相关资源
    最近更新 更多