Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17369] ファイルの概要

このコミットは、Go言語のツールチェインにおけるリンカ (5l および 8l) の修正に関するものです。具体的には、ARMアーキテクチャ向けのリンカ (5l) と386アーキテクチャ向けのリンカ (8l) が、DragonFly BSD環境で正しく動作しない問題を解決します。

コミット

commit e18ed3c111cfeeb6dd6664e9f47cb4a6f935befd
Author: Joel Sing <jsing@google.com>
Date:   Sat Aug 24 01:32:01 2013 +1000

    cmd/5l,cmd/8l: unbreak arm and 386 linkers
    
    Add dragonflydynld to 5l and 8l so that they compile again.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/12739048

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e18ed3c111cfeeb6dd6664e9f47cb4a6f935befd

元コミット内容

cmd/5l,cmd/8l: unbreak arm and 386 linkers

Add dragonflydynld to 5l and 8l so that they compile again.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12739048

変更の背景

このコミットの背景には、Go言語のクロスコンパイルおよび特定のオペレーティングシステム(DragonFly BSD)とアーキテクチャ(ARM、386)の組み合わせにおけるリンカの互換性の問題があります。Go言語は、異なるOSやアーキテクチャ向けにバイナリを生成するクロスコンパイル機能を強力にサポートしていますが、そのためには各ターゲット環境のシステムライブラリや動的リンカのパスをリンカが認識している必要があります。

このコミット以前に、Goのリンカ (5l8l) はDragonFly BSDの動的リンカのパスを認識していなかったため、DragonFly BSD上でARMまたは386アーキテクチャ向けのバイナリをビルドしようとすると、リンカが適切な動的リンカを見つけられずにビルドが失敗していました。これは、Goのツールチェインが新しいOS/アーキテクチャの組み合わせをサポートする際に発生しうる典型的な問題です。

前提知識の解説

リンカ (Linker)

リンカは、コンパイラによって生成されたオブジェクトファイル(機械語コードとデータを含むファイル)を結合し、実行可能なプログラムやライブラリを作成するソフトウェアツールです。リンカの主な役割は以下の通りです。

  1. シンボル解決: オブジェクトファイル間で参照されている関数や変数のアドレスを解決します。
  2. 再配置: コード内のアドレス参照を、最終的なメモリ配置に合わせて調整します。
  3. ライブラリの結合: 静的ライブラリや動的ライブラリをプログラムにリンクします。

Go言語のツールチェインでは、各アーキテクチャに対応する独自のリンカが存在します。例えば、5l はARMアーキテクチャ向けのリンカ、8l は386(x86)アーキテクチャ向けのリンカです。これらはGoのコンパイラ (5g, 8g など) と連携して動作します。

動的リンカ (Dynamic Linker / Runtime Linker)

動的リンカは、プログラムの実行時に共有ライブラリ(ダイナミックリンクライブラリ、DLL、.soファイルなど)をロードし、プログラムとリンクする役割を担います。これにより、複数のプログラムが同じライブラリのコードを共有でき、ディスクスペースの節約やメモリ効率の向上が図られます。

各オペレーティングシステムには、独自の動的リンカが存在し、そのパスや命名規則はOSによって異なります。例えば、Linuxでは /lib/ld-linux.so.2/lib64/ld-linux-x86-64.so.2、FreeBSDでは /usr/libexec/ld-elf.so.1 などが一般的です。

DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUnix系オペレーティングシステムです。高性能とスケーラビリティを目標に開発されており、独自のカーネル設計やファイルシステム(HAMMER)を持っています。他のBSD系OSと同様に、ELF (Executable and Linkable Format) 形式のバイナリを使用し、動的リンカもELF形式の共有ライブラリを扱います。

src/cmd/5l/asm.c および src/cmd/8l/asm.c

これらのファイルは、Go言語のリンカ (5l および 8l) のソースコードの一部です。asm.c という名前が示す通り、アセンブリ言語に関連する処理や、システムコール、特定のOSの動的リンカパスの定義など、低レベルな処理が含まれていることが多いです。Goのリンカは、ターゲットOSの動的リンカのパスをハードコードして持っていることがあり、このコミットはそのようなパスの追加に該当します。

