$30 off During Our Annual Pro Sale. View Details »

Go runtimeの歩き方/how to follow go runtime function

convto
April 23, 2022
240

Go runtimeの歩き方/how to follow go runtime function

Go Conference Sprint 2022 にて発表したLTです。
https://gocon.jp/2022spring/ja/sessions/lt7/

Go の runtime は plan9 ベースのアセンブリでの実装があったり、他ではあまり見かけない compiler directive を使用していたり、 初見だと builtin 関数の名称がわからなかったり、前知識なしにコードが追いづらいです。

そこでこれらの解説や go tool objdump で builtin 関数を追う手法を紹介し、 runtime パッケージを読むための前提知識をまとめます。

以下資料内URL

p4
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/builtin/builtin.go;l=135-156

p7
- https://go.dev/doc/asm

p8
- https://go.dev/play/p/gTlrfNa1v0l

p9
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/runtime/alg.go;l=46-47
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/runtime/asm_amd64.s;l=1077-1087

p11
- https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives

p13
-
https://go.dev/play/p/0PpO7GicM2X

p14
- https://go.dev/play/p/tdVVRLwt3O6

p15
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/runtime/atomic_pointer.go;l=42-43
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/sync/atomic/doc.go;l=140-141
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/sync/atomic/asm.s;l=84-85

p17
- https://convto.hatenablog.com/entry/2022/04/02/222353

p18
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/cmd/compile/internal/typecheck/universe.go;l=32-62

p19
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/cmd/compile/internal/typecheck/const.go;l=538-540
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/cmd/compile/internal/typecheck/const.go;l=864-939

p20
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/cmd/compile/internal/walk/expr.go;l=265-267
- https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/cmd/compile/internal/walk/builtin.go;l=118-124

convto

April 23, 2022
Tweet

More Decks by convto

