[インデックス 18184] ファイルの概要
このコミットは、Go言語の標準ライブラリ crypto/sha512
パッケージにおけるビルドエラーを修正するものです。具体的には、386
(Intel 80386互換アーキテクチャ、32ビットシステム) 環境でのビルドが失敗する問題に対処しています。SHA512ハッシュ関数のブロック処理の実装において、386
アーキテクチャ向けのアセンブリ実装がまだ存在しないにもかかわらず、ビルドタグによってその実装がコンパイル対象に含まれてしまうことが原因でした。
コミット
commit 9a7fb683599536af53fefba693dceff3810cdc8d
Author: Joel Sing <jsing@google.com>
Date: Tue Jan 7 23:50:31 2014 +1100
crypto/sha512: avoid duplicate block declaration on 386
Unbreak the build - we do not have a sha512 block implementation in
386 assembly (yet).
R=golang-codereviews, dave
CC=golang-codereviews
https://golang.org/cl/48520043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9a7fb683599536af53fefba693dceff3810cdc8d
元コミット内容
crypto/sha512: avoid duplicate block declaration on 386
このコミットメッセージは、crypto/sha512
パッケージにおいて、386
アーキテクチャで重複するブロック宣言を回避することを目的としていることを示しています。具体的には、386
向けのアセンブリ実装が存在しないためにビルドが壊れるのを防ぐ、という内容です。
変更の背景
Go言語の標準ライブラリ crypto/sha512
は、セキュアハッシュアルゴリズムSHA-512の実装を提供します。暗号学的ハッシュ関数は、多くの場合、パフォーマンス向上のために特定アーキテクチャ向けのアセンブリ言語で最適化された実装を持ちます。これは、Goのような高水準言語で書かれたコードよりも、CPUのレジスタや命令セットを直接操作することで、より高速な処理を実現できるためです。
このコミットが行われた時点では、crypto/sha512
パッケージには amd64
(64ビットIntel/AMDアーキテクチャ) 向けのアセンブリ最適化された block
関数(SHA-512のコアとなるブロック処理を行う関数)が存在していました。しかし、386
(32ビットIntel/AMDアーキテクチャ) 向けのアセンブリ実装はまだ準備されていませんでした。
Goのビルドシステムでは、ファイルの先頭に記述される「ビルドタグ」という特殊なコメント行を用いて、特定のファイルがどの環境(OSやアーキテクチャなど)でコンパイルされるべきかを制御します。問題となっていた sha512block_decl.go
ファイルは、アセンブリ実装された block
関数のGo側の宣言(Goコードからアセンブリ関数を呼び出すための宣言)を含んでいました。このファイルには当初 // +build 386 amd64
というビルドタグが付与されており、これは「このファイルは 386
または amd64
アーキテクチャでビルドされるべきである」という意味になります。
386
環境でビルドする際、sha512block_decl.go
がコンパイル対象に含まれるにもかかわらず、対応する 386
向けのアセンブリ実装 (sha512block_386.s
のようなファイル) が存在しないため、リンカが block
関数の定義を見つけられず、ビルドエラーが発生していました。このエラーは「重複する宣言」として報告されることがありますが、実態は「宣言はあるが定義がない」というリンカエラーです。
このコミットの目的は、386
環境でのビルドを「壊さない」こと、つまりビルドエラーを解消することでした。
前提知識の解説
Go言語のビルドタグ (Build Tags)
Go言語には、ソースコードファイルのコンパイルを条件付きで行うための「ビルドタグ」という仕組みがあります。これは、ファイルの先頭に // +build tag1 tag2
のような形式で記述される特殊なコメント行です。ビルドタグは、Goコンパイラがそのファイルをコンパイルに含めるかどうかを決定するために使用されます。
// +build tag1 tag2
: 論理OR条件。tag1
またはtag2
のいずれかが有効な場合にファイルがコンパイルされます。// +build tag1,tag2
: 論理AND条件。tag1
とtag2
の両方が有効な場合にファイルがコンパイルされます。// +build !tag
: 論理NOT条件。tag
が有効でない場合にファイルがコンパイルされます。
一般的なタグには、オペレーティングシステム (linux
, windows
, darwin
など)、アーキテクチャ (amd64
, 386
, arm
など)、Goのバージョン (go1.18
など)、またはカスタムタグがあります。このコミットでは、アーキテクチャタグ 386
と amd64
が使用されています。
SHA-512ハッシュ関数
SHA-512 (Secure Hash Algorithm 512-bit) は、NIST (National Institute of Standards and Technology) によってFIPS PUB 180-4で定義された暗号学的ハッシュ関数の一つです。入力されたデータから固定長の512ビット(64バイト)のハッシュ値(メッセージダイジェスト)を生成します。主な特徴は以下の通りです。
- 一方向性: ハッシュ値から元のデータを復元することは計算上困難です。
- 衝突耐性: 異なる入力から同じハッシュ値が生成されること(衝突)は計算上困難です。
- 雪崩効果: 入力データのごくわずかな変更でも、ハッシュ値が大きく変化します。
SHA-512は、データの完全性検証、デジタル署名、パスワードの保存など、様々なセキュリティ関連の用途で利用されます。内部的には、入力データを固定長のブロックに分割し、各ブロックに対して複雑な一連のビット演算(ビットシフト、論理演算、加算など)を繰り返し適用することでハッシュ値を計算します。このブロック処理は計算負荷が高いため、特にパフォーマンスが求められる環境では、アセンブリ言語による最適化が施されることがあります。
アセンブリ言語による最適化
Go言語は、C言語と同様に、パフォーマンスが重要な部分でアセンブリ言語のコードを組み込むことができます。これは、特に暗号処理や低レベルのシステム操作など、最大限の性能を引き出す必要がある場合に用いられます。アセンブリ言語は特定のCPUアーキテクチャの命令セットに直接対応するため、コンパイラが生成する汎用的な機械語よりも効率的なコードを書くことが可能です。
Goでは、アセンブリコードは .s
拡張子を持つファイルに記述され、Goの関数として呼び出せるようにエクスポートされます。Goのビルドシステムは、これらのアセンブリファイルをGoのソースコードと一緒にコンパイルし、最終的なバイナリにリンクします。
技術的詳細
このコミットの技術的な核心は、Goのビルドタグの挙動と、アセンブリ実装の有無によるリンカの動作にあります。
src/pkg/crypto/sha512/sha512block_decl.go
ファイルは、Goコードからアセンブリで実装された block
関数を呼び出すための宣言を提供します。この宣言は、Goコンパイラに対して「block
という名前の関数が外部(この場合はアセンブリファイル)で定義されている」と伝えます。
変更前のビルドタグ // +build 386 amd64
は、この宣言ファイルが 386
または amd64
のいずれかのアーキテクチャでビルドされる場合にコンパイル対象となることを意味していました。
amd64
環境の場合:sha512block_decl.go
がコンパイルされ、対応するsha512block_amd64.s
(仮称) のようなアセンブリファイルもコンパイル・リンクされます。これにより、block
関数の宣言と定義が揃い、ビルドは成功します。386
環境の場合:sha512block_decl.go
がコンパイルされます。しかし、この時点では386
向けのアセンブリ実装ファイル (sha512block_386.s
のようなファイル) が存在しませんでした。結果として、Goコンパイラはblock
関数の宣言を認識しますが、リンカが最終的なバイナリを生成する際に、その宣言に対応する実体(定義)を見つけることができません。これが「undefined reference toblock
」のようなリンカエラー、またはコミットメッセージにある「duplicate block declaration」という形で報告されるビルドの失敗につながっていました。
このコミットは、sha512block_decl.go
ファイルのビルドタグを // +build amd64
に変更することで、この問題を解決しています。この変更により、sha512block_decl.go
は amd64
アーキテクチャでのみコンパイルされるようになります。
amd64
環境の場合: 以前と同様にコンパイル・リンクが成功します。386
環境の場合:sha512block_decl.go
はコンパイル対象から除外されます。これにより、block
関数のアセンブリ実装が存在しない386
環境では、この関数の宣言自体もコンパイルされなくなります。その結果、リンカが未定義のシンボルを探すこともなくなり、ビルドエラーが解消されます。
386
環境では、アセンブリ最適化された block
関数が利用できないため、Go言語で書かれたフォールバックの実装(通常は sha512.go
などに存在する)が代わりに利用されることになります。これにより、機能的には問題なく動作しますが、パフォーマンスはアセンブリ最適化版に劣る可能性があります。コミットメッセージの「(yet)」という言葉は、将来的に 386
向けのアセンブリ実装が追加される可能性を示唆しています。
コアとなるコードの変更箇所
変更は src/pkg/crypto/sha512/sha512block_decl.go
ファイルの1箇所のみです。
--- a/src/pkg/crypto/sha512/sha512block_decl.go
+++ b/src/pkg/crypto/sha512/sha512block_decl.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build 386 amd64
+// +build amd64
package sha512
コアとなるコードの解説
この変更は、ファイルの先頭にあるビルドタグの行を修正しています。
- 変更前:
// +build 386 amd64
- この行は、このファイルが
386
またはamd64
のいずれかのアーキテクチャでビルドされる場合にコンパイル対象となることを示していました。
- この行は、このファイルが
- 変更後:
// +build amd64
- この行は、このファイルが
amd64
アーキテクチャでのみコンパイル対象となることを示しています。
- この行は、このファイルが
このシンプルな変更により、386
環境でビルドする際に、アセンブリ実装が存在しない block
関数の宣言がコンパイルされることを防ぎ、結果としてビルドエラーを解消しています。386
環境では、このファイルがスキップされるため、block
関数のGo言語による純粋な実装が使用されることになります。
関連リンク
- Go言語のビルドタグに関する公式ドキュメント: https://pkg.go.dev/cmd/go#hdr-Build_constraints
- SHA-512に関するNISTのFIPS PUB 180-4: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
- Go言語におけるアセンブリの利用 (Go Assembly): https://go.dev/doc/asm
参考にした情報源リンク
- Go言語の公式ドキュメント
- SHA-512の仕様に関する公開情報
- Go言語のビルドシステムに関する一般的な知識
- コミットメッセージと差分情報
- Goのソースコードリポジトリ (golang/go)
- Go Code Review (golang.org/cl)
- GoのIssue Tracker (golang.org/issue) (このコミットに関連するIssueが存在する可能性)