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

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

このコミットは、Go言語のsyscallパッケージにおいて、FreeBSDオペレーティングシステム向けのメモリ保護(PROT_*)およびメモリマッピング(MAP_*)に関連する定数を追加するものです。これにより、GoプログラムがFreeBSD上でmmapmprotectといったシステムコールをより適切に利用できるようになります。具体的には、src/pkg/syscall/mkerrors.shスクリプトが更新され、FreeBSDのヘッダーファイルからこれらの定数が自動生成されるようになりました。影響を受けるファイルは、zerrors_freebsd_386.gozerrors_freebsd_amd64.gozerrors_freebsd_arm.goなど、FreeBSDの各アーキテクチャ向けの定数定義ファイルです。

コミット

commit 9dd92d522ff771ec4434952ab44660fa1f13b846
Author: Dave Cheney <dave@cheney.net>
Date:   Sat Mar 9 16:25:30 2013 +1100

    syscall: add PROT_* and MAP_* constants to freebsd
    
    Update #4929
    
    Regenerated from FreeBSD-9.1 for amd64 and 386, FreeBSD-CURRENT for arm.
    
    R=devon.odell, minux.ma, rsc
    CC=golang-dev
    https://golang.org/cl/7438053

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

https://github.com/golang/go/commit/9dd92d522ff771ec4434952ab44660fa1f13b846

元コミット内容

syscall: add PROT_* and MAP_* constants to freebsd

Update #4929

Regenerated from FreeBSD-9.1 for amd64 and 386, FreeBSD-CURRENT for arm.

変更の背景

Go言語のsyscallパッケージは、Goプログラムがオペレーティングシステム(OS)のシステムコールを直接呼び出すためのインターフェースを提供します。これにより、OS固有の機能や低レベルな操作が可能になります。しかし、特定のOSやアーキテクチャにおいて、必要な定数やシステムコール定義が不足している場合があります。

このコミットの背景には、GoプログラムがFreeBSD上でメモリマッピング(mmap)やメモリ保護(mprotect)といったシステムコールを正確に利用するために必要なPROT_*(メモリ保護フラグ)およびMAP_*(メモリマッピングフラグ)定数が、syscallパッケージのFreeBSD向け定義に欠けていたという問題があります。これらの定数が不足していると、GoプログラムからFreeBSDのメモリ管理機能を適切に制御することができませんでした。

コミットメッセージにあるUpdate #4929は、GoのIssueトラッカーにおけるIssue 4929: syscall: add PROT_, MAP_ constants to freebsdに対応しています。このIssueでは、FreeBSDのmmap(2)およびmprotect(2)システムコールで使用される定数がGoのsyscallパッケージに存在しないことが報告されており、その追加が求められていました。

前提知識の解説

システムコール (System Call)

システムコールは、ユーザー空間で実行されるプログラムが、カーネル空間で提供されるOSのサービスを利用するためのインターフェースです。ファイルI/O、プロセス管理、メモリ管理、ネットワーク通信など、OSが提供するほとんどの機能はシステムコールを通じてアクセスされます。Go言語のsyscallパッケージは、これらのシステムコールをGoプログラムから直接呼び出すための低レベルなAPIを提供します。

mmapmprotectシステムコール

  • mmap(2): メモリマップドファイル(memory-mapped file)を作成するためのシステムコールです。ファイルの内容をプロセスのアドレス空間に直接マッピングすることで、ファイルI/Oを通常のメモリアクセスとして扱うことができます。これにより、ファイルの内容を読み書きする際に、read()write()のようなシステムコールを介さずに、ポインタを介したメモリ操作で直接アクセスできるようになり、効率的なデータ処理が可能になります。また、ファイルだけでなく、匿名メモリ領域(ファイルに関連付けられていないメモリ領域)を確保するためにも使用されます。
  • mprotect(2): プロセスのアドレス空間内の指定されたメモリ領域の保護属性を変更するためのシステムコールです。メモリ領域を読み取り可能(PROT_READ)、書き込み可能(PROT_WRITE)、実行可能(PROT_EXEC)、またはアクセス不可(PROT_NONE)に設定することができます。これは、セキュリティの強化や、JITコンパイラなどで動的に生成されたコードの実行を許可する際などに利用されます。

PROT_*定数

