[インデックス 15901] ファイルの概要
このコミットは、Go言語のランタイムとビルドシステムにおいて、FreeBSD/ARMアーキテクチャでのCgo(C言語との相互運用機能)を再有効化することを目的としています。具体的には、go/build
パッケージのCgo有効化マップにfreebsd/arm
を追加し、runtime/cgo
パッケージ内のFreeBSD/ARM向けCgoサポートファイル(gcc_freebsd_arm.c
)に、スレッドローカルストレージ (TLS) の読み取りに関する修正を加えています。
コミット
commit 092b7cfb08f6bc843050c71f1aae9ffbf4b512a5
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Sat Mar 23 03:21:30 2013 +0800
runtime/cgo, go/build: re-enable cgo for FreeBSD/ARM.
R=dave, rsc
CC=golang-dev
https://golang.org/cl/7970043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5
元コミット内容
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index f4a84b8a7f..dc3669c1df 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
"darwin/amd64": true,
"freebsd/386": true,
"freebsd/amd64": true,
+ "freebsd/arm": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 3bcb0b2701..73c990c28f 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <sys/types.h>
+#include <machine/sysarch.h>
#include <pthread.h>\n #include <string.h>\n #include "libcgo.h"\n@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));\n void\n __aeabi_read_tp(void)\n {\n-\t// read @ 0xffff1000\n \t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS\n+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000\n+\t\t// GCC inline asm doesn\'t provide a way to provide a constant\n+\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value\n+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000\n+#error Wrong ARM_TP_ADDRESS!\n+#endif\n \t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else\n+\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif\n \t\t\"mov pc, lr\\n\\t\"\n \t);\n }\n```
## 変更の背景
Go言語は、様々なプラットフォームやアーキテクチャをサポートすることを目指しています。Cgoは、GoプログラムからC言語のコードを呼び出すための重要な機能であり、システムコールや既存のCライブラリを利用する際に不可欠です。FreeBSD/ARM環境においてCgoが以前は無効化されていたか、あるいは適切に機能していなかった可能性があります。
このコミットの背景には、FreeBSD/ARM環境でのGo言語の利用を促進し、Cgoを必要とするアプリケーションがこのプラットフォームで動作できるようにするという目的があります。特に、スレッドローカルストレージ (TLS) の扱いがFreeBSD/ARMの特定のバージョンや設定で問題となっていた可能性があり、その問題を解決することでCgoの安定動作を保証しようとしています。`__aeabi_read_tp`関数は、ARMアーキテクチャにおけるTLSポインタの読み取りに関連するものであり、その実装がFreeBSD/ARMの特定の環境に適合していなかったことが、Cgo無効化の一因であったと考えられます。
## 前提知識の解説
### Cgo
Cgoは、Go言語のプログラムからC言語の関数を呼び出したり、C言語のデータ型を扱ったりするためのGoの機能です。Goのコード内で`import "C"`と記述することでCgoが有効になり、C言語のコードをGoのソースファイル内に直接記述したり、既存のCライブラリをリンクしたりすることができます。Cgoは、OSのシステムコールを直接叩く必要がある場合や、既存の高性能なCライブラリ(例えばグラフィックライブラリや暗号ライブラリなど)を利用したい場合に非常に有用です。
### FreeBSD/ARM
FreeBSDは、UNIXライクなオペレーティングシステムの一つで、堅牢性と高性能を特徴としています。ARMは、Advanced RISC Machineの略で、低消費電力と高性能を両立するプロセッサアーキテクチャです。スマートフォン、タブレット、組み込みシステム、そして近年ではサーバーなど、幅広いデバイスで利用されています。FreeBSD/ARMは、FreeBSDオペレーティングシステムがARMアーキテクチャ上で動作する環境を指します。
### スレッドローカルストレージ (TLS)
スレッドローカルストレージ (TLS) は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを持つための仕組みです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自の値を保持できます。これは、スレッドセーフなプログラミングや、スレッドごとに異なるコンテキストを管理する際に不可欠です。
ARMアーキテクチャでは、TLSポインタの取得方法が複数存在し、OSやコンパイラのバージョンによって異なる場合があります。`__aeabi_read_tp`は、ARM Embedded Application Binary Interface (EABI) で定義されている、TLSポインタを読み取るための関数です。この関数の正確な実装は、ターゲットとなるシステム(この場合はFreeBSD/ARM)のTLSメカニズムに依存します。
### `go/build`パッケージ
`go/build`パッケージは、GoのビルドシステムがGoソースファイルを解析し、ビルドタグ、パッケージパス、Cgoの有効/無効などの情報を取得するために使用されます。このパッケージは、Goのツールチェインがどのようにソースコードを解釈し、コンパイルするかを決定する上で中心的な役割を果たします。`cgoEnabled`マップは、特定のオペレーティングシステムとアーキテクチャの組み合わせ(例: `linux/amd64`、`freebsd/arm`)に対してCgoが有効であるかどうかを定義します。
## 技術的詳細
このコミットの技術的な核心は、FreeBSD/ARM環境におけるTLSポインタの取得方法の調整にあります。
以前の`gcc_freebsd_arm.c`の実装では、`__aeabi_read_tp`関数内でTLSポインタを`0xffff1000`という固定アドレスから読み取ろうとしていました。これは、特定のFreeBSD/ARM環境では有効な方法であったかもしれませんが、より一般的な、あるいは異なるバージョンのFreeBSD/ARMでは問題を引き起こす可能性がありました。
新しい実装では、`ARM_TP_ADDRESS`というプリプロセッサマクロを導入しています。
* `#ifdef ARM_TP_ADDRESS`ブロック内では、`ARM_TP_ADDRESS`が定義されている場合に、その値が`0xffff1000`であることをコンパイル時にチェックしています。これは、特定の環境でTLSポインタが固定アドレスに配置されていることを前提とした最適化または特定の要件に対応するためのものです。もし`ARM_TP_ADDRESS`が定義されていても、その値が`0xffff1000`でなければコンパイルエラーを発生させることで、誤ったアドレスが使用されることを防いでいます。
* `#else`ブロックでは、`ARM_TP_ADDRESS`が定義されていない場合(つまり、TLSポインタが固定アドレスにない場合や、より汎用的な方法が必要な場合)に、ARMアーキテクチャのCP15コプロセッサのレジスタからTLSポインタを読み取る命令`mrc p15, 0, r0, c13, c0, 3`を使用しています。この命令は、ARMv6以降のアーキテクチャでTLSレジスタ(TPIDRURWまたはTPIDRURO)からスレッドIDまたはTLSポインタを読み取るための標準的な方法です。
この変更により、FreeBSD/ARM環境におけるTLSポインタの取得がより堅牢になり、異なるFreeBSDのバージョンやARMプロセッサのバリエーションに対応できるようになります。TLSポインタの正確な取得は、CgoがGoとCの間でデータを安全にやり取りし、特にスレッドローカルなコンテキストを正しく管理するために不可欠です。
また、`src/pkg/go/build/build.go`の変更は、Goのビルドシステムに対して、FreeBSD/ARM環境でCgoが利用可能になったことを明示的に通知するものです。これにより、Goのツールチェインは、このプラットフォームでCgoを使用するGoプログラムを正しくビルドできるようになります。
## コアとなるコードの変更箇所
1. **`src/pkg/go/build/build.go`**:
```diff
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
"darwin/amd64": true,
"freebsd/386": true,
"freebsd/amd64": true,
+ "freebsd/arm": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
```
`cgoEnabled`マップに`"freebsd/arm": true,`が追加されました。
2. **`src/pkg/runtime/cgo/gcc_freebsd_arm.c`**:
```diff
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <sys/types.h>
+#include <machine/sysarch.h>
#include <pthread.h>
#include <string.h>
#include "libcgo.h"
@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
void
__aeabi_read_tp(void)
{\n-\t// read @ 0xffff1000
\t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS
+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+\t\t// GCC inline asm doesn\'t provide a way to provide a constant
+\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value
+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000
+#error Wrong ARM_TP_ADDRESS!
+#endif
\t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else
+\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif
\t\t\"mov pc, lr\\n\\t\"\n );\n }
```
`__aeabi_read_tp`関数の実装が変更され、`ARM_TP_ADDRESS`マクロを用いた条件付きコンパイルと、CP15コプロセッサからのTLSポインタ読み取りが追加されました。また、必要なヘッダーファイル`<sys/types.h>`と`<machine/sysarch.h>`がインクルードされています。
## コアとなるコードの解説
### `src/pkg/go/build/build.go`の変更
`cgoEnabled`マップは、Goのビルドプロセスにおいて、どのOS/アーキテクチャの組み合わせでCgoがサポートされているかを定義します。このマップに`"freebsd/arm": true`を追加することで、GoのツールチェインはFreeBSD/ARM環境でCgoを有効にしてビルドを行うことを許可するようになります。これは、Cgoを利用するGoプログラムがFreeBSD/ARM上でコンパイルされるための前提条件となります。
### `src/pkg/runtime/cgo/gcc_freebsd_arm.c`の変更
このファイルは、FreeBSD/ARM環境におけるCgoランタイムの低レベルな部分、特にCgoがGoランタイムとCコードの間でどのように連携するかを扱います。
`__aeabi_read_tp`関数は、ARMアーキテクチャにおいてスレッドローカルストレージ (TLS) のポインタを読み取るためのABI (Application Binary Interface) 規定の関数です。TLSは、各スレッドが独自のデータを持つことを可能にする重要なメカニズムであり、CgoがCライブラリと連携する際に、スレッド固有のコンテキストを正しく管理するために不可欠です。
変更前は、TLSポインタを`0xffff1000`という固定アドレスから読み取るアセンブリ命令がハードコードされていました。これは、特定のFreeBSD/ARMのセットアップでは機能するかもしれませんが、TLSの配置が異なるシステムでは問題を引き起こす可能性があります。
変更後は、より柔軟で堅牢な方法が導入されました。
* **`#ifdef ARM_TP_ADDRESS`**: このプリプロセッサディレクティブは、`ARM_TP_ADDRESS`というマクロが定義されているかどうかをチェックします。このマクロは、コンパイル時にTLSポインタの固定アドレスが定義されている場合に利用されます。
* **`#if ARM_TP_ADDRESS != 0xffff1000`**: もし`ARM_TP_ADDRESS`が定義されていても、その値が期待される`0xffff1000`と異なる場合、コンパイルエラーを発生させます。これは、ハードコードされたアドレスが誤っている場合に早期に問題を検出するための安全策です。
* **`"ldr r0, =0xffff1000\\n\\t" "ldr r0, [r0]\\n\\t"`**: `ARM_TP_ADDRESS`が`0xffff1000`であると確認された場合、引き続きこの固定アドレスからTLSポインタを読み取ります。これは、特定の環境でのパフォーマンス最適化や、特定のTLS実装への対応のために残されている可能性があります。
* **`#else`**: `ARM_TP_ADDRESS`が定義されていない場合、より汎用的な方法が使用されます。
* **`"mrc p15, 0, r0, c13, c0, 3\\n\\t"`**: このアセンブリ命令は、ARMアーキテクチャのCP15コプロセッサからレジスタを読み取るためのものです。具体的には、`c13, c0, 3`はTLSポインタを保持するシステムレジスタ(通常はTPIDRURWまたはTPIDRURO)を指します。この命令を使用することで、OSやコンパイラのバージョンに依存しない、より標準的な方法でTLSポインタを取得できます。
この修正により、FreeBSD/ARM環境におけるCgoのTLS処理が改善され、GoプログラムがC言語のコードとより安定して連携できるようになります。
## 関連リンク
* **Gerrit Change-ID**: `https://golang.org/cl/7970043` (GoプロジェクトのコードレビューシステムであるGerritへのリンク。このコミットのレビュープロセスや関連する議論の詳細が確認できます。)
## 参考にした情報源リンク
* **ARM Architecture Reference Manual**: ARMプロセッサのCP15コプロセッサとTLSレジスタに関する詳細な情報。
* **FreeBSD Documentation**: FreeBSDにおけるTLSの実装に関する情報。
* **Go Language Documentation (Cgo)**: Go言語のCgo機能に関する公式ドキュメント。
* **ARM EABI (Embedded Application Binary Interface) Specification**: `__aeabi_read_tp`のようなABI規定関数の詳細。
# [インデックス 15901] ファイルの概要
このコミットは、Go言語のランタイムとビルドシステムにおいて、FreeBSD/ARMアーキテクチャでのCgo(C言語との相互運用機能)を再有効化することを目的としています。具体的には、`go/build`パッケージのCgo有効化マップに`freebsd/arm`を追加し、`runtime/cgo`パッケージ内のFreeBSD/ARM向けCgoサポートファイル(`gcc_freebsd_arm.c`)に、スレッドローカルストレージ (TLS) の読み取りに関する修正を加えています。
## コミット
commit 092b7cfb08f6bc843050c71f1aae9ffbf4b512a5 Author: Shenghou Ma minux.ma@gmail.com Date: Sat Mar 23 03:21:30 2013 +0800
runtime/cgo, go/build: re-enable cgo for FreeBSD/ARM.
R=dave, rsc
CC=golang-dev
https://golang.org/cl/7970043
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5](https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5)
## 元コミット内容
```diff
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index f4a84b8a7f..dc3669c1df 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
"darwin/amd64": true,
"freebsd/386": true,
"freebsd/amd64": true,
+ "freebsd/arm": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 3bcb0b2701..73c990c28f 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <sys/types.h>
+#include <machine/sysarch.h>
#include <pthread.h>
#include <string.h>
#include "libcgo.h"
@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
void
__aeabi_read_tp(void)
{\n-\t// read @ 0xffff1000
\t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS
+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+\t\t// GCC inline asm doesn\'t provide a way to provide a constant
+\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value
+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000
+#error Wrong ARM_TP_ADDRESS!
+#endif
\t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else
+\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif
\t\t\"mov pc, lr\\n\\t\"\n );\n }
変更の背景
Go言語は、様々なプラットフォームやアーキテクチャをサポートすることを目指しています。Cgoは、GoプログラムからC言語のコードを呼び出したり、既存のCライブラリを利用する際に不可欠な機能です。FreeBSD/ARM環境においてCgoが以前は無効化されていたか、あるいは適切に機能していなかった可能性があります。
このコミットの背景には、FreeBSD/ARM環境でのGo言語の利用を促進し、Cgoを必要とするアプリケーションがこのプラットフォームで動作できるようにするという目的があります。特に、スレッドローカルストレージ (TLS) の扱いがFreeBSD/ARMの特定のバージョンや設定で問題となっていた可能性があり、その問題を解決することでCgoの安定動作を保証しようとしています。__aeabi_read_tp
関数は、ARMアーキテクチャにおけるTLSポインタの読み取りに関連するものであり、その実装がFreeBSD/ARMの特定の環境に適合していなかったことが、Cgo無効化の一因であったと考えられます。
前提知識の解説
Cgo
Cgoは、Go言語のプログラムからC言語の関数を呼び出したり、C言語のデータ型を扱ったりするためのGoの機能です。Goのコード内でimport "C"
と記述することでCgoが有効になり、C言語のコードをGoのソースファイル内に直接記述したり、既存のCライブラリをリンクしたりすることができます。Cgoは、OSのシステムコールを直接叩く必要がある場合や、既存の高性能なCライブラリ(例えばグラフィックライブラリや暗号ライブラリなど)を利用したい場合に非常に有用です。
FreeBSD/ARM
FreeBSDは、UNIXライクなオペレーティングシステムの一つで、堅牢性と高性能を特徴としています。ARMは、Advanced RISC Machineの略で、低消費電力と高性能を両立するプロセッサアーキテクチャです。スマートフォン、タブレット、組み込みシステム、そして近年ではサーバーなど、幅広いデバイスで利用されています。FreeBSD/ARMは、FreeBSDオペレーティングシステムがARMアーキテクチャ上で動作する環境を指します。
スレッドローカルストレージ (TLS)
スレッドローカルストレージ (TLS) は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを持つための仕組みです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自の値を保持できます。これは、スレッドセーフなプログラミングや、スレッドごとに異なるコンテキストを管理する際に不可欠です。
ARMアーキテクチャでは、TLSポインタの取得方法が複数存在し、OSやコンパイラのバージョンによって異なる場合があります。__aeabi_read_tp
は、ARM Embedded Application Binary Interface (EABI) で定義されている、TLSポインタを読み取るための関数です。この関数の正確な実装は、ターゲットとなるシステム(この場合はFreeBSD/ARM)のTLSメカニズムに依存します。
go/build
パッケージ
go/build
パッケージは、GoのビルドシステムがGoソースファイルを解析し、ビルドタグ、パッケージパス、Cgoの有効/無効などの情報を取得するために使用されます。このパッケージは、Goのツールチェインがどのようにソースコードを解釈し、コンパイルするかを決定する上で中心的な役割を果たします。cgoEnabled
マップは、特定のオペレーティングシステムとアーキテクチャの組み合わせ(例: linux/amd64
、freebsd/arm
)に対してCgoが有効であるかどうかを定義します。
技術的詳細
このコミットの技術的な核心は、FreeBSD/ARM環境におけるTLSポインタの取得方法の調整にあります。
以前のgcc_freebsd_arm.c
の実装では、__aeabi_read_tp
関数内でTLSポインタを0xffff1000
という固定アドレスから読み取ろうとしていました。これは、特定のFreeBSD/ARM環境では有効な方法であったかもしれませんが、より一般的な、あるいは異なるバージョンのFreeBSD/ARMでは問題を引き起こす可能性がありました。
新しい実装では、ARM_TP_ADDRESS
というプリプロセッサマクロを導入しています。
#ifdef ARM_TP_ADDRESS
ブロック内では、ARM_TP_ADDRESS
が定義されている場合に、その値が0xffff1000
であることをコンパイル時にチェックしています。これは、特定の環境でTLSポインタが固定アドレスに配置されていることを前提とした最適化または特定の要件に対応するためのものです。もしARM_TP_ADDRESS
が定義されていても、その値が0xffff1000
でなければコンパイルエラーを発生させることで、誤ったアドレスが使用されることを防いでいます。#else
ブロックでは、ARM_TP_ADDRESS
が定義されていない場合(つまり、TLSポインタが固定アドレスにない場合や、より汎用的な方法が必要な場合)に、ARMアーキテクチャのCP15コプロセッサのレジスタからTLSポインタを読み取る命令mrc p15, 0, r0, c13, c0, 3
を使用しています。この命令は、ARMv6以降のアーキテクチャでTLSレジスタ(TPIDRURWまたはTPIDRURO)からスレッドIDまたはTLSポインタを読み取るための標準的な方法です。
この変更により、FreeBSD/ARM環境におけるTLSポインタの取得がより堅牢になり、異なるFreeBSDのバージョンやARMプロセッサのバリエーションに対応できるようになります。TLSポインタの正確な取得は、CgoがGoとCの間でデータを安全にやり取りし、特にスレッドローカルなコンテキストを正しく管理するために不可欠です。
また、src/pkg/go/build/build.go
の変更は、Goのビルドシステムに対して、FreeBSD/ARM環境でCgoが利用可能になったことを明示的に通知するものです。これにより、Goのツールチェインは、このプラットフォームでCgoを使用するGoプログラムを正しくビルドできるようになります。
コアとなるコードの変更箇所
-
src/pkg/go/build/build.go
:--- a/src/pkg/go/build/build.go +++ b/src/pkg/go/build/build.go @@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{ "darwin/amd64": true, "freebsd/386": true, "freebsd/amd64": true, + "freebsd/arm": true, "linux/386": true, "linux/amd64": true, "linux/arm": true,
cgoEnabled
マップに"freebsd/arm": true,
が追加されました。 -
src/pkg/runtime/cgo/gcc_freebsd_arm.c
:--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include <sys/types.h> +#include <machine/sysarch.h> #include <pthread.h> #include <string.h> #include "libcgo.h" @@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked)); void __aeabi_read_tp(void) {\n-\t// read @ 0xffff1000
\t__asm__ volatile (\n+#ifdef ARM_TP_ADDRESS
+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+\t\t// GCC inline asm doesn't provide a way to provide a constant
+\t\t// to "ldr r0, =??" pseudo instruction, so we hardcode the value
+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000
+#error Wrong ARM_TP_ADDRESS!
+#endif
\t\t"ldr r0, =0xffff1000\n\t"\n \t\t"ldr r0, [r0]\n\t"\n+#else
+\t\t"mrc p15, 0, r0, c13, c0, 3\n\t"\n+#endif
\t\t"mov pc, lr\n\t"\n );\n }
```
__aeabi_read_tp
関数の実装が変更され、ARM_TP_ADDRESS
マクロを用いた条件付きコンパイルと、CP15コプロセッサからのTLSポインタ読み取りが追加されました。また、必要なヘッダーファイル<sys/types.h>
と<machine/sysarch.h>
がインクルードされています。
コアとなるコードの解説
src/pkg/go/build/build.go
の変更
cgoEnabled
マップは、Goのビルドプロセスにおいて、どのOS/アーキテクチャの組み合わせでCgoがサポートされているかを定義します。このマップに"freebsd/arm": true
を追加することで、GoのツールチェインはFreeBSD/ARM環境でCgoを有効にしてビルドを行うことを許可するようになります。これは、Cgoを利用するGoプログラムがFreeBSD/ARM上でコンパイルされるための前提条件となります。
src/pkg/runtime/cgo/gcc_freebsd_arm.c
の変更
このファイルは、FreeBSD/ARM環境におけるCgoランタイムの低レベルな部分、特にCgoがGoランタイムとCコードの間でどのように連携するかを扱います。
__aeabi_read_tp
関数は、ARMアーキテクチャにおいてスレッドローカルストレージ (TLS) のポインタを読み取るためのABI (Application Binary Interface) 規定の関数です。TLSは、各スレッドが独自のデータを持つことを可能にする重要なメカニズムであり、CgoがCライブラリと連携する際に、スレッド固有のコンテキストを正しく管理するために不可欠です。
変更前は、TLSポインタを0xffff1000
という固定アドレスから読み取るアセンブリ命令がハードコードされていました。これは、特定のFreeBSD/ARMのセットアップでは機能するかもしれませんが、TLSの配置が異なるシステムでは問題を引き起こす可能性があります。
変更後は、より柔軟で堅牢な方法が導入されました。
#ifdef ARM_TP_ADDRESS
: このプリプロセッサディレクティブは、ARM_TP_ADDRESS
というマクロが定義されているかどうかをチェックします。このマクロは、コンパイル時にTLSポインタの固定アドレスが定義されている場合に利用されます。#if ARM_TP_ADDRESS != 0xffff1000
: もしARM_TP_ADDRESS
が定義されていても、その値が期待される0xffff1000
と異なる場合、コンパイルエラーを発生させます。これは、ハードコードされたアドレスが誤っている場合に早期に問題を検出するための安全策です。"ldr r0, =0xffff1000\\n\\t" "ldr r0, [r0]\\n\\t"
:ARM_TP_ADDRESS
が0xffff1000
であると確認された場合、引き続きこの固定アドレスからTLSポインタを読み取ります。これは、特定の環境でのパフォーマンス最適化や、特定のTLS実装への対応のために残されている可能性があります。
#else
:ARM_TP_ADDRESS
が定義されていない場合、より汎用的な方法が使用されます。"mrc p15, 0, r0, c13, c0, 3\\n\\t"
: このアセンブリ命令は、ARMアーキテクチャのCP15コプロセッサからレジスタを読み取るためのものです。具体的には、c13, c0, 3
はTLSポインタを保持するシステムレジスタ(通常はTPIDRURWまたはTPIDRURO)を指します。この命令を使用することで、OSやコンパイラのバージョンに依存しない、より標準的な方法でTLSポインタを取得できます。
この修正により、FreeBSD/ARM環境におけるCgoのTLS処理が改善され、GoプログラムがC言語のコードとより安定して連携できるようになります。
関連リンク
- Gerrit Change-ID:
https://golang.org/cl/7970043
(GoプロジェクトのコードレビューシステムであるGerritへのリンク。このコミットのレビュープロセスや関連する議論の詳細が確認できます。)
参考にした情報源リンク
- ARM Architecture Reference Manual: ARMプロセッサのCP15コプロセッサとTLSレジスタに関する詳細な情報。
- FreeBSD Documentation: FreeBSDにおけるTLSの実装に関する情報。
- Go Language Documentation (Cgo): Go言語のCgo機能に関する公式ドキュメント。
- ARM EABI (Embedded Application Binary Interface) Specification:
__aeabi_read_tp
のようなABI規定関数の詳細。 __aeabi_read_tp
on ARM architectures: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEG3OGnagdaVtqPgujqHBw-QJm_k76nvDYD8uePac_20vs-gezl8UcHGakVubu7JeqFaU78sgQ3RKIAhXXPcH-wBhizt7vRDIVaQBSWv3oSODfqzFlYiIhKq1_0Ej26Vj4J3eJ0PVfEf8NxQOsoANPxldh01KdiG2BkWY6mUnwjTof0XO3Tb6P-keAnPlPXTIMH2VBKLEOPUw8=- GNU GCC documentation on TLS access models: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQE2JZ59xvMzggOp_mhVSYjibofbwfensZKtryxwXdnFM06sI1Dekb7p1OrwfuQx_TzYQtY6pktepymfmfOSF07Or52riI64b2CO16pr6Qrnd7wnOy7Y4HhSQUqD2pU1rU-K-LzwZM5wdPGo3rTsfw==
- Stack Overflow discussion on
__aeabi_read_tp
: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGFe6dhh-xNOARezDzEwLzx2Ht-C_H17ziFC3i1XjqqdPHQGTvP9TagMk24hPB8HNGE8fRrTOCA57ZypD6A2BKFU5d2CTzE4lYk13axWQ173tQIVRDPwr4enP_2pc_YnBZyPYKrIbVRZEFrUK_uzpSEDarJUhX-aPk_jqbmqgaFC2zUCNsxinPvNDh9HB3rQt26gV60zg== - ARM Community discussion on TLS: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEnuMDtpob6B_5v-KfAkL-rBLgc3dMQSyrH0uEmEHR-cI0pV77v3CqXTRbAu5gZpptlhfRqB_D1Q3mIzMaJeM4SyNAFRMNOsYI0l8HBjOd07FqiI5fOSztl0dm_jdoU61ifU9PpVThqZeDh7K6C3AnoEU-m9q5X90qzLNDLKM79OgbrTt3HNydZZ-pRzM4DISOEGW1dcGNIq-e-7nVwGmwA9DYdt_tY8g==
- Openwall mailing list on
__aeabi_read_tp
: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFKhVk-hIgVhYrrSj-a3B6YcMMjvdJR5j-LAWdabYLPz5OJn2aWMJEBMV3F8hI6SqXus1On54pYke5B8NZGJg5uadMZj1sxzvEWuE2zzipqOAf4bSmNU0v67dQQ2agkcIk8AN1JpDGk9n-26A== - Musl libc
__aeabi_read_tp
implementation: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFpzMQfuiOJBtqFXtsaXwBopk4zXN3FpvaKGVV0wUh0Ju9X9pR-xI6n_lIWCueEN3cVgUeoKPDFurmBiEsfswBKyrd9IMdVt-bmWlXpFw7Wlzp0Rrv2RCje8GQAgkNVr-wESnbmMGqo_rsvqCJqQBIphAEcXGTevvH6JtqdFoXyo-XRtomeQ8xg_qJZWYd6Mcon6VrX7v3Qxqo1_pHGaZfPWX_bf6gTRyIEX3usIrjh_A==