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

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

コミット

commit 72dd01451f58a5b1a1cdd1d92810a8ab0d75d97d
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 11 01:27:03 2013 -0400

    cmd/5l: fix build (define stub machoreloc1)
    
    R=ken2
    CC=golang-dev
    https://golang.org/cl/7694043

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

https://github.com/golang/go/commit/72dd01451f58a5b1a1cdd1d92810a8ab0d75d97d

元コミット内容

このコミットは、Go言語のリンカの一つである cmd/5l のビルドエラーを修正することを目的としています。具体的には、machoreloc1 という関数が定義されていないために発生していたビルド問題を解決するため、この関数のスタブ(仮実装)を定義しています。

変更の背景

この変更が行われた2013年当時、Go言語のリンカはターゲットアーキテクチャごとに異なる名前を持っていました。cmd/5l はARMアーキテクチャ向けのリンカを指していました(現在のGoでは go tool link に統合されています)。

machoreloc1 という関数は、Mach-O形式(macOSなどで使用される実行ファイル形式)におけるリロケーション処理に関連する内部関数です。通常、Mach-O形式の実行ファイルを生成する際に必要となる処理ですが、ARMアーキテクチャ向けのリンカである cmd/5l のビルド環境や特定のコンフィギュレーションにおいて、この machoreloc1 シンボルが期待されるにもかかわらず、その実装が提供されていなかったと考えられます。

このような状況では、リンカのビルドプロセス中に未定義シンボルエラーが発生し、ビルドが失敗します。このコミットは、cmd/5l のビルドを成功させるために、machoreloc1 の最小限のスタブ実装を提供することで、この依存関係の問題を解決しています。スタブ実装は、実際のMach-Oリロケーション処理を行うのではなく、単にビルドエラーを回避するためのプレースホルダーとして機能します。

前提知識の解説

Go言語のリンカ (cmd/5l)

Go言語のビルドプロセスにおいて、リンカはコンパイルされたオブジェクトファイルやライブラリを結合し、実行可能なバイナリを生成する重要な役割を担います。かつてGo言語では、リンカの実行ファイルがターゲットアーキテクチャに基づいて命名されていました。

  • 5l: ARMアーキテクチャ向け
  • 6l: x86-64アーキテクチャ向け
  • 8l: x86-32アーキテクチャ向け

これらの命名規則はGo 1.4で廃止され、現在は go build コマンドの一部として go tool link が内部的に使用されます。リンカは、Goのアーカイブファイルやオブジェクトファイルを読み込み、それらを単一の実行可能バイナリに結合します。-ldflags などのフラグを通じて、ビルド情報(バージョン、コミットハッシュなど)の埋め込み、バイナリサイズの削減(シンボルテーブルやデバッグ情報の削除)、エントリポイントの操作など、様々なビルドオプションを制御できます。

Mach-O形式とリロケーション

Mach-O (Mach Object) は、macOS、iOS、watchOS、tvOSなどのApple製オペレーティングシステムで使用される実行可能ファイル、オブジェクトコード、共有ライブラリ、ダイナミックロード可能コード、およびコアダンプのファイル形式です。WindowsのPE (Portable Executable) やLinuxのELF (Executable and Linkable Format) と同様に、プログラムの実行に必要なコード、データ、メタデータを構造化して格納します。

リロケーション (Relocation) は、コンパイル時にアドレスが確定できないシンボル(例えば、外部ライブラリの関数やグローバル変数)について、プログラムのロード時や実行時に実際のアドレスを解決し、コード内の参照を修正するプロセスです。リンカは、オブジェクトファイル内のリロケーションエントリを読み取り、最終的な実行可能ファイル内で正しいメモリアドレスを指すようにポインタやオフセットを調整します。machoreloc1 のような関数は、このリロケーション処理、特にMach-O形式に特化したリロケーションの計算と適用を担当します。

スタブ関数

