动态链接二进制文件在linux中使用crt吗?



我知道静态链接的二进制文件在链接时使用crt (C Runtime),因为它将cmd参数传递给main,处理TLS存储等。但是,在动态链接的二进制文件中,没有这样的代码,因此在链接时,crt不会链接到它。

但搜索关键词"crt"在ld,glibc甚至linux内核的源代码中,我找不到任何动态链接二进制文件使用crt的线索。

那么这些动态链接的二进制文件如何处理cmd参数传递,TLS初始化等没有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。

最新更新