Aru*_*mar 8 c gcc dynamic-linking static-linking
我有一个简单的 C 程序。我跑:
$ gcc Q1.c -Wall -save-temps -o Q1
Run Code Online (Sandbox Code Playgroud)
然后我检查生成的可执行文件:
$ objdump -f Q1
Q1: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080483b0
Run Code Online (Sandbox Code Playgroud)
然后我用静态链接编译它:
$ gcc Q1.c -Wall -save-temps -static -o Q1
Run Code Online (Sandbox Code Playgroud)
并再次检查文件:
$ objdump -f Q1
Q1: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048e08
Run Code Online (Sandbox Code Playgroud)
静态链接和动态链接对程序的起始地址有什么影响?起始地址是 的地址main(),对吗?
Fre*_*rdt 11
main(),对吗?不是真的:程序的开始不是真的main()。默认情况下,GCC 将生成起始地址对应于_start符号的可执行文件。您可以通过执行objdump --disassemble Q1. 这里有我的一个简单的程序,只做输出return 0;中main():
0000000000400e30 <_start>:
400e30: 31 ed xor %ebp,%ebp
400e32: 49 89 d1 mov %rdx,%r9
400e35: 5e pop %rsi
400e36: 48 89 e2 mov %rsp,%rdx
400e39: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
400e3d: 50 push %rax
400e3e: 54 push %rsp
400e3f: 49 c7 c0 a0 15 40 00 mov $0x4015a0,%r8
400e46: 48 c7 c1 10 15 40 00 mov $0x401510,%rcx
400e4d: 48 c7 c7 40 0f 40 00 mov $0x400f40,%rdi
400e54: e8 f7 00 00 00 callq 400f50 <__libc_start_main>
400e59: f4 hlt
400e5a: 66 90 xchg %ax,%ax
400e5c: 0f 1f 40 00 nopl 0x0(%rax)
Run Code Online (Sandbox Code Playgroud)
正如你在 address 看到的400e54,_start()依次调用__libc_start_main,它初始化必要的东西(pthreads,atexit,...),最后main()用适当的参数(argc,argv 和 env)调用。
当您要求gcc静态链接时,这意味着我上面提到的所有初始化都必须使用可执行文件中的函数来完成。事实上,如果您查看两个可执行文件的大小,您会发现静态版本要大得多。在我的测试中,静态版本是 800K,而共享版本只有 6K。
额外的函数恰好放在 之前_start(),因此更改了起始地址。这是周围静态可执行文件的布局start():
000000000049e960 r translit_from_tbl
0000000000400a76 t _i18n_number_rewrite
0000000000400bc0 t fini
0000000000400bd0 t init_cacheinfo
0000000000400e30 T _start
0000000000400e60 t deregister_tm_clones
0000000000400e90 t register_tm_clones
0000000000400ed0 t __do_global_dtors_aux
Run Code Online (Sandbox Code Playgroud)
这是共享可执行文件的布局:
00000000004003c0 T _start
00000000004003f0 t deregister_tm_clones
00000000004004b0 T main
00000000004004c0 T __libc_csu_init
00000000006008a0 B _end
0000000000400370 T _init
Run Code Online (Sandbox Code Playgroud)
因此,我得到的起始地址略有不同:静态情况下为 0x400e30,共享情况下为 0x4003c0。