我真的很难使用链接器脚本,所以我决定从最小的测试开始,然后开始调整内容。但删除甚至在我的目标文件中的部分的默认链接描述文件的行,都会导致可执行文件急剧增长!
程序:wait_input.S
.intel_syntax noprefix
#include <sys/syscall.h>
.text
.globl _start
_start:
# read(0,rsp,1)
xor edi,edi
mov rsi,rsp
mov edx,1
mov eax,SYS_read
syscall
# exit(0)
xor edi,edi
mov eax,SYS_exit
syscall
超小,但足以看到它做了些什么。现在构建它并从详细输出中获取默认链接描述文件(由====行描述)。
$ gcc -c wait_input.S
$ gcc -o wait_input -nostdlib wait_input.o -Wl,--verbose | awk '!/==/ && p; \
/==/ {p=1-p};' > defaultlinker.x
看一下,我们看到目标文件中只有三个部分(并且只有一个部分包含任何数据),结果可执行文件很小(此时它的ELF标题多于代码)。
$ objdump -h wait_input.o
wait_input.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000001a 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 0000005a 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 0000005a 2**0
ALLOC
$ wc --bytes wait_input
880 wait_input
默认的链接描述文件指的是我在目标文件中没有的所有类型的部分,所以我试图将其削减,但随后突然可执行文件的大小膨胀。稍微玩了一下,我最终发现只删除了两行(对于我的目标文件甚至没有的部分!),导致它:
$ sed -i -e "/build-id/d" defaultlinker.x
$ gcc -nostdlib -o wait_input wait_input.S -Wl,-T defaultlinker.x
$ wc --bytes wait_input
880 wait_input
$ sed -i -e "/interp/d" defaultlinker.x
$ gcc -nostdlib -o wait_input wait_input.S -Wl,-T defaultlinker.x
$ wc --bytes wait_input
2098048 wait_input
,什么?
有人可以解释一下吗?
之前我曾使用微控制器的链接器脚本,而且它们非常直接。我真的很难理解他们的ELF文件。似乎没有什么能与文档相匹配,并且默认的链接描述文件似乎缺少各种重要信息。