[インデックス 19712] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにnacl/arm
アーキテクチャのサポートを導入するものです。具体的には、Native Client (NaCl) 環境でARMプロセッサ上で動作するGoプログラムが、システムコールを適切に実行できるようにするためのアセンブリコード、Goの型定義、および自動生成されたシステムコールラッパーを追加しています。
コミット
commit 837bc4e502e324abe062999fea1a8a07d0f0bdb8
Author: Shenghou Ma <minux@golang.org>
Date: Thu Jul 10 15:15:06 2014 -0400
syscall: nacl/arm support.
LGTM=dave, rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/101620043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/837bc4e502e324abe062999fea1a8a07d0f0bdb8
元コミット内容
このコミットでは、以下の4つの新しいファイルが追加されています。
-
src/pkg/syscall/asm_nacl_arm.s
: このアセンブリファイルは、nacl/arm
アーキテクチャにおける低レベルなシステムコールエントリポイントを提供します。Goランタイムがシステムコールを行う際に呼び出すsyscall·Syscall
関数がここで定義されており、Native Clientサンドボックスへの引数渡しと戻り値の受け取り、およびエラー処理を扱います。 -
src/pkg/syscall/syscall_nacl_arm.go
: このGoファイルは、POSIX系システムで時間表現に一般的に使用されるTimespec
およびTimeval
構造体を定義しています。また、これらの構造体とナノ秒単位の時間を相互変換するためのヘルパー関数(TimespecToNsec
,NsecToTimespec
,TimevalToNsec
,NsecToTimeval
)も含まれており、時間関連のシステムコールを扱う上で不可欠です。 -
src/pkg/syscall/time_nacl_arm.s
: このアセンブリファイルは、Goランタイムの内部タイマー管理に関連するstartTimer
およびstopTimer
関数のスタブを提供し、それぞれtime·startTimer
およびtime·stopTimer
にリダイレクトします。 -
src/pkg/syscall/zsyscall_nacl_arm.go
: このファイルは、mksyscall.pl
スクリプトによって自動生成されたGoコードです。naclClose
,Exit
,naclFstat
,naclRead
,naclSeek
といった特定のNative Clientシステムコールに対するGoラッパー関数が含まれています。これらのラッパーは、asm_nacl_arm.s
で定義された汎用Syscall
関数を適切なシステムコール番号と引数で呼び出します。
変更の背景
このコミットは、Go言語がGoogle Native Client (NaCl) 環境でARMアーキテクチャをサポートするために導入されました。NaClは、ウェブブラウザ内でC/C++コードを安全かつ高性能に実行するためのサンドボックス技術です。当初、NaClはx86アーキテクチャのみをサポートしていましたが、2013年1月にARMサポートが追加されました。
Go 1.3では、NaCl環境でのGoプログラムの実行がサポートされ、特にARMv7Aアーキテクチャ(32ビット)が対象となりました。このコミットは、Goのsyscall
パッケージがNaClのARM環境と適切に連携できるようにするための基盤を提供します。具体的には、GoプログラムがNaClサンドボックス内でファイルI/O、プロセス管理、時間操作などの低レベルなシステム操作を実行できるように、必要なシステムコールインターフェースを実装しています。
これにより、Go開発者はARMベースのデバイス上で動作するNaClアプリケーションを開発できるようになり、Go言語の適用範囲が拡大しました。
前提知識の解説
-
Google Native Client (NaCl): Googleが開発したサンドボックス技術で、ウェブブラウザ(主にGoogle Chrome)内でC/C++などのネイティブコードを安全に実行することを可能にします。NaClは、ソフトウェアベースのフォルト分離(Software-based Fault Isolation: SFI)などの技術を用いて、悪意のあるコードがシステムに損害を与えるのを防ぎながら、ネイティブに近いパフォーマンスを提供します。NaClは、WebAssemblyの登場により現在は非推奨となっていますが、当時はウェブアプリケーションの性能向上に貢献しました。
-
ARMアーキテクチャ: Advanced RISC Machinesの略で、モバイルデバイスや組み込みシステムで広く使用されているRISC(Reduced Instruction Set Computer)ベースのプロセッサアーキテクチャです。低消費電力と高性能を両立できる点が特徴です。
-
Go言語の
syscall
パッケージ: Go言語の標準ライブラリの一部で、オペレーティングシステムの低レベルなプリミティブ(システムコール)にアクセスするためのインターフェースを提供します。ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供するサービスをGoプログラムから呼び出すために使用されます。Go 1.4以降、このパッケージは「ロックダウン」され、新しいコードではgolang.org/x/sys
リポジトリの使用が推奨されていますが、Goランタイム自体は内部的にsyscall
パッケージを広範に利用しています。 -
システムコール (Syscall): オペレーティングシステムが提供するサービスを、ユーザー空間のプログラムがカーネル空間に要求するためのメカニズムです。プログラムが直接ハードウェアにアクセスしたり、他のプロセスと通信したりする際には、システムコールを介してカーネルに処理を依頼します。
-
アセンブリ言語 (Assembly Language): 特定のプロセッサアーキテクチャに特化した低レベルのプログラミング言語です。機械語と1対1に対応しており、ハードウェアを直接制御したり、パフォーマンスが重要な部分を最適化したりする際に使用されます。Goランタイムでは、システムコールの呼び出しや、特定のアーキテクチャに依存する処理のためにアセンブリが用いられることがあります。
技術的詳細
このコミットの核となるのは、GoランタイムがNaClのARM環境でシステムコールをどのように実行するかを定義する点です。
-
asm_nacl_arm.s
: このファイルは、Goのsyscall
パッケージが提供する汎用システムコール関数Syscall
の実装を含んでいます。ARMアーキテクチャでは、システムコールは通常、特定のレジスタにシステムコール番号と引数を設定し、特別な命令(例えばSVC
命令)を実行することでカーネルにトラップします。しかし、NaCl環境では、直接カーネルを呼び出すのではなく、NaClランタイムが提供するサンドボックス化されたインターフェースを介してシステムコールが実行されます。NACL_SYSCALL
およびNACL_SYSJMP
マクロは、NaClのシステムコール呼び出し規約を抽象化しています。MOVW $(0x10000 + ((code)<<5)), R8; BL (R8)
のような命令は、NaClがシステムコールを処理するために使用する特定のメモリ領域(0x10000
をベースアドレスとし、システムコールコードに基づいてオフセットを計算)へのジャンプを生成します。TEXT syscall·Syscall(SB),NOSPLIT,$0-28
は、GoのSyscall
関数のアセンブリ実装です。この関数は、Goのruntime·entersyscall
を呼び出してシステムコールに入る準備をし、引数をARMレジスタ(R0, R1, R2など)にロードし、NaClのシステムコールインターフェースを呼び出します。システムコールからの戻り値はR0とR1に格納され、エラーはR0が負の値の場合に処理されます。最後にruntime·exitsyscall
を呼び出してシステムコールから抜けます。
-
syscall_nacl_arm.go
: このファイルは、Timespec
とTimeval
という2つの重要な構造体を定義しています。これらは、Unix系システムで時間情報を表現するために広く使われるデータ型です。Goのtime
パッケージや他の時間関連のシステムコールがこれらの構造体と連携できるように、NsecToTimespec
やTimespecToNsec
のような変換ヘルパー関数も提供されています。これは、Goの内部的な時間表現(ナノ秒単位のint64
)と、OSが期待する時間構造体との間のブリッジとなります。 -
zsyscall_nacl_arm.go
: このファイルは、mksyscall.pl
スクリプトによって自動生成されるGoコードです。Syscall
関数を直接呼び出す代わりに、naclClose
やnaclRead
のような特定のシステムコールに対するGoラッパー関数を提供します。これにより、Goプログラムはより型安全で使いやすいインターフェースを通じてシステムコールを呼び出すことができます。例えば、naclRead
関数は、ファイルディスクリプタ、バイトスライス、および読み取るバイト数を引数として受け取り、内部でSyscall
を呼び出して実際の読み取り操作を実行します。
コアとなるコードの変更箇所
src/pkg/syscall/asm_nacl_arm.s
#include "../../cmd/ld/textflag.h"
#include "../runtime/syscall_nacl.h"
//
// System call support for ARM, Native Client
//
#define NACL_SYSCALL(code) \
MOVW $(0x10000 + ((code)<<5)), R8; BL (R8)
#define NACL_SYSJMP(code) \
MOVW $(0x10000 + ((code)<<5)), R8; B (R8)
TEXT syscall·Syscall(SB),NOSPLIT,$0-28
BL runtime·entersyscall(SB)
MOVW trap+0(FP), R8
MOVW a1+4(FP), R0
MOVW a2+8(FP), R1
MOVW a3+12(FP), R2
// more args would use R3, and then stack.
MOVW $0x10000, R7
ADD R8<<5, R7
BL (R7)
CMP $0, R0
BGE ok
MOVW $-1, R1
MOVW R1, r1+16(FP)
MOVW R1, r2+20(FP)
RSB $0, R0
MOVW R0, err+24(FP)
BL runtime·exitsyscall(SB)
RET
ok:
MOVW R0, r1+16(FP)
MOVW R1, r2+20(FP)
MOVW $0, R2
MOVW R2, err+24(FP)
BL runtime·exitsyscall(SB)
RET
src/pkg/syscall/syscall_nacl_arm.go
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
type Timespec struct {
Sec int64
Nsec int32
}
type Timeval struct {
Sec int64
Usec int32
}
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int64(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9)
return
}
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int64(nsec / 1e9)
return
}
src/pkg/syscall/zsyscall_nacl_arm.go
// mksyscall.pl -l32 -nacl -arm syscall_nacl.go syscall_nacl_arm.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func naclClose(fd int) (err error) {
_, _, e1 := Syscall(sys_close, uintptr(fd), 0, 0)
if e1 != 0 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Exit(code int) (err error) {
_, _, e1 := Syscall(sys_exit, uintptr(code), 0, 0)
if e1 != 0 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func naclFstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := Syscall(sys_fstat, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func naclRead(fd int, b []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(b) > 0 {
_p0 = unsafe.Pointer(&b[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(sys_read, uintptr(fd), uintptr(_p0), uintptr(len(b)))
n = int(r0)
if e1 != 0 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func naclSeek(fd int, off *int64, whence int) (err error) {
_, _, e1 := Syscall(sys_lseek, uintptr(fd), uintptr(unsafe.Pointer(off)), uintptr(whence))
if e1 != 0 {
err = e1
}
return
}
コアとなるコードの解説
-
src/pkg/syscall/asm_nacl_arm.s
:NACL_SYSCALL
マクロは、NaCl環境でのシステムコール呼び出しのパターンを定義しています。0x10000
はNaClのシステムコールエントリポイントのベースアドレスであり、((code)<<5)
はシステムコール番号に基づいてオフセットを計算します。BL (R8)
は、計算されたアドレスに分岐し、システムコールを実行します。syscall·Syscall
関数は、Goのユーザーコードからシステムコールを呼び出す際の主要なエントリポイントです。BL runtime·entersyscall(SB)
: システムコールに入る前にGoランタイムの状態を調整します。これにより、ガベージコレクションなどのランタイム操作がシステムコール中に中断されないようにします。MOVW trap+0(FP), R8
,MOVW a1+4(FP), R0
,MOVW a2+8(FP), R1
,MOVW a3+12(FP), R2
: Go関数呼び出しのフレームポインタ(FP)からのオフセットを使って、システムコール番号(trap
)と引数(a1
,a2
,a3
)をARMレジスタにロードします。ARMでは、最初の4つの引数はR0からR3レジスタに渡されるのが一般的です。MOVW $0x10000, R7; ADD R8<<5, R7; BL (R7)
: これはNACL_SYSCALL
マクロの展開に相当し、NaClのシステムコールエントリポイントを呼び出します。CMP $0, R0; BGE ok
: システムコールからの戻り値(R0に格納される)をチェックします。NaClのシステムコールでは、エラーが発生した場合、R0に負の値が返されます。- エラー処理 (
MOVW $-1, R1; ... RSB $0, R0; MOVW R0, err+24(FP)
): R0が負の場合、エラーコードをGoのエラー形式に変換し、戻り値として設定します。RSB $0, R0
はR0の符号を反転させ、正のエラーコードにします。 - 成功時の処理 (
MOVW R0, r1+16(FP); MOVW R1, r2+20(FP); MOVW $0, R2; MOVW R2, err+24(FP)
): 成功した場合、R0とR1の戻り値をGoの戻り値(r1
,r2
)に格納し、エラーをnil
に設定します。 BL runtime·exitsyscall(SB)
: システムコールから抜けた後にGoランタイムの状態を復元します。RET
: 関数から戻ります。
-
src/pkg/syscall/syscall_nacl_arm.go
:Timespec
とTimeval
構造体は、秒とナノ秒(またはマイクロ秒)で時間を表現するための標準的な方法を提供します。これらは、stat
構造体やselect
システムコールなど、多くの時間関連のシステムコールで使用されます。TimespecToNsec
やNsecToTimespec
などのヘルパー関数は、Goの内部的な時間表現(ナノ秒単位のint64
)と、OSが期待するこれらの構造体との間のシームレスな変換を可能にします。これにより、Goプログラムは時間関連のシステムコールをより簡単に利用できます。
-
src/pkg/syscall/zsyscall_nacl_arm.go
:naclRead
のような関数は、Goのsyscall
パッケージのユーザーフレンドリーなラッパーです。これらの関数は、Goの型システムを活用し、Syscall
関数への低レベルな呼び出しを抽象化します。Syscall(sys_read, uintptr(fd), uintptr(_p0), uintptr(len(b)))
の部分では、sys_read
というシステムコール番号、ファイルディスクリプタ、読み取りバッファのポインタ、およびバッファの長さをSyscall
関数に渡しています。unsafe.Pointer
は、Goの型安全性を一時的にバイパスして、バイトスライスの基盤となるメモリへのポインタをシステムコールに渡すために使用されます。- 戻り値の
r0
は読み取られたバイト数、e1
はエラーコードを表します。Goの慣例に従い、エラーはerror
インターフェースとして返されます。
関連リンク
- Go Native Client (NaCl) サポート: https://go.dev/doc/go1.3#nacl
- Google Native Client (Wikipedia): https://ja.wikipedia.org/wiki/Google_Native_Client
- ARMアーキテクチャ (Wikipedia): https://ja.wikipedia.org/wiki/ARM%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
- Go言語のシステムコール (golang.org/x/sys): https://pkg.go.dev/golang.org/x/sys
参考にした情報源リンク
- https://go.dev/doc/go1.3#nacl
- https://en.wikipedia.org/wiki/Google_Native_Client
- https://en.wikipedia.org/wiki/ARM_architecture
- https://pkg.go.dev/golang.org/x/sys
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGfrQgzpxFp_SnQF9pFFGK9GV7aIsetDF241GRR5gNB4pe77NVSKpN-B7yu523RYud12pJzOYDoPvCUlzQtgsNHslnetHW9IRBeOZVEwuwY7nJkcXRXJ57DouulxKDTHYcfR6u_zrc0dHS6S5FnExoJSe0Y192M4VokCahcF5HTcgAusyjHVmOgVAQ= (zdnet.com)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGMZJRzTJOxHaKAsU0H5QDK0XAhXoK7gSmg12bqFpIwv99zrgPzj1RMR358AHeJJnpVDGHYup8jXiIQPR-EEFTLSIfRXsFLVbxLtoPT6VzXVNQ9wDg-ptRKss_yyuMHzMN9zNhLQJTSmeH77aQfuhpxHhuTSEducZZh9ICqHxc= (theregister.com)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEkKJIjgf4cKC2KpYQQkm48zskExGbcqdL3TJQtgp-zl0uDsKGEr5dj8x4f0DWwuEbyNNYoAaSdYbFpnfVjnKxAPUgLXDUbAkU668O-umLUV5ZYYnjM_QkdjJv7sAU8y-41uS7wWwf1CGu5u2qk (go.dev)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFWcZve8tEdQjEjVUmkM2UGg5euJyduNfqUSljZZvBCBk731a_FII20oTn8OXZqTA0BVutMosz3pS-t3swynoTaYodXN_v-s4Galo5CUwAGPftOu1J1lNYegyzH03EvQ7Zi (go.dev)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFwzMq0yKn05SgiYqsh8eRn5HlRIrF0MQwwtV4e-pUMbch_AOerDuKCTPHCvhYsir_rGHsG5BNTWTLleUqJM6-B6vGmzat96Qykhm7P6Ns7GRcYfjBRyJ8y_KxqS6oo566cIGydhGCvuzKPiAVL (go.dev)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFiELWuCXVSy4nArN4Mizbfk5NFWnjQHjIik4TD6Et5fFuV0rCi-8lsq25uYLMfM1HGXUueEkif_t5R7wjS4Btqknm7dWq2O_QvIKkE0Rr4IrWvnMglna95Z9Yd5QX_8QQLva1ZZqwL77QsA2g= (wikipedia.org)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHFUXJlrDtDlRLBS1dcMAEuA5NC2jV607neJBGD84SafBbHCKNLOmKE-qkKosCfZ0LWkqHpqEN_gEe5Xaw2u0sov6LwqW55W_s0n3RK0YoNOpvEbYcGFJZRBXHGhg1zig0KyosoPbLh6Kix9U8sop6RElVsJCZvaXmrDkVXijJm (theregister.com)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHUoa4T1WLo6t5p0d9vZWDJCPGyFGKq_dt5A-fdZTk-IEjjFQq5CoDAuIghD2tvQ_ygppYiADiDULdqflEk_KT368WBmmTwoRQQhoa9xySWjW2unvupyYURyRgk5xci_tZyGs-0BprupwOj9I7EwvtNCZn8ryEyS-6gEvfWpG8HsD1B9r1ZOHvEaH0Fv2qc4A== (railway.app)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGz5r3c1L6ZaWPyTxAnE3BUC_WHACKqL7qLBw34u0wlCHRNRgVy58N91gOpRYOslQ34Emm6FkrlpX4ddjXd625tggR79XGTlW12LBopR00F11myC_ZpXFW_zVDEQi6hbazvT0qmZ8kQtpXnjxBY (google.cn)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHtLZiXRSssoE1yrnd3TWZ7Fre_DhLh47nnIvxsXhIrQ7DNBx7Tv9VATZ0SoQPiw9Mse5cL7pfQ2txvjbzKl_hhPS6OOwtO5fYkJmHY6WVoBXFPrMeUeqL35as74qaBNjnr6bQWI6fCQkWxPRKVNzFLl7neV9lQ (leapcell.io)
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEkgK4bQWsTlyXqyXHFEDEdBt95dpK7-F1NzmbS3nUtgjfLg6R55GNRelj3rmWdJsT4k8Y_icbdy7QdhhA5Kuyp-PQ8Ce2NLie5sU52AwPzpfQVKK65Lf-RJwSYmXMRflSiUd6ooVCjA8hlYj8J6w68dojv4zXIfWRaXGE0DrY= (hitzhangjie.pro)