符号 etext、edata 和 end 是在哪里定义的?

发布于 2024-08-12 01:22:50 字数 716 浏览 5 评论 0原文

这是来自 Linux 手册页的代码:

#include <stdio.h>
#include <stdlib.h>

extern char etext, edata, end;

int main() {
    printf("First address past:\n");
    printf("    program text (etext)      %10p\n", &etext);
    printf("    initialized data (edata)  %10p\n", &edata);
    printf("    uninitialized data (end)  %10p\n", &end);

    exit(EXIT_SUCCESS);
}

运行时,下面的程序会产生如下输出:

$ ./a.out
First address past:
    program text (etext)       0x8048568
    initialized data (edata)   0x804a01c
    uninitialized data (end)   0x804a024

Where are etext, edata end Defined ?这些符号是如何赋值的?是通过链接器还是其他什么?

This is a code from Linux man page:

#include <stdio.h>
#include <stdlib.h>

extern char etext, edata, end;

int main() {
    printf("First address past:\n");
    printf("    program text (etext)      %10p\n", &etext);
    printf("    initialized data (edata)  %10p\n", &edata);
    printf("    uninitialized data (end)  %10p\n", &end);

    exit(EXIT_SUCCESS);
}

when run, the program below produces output such as the following:

$ ./a.out
First address past:
    program text (etext)       0x8048568
    initialized data (edata)   0x804a01c
    uninitialized data (end)   0x804a024

Where are etext, edata end defined ? How those symbols are assigned values ? Is it by linker or something else ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

久光 2024-08-19 01:22:50

请注意,在 Mac OS X 上,上面的代码可能不起作用!相反,您可以:

#include <stdio.h>
#include <stdlib.h>
#include <mach-o/getsect.h>

int main(int argc, char *argv[])
{
    printf("    program text (etext)      %10p\n", (void*)get_etext());
    printf("    initialized data (edata)  %10p\n", (void*)get_edata());
    printf("    uninitialized data (end)  %10p\n", (void*)get_end());

    exit(EXIT_SUCCESS);
}

Note that on Mac OS X, the code above may not work! Instead you can have:

#include <stdio.h>
#include <stdlib.h>
#include <mach-o/getsect.h>

int main(int argc, char *argv[])
{
    printf("    program text (etext)      %10p\n", (void*)get_etext());
    printf("    initialized data (edata)  %10p\n", (void*)get_edata());
    printf("    uninitialized data (end)  %10p\n", (void*)get_end());

    exit(EXIT_SUCCESS);
}
等风来 2024-08-19 01:22:50

GCC 的作用

进一步扩展kgiannakakis

这些符号由链接器脚本的 PROVIDE 关键字定义,记录在 https://sourceware.org/binutils/docs-2.25/ld/PROVIDE.html#PROVIDE

默认脚本是在构建 Binutils 时生成的,并嵌入到 ld 可执行文件:默认情况下不使用可能安装在您的发行版中的外部文件,例如 /usr/lib/ldscripts 中的文件。

回显要使用的链接器脚本:

ld -verbose | less

在 binutils 2.24 中它包含:

.text           :
{
  *(.text.unlikely .text.*_unlikely .text.unlikely.*)
  *(.text.exit .text.exit.*)
  *(.text.startup .text.startup.*)
  *(.text.hot .text.hot.*)
  *(.text .stub .text.* .gnu.linkonce.t.*)
  /* .gnu.warning sections are handled specially by elf32.em.  */
  *(.gnu.warning)
}
.fini           :
{
  KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1        : { *(.rodata1) }

所以我们还发现:

  • __etext_etext 也可以工作
  • etext 不是.text 部分的末尾,而是 .fini(也包含代码
  • etext)不在该段的末尾,带有 < code>.rodata 紧随其后,因为 Binutils 将所有只读部分转储到同一段

PROVIDE 生成弱符号:如果您也在 C 代码中定义了这些符号,您的定义将获胜并隐藏这个。

最小的 Linux 32 位示例

为了真正理解事物是如何工作的,我喜欢创建最小的示例!

main.S:

.section .text
    /* Exit system call. */
    mov $1, %eax
    /* Exit status. */
    mov sdata, %ebx
    int $0x80
.section .data
    .byte 2

link.ld:

SECTIONS
{
    . = 0x400000;
    .text :
    {
        *(.text)
        sdata = .;
        *(.data)
    }
}

编译运行:

gas --32 -o main.o main.S
ld -m elf_i386 -o main -T link.ld main.o
./main
echo $?

输出:

 2

解释:sdata 指向开头的第一个字节接下来的 >.data 部分。

因此,通过控制该部分的第一个字节,我们可以控制退出状态!

GitHub 上的此示例

What GCC does

Expanding kgiannakakis a bit more.

Those symbols are defined by the PROVIDE keyword of the linker script, documented at https://sourceware.org/binutils/docs-2.25/ld/PROVIDE.html#PROVIDE

The default scripts are generated when you build Binutils, and embedded into the ld executable: external files that may be installed in your distribution like in /usr/lib/ldscripts are not used by default.

Echo the linker script to be used:

ld -verbose | less

In binutils 2.24 it contains:

.text           :
{
  *(.text.unlikely .text.*_unlikely .text.unlikely.*)
  *(.text.exit .text.exit.*)
  *(.text.startup .text.startup.*)
  *(.text.hot .text.hot.*)
  *(.text .stub .text.* .gnu.linkonce.t.*)
  /* .gnu.warning sections are handled specially by elf32.em.  */
  *(.gnu.warning)
}
.fini           :
{
  KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1        : { *(.rodata1) }

So we also discover that:

  • __etext and _etext will also work
  • etext is not the end of the .text section, but rather .fini, which also contains code
  • etext is not at the end of the segment, with .rodata following it, since Binutils dumps all readonly sections into the same segment

PROVIDE generates weak symbols: if you also define those symbols in your C code, your definition will win and hide this one.

Minimal Linux 32-bit example

To truly understand how things work, I like to create minimal examples!

main.S:

.section .text
    /* Exit system call. */
    mov $1, %eax
    /* Exit status. */
    mov sdata, %ebx
    int $0x80
.section .data
    .byte 2

link.ld:

SECTIONS
{
    . = 0x400000;
    .text :
    {
        *(.text)
        sdata = .;
        *(.data)
    }
}

Compile and run:

gas --32 -o main.o main.S
ld -m elf_i386 -o main -T link.ld main.o
./main
echo $?

Output:

 2

Explanation: sdata points to the first byte of the start of the .data section that follows.

So by controlling the first byte of that section, we control the exit status!

This example on GitHub.

ゝ偶尔ゞ 2024-08-19 01:22:50

这些符号对应于各个程序段的开头。它们由链接器设置。

Those symbols correspond to the beginnings of various program segments. They are set by the linker.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文