yutopp's blog

サンドバッグになりたい

goを自分でビルドして標準ライブラリを改造してみる

gorountineのstackが再確保されたとき、stack上のポインタの値はどうなるのか - yutopp's blog で サラッと 動作が気になるので、runtime.stackDebugを4に書き換えた改造runtimeで再度出力を見てみる。 と書きました。

この記事は、自分でgoをビルドして標準ライブラリ(例としてruntime)を差し替える方法のメモです。

環境は以下

$ uname -v
Darwin Kernel Version 22.1.0: Sun Oct  9 20:14:30 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8103
$ go version
go version go1.19.4 darwin/arm64

goのビルドをする

実際、Installing Go from source - The Go Programming Language に書いてあるとおりでgoのビルドが完了するのでやります。

ホストにgoがインストールされていれば、勝手にそれをbootstrapに使ってビルドをしてくれます。

# sourceを取ってくる
$ wget https://go.dev/dl/go1.19.4.darwin-arm64.tar.gz
# 解凍
$ tar -xf go1.19.4.darwin-arm64.tar.gz
# ビルド
$ cd go/src
$ ./all.bash

これだけでテストが通るのを待てば完了。簡単すぎる...。

実際に使う場合は、ビルドした go ディレクトリ (多分これは自由に名前を変えて平気) の bin 以下のバイナリを呼びます。

$ go/bin/go version
go version go1.19.4 darwin/arm64

runtimeの差し替え

さきほどのディレクトリの、src 以下に標準ライブラリ含めソースコードが配置されているので、これを変更してみます。

ここでは、例として runtime/stack.go を変更します。

# 雑にいじる場合はこんな感じで直に適当なエディタで開けばok (補完はこのままだと効かない)
$ code go/src/runtime/stack.go

試しにstackの初期化時に最悪なメッセージを表示するruntimeにしてみます。以下のように適当なprintを足してみましょう。

175: func stackinit() {
176: +   println("進捗どうですか?")
177:     if _StackCacheSize&_PageMask != 0 {

さて、この runtime をインストールしてみます。先程ビルドしたgo/bin/goを用いて、以下のコマンドを実行すれば良いようです [1]。

# -a は強制リビルド。-v はパッケージ名の表示 [2]
$ go/bin/go install -a -v runtime

実行してみる

では適当なコードをビルドして実行結果を見てみましょう。以下を main.go という名前で保存します。

package main

func main() {
}

ビルド。

$ go/bin/go build main.go

実行してみます。

$ ./main
進捗どうですか?

最悪なgo runtimeの完成です。よかったですね。


[1] go - Golang Runtime recompile - Stack Overflow が参考になった。

[2] go command - cmd/go - Go Packages