符号 etext、edata 和 end 是在哪里定义的?
这是来自 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请注意,在 Mac OS X 上,上面的代码可能不起作用!相反,您可以:
Note that on Mac OS X, the code above may not work! Instead you can have:
GCC 的作用
进一步扩展kgiannakakis。
这些符号由链接器脚本的
PROVIDE
关键字定义,记录在 https://sourceware.org/binutils/docs-2.25/ld/PROVIDE.html#PROVIDE默认脚本是在构建 Binutils 时生成的,并嵌入到
ld 可执行文件:默认情况下不使用可能安装在您的发行版中的外部文件,例如
/usr/lib/ldscripts
中的文件。回显要使用的链接器脚本:
在 binutils 2.24 中它包含:
所以我们还发现:
__etext
和_etext
也可以工作etext
不是.text
部分的末尾,而是.fini
(也包含代码etext
)不在该段的末尾,带有 < code>.rodata 紧随其后,因为 Binutils 将所有只读部分转储到同一段PROVIDE
生成弱符号:如果您也在 C 代码中定义了这些符号,您的定义将获胜并隐藏这个。最小的 Linux 32 位示例
为了真正理解事物是如何工作的,我喜欢创建最小的示例!
main.S
:link.ld
:编译运行:
输出:
解释:
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#PROVIDEThe 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:
In binutils 2.24 it contains:
So we also discover that:
__etext
and_etext
will also worketext
is not the end of the.text
section, but rather.fini
, which also contains codeetext
is not at the end of the segment, with.rodata
following it, since Binutils dumps all readonly sections into the same segmentPROVIDE
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
:link.ld
:Compile and run:
Output:
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.
这些符号在链接器脚本文件中定义< /a> (死链接副本 位于 archive.org)。
These symbols are defined in a linker script file (dead link copy at archive.org).
这些符号对应于各个程序段的开头。它们由链接器设置。
Those symbols correspond to the beginnings of various program segments. They are set by the linker.