// 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 }