Slide 1

Slide 1 text

© 2023 Wantedly, Inc. ログから学ぶgo build golang.tokyo #33 Sep. 29 2023 - nasa

Slide 2

Slide 2 text

今日のテーマ © 2023 Wantedly, Inc.

Slide 3

Slide 3 text

テーマ go buildのログを元に ソースコードが実行ファイルにな るまでを理解する © 2023 Wantedly, Inc.

Slide 4

Slide 4 text

準備 © 2023 Wantedly, Inc.

Slide 5

Slide 5 text

準備 package main import "fmt" func main() { fmt.Println("Hello World") } © 2023 Wantedly, Inc. 利用するコード (main.go)

Slide 6

Slide 6 text

準備 go buildコマンド © 2023 Wantedly, Inc. go build -x -p 1 -work main.go

Slide 7

Slide 7 text

準備 go buildコマンド © 2023 Wantedly, Inc. go build -x -p 1 -work main.go -xオプションによりgo buildに呼び出されるコマンドを表示

Slide 8

Slide 8 text

go buildコマンド © 2023 Wantedly, Inc. go build -x -p 1 -work main.go -pオプションは並列数 ログの読み取りやすさのために1並列で実行 準備

Slide 9

Slide 9 text

go buildコマンド © 2023 Wantedly, Inc. go build -x -p 1 -work main.go -workは作業ディレクトリを残すオプション ビルド中に吐かれる中間生成物を残しといて調査に使う 準備

Slide 10

Slide 10 text

では実行してみよう © 2023 Wantedly, Inc.

Slide 11

Slide 11 text

© 2023 Wantedly, Inc. $ go build -x -p 1 -work main.go WORK=/var/folders/xx/xxxxxxxxxxxxx/T/go-buildxxxxxxxx mkdir -p $WORK/b005/ cat >/var/folders/xx/xxxxxxxxxxxxx/T/go-buildxxxxxxxx/b005/importcfg << 'EOF' # internal # import config EOF cd /Users/xxxxx/lab/sandbox/playground_go /usr/local/go/pkg/tool/xxxxxxxx/compile -o $WORK/b005/_pkg_.a -trimpath "$WORK/b005=>" -p internal/goarch -std -+ -complete -buildid M8znE3RFNIIsfAk_eE8O/M8znE3RFNIIsfAk_eE8O -goversion go1.20.1 -c=8 -nolocalimports -importcfg $WORK/b005/importcfg -pack /usr/local/go/src/internal/goarch/goarch.go /usr/local/go/src/internal/goarch/goarch_amd64.go /usr/local/go/src/internal/goarch/zgoarch_amd64.go /usr/local/go/pkg/tool/xxxxxxxx/buildid -w $WORK/b005/_pkg_.a # internal cp $WORK/b005/_pkg_.a /Users/xxxxx/Library/Caches/go-build/8c/8cf7915e43e6ec3a1ceac20e15009d87c0d26d4aa40409e5dc8b2e935d6d1014-d # internal mkdir -p $WORK/b006/ cat >/var/folders/xx/xxxxxxxxxxxxx/T/go-buildxxxxxxxx/b006/importcfg << 'EOF' # internal # import config EOF /usr/local/go/pkg/tool/xxxxxxxx/compile -o $WORK/b006/_pkg_.a -trimpath "$WORK/b006=>" -p internal/unsafeheader -std -complete -buildid sD4mccwa9DUJsmqBZGxG/sD4mccwa9DUJsmqBZGxG -goversion go1.20.1 -c=8 -nolocalimports -importcfg $WORK/b006/importcfg -pack /usr/local/go/src/internal/unsafeheader/unsafeheader.go /usr/local/go/pkg/tool/xxxxxxxx/buildid -w $WORK/b006/_pkg_.a # internal

Slide 12

Slide 12 text

© 2023 Wantedly, Inc. なんかいっぱい出た

Slide 13

Slide 13 text

© 2023 Wantedly, Inc. 発表を聞き終わった後にはこれが理解できる(はず)

Slide 14

Slide 14 text

全体像 © 2023 Wantedly, Inc.

Slide 15

Slide 15 text

© 2023 Wantedly, Inc. 複数のビルドステップ 全体像 mkdirを境として複数のビルドステップが存在 今回の例だとb001~b041

Slide 16

Slide 16 text

全体像 © 2023 Wantedly, Inc. 簡略化した全体像 各ステップの出力ファイルの依存関係を表した図 例えば、b040の出力がb031で使用される パッケージの依存関係に基づいてコンパイル 最後のb001/execで実行ファイルが生成

Slide 17

Slide 17 text

全体像 © 2023 Wantedly, Inc. 下記のように名付けて話を進めます b001~b041全体をコンパイルプロセス b001/execをリンクプロセス

Slide 18

Slide 18 text

