![開始アドレスに対する静的および動的リンクの影響](https://rvso.com/image/31682/%E9%96%8B%E5%A7%8B%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E9%9D%99%E7%9A%84%E3%81%8A%E3%82%88%E3%81%B3%E5%8B%95%E7%9A%84%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AE%E5%BD%B1%E9%9F%BF.png)
簡単な 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()
よね?
答え1
開始アドレスは のアドレスです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)
アドレス を見るとわかるように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 です。