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
不在段的末尾,后面跟着 .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 上的示例。