Transcript

  1. Go runtime ͷา͖ํ Go Conference 2022 Spring LT 2022-04-23 @convto

  2. @convto גࣜձࣾKyashॴଐ ϨΠϠ௿Ίͷٕज़΍҉߸ٕज़ʹڵຯ ͋Γ աڈʹ͸protobufͷ؆қతͳύʔα ʔॻ͍ͨΓplain RSA࣮૷ॻ͍ͨΓ ͠·ͨ͠

  3. ൃදͷ໨త • ͋Δ͍ͯͲGoΛॻ͍͍ͯΔͱ৭ʑͳཧ༝Ͱruntime͕ಡΈͨ͘ͳΔ • goroutine΍GCͷڍಈཧղ • ͦͷଞٕज़తڵຯ • ͱ͸͍͑runtime͸લ஌ࣝͳͩ͠ͱҰ෦ίʔυ͕௥͍ͮΒ͍ •

    ؔ਺ఆٛͱ࣮૷͕ผϑΝΠϧʹ͋ΔΑ͏ͳέʔεͷ௥͍ํΛ͋Δఔ౓·ͱΊͯɺruntimeΛಡΉ લ஌ࣝΛ੔͑Δ͜ͱ͕໨త • runtime΍compilerଆͰ۩ମతʹߦΘΕ͍ͯΔॲཧʹ͍ͭͯɺৄࡉʹ͸৮Ε·ͤΜ • ͋͘·Ͱॲཧͷ௥͍ํΛ঺հ͢Δ͜ͱ͕໨తͰ͢ʂڵຯ࣋ͬͨํ͸ͥͻಡΜͰΈ͍ͯͩ͘͞
  4. ྫ: builtinؔ਺ https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/builtin/builtin.go;l=135-156 • builtin pkg ͸υΩϡϝϯ τ༻ఆٛͷΈ •

    ࣮૷͸Ͳͩ͜Ζ͏ʁ • unsafe pkg ͳͲ΋ಉ༷
  5. Contents 1. ΞηϯϒϦʹΑΔ࣮૷ • ॻ͖ํͷ঺հ • runtimeͷ࣮ྫ 2. //go:linkname σΟϨΫςΟϒ

    • linknameσΟϨΫςΟϒͷ঺հ • runtimeͷ࣮ྫ 3. builtin/unsafe • src/cmd/compile/internal/gc ͷ௥͍ํ • go tool objdump Λ࢖͏ 4. ·ͱΊ
  6. ΞηϯϒϦʹΑΔ࣮૷

  7. Goͷؔ਺࣮૷͸ΞηϯϒϦͰ΋Ͱ͖Δ • GoͰ͸ؔ਺ͷ࣮૷Λplan9ϕʔεͷΞηϯϒϦͰॻ͚Δ • ΞʔΩςΫνϟ΍OSࠩ෼Λߟྀ͢ΔύοέʔδͰར༻͞Ε͍ͯΔ • ͜ͷΞηϯϒϦ͸ந৅Խ͞Εͨ΋ͷͰ͋Γɺجຊ͸ର৅ͷΞʔΩςΫνϟͱ௚઀ ݁ͼ͍͍ͭͯͳ͍ɻҰ෦໋ྩ͸CPUͷ໋ྩΛ௚઀දݱ͍ͯ͠Δɻ • https://go.dev/doc/asm

    ʹ΋هࡌ͕͋Δ௨Γɺͳʹ͕ந৅తͳ໋ྩͰɺͳʹ͕ ۩ମతͳ໋ྩ͔ͷ໢ཏతͳυΩϡϝϯτ͸ͳ͍໛༷ • Go࣮૷Ͱ֬ೝͨ͠ൣғͰ͸ɺx86_64ͷAESENCͳͲ͸ͦͷ··ͩͬͨ
  8. ॻ͖ํͷ঺հ https://go.dev/play/p/gTlrfNa1v0l • playgroundͰ࣍ͷΑ͏ʹॻ ͚Δ • ࣗ෼Ͱ༡ΜͰΈ͍ͨਓ͸ https://go.dev/doc/asm ͱɺதͷϦϯΫΛҰ௨Γಡ ΉͱΑ͛͞

  9. runtimeͷ࣮ྫ https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/runtime/alg.go;l=46-47 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/runtime/asm_amd64.s;l=1077-1087 • ࣮ࡍಡΉͷ͸ͪΐͬͱେ ม͔΋͠Εͳ͍ • Ͱ΋࣮૷ͱఆٛͷؔ܎͕

    Θ͔Δͱɺ͍͔ͭಡΈͨ ͘ͳͬͨͱ͖ʹಡΊΔ
  10. //go: linknameσΟϨΫςΟϒ

  11. σΟϨΫςΟϒͱ͸ • ಛघͳܗࣜͷίϝϯτͱ֤ͯ͠छཁٻΛ఻͑ΒΕΔ • ࠷ۙͩͱ //go: embed ͋ͨΓ͕هԱʹ৽͍͠ • ίϯύΠϥͷڍಈʹؔ࿈͢Δ΋ͷ͸

    https://pkg.go.dev/cmd/compile#hdr- Compiler_Directives ʹ͍͔ͭ͘هࡌ͕͋Δ(͜͜ʹॻ͔Εͯͳ͍΋ͷ΋ιʔ είʔυΈͯΔͱී௨ʹ͋ΔɻࠔͬͨΒ౎౓άάΔͳΓίϯύΠϥଆΛಡΉ ͳΓ͢Ε͹Α͍) • linknameͱ͔nosplit͸Α͘ݟ͔͚Δ
  12. linknameσΟϨΫςΟϒͱ͸ • `//go:linkname localname [importpath.name]` ͷܗͰࢦఆ • localnameͰఆٛͨ͠ม਺/ؔ਺ͷobject fileͷγϯϘϧ໊Λimportpath.nameͷ΋ͷʹͰ͖Δ •

    Α͏͸ϓϩάϥϜ͔Β͸localnameͰݺ͹Ε·͕͢ɺόΠφϦ্Ͱ͸importpath.nameͷݺͼग़͠ ʹͳΓ·͢ • ඇެ։࣮૷Λݺͼग़͢Α͏ʹ͔ͭ͏ύλʔϯɺඇެ։࣮૷Λlocalnameͷఆٛ಺༰Ͱ্ॻ͖͢ΔΑ ͏ʹ͔ͭ͏ύλʔϯͳͲ͋Γ·͕͢ɺࠓճ͸࣌ؒͷ౎߹্ɺඇެ։࣮૷Λݺͼग़͢Α͏ͳύλʔ ϯͷΈ঺հ • importͯ͠ͳ͍(΋͘͠͸runtimeͰ࣮૷͞Ε͍ͯͳ͍)Ϟδϡʔϧͷม਺/ؔ਺ʹ޲͚Δͱɺଘࡏ͠ ͳ͍޲͖ઌʹ޲͍ͯյΕΔ
  13. ॻ͖ํͷ঺հ https://go.dev/play/p/knFXmUPcsd- • ඇެ։ͷॲཧΛಡΈग़ͯ͠ͳΜ ΍͔΍΍ͬͨΓ • ༨ஊͰ͕͢reflectύοέʔδͷඇ ެ։ॲཧ typelinks() ΍

    rtypeof() ͱ૊Έ߹ΘͤΔͱΰϦΰϦʹܕ ৘ใΛऔΓग़ͨ͠ΓͰ͖·͢
  14. յΕΔྫ https://go.dev/play/p/tdVVRLwt3O6 • ͜Ε͸γϯϘϧஔ͖׵͑ ઌͷstrconv.lowerΛ importͯ͠ͳ͍ྫ • ଘࡏ͠ͳ͍޲͖ઌʹlink͠ Α͏ͱͯ͠ࢮ͵

  15. runtimeͷ࣮ྫ https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/runtime/atomic_pointer.go;l=42-43 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/sync/atomic/doc.go;l=140-141 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/sync/atomic/asm.s;l=84-85 • ίʔυྔগͳͯ͘આ໌͠΍͢ ͍ྫ

    • ΞηϯϒϦܦ༝ͯ͠δϟϯϓ͠ ͨΓͯ͠Δ͚ͲͪΌΜͱ௥͑Δ • linkname͸΄͔ʹ΋cgoܥͷॲ ཧͰ΋ଟ༻͞ΕͯΔ
  16. builtin/unsafe

  17. builtin/unsafe • runtime಺ʹ͸builtinͷ࣮૷ͱࢥΘ͖ؔ͠਺͕͍͔ͭ͋͘Δ͕ɺbuiltinؔ਺ͷ໊ લ͔ΒٯҾ͖ͮ͠Β͍(newobjectΈ͍ͨͳͪΐͬͱҧ͏໊લʹͳͬͯΔ) • unsafe͸ͦ΋ͦ΋runtimeʹͦΕͬΆ͍࣮૷͕ͳ͍ • ίϯύΠϥଆΛಡΉΞϓϩʔνͱɺgo tool objdumpͷΞϓϩʔνΛ঺հ͠·͢

    • ࣌ؒͷ౎߹্దٓ͸͠ΐΔͷͰৄ͘͠ίʔυ௥͍͔͚͍ͨํ͸ɺҎલ௥͍͔͚ ͨͱ͖ͷϝϞ https://convto.hatenablog.com/entry/2022/04/02/222353 Λ͝ ΒΜ͍ͩ͘͞
  18. ίϯύΠϥ࣮૷ ͔Β௥͍͔͚Δ 1 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/cmd/compile/internal/typecheck/ universe.go;l=32-62 • ίϯύΠϧ࣌ʹΑΈͱͬͨτʔΫ ϯΛதؒදݱʹ͢Δ •

    ͦͷͱ͖ʹbuiltin࣮૷ͱඥ෇͚ͨ Γunsafe࣮૷ͨ͠Γͯ͠Δ • →͸builtinͱ͔unsafeͷτʔΫϯ ͱதؒදݱͷOPඥ෇͚ͯΔͱ͜
  19. ίϯύΠϥ࣮૷ ͔Β௥͍͔͚Δ 2 unsafeฤ https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/cmd/compile/internal/typecheck/ const.go;l=538-540 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/cmd/compile/internal/typecheck/ const.go;l=864-939

    • தؒදݱͷOPͱඥ෇͍ͨͷͰɺͭ͗ ͸OPಡΜͰΔͱ͜ΖΛݟͯΈΔ • ͍Ζ͍Ζ௥͍͔͚ΔͱˠͷՕॴ͕ unsafeͷOPʹର͢Δ࣮૷ͳΑ͏ • νϥݟͨ͠ൣғͩͱɺܕ͝ͱʹsizeͱ ͔͕Θ͔ΔͷͰͦΕΛݩʹؤுͬͯ ܭࢉͯ͠ΔͬΆ͍͚Ͳৄࡉ͸ׂѪ
  20. ίϯύΠϥ࣮૷ ͔Β௥͍͔͚Δ 3 builtinฤ https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/cmd/compile/internal/walk/expr.go;l=265-267 https://cs.opensource.google/go/go/+/refs/tags/ go1.18:src/cmd/compile/internal/walk/ builtin.go;l=118-124 •

    close() Λྫʹ͓͍͔͚ʂ • walkExpr1() ͱ͍͏ॲཧͰbuiltinͷOP͔Βதؒද ݱ͕࡞ΒΕ͍ͯΔ • ͦͷͳ͔Ͱ͞Βʹ walkClose() ͕ݺ͹Εruntime࣮ ૷ͱඥ෇͚ΒΕ͍ͯΔ • mkcall() ͸ࢦఆͨؔ͠਺callͷதؒදݱΛಘΔ΍ͭ • ͜ͷྫͰ͸࠷ऴతʹ͸runtimeͷ closechan() Λ call͢Δதؒදݱ͕ಘΒΕΔ
  21. go tool Λ࢖͏ • ίϯύΠϥ࣮૷ಡΉͷ͸࣮͚֬ͩͲ໘౗ • ͦΜͳͱ͖͸ `go tool objdump`

    Λ࢖͓͏ʂ • ద౰ͳ࠷খίʔυॻ͍࣮ͯߦ͢ΔͱͦΕͬΆ ͍ͷ͕ग़ͯ͘ΔͷͰ໨੕͚ͭΔͷʹ͓͢͢Ί • →͸print() ͷ࣮૷Λ୳͢ྫ • ͪͳΈʹ࣮ࡍʹruntimeͷ࣮૷ΛݟΔͱܕ͝ ͱʹprintॲཧ͕४උ͞ΕͯΔ͜ͱ΋Θ͔Δ
  22. ·ͱΊ

  23. ίʔυ௥͍ํ·ͱΊ • ΞηϯϒϦͰ࣮૷͞ΕͯΔ͜ͱ͕͋Δ • σΟϨΫςΟϒ͍ͬͺ͍͋Δ • linknameͰ޲͖ઌ͕ஔ͖׵͑ΒΕͯΔͱ͖͕͋Δ • unsafe/builtin͸ίϯύΠϥಡΜͩΓ go

    tool Ͱ͓஡Λ୙ͨ͠Γ͠Α͏ • Go͸runtimeଆͰඇಉظαϙʔτ͕͋ͬͨΓlibcґଘͳ͔ͬͨΓɺ͔ ͳΓϢχʔΫͳݴޠͳͷͰ໘ന͍Ͱ͢ʂΈͳ͞Μ΋ڵຯ͋Ε͹ͥͻʂ
  24. ͓·͚ • ࣮૷௥͍͔ͨϑϩʔνϟʔ τΛੜ࢈͠·ͨ͠ • ΄͔ʹ΋ύλʔϯ͋Δ͔΋ ͚ͩͲେମͳΜͱ͔ͳΔ͸ ͣ • Α͔ͬͨΒͥͻ

    • cmd/compile/internal ΑΉ • go tool objdumpͰ໨੕Λ͚ͭΔ ஔ͖׵͑ઌͷ࣮૷ΛಡΉ ΞηϯϒϦͷ࣮૷Λ֬ೝ VOTBGF PSCVJMUJO MJOLOBNF Y Y N N ࣮૷͕ͳ͍ʂͷϑϩʔνϟʔτ
  25. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