aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/debug')
-rw-r--r--src/runtime/debug/mod.go104
1 files changed, 58 insertions, 46 deletions
diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go
index 11f995ba75..8c6c48089b 100644
--- a/src/runtime/debug/mod.go
+++ b/src/runtime/debug/mod.go
@@ -7,7 +7,6 @@ package debug
import (
"bytes"
"fmt"
- "strings"
)
// exported from runtime
@@ -17,11 +16,19 @@ func modinfo() string
// in the running binary. The information is available only
// in binaries built with module support.
func ReadBuildInfo() (info *BuildInfo, ok bool) {
- return readBuildInfo(modinfo())
+ data := modinfo()
+ if len(data) < 32 {
+ return nil, false
+ }
+ data = data[16 : len(data)-16]
+ bi := &BuildInfo{}
+ if err := bi.UnmarshalText([]byte(data)); err != nil {
+ return nil, false
+ }
+ return bi, true
}
-// BuildInfo represents the build information read from
-// the running binary.
+// BuildInfo represents the build information read from a Go binary.
type BuildInfo struct {
Path string // The main package path
Main Module // The module containing the main package
@@ -71,80 +78,85 @@ func (bi *BuildInfo) MarshalText() ([]byte, error) {
return buf.Bytes(), nil
}
-func readBuildInfo(data string) (*BuildInfo, bool) {
- if len(data) < 32 {
- return nil, false
- }
- data = data[16 : len(data)-16]
+func (bi *BuildInfo) UnmarshalText(data []byte) (err error) {
+ *bi = BuildInfo{}
+ lineNum := 1
+ defer func() {
+ if err != nil {
+ err = fmt.Errorf("could not parse Go build info: line %d: %w", lineNum, err)
+ }
+ }()
- const (
- pathLine = "path\t"
- modLine = "mod\t"
- depLine = "dep\t"
- repLine = "=>\t"
+ var (
+ pathLine = []byte("path\t")
+ modLine = []byte("mod\t")
+ depLine = []byte("dep\t")
+ repLine = []byte("=>\t")
+ newline = []byte("\n")
+ tab = []byte("\t")
)
- readEntryFirstLine := func(elem []string) (Module, bool) {
+ readModuleLine := func(elem [][]byte) (Module, error) {
if len(elem) != 2 && len(elem) != 3 {
- return Module{}, false
+ return Module{}, fmt.Errorf("expected 2 or 3 columns; got %d", len(elem))
}
sum := ""
if len(elem) == 3 {
- sum = elem[2]
+ sum = string(elem[2])
}
return Module{
- Path: elem[0],
- Version: elem[1],
+ Path: string(elem[0]),
+ Version: string(elem[1]),
Sum: sum,
- }, true
+ }, nil
}
var (
- info = &BuildInfo{}
last *Module
- line string
+ line []byte
ok bool
)
- // Reverse of cmd/go/internal/modload.PackageBuildInfo
+ // Reverse of BuildInfo.String()
for len(data) > 0 {
- line, data, ok = strings.Cut(data, "\n")
+ line, data, ok = bytes.Cut(data, newline)
if !ok {
break
}
switch {
- case strings.HasPrefix(line, pathLine):
+ case bytes.HasPrefix(line, pathLine):
elem := line[len(pathLine):]
- info.Path = elem
- case strings.HasPrefix(line, modLine):
- elem := strings.Split(line[len(modLine):], "\t")
- last = &info.Main
- *last, ok = readEntryFirstLine(elem)
- if !ok {
- return nil, false
+ bi.Path = string(elem)
+ case bytes.HasPrefix(line, modLine):
+ elem := bytes.Split(line[len(modLine):], tab)
+ last = &bi.Main
+ *last, err = readModuleLine(elem)
+ if err != nil {
+ return err
}
- case strings.HasPrefix(line, depLine):
- elem := strings.Split(line[len(depLine):], "\t")
+ case bytes.HasPrefix(line, depLine):
+ elem := bytes.Split(line[len(depLine):], tab)
last = new(Module)
- info.Deps = append(info.Deps, last)
- *last, ok = readEntryFirstLine(elem)
- if !ok {
- return nil, false
+ bi.Deps = append(bi.Deps, last)
+ *last, err = readModuleLine(elem)
+ if err != nil {
+ return err
}
- case strings.HasPrefix(line, repLine):
- elem := strings.Split(line[len(repLine):], "\t")
+ case bytes.HasPrefix(line, repLine):
+ elem := bytes.Split(line[len(repLine):], tab)
if len(elem) != 3 {
- return nil, false
+ return fmt.Errorf("expected 3 columns for replacement; got %d", len(elem))
}
if last == nil {
- return nil, false
+ return fmt.Errorf("replacement with no module on previous line")
}
last.Replace = &Module{
- Path: elem[0],
- Version: elem[1],
- Sum: elem[2],
+ Path: string(elem[0]),
+ Version: string(elem[1]),
+ Sum: string(elem[2]),
}
last = nil
}
+ lineNum++
}
- return info, true
+ return nil
}