rtcov.mx raw

   1  // Copyright 2022 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 rtcov
   6  
   7  import "unsafe"
   8  
   9  // This package contains types whose structure is shared between
  10  // the runtime package and the "runtime/coverage" implementation.
  11  
  12  // CovMetaBlob is a container for holding the meta-data symbol (an
  13  // RODATA variable) for an instrumented Go package. Here "p" points to
  14  // the symbol itself, "len" is the length of the sym in bytes, and
  15  // "hash" is an md5sum for the sym computed by the compiler. When
  16  // the init function for a coverage-instrumented package executes, it
  17  // will make a call into the runtime which will create a covMetaBlob
  18  // object for the package and chain it onto a global list.
  19  type CovMetaBlob struct {
  20  	P                  *byte
  21  	Len                uint32
  22  	Hash               [16]byte
  23  	PkgPath            []byte
  24  	PkgID              int
  25  	CounterMode        uint8 // coverage.CounterMode
  26  	CounterGranularity uint8 // coverage.CounterGranularity
  27  }
  28  
  29  // CovCounterBlob is a container for encapsulating a counter section
  30  // (BSS variable) for an instrumented Go module. Here "counters"
  31  // points to the counter payload and "len" is the number of uint32
  32  // entries in the section.
  33  type CovCounterBlob struct {
  34  	Counters *uint32
  35  	Len      uint64
  36  }
  37  
  38  // Meta is the top-level container for bits of state related to
  39  // code coverage meta-data in the runtime.
  40  var Meta struct {
  41  	// List contains the list of currently registered meta-data
  42  	// blobs for the running program.
  43  	List []CovMetaBlob
  44  
  45  	// PkgMap records mappings from hard-coded package IDs to
  46  	// slots in the List above.
  47  	PkgMap map[int]int
  48  
  49  	// Set to true if we discover a package mapping glitch.
  50  	hardCodedListNeedsUpdating bool
  51  }
  52  
  53  // AddMeta is invoked during package "init" functions by the
  54  // compiler when compiling for coverage instrumentation; here 'p' is a
  55  // meta-data blob of length 'dlen' for the package in question, 'hash'
  56  // is a compiler-computed md5.sum for the blob, 'pkpath' is the
  57  // package path, 'pkid' is the hard-coded ID that the compiler is
  58  // using for the package (or -1 if the compiler doesn't think a
  59  // hard-coded ID is needed), and 'cmode'/'cgran' are the coverage
  60  // counter mode and granularity requested by the user. Return value is
  61  // the ID for the package for use by the package code itself,
  62  // or 0 for impossible errors.
  63  func AddMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkgpath []byte, pkgid int, cmode uint8, cgran uint8) uint32 {
  64  	slot := len(Meta.List)
  65  	Meta.List = append(Meta.List, CovMetaBlob{
  66  		P:                  (*byte)(p),
  67  		Len:                dlen,
  68  		Hash:               hash,
  69  		PkgPath:            pkgpath,
  70  		PkgID:              pkgid,
  71  		CounterMode:        cmode,
  72  		CounterGranularity: cgran,
  73  	})
  74  	if pkgid != -1 {
  75  		if Meta.PkgMap == nil {
  76  			Meta.PkgMap = map[int]int{}
  77  		}
  78  		if _, ok := Meta.PkgMap[pkgid]; ok {
  79  			return 0
  80  		}
  81  		// Record the real slot (position on meta-list) for this
  82  		// package; we'll use the map to fix things up later on.
  83  		Meta.PkgMap[pkgid] = slot
  84  	}
  85  
  86  	// ID zero is reserved as invalid.
  87  	return uint32(slot + 1)
  88  }
  89