Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ログから学ぶgo build
Search
nasa
September 28, 2023
Technology
1.6k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ログから学ぶgo build
https://golangtokyo.connpass.com/event/293636/
nasa
September 28, 2023
More Decks by nasa
See All by nasa
難解な自己紹介プログラムを書く
nasa_desu
1
400
鉄は熱いうちに打て - Kaigi Effect LT大会
nasa_desu
2
610
リンカを変えてgo buildを 速く出来るか
nasa_desu
2
4k
RustでOS開発はじめの一歩
nasa_desu
8
7.6k
goのメモリアロケーターの話
nasa_desu
1
840
GoとRust - 並行処理編
nasa_desu
5
4.2k
Other Decks in Technology
See All in Technology
属人化を叩き割れ!「制作加速」と「安定化」の矛盾を打破する:8年目プロダクトが辿り着いた「ミスが起こり得ない」アセット制作フローの全貌
gree_tech
PRO
0
140
ソフトウェアサプライチェーンの構造的リスクとコンテナ環境の保護
kyohmizu
5
840
Invisible to AI? Making TYPO3 Sites Quotable by AI Search Systems
wolfgangwagner
0
240
Kiro Crew で始める マルチエージェント開発
miu_crescent
PRO
0
160
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
9.4k
なぜ Temporal の大小比較には compare しかないのか / Why Does Temporal Only Have compare() for Comparisons
kazukihayase
1
200
FDEの心得
noriakioji
5
6.4k
同じWAFが、攻撃の“形”は弾く── 正当な“形”の不正は通す
kuroneko13
0
270
【GCC2026】TrueHDRIを用いたルックデブ環境とライティングテクニック
bandainamcostudios
PRO
0
260
20分でわかるセキュアAPI
nwiizo
2
330
Oracle MCP Servers Explained
thatjeffsmith
0
410
医療の現場を変革に挑戦した半年間の軌跡 - PythonとAIで現場を変える / From Code to Care
soudai
PRO
1
570
Featured
See All Featured
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
Design in an AI World
tapps
1
290
Art, The Web, and Tiny UX
lynnandtonic
304
22k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
280
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
300
Git: the NoSQL Database
bkeepers
PRO
432
67k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
440
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
73
41k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
620
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Transcript
© 2023 Wantedly, Inc. ログから学ぶgo build golang.tokyo #33 Sep. 29
2023 - nasa
今日のテーマ © 2023 Wantedly, Inc.
テーマ go buildのログを元に ソースコードが実行ファイルにな るまでを理解する © 2023 Wantedly, Inc.
準備 © 2023 Wantedly, Inc.
準備 package main import "fmt" func main() { fmt.Println("Hello World")
} © 2023 Wantedly, Inc. 利用するコード (main.go)
準備 go buildコマンド © 2023 Wantedly, Inc. go build -x
-p 1 -work main.go
準備 go buildコマンド © 2023 Wantedly, Inc. go build -x
-p 1 -work main.go -xオプションによりgo buildに呼び出されるコマンドを表示
go buildコマンド © 2023 Wantedly, Inc. go build -x -p
1 -work main.go -pオプションは並列数 ログの読み取りやすさのために1並列で実行 準備
go buildコマンド © 2023 Wantedly, Inc. go build -x -p
1 -work main.go -workは作業ディレクトリを残すオプション ビルド中に吐かれる中間生成物を残しといて調査に使う 準備
では実行してみよう © 2023 Wantedly, Inc.
© 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
© 2023 Wantedly, Inc. なんかいっぱい出た
© 2023 Wantedly, Inc. 発表を聞き終わった後にはこれが理解できる(はず)
全体像 © 2023 Wantedly, Inc.
© 2023 Wantedly, Inc. 複数のビルドステップ 全体像 mkdirを境として複数のビルドステップが存在 今回の例だとb001~b041
全体像 © 2023 Wantedly, Inc. 簡略化した全体像 各ステップの出力ファイルの依存関係を表した図 例えば、b040の出力がb031で使用される パッケージの依存関係に基づいてコンパイル 最後のb001/execで実行ファイルが生成
全体像 © 2023 Wantedly, Inc. 下記のように名付けて話を進めます b001~b041全体をコンパイルプロセス b001/execをリンクプロセス
全体像 © 2023 Wantedly, Inc. コンパイルプロセスでは利用するパッケージ毎に コンパイルする ソースコードが機械語へ リンクプロセスでは機械語をつなぎ合わせて実 行ファイルにする
全体像 © 2023 Wantedly, Inc. 依存関係を考慮しないと下記
全体像 © 2023 Wantedly, Inc. (余談) 簡略化しないとこうなる
コンパイルプロセス © 2023 Wantedly, Inc.
© 2023 Wantedly, Inc. パッケージ毎にソースコードを機械語に変換する コンパイルプロセス
コンパイルプロセス 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
コンパイルプロセス © 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ファイルに情報をまとめている
© 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構築・型チェックに利用 コンパイルプロセス
© 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で個々のファイルを見ることが出来る コンパイルプロセス
© 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で人が読める形式に コンパイルプロセス
© 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 コンパイルプロセス
(余裕があれば) 低レベルなパッケージの コンパイル © 2023 Wantedly, Inc.
© 2023 Wantedly, Inc. 標準パッケージを見てみると一部関数はアセンブリ言語で実装し てある こういった低レベルなパッケージは先程とはプロセスが異なる コンパイルプロセス
コンパイルプロセス 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
コンパイルプロセス © 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
コンパイルプロセス © 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を利用
コンパイルプロセス © 2023 Wantedly, Inc. 1. compile /usr/local/go/pkg/tool/darwin_arm64/pack r $WORK/b028/_pkg_.a
$WORK/b028/asm.o # internal 最後に生成物をまとめる
リンクプロセス © 2023 Wantedly, Inc.
リンク © 2023 Wantedly, Inc. リンクって何? コンパイルプロセスで作ったオブジェクトファイル(.oファイル)をつなぎ合わせて実行ファイルを作 る
リンク © 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にまとまっている
リンク © 2023 Wantedly, Inc. アドレス情報を埋める オブジェクトファイルと実行ファイルの差分を見てみる `R_CALL`が消え、0(PC)と適当な値だったがアドレス(ラベル)になっている
リンク © 2023 Wantedly, Inc. 実行ファイル macOSやLinuxなどターゲットに応じた実行形式をサポートしている macOSだったらMach-O linuxならELF $
file main main: Mach-O 64-bit executable arm64
ということで 実行ファイルが手に入った🎉 © 2023 Wantedly, Inc.
まとめ © 2023 Wantedly, Inc.
まとめ © 2023 Wantedly, Inc. • ログや生成ファイルをガチャガチャやるだけでも色々と分かる • 豊富なデバッグオプション・デバッグツールが揃ってる
まとめ © 2023 Wantedly, Inc. 扱ったのはほんの一部
俺達の戦いはこれから? © 2023 Wantedly, Inc.
自己紹介 © 2023 Wantedly, Inc. • nasa (Asan Kondo) •
Wantedly,Inc.所属 • 推薦基盤の開発・運用 • ハンドルネームnasaが欲しい ◦ GitHub: @k-nasa ◦ X(Twitter): @nasa_desu
ご清聴ありがとうございました © 2023 Wantedly, Inc.