スタブ関数 (Stub Function) とは、実際の機能を持たない、あるいは最小限の機能しか持たない仮の関数実装のことです。ソフトウェア開発において、以下のような目的で利用されます。

  • ビルドの成功: まだ実装されていない、または特定のビルド環境では不要な関数が、コンパイルやリンクの段階で参照される場合に、未定義エラーを回避するために使用されます。
  • テスト: 依存するモジュールがまだ完成していない場合や、テスト対象のモジュールから外部への呼び出しをシミュレートする場合に、テスト用のダミーとして使用されます。
  • プレースホルダー: 将来的に実装される機能のインターフェースを定義し、コードの構造を先に構築する際に使用されます。

このコミットにおける machoreloc1 のスタブ実装は、前述の「ビルドの成功」を目的としています。

技術的詳細

このコミットは、src/cmd/5l/asm.c ファイルに machoreloc1 関数のスタブ実装を追加することで、cmd/5l リンカのビルド問題を解決しています。

cmd/5l はARMアーキテクチャ向けのリンカであり、Mach-O形式は主にApple製品のOSで使用されます。通常、ARMアーキテクチャのGoプログラムがMach-O形式で出力されるのは、iOSなどのAppleプラットフォームをターゲットにする場合です。しかし、このコミットが行われた時点では、cmd/5l のビルド環境や構成によっては、Mach-Oリロケーションの完全な実装が不要であるか、あるいはまだ提供されていなかった可能性があります。

それにもかかわらず、リンカのコードベース全体で machoreloc1 シンボルが参照されている場合、その定義がなければビルドエラーが発生します。この問題を回避するため、開発者は machoreloc1 をスタブとして定義することを選択しました。

スタブ実装は以下の特徴を持ちます。

  • int machoreloc1(Reloc *r, vlong sectoff): 関数シグネチャは、リロケーション情報 (Reloc *r) とセクションオフセット (vlong sectoff) を引数として受け取ることが期待されていることを示唆しています。
  • USED(r);USED(sectoff);: これらのマクロは、引数が関数内で使用されていないことによるコンパイラの警告を抑制するために使用されます。これは、この関数が実際の処理を行わないスタブであることを明確に示しています。
  • return -1;: この関数は常に -1 を返します。これは、リロケーション処理が失敗した、あるいはこのコンテキストでは適用できないことを示す一般的なエラーコードとして解釈できます。

このアプローチにより、cmd/5l のビルドは machoreloc1 シンボルが定義されたことで成功するようになりますが、実際のMach-Oリロケーション処理は行われません。これは、cmd/5l がターゲットとする環境でMach-Oリロケーションが不要であるか、あるいは別のメカニズムで処理されることを前提としているためと考えられます。

また、コミットには archreloc 関数と addpltreloc 関数の周辺のインデント修正も含まれています。これらは、新しい machoreloc1 関数の追加に伴うコードの整形、または既存のコードベースのスタイルガイドに合わせた調整である可能性が高いです。

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

src/cmd/5l/asm.c ファイルにおいて、以下の変更が行われました。

