aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/debug/mod.go
diff options
context:
space:
mode:
authorHana Kim <hyangah@gmail.com>2018-10-23 17:00:29 -0400
committerHyang-Ah Hana Kim <hyangah@gmail.com>2018-11-13 17:16:48 +0000
commit45e9c5538b3956d98ef0337fc19ed8d45eb17090 (patch)
tree6adcb1d65d5188d58e03fa7271093fbaa66523b7 /src/runtime/debug/mod.go
parent978cfa8e46d71992395d67382e96036596520cb6 (diff)
downloadgo-45e9c5538b3956d98ef0337fc19ed8d45eb17090.tar.xz
runtime/debug: add API to read module info in binary
When module is enabled, the go tool embeds build information related to the module in the binary including the dependencies and the replace information (See src/cmd/go/internal/modload.PackageBuildInfo). The newly introduced ReadBuildInfo reads the information and makes it accessible programmatically. Update #26404 Change-Id: Ide37022d609b4a8fb6b5ce02afabb73f04fbb532 Reviewed-on: https://go-review.googlesource.com/c/144220 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/runtime/debug/mod.go')
-rw-r--r--src/runtime/debug/mod.go105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go
new file mode 100644
index 0000000000..2c5aa27b6e
--- /dev/null
+++ b/src/runtime/debug/mod.go
@@ -0,0 +1,105 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package debug
+
+import (
+ "strings"
+)
+
+// set using cmd/go/internal/modload.ModInfoProg
+var modinfo string
+
+// ReadBuildInfo returns the build information embedded
+// in the running binary. The information is available only
+// in binaries built with module support.
+func ReadBuildInfo() (info *BuildInfo, ok bool) {
+ return readBuildInfo(modinfo)
+}
+
+// BuildInfo represents the build information read from
+// the running binary.
+type BuildInfo struct {
+ Path string // The main package path
+ Main Module // The main module information
+ Deps []*Module // Module dependencies
+}
+
+// Module represents a module.
+type Module struct {
+ Path string // module path
+ Version string // module version
+ Sum string // checksum
+ Replace *Module // replaced by this module
+}
+
+func readBuildInfo(data string) (*BuildInfo, bool) {
+ if len(data) < 32 {
+ return nil, false
+ }
+ data = data[16 : len(data)-16]
+
+ const (
+ pathLine = "path\t"
+ modLine = "mod\t"
+ depLine = "dep\t"
+ repLine = "=>\t"
+ )
+
+ info := &BuildInfo{}
+
+ var line string
+ // Reverse of cmd/go/internal/modload.PackageBuildInfo
+ for len(data) > 0 {
+ i := strings.IndexByte(data, '\n')
+ if i < 0 {
+ break
+ }
+ line, data = data[:i], data[i+1:]
+ switch {
+ case strings.HasPrefix(line, pathLine):
+ elem := line[len(pathLine):]
+ info.Path = elem
+ case strings.HasPrefix(line, modLine):
+ elem := strings.Split(line[len(modLine):], "\t")
+ if len(elem) != 3 {
+ return nil, false
+ }
+ info.Main = Module{
+ Path: elem[0],
+ Version: elem[1],
+ Sum: elem[2],
+ }
+ case strings.HasPrefix(line, depLine):
+ elem := strings.Split(line[len(depLine):], "\t")
+ if len(elem) != 2 && len(elem) != 3 {
+ return nil, false
+ }
+ sum := ""
+ if len(elem) == 3 {
+ sum = elem[2]
+ }
+ info.Deps = append(info.Deps, &Module{
+ Path: elem[0],
+ Version: elem[1],
+ Sum: sum,
+ })
+ case strings.HasPrefix(line, repLine):
+ elem := strings.Split(line[len(repLine):], "\t")
+ if len(elem) != 3 {
+ return nil, false
+ }
+ last := len(info.Deps) - 1
+ if last < 0 {
+ return nil, false
+ }
+ info.Deps[last].Replace = &Module{
+ Path: elem[0],
+ Version: elem[1],
+ Sum: elem[2],
+ }
+ }
+ }
+ return info, true
+}