Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何获取初始化数据段的第一个地址_C_Linux - Fatal编程技术网

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

C 如何获取初始化数据段的第一个地址,c,linux,C,Linux,我的程序使用gcc在linux上运行。通过手册页面,我找到了edata,它表示初始化数据段的第一个地址过去的结束的。 但是我想知道初始化数据段的第一个地址 我怎样才能得到它 我尝试将etext作为初始化数据段的第一个地址。然后,当我增加地址并访问其中存储的变量时,我得到了一个段错误。我认为etext和edata之间的一些地址空间没有映射到虚拟内存中。是吗?您可以使用linux工具size(Debian/Ubuntu中的binutils包) 范例 size -A /usr/bin/gcc 导致

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


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

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

这取决于链接器脚本。例如,在某些平台上,在bss的开头有符号
\u\u bss\u start
。它是一个没有任何相关数据的符号,您可以通过
extern
声明具有该名称的变量(仅为了获取该变量的地址)来获取指向它的指针。例如:

#include <stdio.h>

extern char __bss_start;

int main()
{
    printf("%p\n", &__bss_start);

    return 0;
}
您还可以看到您提到的
edata
,但由于
edata
不是为实现保留的(如果没有使用
PROVIDE
则仅表示创建此符号),您可能应该改用
\u edata

如果希望地址位于
数据
部分的开头,可以修改链接器脚本:

__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);
}
如果您不想修改链接器脚本,另一个选项是使用
\uuuu executable\u start
并解析ELF头(希望可执行文件充分线性映射)


至于
\u etext
,它是
文本
部分的结尾(你也可以在链接器脚本中阅读,但我没有将其包含在摘录中),但是
文本
部分后面紧跟着
rodata
,试图在那里写可能会出错。

你如何找到
edata
?您不能使用相同的技术来查找
数据
?为什么不直接读取二进制文件并找到
数据
段呢?但我最好奇的是你为什么需要它?您试图解决的原始问题是什么?(相关阅读:)@JoachimPileborg。我搜索这个问题,只找到了edata,etext,end。这就是我在这里寻求帮助的原因。@JoachimPileborg我的问题还不清楚吗?我已经阅读了相关文件并进行了搜索。如果你不能回答,就走开。或者,我会感谢你。不要评判我,也不要问我为什么想知道。这是愚蠢的。我猜数据段从
etext
之后的下一页边界开始,至少它是根据链接器脚本开始的。@fanux-我们只是好奇您是否找到了使用该信息的方法。Joachim和我显然没有。但我期望的是一个函数、一个变量或一个宏。。。谢谢,变量uu data_start和data_start可以直接在程序中使用,无需在ldscript中定义。它们都是初始化数据段的第一个地址,并且它们的值相同。它们的用法与etext和edata一样。这可能只适用于使用gcc的Linux,因为我没有在其他编译器和平台上测试它。@fanux看起来这些符号来自链接器脚本以外的其他地方。它实际上取决于节如何组合以形成可执行文件中的数据节,
\uu data\u start
crt0.o
节中的第一个,这使得它位于可执行文件的数据节的第一位。无论如何,任何这样的特性都依赖于正在使用的编译器/链接器-如果要使用另一个编译器/链接器,则必须研究如何执行此操作。
__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);
}
gcc -o execfile source.c -Wl,-T ldscript