動的リンク
リンカを用いた静的リンクと異なり、実行時にライブラリを読み込む。
バイナリサイズが極めて小さくなり(libcであれば1/100程度)、ライブラリをアップデートしてもプロジェクトを再コンパイルする必要がないという大きな利点がある。
また、仮想メモリを用いているため実メモリにロードされたライブラリを複数のプロセスの仮想アドレス空間にマップしてロードされたものとして利用できる。
次のコードをdisassembleして見ていく。
code:sample.c
int main(void){printf("hello\n");}
objdump -d -j .text a.outでこのコードの部分のアセンブリを読みに行ける。
この中でもmain関数の部分を読むと、次のような形で出力される。
code:result
objdump -d -j .text a.out
...
0000000000001139 <main>:
1139: 55 push %rbp
113a: 48 89 e5 mov %rsp,%rbp
113d: 48 8d 3d c0 0e 00 00 lea 0xec0(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
1144: e8 e7 fe ff ff callq 1030 <puts@plt>
1149: b8 00 00 00 00 mov $0x0,%eax
114e: 5d pop %rbp
114f: c3 retq
...
ここでputs関数(1030番地に存在)は動的リンクするライブラリ内の関数であり、<puts@plt>という表示がそれを表している。
つまりputsは.pltセクションにあるということなので、次は.pltセクションを読みに行く。
code:next
objdump -d -j .plt a.out
セクション .plt の逆アセンブル:
0000000000001020 <.plt>:
1020: ff 35 e2 2f 00 00 pushq 0x2fe2(%rip) # 4008 <_GLOBAL_OFFSET_TABLE_+0x8>
1026: ff 25 e4 2f 00 00 jmpq *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 jmpq *0x2fe2(%rip) # 4018 <puts@GLIBC_2.2.5>
1036: 68 00 00 00 00 pushq $0x0
103b: e9 e0 ff ff ff jmpq 1020 <.plt>