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

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

このコミットは、Go言語のリンカ(cmd/5l, cmd/6l, cmd/8l)におけるDragonFly BSDのダイナミックリンカのパスに関する修正です。具体的には、ld-elf.so.2のパスが誤っていたのを修正し、一部のアーキテクチャでは一時的にXXXに設定することで、今後の正確なパス設定を促しています。

コミット

commit d0206101c87301fa4ac45d7f0bc7c2dc39a7bc47
Author: Joel Sing <jsing@google.com>
Date:   Sat Aug 31 22:02:21 2013 +1000

    cmd/5l,cmd/6l,cmd/8l: fix dragonflydynld path
    
    R=golang-dev, bradfitz, dave
    CC=golang-dev
    https://golang.org/cl/13225043

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

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

元コミット内容

cmd/5l,cmd/6l,cmd/8l: fix dragonflydynld path

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

変更の背景

このコミットの背景には、Go言語のリンカが様々なオペレーティングシステム(OS)やアーキテクチャに対応する際に、それぞれのOSが使用するダイナミックリンカのパスを正確に指定する必要があるという問題があります。ダイナミックリンカは、プログラムが実行時に必要とする共有ライブラリ(ダイナミックリンクライブラリ、DLLsやShared Objects, SOs)をロードし、プログラムとリンクする役割を担います。

Go言語のリンカは、生成する実行ファイルに、その実行ファイルがどのダイナミックリンカを使用すべきかという情報を埋め込みます。この情報が誤っていると、生成された実行ファイルは正しく共有ライブラリをロードできず、実行に失敗します。

DragonFly BSDは、FreeBSDからフォークしたオープンソースのUnix系オペレーティングシステムであり、独自のパス構造を持つことがあります。以前のGoリンカの実装では、DragonFly BSDのダイナミックリンカのパスが/libexec/ld-elf.so.2と誤って設定されていた可能性があります。しかし、実際のDragonFly BSDシステムでは、このパスが異なる、あるいは特定のアーキテクチャで異なるパスを使用していることが判明したため、この修正が必要となりました。

特に、cmd/5l (ARM), cmd/6l (AMD64), cmd/8l (386) はそれぞれ異なるアーキテクチャに対応するリンカであり、それぞれのリンカが正しいOS固有のダイナミックリンカパスを持つことが重要です。このコミットは、これらのリンカがDragonFly BSD上で生成するバイナリが正しく動作するように、ダイナミックリンカのパスを修正することを目的としています。

前提知識の解説

1. ダイナミックリンカ (Dynamic Linker)

ダイナミックリンカ(またはランタイムリンカ、プログラムローダー)は、オペレーティングシステムの一部であり、プログラムが実行を開始する際に、そのプログラムが依存する共有ライブラリ(ダイナミックリンクライブラリ、Shared Objectsなど)をメモリにロードし、プログラムのアドレス空間にマッピングする役割を担います。これにより、複数のプログラムが同じライブラリのコードを共有でき、メモリ使用量の削減やディスク容量の節約に貢献します。

Unix系システムでは、通常/lib/ld-linux.so.2 (Linux), /usr/libexec/ld-elf.so.1 (FreeBSD), /libexec/ld.elf_so (NetBSD) のようなパスに配置されています。プログラムの実行ファイル(ELF形式など)のヘッダには、どのダイナミックリンカを使用すべきかという情報(インタープリタパス)が埋め込まれています。

2. ELF (Executable and Linkable Format)

ELFは、Unix系オペレーティングシステムで広く使用されている実行ファイル、オブジェクトファイル、共有ライブラリの標準ファイル形式です。ELFファイルは、プログラムコード、データ、シンボルテーブル、セクションヘッダ、プログラムヘッダなど、実行に必要な様々な情報を含んでいます。ダイナミックリンカのパスは、ELFファイルのプログラムヘッダの一部として指定されます。

3. Go言語のリンカ (cmd/5l, cmd/6l, cmd/8l)

Go言語のツールチェインには、各アーキテクチャに対応するリンカが含まれています。

  • cmd/5l: ARMアーキテクチャ用のリンカ
  • cmd/6l: AMD64 (x86-64) アーキテクチャ用のリンカ
  • cmd/8l: 386 (x86) アーキテクチャ用のリンカ

これらのリンカは、Goのソースコードから実行ファイルを生成する際に、OS固有の情報を埋め込む役割も担っています。その情報の一つが、ダイナミックリンカのパスです。

4. DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUnix系オペレーティングシステムです。FreeBSDとは異なるカーネル設計やシステムコンポーネントを採用しており、ファイルシステム(HAMMER)や仮想メモリ管理など、独自の進化を遂げています。そのため、システムパスやライブラリの配置がFreeBSDと異なる場合があります。

5. ld-elf.so.2

ld-elf.so.2は、FreeBSDやDragonFly BSDなどのBSD系システムで一般的に使用されるELF形式のダイナミックリンカのファイル名です。バージョン番号の「2」は、リンカのABI(Application Binary Interface)のバージョンを示しています。

技術的詳細

このコミットは、Go言語のリンカが生成する実行ファイルに埋め込まれるDragonFly BSDのダイナミックリンカのパスを修正しています。具体的には、src/cmd/5l/asm.c, src/cmd/6l/asm.c, src/cmd/8l/asm.cの3つのファイルが変更されています。

