[インデックス 18238] ファイルの概要
このコミットは、Goコンパイラツールチェーンの一部であるcmd/link
(Goリンカ)に関連するビルドの問題を修正するものです。具体的には、darwin/amd64
アーキテクチャ向けのリンカのテストデータであるlink.hello.darwin.amd64
という「ゴールデンファイル」が、チェックインされているコードよりも先行していたために発生した問題を解決します。
コミット
commit 6e8b4920c1ce5853d4b1ceb2b7b1149f0a2ba203
Author: Russ Cox <rsc@golang.org>
Date: Mon Jan 13 23:20:53 2014 -0500
cmd/link: fix build
The golden file for link.hello.darwin.amd64
was a little ahead of the checked-in code.
R=iant
TBR=iant
CC=golang-codereviews
https://golang.org/cl/51870043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6e8b4920c1ce5853d4b1ceb2b7b1149f0a2ba203
元コミット内容
cmd/link: fix build
link.hello.darwin.amd64
のゴールデンファイルが、チェックインされているコードよりも少し先行していました。
変更の背景
Goのビルドシステムでは、リンカのようなツールが生成する出力の正確性を検証するために「ゴールデンファイル」というテスト手法が用いられます。ゴールデンファイルは、特定の入力に対してツールが生成すべき期待される出力を事前に記録したものです。テスト実行時には、実際の出力がこのゴールデンファイルの内容と一致するかどうかを比較します。
このコミットの背景にある問題は、src/cmd/link/testdata/link.hello.darwin.amd64
というファイルが、Goリンカのdarwin/amd64
(macOS 64-bit)環境での出力の「正しい」状態を示すゴールデンファイルであったことです。しかし、何らかの理由でこのゴールデンファイルが、現在のGoリンカのコードが生成する出力と一致しない状態になっていました。コミットメッセージにある「The golden file for link.hello.darwin.amd64 was a little ahead of the checked-in code.」という記述は、ゴールデンファイルが将来のリンカの変更を反映して更新されたものの、その変更に対応するリンカのコード自体がまだリポジトリにマージされていないか、あるいは一時的にリバートされた状態であったことを示唆しています。
このような状態では、リンカのテストを実行すると、ゴールデンファイルとの不一致によりテストが失敗し、ビルドが通らなくなります。このコミットは、この不一致を解消し、現在のリンカのコードベースとゴールデンファイルが同期するように修正することで、ビルドが正常に完了するようにすることを目的としています。
前提知識の解説
Goリンカ (cmd/link
)
Goコンパイラツールチェーンにおいて、cmd/link
は非常に重要な役割を担っています。Goのソースコードはまずcmd/compile
によってオブジェクトファイル(.o
ファイル)にコンパイルされます。これらのオブジェクトファイルは、まだ実行可能な形式ではありません。cmd/link
は、これらのオブジェクトファイル、Goランタイムライブラリ、およびその他の必要なライブラリを結合し、最終的な実行可能バイナリを生成する役割を担います。このプロセスには、シンボルの解決、メモリレイアウトの決定、セクションの配置などが含まれます。
ゴールデンファイルテスト (Golden File Testing)
ゴールデンファイルテストは、ソフトウェア開発におけるテスト手法の一つです。特に、コンパイラ、リンカ、コードジェネレータ、画像処理ツールなど、複雑な出力を生成するプログラムのテストで有効です。
- 参照出力の生成: プログラムの正しいバージョン(または特定の機能)が生成する出力(テキスト、バイナリ、画像など)を「ゴールデンファイル」として保存します。
- テスト実行: テスト時には、プログラムを再度実行し、その出力を生成します。
- 比較: 生成された出力とゴールデンファイルの内容をバイト単位または行単位で比較します。
- 結果: 両者が完全に一致すればテストは成功し、不一致があればテストは失敗します。
この手法の利点は、プログラムの出力が意図せず変更されていないことを保証できる点です。欠点は、ゴールデンファイルが古くなったり、意図的な変更があった場合に手動で更新する必要があることです。
darwin/amd64
これは、Goのクロスコンパイルターゲットを示す表記です。
darwin
: オペレーティングシステムがmacOS(旧OS X)であることを示します。amd64
: CPUアーキテクチャが64ビットのAMDまたはIntelプロセッサであることを示します。
Goは強力なクロスコンパイル機能を持ち、開発者は異なるOSやアーキテクチャ向けのバイナリを簡単にビルドできます。cmd/link
は、この指定に基づいて、特定のターゲット環境で実行可能なバイナリを生成します。
Mach-O (Mach Object) ファイルフォーマット
macOS(Darwin)およびiOSで使用される実行可能ファイル、オブジェクトコード、共有ライブラリ、ダイナミックローダブルバンドル、およびコアダンプのファイルフォーマットです。Mach-Oファイルは、ヘッダ、ロードコマンド、セグメント、セクションなどで構成され、プログラムのコード、データ、シンボル情報などが格納されます。Goリンカがdarwin/amd64
向けに生成する実行可能ファイルは、このMach-Oフォーマットに従います。
技術的詳細
このコミットは、src/cmd/link/testdata/link.hello.darwin.amd64
というファイルのバイナリ内容を変更しています。このファイルは、Goリンカがhello.go
のような単純なプログラムをdarwin/amd64
向けにリンクした際に生成される、期待されるMach-Oバイナリのダンプ(またはその一部)です。
差分を見ると、主にファイルの先頭部分、特にオフセット0x10
、0x60
、0x80
、0x90
、0xa0
、0x100
、0x110
、0x120
、0x130
、0x190
、0x1a0
、0x220
付近の16進数値が変更されています。これらのオフセットは、Mach-Oファイルのヘッダやロードコマンド、特にセグメントやセクションのサイズ、オフセット、フラグなどに関する情報が格納されている領域に相当します。
具体的には、以下のような変更が見られます(一部抜粋):
0x10
:d0 02 00 00
から30 02 00 00
へ変更。これは、Mach-Oヘッダ内のsizeofcmds
フィールド(ロードコマンドの合計サイズ)や、セグメントの仮想アドレス空間におけるサイズなど、何らかのサイズ情報が変更された可能性を示唆します。0x60
:38 01 00 00
から98 00 00 00
へ変更。これも同様に、セグメントのサイズやオフセットに関連する値の変更と考えられます。0x80
、0x90
、0xa0
付近:__TEXT
セグメント内のセクション(例:__text
)のサイズやオフセット、フラグなどが変更されています。特に0xa0
の03 00 00 00
が01 00 00 00
に変わっているのは、セクションの属性やフラグの変更を示唆します。0x100
以降:__rodata
セクションや__DATA
セグメントに関連する変更が見られます。特に__rodata
セクションが削除され、__DATA
セグメントの定義が変更されているように見えます。これは、リンカが生成するバイナリのメモリレイアウトやセクション構成が変更されたことを示しています。
これらの変更は、Goリンカの内部的な挙動、例えばメモリ管理、セクションの配置、または特定のランタイムデータの扱いに関する微調整の結果として生じたものと考えられます。ゴールデンファイルが「先行していた」ということは、これらの変更がリンカのコードベースにマージされる前に、誤ってゴールデンファイルが更新されてしまったか、あるいは一時的な実験的な変更がゴールデンファイルに反映されてしまったことを意味します。このコミットは、その不一致を解消するために、ゴールデンファイルを現在のリンカの出力に合わせて「巻き戻し」たものです。
コアとなるコードの変更箇所
このコミットで変更されたファイルは以下の1つのみです。
src/cmd/link/testdata/link.hello.darwin.amd64
このファイルは、Goリンカのテストスイートで使用されるバイナリのゴールデンファイルであり、実際のGoのソースコードではありません。変更内容は、このバイナリファイルの特定のバイト列の修正です。
コアとなるコードの解説
変更されたファイルはバイナリデータ(またはバイナリデータの16進数表現)であるため、通常のソースコードのように「解説」することはできません。しかし、その変更が何を意味するかは、Mach-Oファイルフォーマットの知識と照らし合わせることで推測できます。
差分は、主にMach-Oファイルの以下の部分に影響を与えています。
- Mach-Oヘッダ: ファイルの先頭部分で、CPUタイプ、サブタイプ、ファイルタイプ(実行可能ファイルかライブラリかなど)、ロードコマンドの数とサイズなどの基本的な情報が格納されています。
- ロードコマンド: ヘッダの直後に続き、バイナリの構造を定義する一連のコマンドです。これには、セグメント(
__TEXT
,__DATA
など)の定義、シンボルテーブル、ダイナミックリンカ情報などが含まれます。 - セグメントとセクション: ロードコマンドによって定義される、コードやデータが実際に格納される領域です。例えば、
__TEXT
セグメントには実行可能なコードが、__DATA
セグメントには初期化されたデータが格納されます。
このコミットの変更は、これらのMach-O構造体内の特定のオフセットやサイズを示す値が修正されたことを示しています。例えば、__rodata
セクションが削除され、__DATA
セグメントの構造が変更されたように見えるのは、Goリンカが生成するバイナリのメモリレイアウトやセクションの割り当て方法に微調整があったことを示唆しています。これは、リンカの最適化、新しい機能の追加、または特定のバグ修正の結果として発生する可能性があります。
この修正は、リンカのテストが正しく機能するために不可欠です。ゴールデンファイルが現在のリンカの出力と一致しない場合、テストは常に失敗し、開発者はリンカの変更が意図しない副作用をもたらしたのか、それとも単にゴールデンファイルが古いのかを判断できなくなります。このコミットは、この「テストのノイズ」を取り除き、開発者がリンカの変更を自信を持って進められるようにするためのものです。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- GoのIssue Tracker (Goのバグ報告や機能要望): https://go.dev/issue
- Goのコードレビューシステム (Gerrit): https://go.dev/cl
- このコミットに関連するGerritチェンジリスト: https://golang.org/cl/51870043
参考にした情報源リンク
- Go言語のドキュメント: https://go.dev/doc/
- Goのコンパイラとリンカに関する情報 (Goのソースコード内): https://github.com/golang/go/tree/master/src/cmd/compile および https://github.com/golang/go/tree/master/src/cmd/link
- Mach-Oファイルフォーマットに関するAppleのドキュメント (開発者向け): https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (アーカイブされたドキュメントですが、基本的な概念は有効です)
- ゴールデンファイルテストに関する一般的な情報 (例: Wikipediaやテストフレームワークのドキュメント)