リンカ
複数のオブジェクトファイルを 1 つにまとめ、 シンボルの参照を解決する。
main.o ( printf を呼んでいるが、実体を知らない )
utils.o
libc.a ( printf の実体がある )
↓ リンカ
a.out2 つの仕事#
シンボル解決#
「どこかで定義された printf を使う」という
未定義参照を、実際の定義に結びつける。
見つからなければ undefined reference to 'printf'。
定義が 2 つあれば multiple definition。
リンク時のエラーの大半はこの 2 つ。
再配置#
各オブジェクトファイルは「アドレス 0 から始まる」前提で アセンブルされている。 統合するとき、実際の配置に合わせて アドレスを書き換える。
再配置情報(.rela セクション)に
「ここを、このシンボルのアドレスで埋めよ」と記録されている。
動的リンク#
実行時に共有ライブラリを解決する。
| 仕組み | 役割 |
|---|---|
| PLT | 関数呼び出しの中継地点 |
| GOT | 実際のアドレスを入れる表 |
初回呼び出し時に解決してGOT に書き込み、 2 回目以降は直接飛ぶ(遅延束縛)。 使わない関数を解決しない分、起動が速くなる。
リンク時最適化 (LTO)#
通常、最適化はファイル単位で行われるので、 ファイルをまたいだインライン展開ができない。
LTO はコンパイル時に中間表現を保存しておき、 リンク時にプログラム全体を見て最適化する。 効果は大きいが、リンクが非常に遅くなる。
参考文献#
- John R. Levine. Linkers and Loaders. Morgan Kaufmann, 1999.
- Randal E. Bryant, David R. O’Hallaron. Computer Systems: A Programmer’s Perspective, 3rd ed. Pearson, 2016. https://csapp.cs.cmu.edu/
- Tool Interface Standard (TIS). Executable and Linking Format (ELF) Specification, v1.2. https://refspecs.linuxfoundation.org/elf/elf.pdf