PROT_*定数は、mmapmprotectシステムコールでメモリ領域に設定する保護属性を定義します。

  • PROT_NONE: アクセス不可。
  • PROT_READ: 読み取り可能。
  • PROT_WRITE: 書き込み可能。
  • PROT_EXEC: 実行可能。

これらの定数はビットフラグとして組み合わせて使用できます(例: PROT_READ | PROT_WRITE)。

MAP_*定数

MAP_*定数は、mmapシステムコールでメモリ領域をマッピングする際の動作を制御するフラグです。

  • MAP_SHARED: マッピングされたメモリ領域への変更が、そのメモリ領域を共有する他のプロセスや、元のファイルに反映されることを意味します。
  • MAP_PRIVATE: マッピングされたメモリ領域への変更が、呼び出し元のプロセスにのみ影響し、他のプロセスや元のファイルには反映されないことを意味します。これは「コピーオンライト」メカニズムによって実現されます。
  • MAP_ANON または MAP_ANONYMOUS: ファイルではなく、匿名メモリ領域をマッピングすることを示します。これは、プロセスが共有メモリやプライベートなヒープ領域を確保する際によく使用されます。
  • MAP_FIXED: 指定されたアドレスに正確にマッピングすることを試みます。
  • MAP_STACK: スタック領域として使用されるメモリ領域をマッピングすることを示します。

Goのsyscallパッケージと定数生成

Goのsyscallパッケージは、各OSおよびアーキテクチャ固有のシステムコール定数や構造体を定義しています。これらの定数は、手動で記述されるのではなく、通常はOSのCヘッダーファイルから自動生成されます。これは、OSのバージョンアップやパッチによって定数の値が変更された場合に、手動でGoのコードを更新する手間を省き、正確性を保つためです。

Goのソースコード内には、mkerrors.shmksyscall.shといったスクリプトが存在し、これらがCヘッダーファイルを解析してGoの定数定義ファイルを生成します。生成されたファイルは、通常zerrors_*.gozsysnum_*.goといった命名規則に従います。

クロスコンパイルとアーキテクチャ固有の定数

Goはクロスコンパイルを強力にサポートしており、あるOS/アーキテクチャ上で別のOS/アーキテクチャ向けのバイナリを生成できます。システムコール定数はOSだけでなく、CPUアーキテクチャ(例: amd64, 386, arm)によっても値が異なる場合があります。そのため、syscallパッケージでは、各OSとアーキテクチャの組み合わせごとに異なる定数定義ファイル(例: zerrors_freebsd_amd64.go, zerrors_freebsd_386.go, zerrors_freebsd_arm.go)が用意されています。

技術的詳細

このコミットの主要な技術的変更点は、FreeBSD向けのPROT_*およびMAP_*定数をGoのsyscallパッケージに追加することです。これは、src/pkg/syscall/mkerrors.shスクリプトの変更と、それによって再生成されたFreeBSD固有の定数定義ファイルによって実現されています。

  1. mkerrors.shの変更: mkerrors.shスクリプトは、Goのsyscallパッケージで利用されるOS固有の定数をCヘッダーファイルから抽出・生成するためのシェルスクリプトです。このコミットでは、mkerrors.sh内のincludes_FreeBSD変数に、FreeBSDのsys/mman.hヘッダーファイルが追加されました。 sys/mman.hは、mmapmprotectシステムコールに関連する定数(PROT_*, MAP_*など)を定義しているヘッダーファイルです。このヘッダーファイルがmkerrors.shの処理対象に追加されたことで、スクリプトが実行される際にこれらの定数がGoのコードとして自動生成されるようになります。

  2. 定数定義ファイルの再生成: mkerrors.shの変更後、FreeBSDの各アーキテクチャ(amd64, 386, arm)向けに以下のファイルが再生成されました。

    • src/pkg/syscall/zerrors_freebsd_386.go
    • src/pkg/syscall/zerrors_freebsd_amd64.go
    • src/pkg/syscall/zerrors_freebsd_arm.go

    これらのファイルには、PROT_EXEC, PROT_NONE, PROT_READ, PROT_WRITEといったPROT_*定数と、MAP_ANON, MAP_ANONYMOUS, MAP_COPY, MAP_FILE, MAP_FIXED, MAP_PRIVATE, MAP_SHARED, MAP_STACKといったMAP_*定数が追加されています。これらの定数は、FreeBSDのシステムヘッダーファイルで定義されている値に対応しています。

    また、これらの主要な定数以外にも、FreeBSDのバージョン9.1(amd64および386向け)とFreeBSD-CURRENT(arm向け)から、他の多くのシステムコール関連定数(例: B*BIOC*BPF_T_*DLT_*IFF_*IFT_*IPPROTO_*MADV_*MSG_*MS_*NET_RT_*NOTE_*O_*RLIMIT_*RT_*RUSAGE_*SIOC*SO_*TCP_*TIOC*V*W*など)が追加または更新されています。これは、mkerrors.shが広範な定数を抽出する能力を持っているためです。

  3. zsysnum_freebsd_*.goの変更: zsysnum_freebsd_386.go, zsysnum_freebsd_amd64.go, zsysnum_freebsd_arm.goファイルも更新されています。これらのファイルはシステムコール番号を定義しており、このコミットでは新しいシステムコール(例: SYS_CLOCK_GETCPUCLOCKID2, SYS_WAIT6)や既存のシステムコールの引数型(SYS_CAP_NEWu_int64_tからuint64_tへの変更)が反映されています。これは、FreeBSDのシステムコールインターフェースの進化に対応するためのものです。