--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -295,6 +295,16 @@ elfsetupplt(void)
  	}
 }
 
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+	USED(r);
+	USED(sectoff);
+
+	return -1;
+}
+
+
 int
 archreloc(Reloc *r, Sym *s, vlong *val)
 {
@@ -325,15 +335,16 @@ archreloc(Reloc *r, Sym *s, vlong *val)
  		*val = braddoff((0xff000000U & (uint32)r->add), 
  		                (0xffffff & (uint32)
  		                   ((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
-	return 0;
-}
-return -1;
+\t\treturn 0;\n+\t}\n+\treturn -1;\n }
 
 static Reloc *
 addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
 {
-Reloc *r;\n+\tReloc *r;\n+\n \tr = addrel(plt);\n \tr->sym = got;\n \tr->off = plt->size;\n```

## コアとなるコードの解説

### `machoreloc1` 関数の追加

```c
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+	USED(r);
+	USED(sectoff);
+
+	return -1;
+}

このコードブロックは、machoreloc1 という名前の新しい関数を定義しています。

  • int machoreloc1(Reloc *r, vlong sectoff): この行は関数のシグネチャです。int は戻り値の型が整数であることを示し、Reloc *rvlong sectoff はそれぞれリロケーション情報へのポインタとセクションオフセットを引数として受け取ることを示します。
  • USED(r);USED(sectoff);: これらの行は、引数 rsectoff が関数内で使用されていないことをコンパイラに伝えるためのマクロです。これにより、「未使用の変数」に関する警告が抑制されます。これは、この関数が実際の処理を行わないスタブであることを明確に示しています。
  • return -1;: この行は、関数が常に -1 を返すことを意味します。これは、このスタブ実装が実際のリロケーション処理を行わず、呼び出し元に対して「処理なし」または「エラー」を示す一般的な方法です。

archreloc 関数の修正

@@ -325,15 +335,16 @@ archreloc(Reloc *r, Sym *s, vlong *val)
  		*val = braddoff((0xff000000U & (uint32)r->add), 
  		                (0xffffff & (uint32)
  		                   ((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
-	return 0;
-}
-return -1;
+\t\treturn 0;\n+\t}\n+\treturn -1;\n }

この部分では、archreloc 関数の末尾のインデントと構造が修正されています。元のコードでは return 0; の後に return -1; が続いており、これは到達不能なコードでした。修正後のコードでは、return 0;if ブロックの内部に適切に配置され、その後に return -1; が続くことで、条件に応じた適切な戻り値が返されるようになっています。これは、コードの可読性と正確性を向上させるための整形またはバグ修正の一部と考えられます。

addpltreloc 関数の修正

 static Reloc *
 addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
 {
-Reloc *r;\n+\tReloc *r;\n+\n \tr = addrel(plt);\n \tr->sym = got;\n \tr->off = plt->size;\n```
この部分では、`addpltreloc` 関数内の変数 `r` の宣言のインデントが修正されています。元のコードでは `Reloc *r;` が行頭から始まっていましたが、修正後は適切なインデントが適用されています。また、その後に空行が追加されています。これらは、コードのスタイルと可読性を向上させるための整形変更です。

## 関連リンク

*   [https://github.com/golang/go/commit/72dd01451f58a5b1a1cdd1d92810a8ab0d75d97d](https://github.com/golang/go/commit/72dd01451f58a5b1a1cdd1d92810a8ab0d75d97d)

## 参考にした情報源リンク

*   [Go linker - go.dev](https://go.dev/doc/cmd/go#hdr-Link_packages_and_dependencies)
*   [Go linker flags - codingexplorations.com](https://codingexplorations.com/go-linker-flags/)
*   [What is Mach-O? - stackoverflow.com](https://stackoverflow.com/questions/1000000/what-is-mach-o)
*   [Mach-O Relocation - github.com (golang/go repository)](https://github.com/golang/go/blob/master/src/cmd/link/internal/ld/macho.go)
*   [Go linker `cmd/5l` - googlesource.com](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHokDwn877zKEiiFeTDfxawXN5f2j_8t4B55RsRgq0BxXPSWSXJI7UqPvaWMcrT9928wZqorghWeNuB2WuXFmr1ldm1vjnuo2cqMSfVbB0dqNeaz6JVT2omhKrBCSXtD8FYi7iQTEBX-I7C6CHhp3BeTeaRsmK0PsMEfoKAzg==)
*   [Go linker `cmd/5l` - altoros.com](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHYsvtgOZ8XH32jN7-Mo7sVzE6XenocGvtUUnKL8xl8qAAdUTr02l29-Xq3pNU-fjQU2YcAWR-C48TtaPQULImbluy-L0Qv5SEgB_fcmbtjzg0BMxx1vHNjw6VssBgnlBv7rkXyYyp8ZDjIRF0wc-MmukH15SzECz3A7jStCUG7RC7cEEnJ0HXtOMgm2lSsL0InHor85iKwlw==)