[インデックス 18795] ファイルの概要
このコミットは、Goコンパイラの一部であるcmd/6a
(amd64アーキテクチャ用アセンブラ)に、nacl/amd64p32
ターゲットのサポートを追加するものです。具体的には、nacl/amd64p32
環境でビルドする際に、amd64p32
リンカモデルを使用するように変更を加えています。
コミット
commit e509bbc943e817317e4db04b48f2895bec712c2f
Author: Dave Cheney <dave@cheney.net>
Date: Fri Mar 7 16:02:25 2014 +1100
cmd/6a: add support for nacl/amd64p32
Replaces CL 70000043.
Switch to the amd64p32 linker model if we are building under nacl/amd64p32.
No need to introduce linkarchinit() as 6a contains its own main() function.
LGTM=rsc
R=rsc, minux.ma
CC=golang-codereviews
https://golang.org/cl/72020043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e509bbc943e817317e4db04b48f2895bec712c2f
元コミット内容
cmd/6a
: nacl/amd64p32
のサポートを追加。
CL 70000043を置き換える。
nacl/amd64p32
でビルドしている場合、amd64p32
リンカモデルに切り替える。
6a
は独自のmain()
関数を含んでいるため、linkarchinit()
を導入する必要はない。
変更の背景
このコミットは、GoコンパイラがGoogle Native Client (NaCl) 環境のamd64p32
アーキテクチャを正しくサポートするために行われました。以前の変更(CL 70000043)を置き換え、より適切な方法でnacl/amd64p32
のリンカモデルを適用しています。
nacl/amd64p32
は、64ビットのAMD64命令セットを使用しながら、32ビットのポインタと32ビットのint
/uint
型を持つ特殊なメモリモデルを特徴としていました。Goコンパイラがこの特定の環境向けにバイナリを生成するためには、リンカがこのメモリモデルを認識し、それに合わせて動作する必要がありました。このコミットは、cmd/6a
(Goのamd64アセンブラ/リンカの一部)が、GOARCH=amd64p32
の場合に適切なリンカ設定を適用するように修正することで、この要件を満たしています。
前提知識の解説
cmd/6a
: Goツールチェーンの一部で、AMD64アーキテクチャ向けのアセンブラおよびリンカのフロントエンドです。Goのソースコードがコンパイルされると、最終的な実行可能ファイルを生成するためにこのツールが使用されます。nacl/amd64p32
: Google Native Client (NaCl) は、ウェブブラウザ内でネイティブコードを安全に実行するためのサンドボックス技術です。nacl/amd64p32
は、NaClがサポートしていた特定のアーキテクチャターゲットの一つで、64ビットの命令セットを持ちながら、32ビットのポインタサイズを持つという特徴がありました。これは、メモリ効率とアドレス空間のバランスを取るための設計でした。amd64p32 linker model
:amd64p32
アーキテクチャに特化したリンカの動作モデルです。通常の64ビットシステムとは異なり、ポインタが32ビット幅であるため、リンカはアドレス解決やシンボル配置においてこの制約を考慮する必要があります。linknew
: Goのリンカ内部で使用される関数で、新しいリンカコンテキスト(LinkCtxt
)を初期化します。この関数は、ターゲットアーキテクチャに応じたリンカ設定(LinkArch
)を受け取ります。LinkArch
: リンカが特定のアーキテクチャ(例:amd64
,arm
,amd64p32
など)で動作するために必要な情報(レジスタセット、命令セット、ポインタサイズなど)をカプセル化した構造体です。GOARCH
: Goの環境変数の一つで、ビルドターゲットのアーキテクチャを指定します。例えば、GOARCH=amd64
は64ビットIntel/AMDアーキテクチャを、GOARCH=amd64p32
はamd64p32
アーキテクチャを意味します。main()
関数: C言語やGo言語などのプログラムのエントリポイントとなる関数です。cmd/6a
はそれ自体が独立した実行可能プログラムであるため、独自のmain()
関数を持っています。
技術的詳細
このコミットの主要な目的は、cmd/6a
がnacl/amd64p32
環境でビルドされる際に、適切なリンカモデル(amd64p32
)を使用するようにすることです。
変更前は、cmd/6a
のmain
関数内で、リンカコンテキストの初期化時に常に&linkamd64
(標準のamd64リンカ設定)が使用されていました。
ctxt = linknew(&linkamd64);
このコミットでは、GOARCH
環境変数の値をチェックし、それが"amd64p32"
である場合に、リンカコンテキストの初期化に使用するLinkArch
ポインタを&linkamd64p32
に切り替えるロジックが追加されました。
if(strcmp(p, "amd64p32") == 0)
thelinkarch = &linkamd64p32;
ctxt = linknew(thelinkarch);
これにより、nacl/amd64p32
向けにビルドする際に、リンカが32ビットポインタの特性を正しく処理できるようになります。また、thelinkarch
というグローバル変数(LinkArch*
型)が導入され、リンカの初期化時にこの変数を通じて適切なアーキテクチャ設定が渡されるようになりました。
コミットメッセージにある「No need to introduce linkarchinit() as 6a contains its own main() function.」という記述は、Goの他のツール(例えば、cmd/go
)では、リンカのアーキテクチャ初期化を共通のヘルパー関数(linkarchinit()
のようなもの)で行う場合がありますが、cmd/6a
は独立した実行可能ファイルであり、独自のmain()
関数内で直接リンカの初期化ロジックを制御できるため、そのような共通関数を導入する必要がないことを示しています。
コアとなるコードの変更箇所
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -63,6 +63,8 @@ Lconv(Fmt *fp)
return linklinefmt(ctxt, fp);
}
+LinkArch* thelinkarch = &linkamd64;
+
void
main(int argc, char *argv[])
{
@@ -72,18 +74,20 @@ main(int argc, char *argv[])
thechar = '6';
thestring = "amd64";
- ctxt = linknew(&linkamd64);
- ctxt->diag = yyerror;
- ctxt->bso = &bstdout;
- Binit(&bstdout, 1, OWRITE);
- listinit6();
- fmtinstall('L', Lconv);
-
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
+ if(strcmp(p, "amd64p32") == 0)
+ thelinkarch = &linkamd64p32;
+
+ ctxt = linknew(thelinkarch);
+ ctxt->diag = yyerror;
+ ctxt->bso = &bstdout;
+ Binit(&bstdout, 1, OWRITE);
+ listinit6();
+ fmtinstall('L', Lconv);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
コアとなるコードの解説
-
LinkArch* thelinkarch = &linkamd64;
の追加:lex.c
ファイルの冒頭付近に、LinkArch
型へのポインタであるthelinkarch
というグローバル変数が新しく宣言され、デフォルト値として標準のlinkamd64
(amd64アーキテクチャのリンカ設定)で初期化されています。これは、リンカの初期化時に使用されるアーキテクチャ設定を動的に変更するための準備です。
-
main
関数内のリンカ初期化ロジックの変更:- 変更前は、
main
関数内でctxt = linknew(&linkamd64);
と直接linkamd64
を使用してリンカコンテキストが初期化されていました。 - 変更後、
getgoarch()
関数で取得したGOARCH
の値(変数p
に格納)が"amd64p32"
と一致するかどうかがチェックされます。 - もし一致した場合、
thelinkarch
ポインタは&linkamd64p32
(amd64p32
アーキテクチャのリンカ設定)を指すように更新されます。 - 最終的に、
ctxt = linknew(thelinkarch);
という行で、thelinkarch
が指す先のLinkArch
構造体に基づいてリンカコンテキストが初期化されます。これにより、GOARCH
の値に応じて適切なリンカモデルが選択されるようになります。 - リンカコンテキストの初期化(
ctxt = linknew(...)
)より後の行(ctxt->diag = yyerror;
など)は、if
ブロックの外に移動され、GOARCH
の値に関わらず共通して実行されるようになりました。これは、リンカコンテキストの初期化が完了した後に、診断関数や出力バッファの設定などを行うためです。
- 変更前は、
この変更により、GoのビルドシステムがGOARCH=amd64p32
を指定してcmd/6a
を呼び出した際に、amd64p32
に特化したリンカの挙動が有効になり、NaCl環境向けの正しいバイナリが生成されるようになりました。
関連リンク
- Go CL 72020043: https://golang.org/cl/72020043
参考にした情報源リンク
- Goの
nacl/amd64p32
に関する情報:- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGaGep4u14JQ6F_jb0X-CVaNqbcdrz2AEYaD9pXa2LOs4eCGnEKvaQ8G-Fo-5OdwWYbE-aySplC1EiOcg7TQccniNkD0yGBGjm0S8s_kf7B5matiCeY_aERibprnpwD4l6ecGPr4oMoHf6geBpx5p9CYiU4NiFmmQ-6flYDc64=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHTBKTzjH12jmFEuPYmauHuzRnwH78nGpfHoZfB2cy-3IhoNd0rplsuB7l99KSKgSAekor-ndJZdo8LJeYnPl0VgBEeMG_3m5OAPP5lb6RJrspwOj7cV-qXB2w3NPoKn0n66ApG1R1KAk59MNbIGwZKsIJzBMjh_JZeDHMq0dkbsLzT0lJw7unpYczE_87xvxGPFS8met_3SLas0kmE5-sB5cS4BN7_aCx3YV-3
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGlFRaPGweyLNj0jzt7tMECpskbG0wDsnDcCBcQNrmLGIcXoxhUN8q7XvjkNJ5RbnicsL-jPUBbBiznSI3ELWyfhLEaRKeQqRXfwaYuerhL3ohXjth1pTw2fQil2cUxohM1OwZCsCMijug3pAZaMJw6U7zUtH1YHdS_Zr8buxTd136957og0A==