我知道静态链接的二进制文件在链接时使用crt (C Runtime),因为它将cmd参数传递给main
,处理TLS存储等。但是,在动态链接的二进制文件中,没有这样的代码,因此在链接时,crt不会链接到它。
但搜索关键词"crt"在ld
,glibc
甚至linux内核的源代码中,我找不到任何动态链接二进制文件使用crt的线索。
无论二进制文件是否与其他库链接或链接。crt总是"静态"的。包含在可执行文件中。
让我们在现实生活中,考虑以下设置:
==> main.c <==
#include <stdio.h>
int main(int argc, char **argv) {
puts(argv[0]);
}
==> compile.sh <==
#!/bin/bash
set -x
gcc -static main.c -o static.out
gcc main.c -o dynamic.out
ldd static.out
ldd dynamic.out
./static.out
./dynamic.out
objdump -D static.out | grep -C10 '<_start>:'
objdump -D dynamic.out | grep -C10 '<_start>:'
./compile.sh
脚本执行输出:
+ gcc -static main.c -o static.out
+ gcc main.c -o dynamic.out
+ ldd static.out
not a dynamic executable
+ ldd dynamic.out
linux-vdso.so.1 (0x00007ffc226e7000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f079878e000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f07989cf000)
+ ./static.out
./static.out
+ ./dynamic.out
./dynamic.out
+ objdump -D static.out
+ grep -C10 '<_start>:'
0000000000401508 <read_encoded_value_with_base.cold>:
401508: 50 push %rax
401509: 67 e8 cb fb ff ff addr32 call 4010da <abort>
000000000040150f <__gcc_personality_v0.cold>:
40150f: 67 e8 c5 fb ff ff addr32 call 4010da <abort>
401515: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
40151c: 00 00 00
40151f: 90 nop
0000000000401520 <_start>:
401520: f3 0f 1e fa endbr64
401524: 31 ed xor %ebp,%ebp
401526: 49 89 d1 mov %rdx,%r9
401529: 5e pop %rsi
40152a: 48 89 e2 mov %rsp,%rdx
40152d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
401531: 50 push %rax
401532: 54 push %rsp
401533: 45 31 c0 xor %r8d,%r8d
401536: 31 c9 xor %ecx,%ecx
+ objdump -D dynamic.out
+ grep -C10 '<_start>:'
1026: ff 25 e4 2f 00 00 jmp *0x2fe4(%rip) # 4010 <_GLOBAL_OFFSET_TABLE_+0x10>
102c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000001030 <puts@plt>:
1030: ff 25 e2 2f 00 00 jmp *0x2fe2(%rip) # 4018 <puts@GLIBC_2.2.5>
1036: 68 00 00 00 00 push $0x0
103b: e9 e0 ff ff ff jmp 1020 <_init+0x20>
Disassembly of section .text:
0000000000001040 <_start>:
1040: f3 0f 1e fa endbr64
1044: 31 ed xor %ebp,%ebp
1046: 49 89 d1 mov %rdx,%r9
1049: 5e pop %rsi
104a: 48 89 e2 mov %rsp,%rdx
104d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1051: 50 push %rax
1052: 54 push %rsp
1053: 45 31 c0 xor %r8d,%r8d
1056: 31 c9 xor %ecx,%ecx
我们可以得知:
- 静态的。out是静态可执行文件
- 动态。out是动态可执行文件
- 两个可执行文件都包含
_start
符号 的代码 _start
符号来源于crt
因此,两个可执行文件都包含crt。