このページの目次
リンカスクリプトと再配置
カバー範囲: ld スクリプト構文 → 再配置タイプ → GOT/PLT 再配置 → リンカリラクセーション → LLD vs GNU ld vs gold → R_AARCH64_ADR_GOT_PAGE 適用: binutils ld, LLD, 静的/動的リンク
再配置: リンカの役割
コンパイル時 (gcc -c):
.o ファイル内に RELA エントリが存在 → 「このアドレスに値を埋め込む必要がある。対象シンボルはこれだ」と記録
例: R_X86_64_PLT32: この 4バイトのオフセットには、シンボルの PLT 番地を埋め込む必要がある
リンク時 (ld):
全 .o の RELA を走査 → シンボルを解決 → 番地を埋め込む
動的シンボルの場合 → .rela.plt を生成 (実行時に ld.so によって解決される)
一般的な再配置タイプ
// x86-64 (AMD64):
R_X86_64_64: 直接の 64ビット絶対番地
R_X86_64_PC32: 32ビット PC
R_X86_64_PLT32: PC32 に類似するが、対象が PLT 内にある
R_X86_64_GOTPCREL: GOT エントリの PC 相対オフセット
R_X86_64_COPY: 共有ライブラリ内の変数をメインプログラムの .bss にコピー
// ARM64 (AArch64):
R_AARCH64_ABS64: 絶対番地
R_AARCH64_ADR_PREL_PG_HI21: PC 相対、
R_AARCH64_ADD_ABS_LO12_NC:
R_AARCH64_LDST64_ABS_LO12_NC: 読み込み/書き込み、ページ内オフセット
R_AARCH64_ADR_GOT_PAGE: GOT エントリの PC 相対、ページ粒度 + 読み込み
ld スクリプト: リンカスクリプト
/* デフォルトの ld スクリプト: /usr/lib/ldscripts/elf_x86_64.x */
SECTIONS
{
/* 開始: コードセグメント (Read + Execute) */
. = 0x400000 + SIZEOF_HEADERS; /* PIE 以外 */
.text : { *(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*) }
/* 読み取り専用データ */
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
. = ALIGN(0x1000);
__init_array_start = .;
.init_array : { *(.init_array) }
__init_array_end = .;
/* 読み書き可能セグメント (次のページから開始) */
. = ALIGN(0x1000);
.data : { *(.data .data.* .gnu.linkonce.d.*) }
.bss : { *(.bss .bss.* .gnu.linkonce.b.*) }
}
LLD vs GNU ld vs gold
| GNU ld (BFD) | gold | LLD (LLVM) | |
|---|---|---|---|
| 速度 | ベンチマーク | 2〜3倍高速 | 3〜5倍高速 |
| メモリ | 高い | より低い | 低い |
| LTO | 対応 (GCC LTO) | 対応 (GCC LTO) | 対応 (ThinLTO) |
| リンカスクリプト | 完全対応 | 一部 | 大部分 |
| デフォルト | 伝統的 | 保守終了 | 将来標準 |
リンカリラクセーション
特定の再配置は「リラクセーション」によって最適化できる:
RISC-V / ARM64 でサポート:
例: R_RISCV_CALL → リンク時にターゲットまでの距離が分かる → より短い命令列を使用
→ call (32ビットオフセット) → jal (20ビットオフセット) 距離が十分であれば
→ コードが短くなり + 高速化
x86 はリラクセーションに対応していない (命令サイズが固定で、最適化の余地がない)
デバッグ
# 再配置テーブルを表示
# デフォルトの ld スクリプトを表示
|
# リンクプロセスのトレース
# 未定義シンボル
|
参考
- ドキュメント:
info ld, ELF spec (System V ABI, Chapter 4) - ソースコード:
binutils/ld/,lld/ELF/ - LWN: "Linker relaxation"
キーワード: relocation, R_X86_64_PLT32, R_AARCH64_ADR_GOT_PAGE, ld script, LLD, gold, linker relaxation