技術的詳細

このコミットの技術的な核心は、Goのリンカが特定のOS(DragonFly BSD)の動的リンカのパスを認識するように修正することです。

Goのリンカは、生成するバイナリが動的リンクを必要とする場合、そのバイナリのヘッダに、実行時に使用すべき動的リンカのパスを埋め込みます。これにより、OSのローダーがプログラムを起動する際に、指定された動的リンカをロードし、必要な共有ライブラリを解決できるようになります。

コミットの変更内容を見ると、src/cmd/5l/asm.csrc/cmd/8l/asm.c の両方に char dragonflydynld[] = "/libexec/ld-elf.so.2"; という行が追加されています。これは、DragonFly BSDにおけるELF形式の動的リンカの標準パスが /libexec/ld-elf.so.2 であることをGoのリンカに教え込むものです。

このパスがリンカに認識されていないと、GoのコンパイラとリンカがDragonFly BSD向けの実行ファイルを生成しようとした際に、動的リンクに必要な情報(特に動的リンカのパス)をバイナリに正しく埋め込むことができません。その結果、ビルドプロセスが失敗するか、生成されたバイナリが実行時に動的ライブラリをロードできずにクラッシュするなどの問題が発生します。

この修正により、GoのリンカはDragonFly BSD環境でARMおよび386アーキテクチャ向けのバイナリを生成する際に、正しい動的リンカのパスをバイナリに埋め込むことができるようになり、ビルドが成功し、生成されたバイナリが正しく実行されるようになります。

コアとなるコードの変更箇所

--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -41,6 +41,7 @@ char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
 char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
 char openbsddynld[] = "XXX";
 char netbsddynld[] = "/libexec/ld.elf_so";
+char dragonflydynld[] = "/libexec/ld-elf.so.2";
 
 int32
 entryvalue(void)
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index ab597a9ab3..61265daaa2 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -41,6 +41,7 @@ char linuxdynld[] = "/lib/ld-linux.so.2";
 char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
 char openbsddynld[] = "/usr/libexec/ld.so";
 char netbsddynld[] = "/usr/libexec/ld.elf_so";
+char dragonflydynld[] = "/libexec/ld-elf.so.2";
 
 int32
 entryvalue(void)

コアとなるコードの解説

変更は非常にシンプルで、src/cmd/5l/asm.csrc/cmd/8l/asm.c の両ファイルに以下の行が追加されています。

char dragonflydynld[] = "/libexec/ld-elf.so.2";

この行は、Goのリンカが認識する動的リンカのパスのリストに、DragonFly BSDの動的リンカのパスを追加しています。

  • char dragonflydynld[]: これは、dragonflydynld という名前の文字列配列(C言語における文字列)を宣言しています。この名前は、他のOSの動的リンカパス(例: linuxdynld, freebsddynld など)と命名規則を合わせています。
  • "/libexec/ld-elf.so.2": これは、DragonFly BSDシステムにおけるELF形式の動的リンカの標準的なファイルパスです。Goのリンカは、ターゲットOSがDragonFly BSDであると判断した場合、このパスを生成する実行ファイルのELFヘッダに埋め込みます。

この変更により、GoのリンカはDragonFly BSD環境で生成されるバイナリが、実行時に正しい動的リンカを見つけられるようになり、結果としてビルドエラーが解消され、生成されたバイナリが正しく動作するようになります。これは、GoがサポートするOSとアーキテクチャの組み合わせを拡張する上で不可欠な修正の一つです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Goのリンカに関するドキュメントや議論 (GoのメーリングリストやIssue Tracker):
  • ELF (Executable and Linkable Format) の仕様に関する情報
  • 動的リンカに関する一般的な情報 (Linux man pages, BSD man pagesなど)
  • DragonFly BSDのファイルシステム階層に関する情報