github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/runtime/debug/mod.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package debug 6 7 import ( 8 "strings" 9 _ "unsafe" // for go:linkname 10 ) 11 12 // exported from runtime 13 func modinfo() string 14 15 // ReadBuildInfo returns the build information embedded 16 // in the running binary. The information is available only 17 // in binaries built with module support. 18 func ReadBuildInfo() (info *BuildInfo, ok bool) { 19 return readBuildInfo(modinfo()) 20 } 21 22 // BuildInfo represents the build information read from 23 // the running binary. 24 type BuildInfo struct { 25 Path string // The main package path 26 Main Module // The module containing the main package 27 Deps []*Module // Module dependencies 28 } 29 30 // Module represents a module. 31 type Module struct { 32 Path string // module path 33 Version string // module version 34 Sum string // checksum 35 Replace *Module // replaced by this module 36 } 37 38 func readBuildInfo(data string) (*BuildInfo, bool) { 39 if len(data) < 32 { 40 return nil, false 41 } 42 data = data[16 : len(data)-16] 43 44 const ( 45 pathLine = "path\t" 46 modLine = "mod\t" 47 depLine = "dep\t" 48 repLine = "=>\t" 49 ) 50 51 info := &BuildInfo{} 52 53 var line string 54 // Reverse of cmd/go/internal/modload.PackageBuildInfo 55 for len(data) > 0 { 56 i := strings.IndexByte(data, '\n') 57 if i < 0 { 58 break 59 } 60 line, data = data[:i], data[i+1:] 61 switch { 62 case strings.HasPrefix(line, pathLine): 63 elem := line[len(pathLine):] 64 info.Path = elem 65 case strings.HasPrefix(line, modLine): 66 elem := strings.Split(line[len(modLine):], "\t") 67 if len(elem) != 3 { 68 return nil, false 69 } 70 info.Main = Module{ 71 Path: elem[0], 72 Version: elem[1], 73 Sum: elem[2], 74 } 75 case strings.HasPrefix(line, depLine): 76 elem := strings.Split(line[len(depLine):], "\t") 77 if len(elem) != 2 && len(elem) != 3 { 78 return nil, false 79 } 80 sum := "" 81 if len(elem) == 3 { 82 sum = elem[2] 83 } 84 info.Deps = append(info.Deps, &Module{ 85 Path: elem[0], 86 Version: elem[1], 87 Sum: sum, 88 }) 89 case strings.HasPrefix(line, repLine): 90 elem := strings.Split(line[len(repLine):], "\t") 91 if len(elem) != 3 { 92 return nil, false 93 } 94 last := len(info.Deps) - 1 95 if last < 0 { 96 return nil, false 97 } 98 info.Deps[last].Replace = &Module{ 99 Path: elem[0], 100 Version: elem[1], 101 Sum: elem[2], 102 } 103 } 104 } 105 return info, true 106 }