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 main module information
    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  	info := &BuildInfo{}
    51  
    52  	var line string
    53  	// Reverse of cmd/go/internal/modload.PackageBuildInfo
    54  	for len(data) > 0 {
    55  		i := strings.IndexByte(data, '\n')
    56  		if i < 0 {
    57  			break
    58  		}
    59  		line, data = data[:i], data[i+1:]
    60  		switch {
    61  		case strings.HasPrefix(line, pathLine):
    62  			elem := line[len(pathLine):]
    63  			info.Path = elem
    64  		case strings.HasPrefix(line, modLine):
    65  			elem := strings.Split(line[len(modLine):], "\t")
    66  			if len(elem) != 3 {
    67  				return nil, false
    68  			}
    69  			info.Main = Module{
    70  				Path:    elem[0],
    71  				Version: elem[1],
    72  				Sum:     elem[2],
    73  			}
    74  		case strings.HasPrefix(line, depLine):
    75  			elem := strings.Split(line[len(depLine):], "\t")
    76  			if len(elem) != 2 && len(elem) != 3 {
    77  				return nil, false
    78  			}
    79  			sum := ""
    80  			if len(elem) == 3 {
    81  				sum = elem[2]
    82  			}
    83  			info.Deps = append(info.Deps, &Module{
    84  				Path:    elem[0],
    85  				Version: elem[1],
    86  				Sum:     sum,
    87  			})
    88  		case strings.HasPrefix(line, repLine):
    89  			elem := strings.Split(line[len(repLine):], "\t")
    90  			if len(elem) != 3 {
    91  				return nil, false
    92  			}
    93  			last := len(info.Deps) - 1
    94  			if last < 0 {
    95  				return nil, false
    96  			}
    97  			info.Deps[last].Replace = &Module{
    98  				Path:    elem[0],
    99  				Version: elem[1],
   100  				Sum:     elem[2],
   101  			}
   102  		}
   103  	}
   104  	return info, true
   105  }
   106  

View as plain text