全体像 © 2023 Wantedly, Inc. コンパイルプロセスでは利用するパッケージ毎に コンパイルする ソースコードが機械語へ リンクプロセスでは機械語をつなぎ合わせて実 行ファイルにする

Slide 19

Slide 19 text

全体像 © 2023 Wantedly, Inc. 依存関係を考慮しないと下記

Slide 20

Slide 20 text

全体像 © 2023 Wantedly, Inc. (余談) 簡略化しないとこうなる

Slide 21

Slide 21 text

コンパイルプロセス © 2023 Wantedly, Inc.

Slide 22

Slide 22 text

© 2023 Wantedly, Inc. パッケージ毎にソースコードを機械語に変換する コンパイルプロセス

Slide 23

Slide 23 text

コンパイルプロセス 1. importcfgの作成 2. compile 3. ビルドキャッシュの作成 © 2023 Wantedly, Inc. mkdir -p $WORK/b002/ # 1. importcfg cat >/var/folders/gb/0bh7j48d59n5fsy0wvpjd2fm0000gn/T/go-build3269867993/b002/importcfg << 'EOF' # internal # import config EOF # 2. compile /usr/local/go/pkg/tool/darwin_arm64/compile -o $WORK/b002/_pkg_.a -importcfg $WORK/b002/importcfg /usr/local/go/src/fmt/scan.go # 3. build cache /usr/local/go/pkg/tool/darwin_arm64/buildid -w $WORK/b002/_pkg_.a # internal cp $WORK/b002/_pkg_.a /Users/Library/Caches/go-build/b6/b68267d8212b1d8b8e54044a24b10869a453ec4e4a25163833c4f5928bd66aa6-d # internal

Slide 24

Slide 24 text

コンパイルプロセス © 2023 Wantedly, Inc. 1. importcfg cat >/var/folders/gb/0bh7j48d59n5fsy0wvpjd2fm0000gn/T/go-build717416899/b033/importcfg << 'EOF' # internal # import config packagefile errors=/var/folders/gb/0bh7j48d59n5fsy0wvpjd2fm0000gn/T/go-build717416899/b003/_pkg_.a packagefile internal/syscall/unix=/var/folders/gb/0bh7j48d59n5fsy0wvpjd2fm0000gn/T/go-build717416899/b034/_pkg_.a (略) EOF コンパイル時に依存しているパッケージの情報が必要になる importcfgファイルに情報をまとめている

Slide 25

Slide 25 text

© 2023 Wantedly, Inc. 2. compile $ /usr/local/go/pkg/tool/darwin_arm64/compile \ -o $WORK/b005/_pkg_.a \ -importcfg $WORK/b005/importcfg \ /usr/local/go/src/internal/goarch/goarch.go -o 出力ファイル -importcfg 先程作ったimportcfgはここで使う。AST構築・型チェックに利用 コンパイルプロセス

Slide 26

Slide 26 text

© 2023 Wantedly, Inc. 2. compile $ go tool pack t $WORK/b002/_pkg_.a # 中身の確認 __.PKGDEF _go_.o $ go tool pack x $WORK/b002/_pkg_.a # 取り出す はたして何が作成されたのか? .aはアーカイブファイル(複数のファイルをまとめて一つのファイルへ変換したファイル) go tool packで個々のファイルを見ることが出来る コンパイルプロセス

Slide 27

Slide 27 text

© 2023 Wantedly, Inc. 2. compile $ go tool objdump _go_.o … SUB $80, RSP, R17 CMP R16, R17 BLS 256(PC) __.PKGDEF パッケージ情報が詰まったファイル _go.o オブジェクトファイル プログラムの断片で機械語が書いてある go tool objdumpで人が読める形式に コンパイルプロセス

Slide 28

Slide 28 text

© 2023 Wantedly, Inc. 3. ビルドキャッシュ 各ステップごとにキャッシュを作成 ソースコードが変わってなければキャッシュを再利用 mkdir -p $WORK/b005/ (略) /usr/local/go/pkg/tool/xxxxxxxx/buildid -w $WORK/b005/_pkg_.a # internal cp $WORK/b005/_pkg_.a /Users/xxxxx/Library/Caches/go-build/8c/8cf7915e43e6ec3a1ceac20e15009d87c0d26d4aa40409e5dc8b2e935d6d10 14-d # internal コンパイルプロセス

Slide 29

Slide 29 text

(余裕があれば) 低レベルなパッケージの コンパイル © 2023 Wantedly, Inc.

Slide 30

Slide 30 text

© 2023 Wantedly, Inc. 標準パッケージを見てみると一部関数はアセンブリ言語で実装し てある こういった低レベルなパッケージは先程とはプロセスが異なる コンパイルプロセス

Slide 31

Slide 31 text

