Black Lives Matter. Support the Equal Justice Initiative.

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