この変更により、GoプログラムはFreeBSD上でメモリマッピングやメモリ保護を必要とする高度な操作を、Goのsyscallパッケージを通じて直接、かつ正確に行えるようになります。

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

このコミットで変更された主要なファイルは以下の通りです。

  • src/pkg/syscall/mkerrors.sh: 定数生成スクリプト
  • src/pkg/syscall/zerrors_freebsd_386.go: FreeBSD/386アーキテクチャ向けエラー・定数定義
  • src/pkg/syscall/zerrors_freebsd_amd64.go: FreeBSD/amd64アーキテクチャ向けエラー・定数定義
  • src/pkg/syscall/zerrors_freebsd_arm.go: FreeBSD/armアーキテクチャ向けエラー・定数定義
  • src/pkg/syscall/zsysnum_freebsd_386.go: FreeBSD/386アーキテクチャ向けシステムコール番号定義
  • src/pkg/syscall/zsysnum_freebsd_amd64.go: FreeBSD/amd64アーキテクチャ向けシステムコール番号定義
  • src/pkg/syscall/zsysnum_freebsd_arm.go: FreeBSD/armアーキテクチャ向けシステムコール番号定義

変更の概要:

  • src/pkg/syscall/mkerrors.sh:

    • includes_FreeBSD変数に#include <sys/mman.h>が追加されました。これにより、sys/mman.hで定義されている定数(PROT_*, MAP_*など)が生成対象に含まれるようになります。
  • src/pkg/syscall/zerrors_freebsd_386.go, src/pkg/syscall/zerrors_freebsd_amd64.go, src/pkg/syscall/zerrors_freebsd_arm.go:

    • PROT_EXEC, PROT_NONE, PROT_READ, PROT_WRITEなどのPROT_*定数が追加されました。
    • MAP_ANON, MAP_ANONYMOUS, MAP_COPY, MAP_FILE, MAP_FIXED, MAP_HASSEMAPHORE, MAP_NOCORE, MAP_NORESERVE, MAP_NOSYNC, MAP_PREFAULT_READ, MAP_PRIVATE, MAP_RENAME, MAP_RESERVED0080, MAP_RESERVED0100, MAP_SHARED, MAP_STACKなどのMAP_*定数が追加されました。
    • その他、FreeBSDのバージョンアップに伴う多数の新しい定数や既存定数の値の更新が行われました。例えば、DLT_*IFF_*IPPROTO_*TCP_*など、多岐にわたる定数が追加・更新されています。
    • ELASTエラーコードの値が更新され、新しいエラーコードECAPMODEが追加されました。
  • src/pkg/syscall/zsysnum_freebsd_386.go, src/pkg/syscall/zsysnum_freebsd_amd64.go, src/pkg/syscall/zsysnum_freebsd_arm.go:

    • 新しいシステムコール番号(例: SYS_CLOCK_GETCPUCLOCKID2, SYS_WAIT6)が追加されました。
    • SYS_CAP_NEWシステムコールの引数型がu_int64_tからuint64_tに変更されました。
    • ARMアーキテクチャ向けには、SYS_CAP_RIGHTS_GET, SYS_CAP_RIGHTS_LIMIT, SYS_CAP_IOCTLS_LIMIT, SYS_CAP_IOCTLS_GET, SYS_CAP_FCNTLS_LIMIT, SYS_CAP_FCNTLS_GETなどの新しいシステムコールが追加されています。

