C

靜態和動態連結對起始地址的影響

  • May 4, 2013

我有一個簡單的 C 程序。我跑:

$ gcc Q1.c -Wall -save-temps -o Q1

然後我檢查生成的執行檔:

$  objdump -f Q1
Q1:     file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080483b0

然後我用靜態連結編譯它:

$ gcc Q1.c -Wall -save-temps -static -o Q1

並再次檢查文件:

$ objdump -f Q1
Q1:     file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048e08

靜態連結和動態連結對程序的起始地址有什麼影響?起始地址是 的地址main(),對吧?

起始地址是 的地址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)

正如您在 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

這是共享執行檔的佈局:

00000000004003c0 T _start
00000000004003f0 t deregister_tm_clones
00000000004004b0 T main
00000000004004c0 T __libc_csu_init
00000000006008a0 B _end
0000000000400370 T _init

結果,我得到的起始地址略有不同:靜態情況下的 0x400e30 和共享情況下的 0x4003c0。

引用自:https://unix.stackexchange.com/questions/74678