...

Source file src/runtime/debug/mod.go

Documentation: runtime/debug

		 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  )
		10  
		11  // exported from runtime
		12  func modinfo() string
		13  
		14  // ReadBuildInfo returns the build information embedded
		15  // in the running binary. The information is available only
		16  // in binaries built with module support.
		17  func ReadBuildInfo() (info *BuildInfo, ok bool) {
		18  	return readBuildInfo(modinfo())
		19  }
		20  
		21  // BuildInfo represents the build information read from
		22  // the running binary.
		23  type BuildInfo struct {
		24  	Path string		// The main package path
		25  	Main Module		// The module containing the main package
		26  	Deps []*Module // Module dependencies
		27  }
		28  
		29  // Module represents a module.
		30  type Module struct {
		31  	Path		string	// module path
		32  	Version string	// module version
		33  	Sum		 string	// checksum
		34  	Replace *Module // replaced by this module
		35  }
		36  
		37  func readBuildInfo(data string) (*BuildInfo, bool) {
		38  	if len(data) < 32 {
		39  		return nil, false
		40  	}
		41  	data = data[16 : len(data)-16]
		42  
		43  	const (
		44  		pathLine = "path\t"
		45  		modLine	= "mod\t"
		46  		depLine	= "dep\t"
		47  		repLine	= "=>\t"
		48  	)
		49  
		50  	readEntryFirstLine := func(elem []string) (Module, bool) {
		51  		if len(elem) != 2 && len(elem) != 3 {
		52  			return Module{}, false
		53  		}
		54  		sum := ""
		55  		if len(elem) == 3 {
		56  			sum = elem[2]
		57  		}
		58  		return Module{
		59  			Path:		elem[0],
		60  			Version: elem[1],
		61  			Sum:		 sum,
		62  		}, true
		63  	}
		64  
		65  	var (
		66  		info = &BuildInfo{}
		67  		last *Module
		68  		line string
		69  		ok	 bool
		70  	)
		71  	// Reverse of cmd/go/internal/modload.PackageBuildInfo
		72  	for len(data) > 0 {
		73  		i := strings.IndexByte(data, '\n')
		74  		if i < 0 {
		75  			break
		76  		}
		77  		line, data = data[:i], data[i+1:]
		78  		switch {
		79  		case strings.HasPrefix(line, pathLine):
		80  			elem := line[len(pathLine):]
		81  			info.Path = elem
		82  		case strings.HasPrefix(line, modLine):
		83  			elem := strings.Split(line[len(modLine):], "\t")
		84  			last = &info.Main
		85  			*last, ok = readEntryFirstLine(elem)
		86  			if !ok {
		87  				return nil, false
		88  			}
		89  		case strings.HasPrefix(line, depLine):
		90  			elem := strings.Split(line[len(depLine):], "\t")
		91  			last = new(Module)
		92  			info.Deps = append(info.Deps, last)
		93  			*last, ok = readEntryFirstLine(elem)
		94  			if !ok {
		95  				return nil, false
		96  			}
		97  		case strings.HasPrefix(line, repLine):
		98  			elem := strings.Split(line[len(repLine):], "\t")
		99  			if len(elem) != 3 {
	 100  				return nil, false
	 101  			}
	 102  			if last == nil {
	 103  				return nil, false
	 104  			}
	 105  			last.Replace = &Module{
	 106  				Path:		elem[0],
	 107  				Version: elem[1],
	 108  				Sum:		 elem[2],
	 109  			}
	 110  			last = nil
	 111  		}
	 112  	}
	 113  	return info, true
	 114  }
	 115  

View as plain text