【发布时间】:2021-05-13 09:03:13
【问题描述】:
考虑以下用于 64 位 linux 的气体(GNU 汇编器)文件
go.s
.global _start
.text
_start:
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # we want return code 0
syscall
现在编译:
rm -f go go.o
as -o go.o go.s
ld -o go -s -nostartfiles go.o
ls -l go # -> 344 bytes
我们得到了 344 字节的超小尺寸。
太棒了!使用 gcc 和单独的ld 命令:
# gcc with separate link
rm -f go go.o
gcc -xassembler -c go.s
ld -s -nostartfiles -o go go.o
ls -l go # -> 344 bytes
但是如何只使用一个 gcc 命令来获得这么小的尺寸?
# single gcc command
rm -f go go.o
gcc -xassembler -s -static -nostartfiles -o go go.s
ls -l go # -> 4400 bytes too big!!!
该死的 4400 字节!哪个单行 gcc 调用将提供 344 个字节?
使用-v 标志运行上述单行...
gcc -v -xassembler -s -static -nostartfiles -o go go.s
... 表明
-nostartfiles 未传递给 collect2 链接命令。
嗯……
所以任务:向我展示给出最小尺寸的单行 gcc 调用!
谢谢。
用-v 标志试验:
gcc -v -xassembler -s -static -nostartfiles -o go go.s
执行以下操作:
as -v --64 -o go.o go.s
# will give 4400 bytes
/usr/lib/gcc/x86_64-linux-gnu/8/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/8/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --build-id -m elf_x86_64 --hash-style=gnu -static -o go -s -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/8/../../.. go.o --start-group -lgcc -lgcc_eh -lc --end-group
在/usr/lib/gcc/x86_64-linux-gnu/8/collect2 命令(上图)中手动添加-nostartfiles(直接在collect2 之后)会得到520 字节的大小。
手动添加-nostartfiles(直接在collect2之后)并删除--build-id会得到344字节的大小。正如我们所见,here、-Wl,--build-id=none 应该删除 build-id。
但是如何指示 gcc 将-nostartfiles 传递给ld 或collect2?
回应 Jester 的评论:
执行以下操作 (-Wl,-nostartfiles):
gcc -Wl,-nostartfiles,--build-id=none -v -xassembler -s -static -nostartfiles -o go go.s
将在collect2 命令的末尾添加-nostartfiles 太远,结果甚至没有创建输出二进制文件go。如何给出命令,以便-nostartfiles 出现在collect2 ... 命令的前面:我知道它有效,如果我手动将-nostartfiles 构造为在开头的标志。
查看here,有人声称-Wl,-nostartfiles 将无法正确处理。但是如果我只是使用gcc -nostartflags ...,那么它不会传递给链接器:Maby this is a bug in gcc??
可能所有代码都被优化掉了……什么都没有留下??见here
【问题讨论】:
-
你试过
-Wl,-nostartfiles吗? -
是的。它确实不工作。
-v标志显示-nostartfiles被添加到collects2链接命令 (/usr/lib/gcc/x86_64-linux-gnu/8/collect2 .... go.o --build-id=none -nostartfiles --start-group -lgcc -lgcc_eh -lc --end-group) 的末尾;结果是:输出二进制文件go甚至没有被创建!!!!!
标签: assembly gcc ld gnu-assembler