コンパイルプロセス 1. symabi 2. compile © 2023 Wantedly, Inc. /usr/local/go/pkg/tool/darwin_arm64/asm -p sync/atomic -gensymabis -o $WORK/b028/symabis ./asm.s /usr/local/go/pkg/tool/darwin_arm64/compile \ -o $WORK/b028/_pkg_.a \ -symabis $WORK/b028/symabis \ -importcfg $WORK/b028/importcfg \ -asmhdr $WORK/b028/go_asm.h \ /usr/local/go/src/sync/atomic/value.go /usr/local/go/pkg/tool/darwin_arm64/asm -p sync/atomic -o $WORK/b028/asm.o ./asm.s /usr/local/go/pkg/tool/darwin_arm64/pack r $WORK/b028/_pkg_.a $WORK/b028/asm.o # internal

Slide 32

Slide 32 text

コンパイルプロセス © 2023 Wantedly, Inc. 1. symabis usr/local/go/pkg/tool/darwin_arm64/asm -p sync/atomic -gensymabis -o $WORK/b028/symabis ./asm.s アセンブリのABIをファイルに書き出す ABIは呼出規約を定めたもの 引数のこの順番でスタック・レジスタに置きますね 返り値はこの順番でスタック・レジスタに置きますね ABIドキュメント: https://github.com/golang/go/blob/master/src/cmd/compile/abi-internal.md ソースコード: src/cmd/internal/obj/link.go

Slide 33

Slide 33 text

コンパイルプロセス © 2023 Wantedly, Inc. 1. compile /usr/local/go/pkg/tool/darwin_arm64/compile -o $WORK/b028/_pkg_.a -p sync/atomic -symabis $WORK/b028/symabis -importcfg $WORK/b028/importcfg -pack -asmhdr $WORK/b028/go_asm.h \ /usr/local/go/src/sync/atomic/doc.go \ /usr/local/go/src/sync/atomic/type.go \ /usr/local/go/src/sync/atomic/value.go /usr/local/go/pkg/tool/darwin_arm64/asm -p sync/atomic -o $WORK/b028/asm.o ./asm.s ソースコードとアセンブリ言語を機械語に変換 さっき生成したsymabisを利用

Slide 34

Slide 34 text

コンパイルプロセス © 2023 Wantedly, Inc. 1. compile /usr/local/go/pkg/tool/darwin_arm64/pack r $WORK/b028/_pkg_.a $WORK/b028/asm.o # internal 最後に生成物をまとめる

Slide 35

Slide 35 text

リンクプロセス © 2023 Wantedly, Inc.

Slide 36

Slide 36 text

リンク © 2023 Wantedly, Inc. リンクって何? コンパイルプロセスで作ったオブジェクトファイル(.oファイル)をつなぎ合わせて実行ファイルを作 る

Slide 37

Slide 37 text

リンク © 2023 Wantedly, Inc. アドレス情報を埋める オブジェクトファイルでは関数のアドレスを仮置きしている `R_CALLARM64`のように仮置きの場所がマーキングしてある $ go tool objdump b001/_pkg_.a TEXT main.main(SB) gofile../main.go print.go:314 0x13cc 94000000 CALL 0(PC) [0:4]R_CALLARM64:fmt.Fprintln 余談: リロケーションタイプはsrc/cmd/internal/objabi/reloctype.goにまとまっている

Slide 38

Slide 38 text

リンク © 2023 Wantedly, Inc. アドレス情報を埋める オブジェクトファイルと実行ファイルの差分を見てみる `R_CALL`が消え、0(PC)と適当な値だったがアドレス(ラベル)になっている

Slide 39

Slide 39 text

リンク © 2023 Wantedly, Inc. 実行ファイル macOSやLinuxなどターゲットに応じた実行形式をサポートしている macOSだったらMach-O linuxならELF $ file main main: Mach-O 64-bit executable arm64

Slide 40

Slide 40 text

ということで 実行ファイルが手に入った🎉 © 2023 Wantedly, Inc.

Slide 41

Slide 41 text

まとめ © 2023 Wantedly, Inc.

Slide 42

Slide 42 text

まとめ © 2023 Wantedly, Inc. ● ログや生成ファイルをガチャガチャやるだけでも色々と分かる ● 豊富なデバッグオプション・デバッグツールが揃ってる

Slide 43

Slide 43 text

まとめ © 2023 Wantedly, Inc. 扱ったのはほんの一部

Slide 44

Slide 44 text

俺達の戦いはこれから? © 2023 Wantedly, Inc.

Slide 45

Slide 45 text

自己紹介 © 2023 Wantedly, Inc. ● nasa (Asan Kondo) ● Wantedly,Inc.所属 ● 推薦基盤の開発・運用 ● ハンドルネームnasaが欲しい ○ GitHub: @k-nasa ○ X(Twitter): @nasa_desu

Slide 46

Slide 46 text

ご清聴ありがとうございました © 2023 Wantedly, Inc.