これらのファイルには、各OSのダイナミックリンカのパスを定義するグローバル変数が含まれています。例えば、char dragonflydynld[]という変数がそれにあたります。

変更前は、すべてのアーキテクチャでdragonflydynld[] = "/libexec/ld-elf.so.2";と定義されていました。しかし、このパスはDragonFly BSDのすべてのアーキテクチャで正しいとは限りません。

コミットの変更内容は以下の通りです。

  • src/cmd/5l/asm.c (ARMアーキテクチャ用リンカ):

    • char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • から
    • char dragonflydynld[] = "XXX";
    • に変更されています。これは、ARMアーキテクチャにおけるDragonFly BSDの正確なダイナミックリンカパスが不明確であるか、あるいは特定のパスが存在しない可能性を示唆しています。XXXとすることで、このパスが未定義または未検証であることを明示し、今後の修正を促しています。
  • src/cmd/6l/asm.c (AMD64アーキテクチャ用リンカ):

    • char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • から
    • char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
    • に変更されています。これは、AMD64アーキテクチャのDragonFly BSDでは、ダイナミックリンカのパスが/usr/libexec/ld-elf.so.2であることが正しいと判断されたことを意味します。/usr/libexecは、システム管理者がインストールしたプログラムやライブラリが配置される一般的な場所です。
  • src/cmd/8l/asm.c (386アーキテクチャ用リンカ):

    • char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • から
    • char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
    • に変更されています。AMD64と同様に、386アーキテクチャのDragonFly BSDでもダイナミックリンカのパスが/usr/libexec/ld-elf.so.2であることが正しいと判断されました。

この修正により、Go言語でビルドされたDragonFly BSD向けの実行ファイルが、正しいダイナミックリンカを見つけて共有ライブラリをロードできるようになり、実行時のエラーが回避されます。特に、/libexec/usr/libexecの違いは、システムにおける標準的なバイナリの配置場所に関する慣習の違いを反映しており、OSのバージョンや設定によって異なる場合があります。

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

diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 020dbdaae1..33cdf80968 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -41,7 +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";
+char dragonflydynld[] = "XXX";
 
 int32
 entryvalue(void)
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 31c6b83b3a..a09cc9727c 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -43,7 +43,7 @@ char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
 char freebsddynld[] = "/libexec/ld-elf.so.1";
 char openbsddynld[] = "/usr/libexec/ld.so";
 char netbsddynld[] = "/libexec/ld.elf_so";
-char dragonflydynld[] = "/libexec/ld-elf.so.2";
+char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
 
 char	zeroes[32];
 
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 61265daaa2..f7e33b7c6c 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -41,7 +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[] = "/libexec/ld.elf_so";
-char dragonflydynld[] = "/libexec/ld-elf.so.2";
+char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
 
 int32
 entryvalue(void)

コアとなるコードの解説

上記の差分は、Go言語のリンカが使用する、各オペレーティングシステムおよびアーキテクチャに対応するダイナミックリンカのパスを定義している部分です。

  • src/cmd/5l/asm.c (ARM):

    • 変更前: char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • 変更後: char dragonflydynld[] = "XXX";
    • ARMアーキテクチャにおけるDragonFly BSDのダイナミックリンカパスが、一時的にXXXに設定されています。これは、この時点での正確なパスが不明確であるか、あるいは特定のパスが存在しないため、明示的に未定義の状態を示し、今後の調査や修正を促すためのプレースホルダーです。Goのリンカは、このXXXという値を見て、DragonFly BSDのARMバイナリを生成する際に、ダイナミックリンカのパスを埋め込まないか、あるいはエラーを発生させる可能性があります。
  • src/cmd/6l/asm.c (AMD64):

    • 変更前: char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • 変更後: char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
    • AMD64アーキテクチャのDragonFly BSDでは、ダイナミックリンカの正しいパスが/usr/libexec/ld-elf.so.2であることが確認され、修正されました。これにより、AMD64のGoバイナリがDragonFly BSD上で正しく実行されるようになります。
  • src/cmd/8l/asm.c (386):

    • 変更前: char dragonflydynld[] = "/libexec/ld-elf.so.2";
    • 変更後: char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
    • 386アーキテクチャのDragonFly BSDでも、AMD64と同様に、ダイナミックリンカの正しいパスが/usr/libexec/ld-elf.so.2であることが確認され、修正されました。

これらの変更は、Go言語がサポートする各OS/アーキテクチャの組み合わせにおいて、生成されるバイナリがその環境で正しく動作するための重要な調整です。特に、ダイナミックリンカのパスは、プログラムの実行に不可欠な要素であり、誤ったパスが埋め込まれると、プログラムは起動すらできません。この修正は、Go言語のクロスコンパイル機能の正確性と信頼性を向上させるものです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されているhttps://golang.org/cl/13225043は、Gerritの変更リストへのリンクです。)
  • DragonFly BSDのファイルシステム階層に関する情報 (公式ドキュメントやコミュニティフォーラムなど)
  • Unix系システムのダイナミックリンカに関する一般的な情報 (manページ、技術記事など)