コアとなるコードの解説

src/pkg/syscall/mkerrors.shの変更

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -43,6 +43,7 @@ includes_FreeBSD='\
 #include <sys/socket.h>\
 #include <sys/sockio.h>\
 #include <sys/sysctl.h>\
+#include <sys/mman.h>\
 #include <sys/wait.h>\
 #include <sys/ioctl.h>\
 #include <net/bpf.h>\

この変更は、mkerrors.shスクリプトがFreeBSDのシステムコール定数を生成する際に参照するCヘッダーファイルのリストに、<sys/mman.h>を追加するものです。 mkerrors.shは、includes_FreeBSD変数に定義されたCヘッダーファイルを読み込み、その中に定義されているマクロや定数をGoのコードに変換します。<sys/mman.h>は、mmap(2)mprotect(2)システムコールで使用されるPROT_*MAP_*といったメモリマッピング関連の定数を定義しています。この行が追加されたことで、スクリプトが実行されるたびに、これらの重要な定数がGoのsyscallパッケージに自動的に取り込まれるようになります。これにより、GoプログラムがFreeBSDのメモリ管理機能をより完全に利用できるようになります。

src/pkg/syscall/zerrors_freebsd_386.go (amd64, armも同様) の変更

--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/pkg/syscall/zerrors_freebsd_386.go
@@ -92,6 +92,31 @@ const (
 	AF_VENDOR45                       = 0x81
 	AF_VENDOR46                       = 0x83
 	AF_VENDOR47                       = 0x85
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B460800                           = 0x70800
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B921600                           = 0xe1000
+	B9600                             = 0x2580
 	BIOCFEEDBACK                      = 0x8004427c
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
...
@@ -867,10 +973,44 @@ const (
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
 	IP_UNBLOCK_SOURCE                 = 0x49
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
 	LOCK_UN                           = 0x8
+	MADV_AUTOSYNC                     = 0x7
+	MADV_CORE                         = 0x9
+	MADV_DONTNEED                     = 0x4
+	MADV_FREE                         = 0x5
+	MADV_NOCORE                       = 0x8
+	MADV_NORMAL                       = 0x0
+	MADV_NOSYNC                       = 0x6
+	MADV_PROTECT                      = 0xa
+	MADV_RANDOM                       = 0x1
+	MADV_SEQUENTIAL                   = 0x2
+	MADV_WILLNEED                     = 0x3
+	MAP_ANON                          = 0x1000
+	MAP_ANONYMOUS                     = 0x1000
+	MAP_COPY                          = 0x2
+	MAP_FILE                          = 0x0
+	MAP_FIXED                         = 0x10
+	MAP_HASSEMAPHORE                  = 0x200
+	MAP_NOCORE                        = 0x20000
+	MAP_NORESERVE                     = 0x40
+	MAP_NOSYNC                        = 0x800
+	MAP_PREFAULT_READ                 = 0x40000
+	MAP_PRIVATE                       = 0x2
+	MAP_RENAME                        = 0x20
+	MAP_RESERVED0080                  = 0x80
+	MAP_RESERVED0100                  = 0x100
+	MAP_SHARED                        = 0x1
+	MAP_STACK                         = 0x400
+	MCL_CURRENT                       = 0x1
+	MCL_FUTURE                        = 0x2
 	MSG_COMPAT                        = 0x8000
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
...
@@ -933,6 +1084,14 @@ const (
 	O_TRUNC                           = 0x400
 	O_TTY_INIT                        = 0x80000
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PROT_EXEC                         = 0x4
+	PROT_NONE                         = 0x0
+	PROT_READ                         = 0x1
+	PROT_WRITE                        = 0x2
 	RLIMIT_AS                         = 0xa
 	RLIMIT_CORE                       = 0x4
 	RLIMIT_CPU                        = 0x0

これらの差分は、mkerrors.shスクリプトの実行によって再生成されたzerrors_freebsd_386.goファイル(amd64およびarm版も同様)の内容を示しています。 特に注目すべきは、MAP_*定数とPROT_*定数の追加です。

  • MAP_*定数: MAP_ANON, MAP_ANONYMOUS, MAP_PRIVATE, MAP_SHAREDなどが追加されています。これらはmmapシステムコールでメモリ領域をマッピングする際の動作を指定するために不可欠なフラグです。例えば、MAP_ANONはファイルではなく匿名メモリ領域を確保する場合に、MAP_SHAREDは複数のプロセス間でメモリを共有する場合にそれぞれ使用されます。
  • PROT_*定数: PROT_EXEC, PROT_NONE, PROT_READ, PROT_WRITEが追加されています。これらはmmapmprotectシステムコールでメモリ領域のアクセス権限を設定するために使用されます。例えば、PROT_READ | PROT_WRITEは読み書き可能なメモリ領域を意味します。

これらの定数がGoのsyscallパッケージに追加されたことで、GoプログラムはFreeBSD上でメモリマッピングやメモリ保護を必要とする低レベルな操作を、Goの型安全なインターフェースを通じて直接行えるようになります。これにより、Goでより高度なシステムプログラミングが可能になり、例えば、JITコンパイラの実装や、特定のメモリ領域のアクセス権限を動的に変更するようなアプリケーションの開発が容易になります。

src/pkg/syscall/zsysnum_freebsd_386.go (amd64, armも同様) の変更

--- a/src/pkg/syscall/zsysnum_freebsd_386.go
+++ b/src/pkg/syscall/zsysnum_freebsd_386.go
@@ -149,6 +149,7 @@ const (
 	SYS_FFCLOCK_GETCOUNTER       = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
 	SYS_FFCLOCK_SETESTIMATE      = 242 // { int ffclock_setestimate( \
 	SYS_FFCLOCK_GETESTIMATE      = 243 // { int ffclock_getestimate( \
+	SYS_CLOCK_GETCPUCLOCKID2     = 247 // { int clock_getcpuclockid2(id_t id,\
 	SYS_NTP_GETTIME              = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
 	SYS_MINHERIT                 = 250 // { int minherit(void *addr, size_t len, \
 	SYS_RFORK                    = 251 // { int rfork(int flags); }
@@ -320,7 +321,7 @@ const (
 	SYS_JAIL_REMOVE              = 508 // { int jail_remove(int jid); }
 	SYS_CLOSEFROM                = 509 // { int closefrom(int lowfd); }
 	SYS_LPATHCONF                = 513 // { int lpathconf(char *path, int name); }
-	SYS_CAP_NEW                  = 514 // { int cap_new(int fd, u_int64_t rights); }
+	SYS_CAP_NEW                  = 514 // { int cap_new(int fd, uint64_t rights); }
 	SYS_CAP_GETRIGHTS            = 515 // { int cap_getrights(int fd, \
 	SYS_CAP_ENTER                = 516 // { int cap_enter(void); }
 	SYS_CAP_GETMODE              = 517 // { int cap_getmode(u_int *modep); }
@@ -337,4 +338,5 @@ const (
 	SYS_RCTL_REMOVE_RULE         = 529 // { int rctl_remove_rule(const void *inbufp, \
 	SYS_POSIX_FALLOCATE          = 530 // { int posix_fallocate(int fd, \
 	SYS_POSIX_FADVISE            = 531 // { int posix_fadvise(int fd, off_t offset, \
+	SYS_WAIT6                    = 532 // { int wait6(int idtype, int id, \
 )

この差分は、FreeBSDのシステムコール番号定義ファイルであるzsysnum_freebsd_386.go(amd64およびarm版も同様)の変更を示しています。 主な変更点は以下の通りです。

  • 新しいシステムコールの追加: SYS_CLOCK_GETCPUCLOCKID2SYS_WAIT6といった新しいシステムコールが追加されています。これらはFreeBSDの新しいバージョンで導入された機能に対応するためのものです。
  • 既存システムコールの引数型の変更: SYS_CAP_NEWシステムコールの引数型がu_int64_tからuint64_tに変更されています。これは、C言語の型定義の変更や、Goの型システムとの整合性を保つための調整と考えられます。
  • ARMアーキテクチャ固有の追加: ARM版のzsysnum_freebsd_arm.goでは、SYS_CAP_RIGHTS_GETSYS_CAP_RIGHTS_LIMITなど、FreeBSDのCapability Modeに関連するシステムコールが多数追加されています。これは、ARMアーキテクチャにおけるFreeBSDのCapability Modeのサポート強化を反映しています。

これらの変更は、GoのsyscallパッケージがFreeBSDの最新のシステムコールインターフェースに追従し、GoプログラムがFreeBSDの新しい機能や改善されたAPIを利用できるようにするために重要です。

関連リンク

参考にした情報源リンク