github.com/primecitizens/pcz/std@v0.2.1/core/cover/meta.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  //
     4  // Copyright 2022 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  package cover
     9  
    10  import (
    11  	"unsafe"
    12  
    13  	"github.com/primecitizens/pcz/std/core/abi"
    14  	"github.com/primecitizens/pcz/std/core/assert"
    15  )
    16  
    17  // CovMetaBlob is a container for holding the meta-data symbol (an
    18  // RODATA variable) for an instrumented Go package. Here "p" points to
    19  // the symbol itself, "len" is the length of the sym in bytes, and
    20  // "hash" is an md5sum for the sym computed by the compiler. When
    21  // the init function for a coverage-instrumented package executes, it
    22  // will make a call into the runtime which will create a covMetaBlob
    23  // object for the package and chain it onto a global list.
    24  type CovMetaBlob struct {
    25  	P                  *byte
    26  	Len                uint32
    27  	Hash               [16]byte
    28  	PkgPath            string
    29  	PkgID              int
    30  	CounterMode        uint8 // coverage.CounterMode
    31  	CounterGranularity uint8 // coverage.CounterGranularity
    32  }
    33  
    34  // CovCounterBlob is a container for encapsulating a counter section
    35  // (BSS variable) for an instrumented Go module. Here "counters"
    36  // points to the counter payload and "len" is the number of uint32
    37  // entries in the section.
    38  type CovCounterBlob struct {
    39  	Counters *uint32
    40  	Len      uint64
    41  }
    42  
    43  var (
    44  	// covMeta is the top-level container for bits of state related to
    45  	// code coverage meta-data in the runtime.
    46  	covMeta struct {
    47  		// metaList contains the list of currently registered meta-data
    48  		// blobs for the running program.
    49  		metaList []CovMetaBlob
    50  
    51  		// pkgMap records mappings from hard-coded package IDs to
    52  		// slots in the covMetaList above.
    53  		pkgMap map[int]int
    54  
    55  		// Set to true if we discover a package mapping glitch.
    56  		hardCodedListNeedsUpdating bool
    57  	}
    58  )
    59  
    60  func GetCovMetaList() []CovMetaBlob {
    61  	return covMeta.metaList
    62  }
    63  
    64  func GetCovPkgMap() map[int]int {
    65  	return covMeta.pkgMap
    66  }
    67  
    68  func AppendCovCounterList(res []CovCounterBlob) {
    69  	const (
    70  		u32sz = unsafe.Sizeof(uint32(0))
    71  	)
    72  
    73  	for i, iter := 0, abi.ModuleIter(0); ; i++ {
    74  		md, more := iter.Nth(i)
    75  		if !more {
    76  			break
    77  		}
    78  
    79  		if md.CovCtrs == md.ECovCtrs {
    80  			continue
    81  		}
    82  
    83  		res = append(res, CovCounterBlob{
    84  			Counters: (*uint32)(unsafe.Pointer(md.CovCtrs)),
    85  			Len:      uint64((md.ECovCtrs - md.CovCtrs) / u32sz),
    86  		})
    87  	}
    88  }
    89  
    90  // AddCovMeta is invoked during package "init" functions by the
    91  // compiler when compiling for coverage instrumentation; here 'p' is a
    92  // meta-data blob of length 'dlen' for the package in question, 'hash'
    93  // is a compiler-computed md5.sum for the blob, 'pkpath' is the
    94  // package path, 'pkid' is the hard-coded ID that the compiler is
    95  // using for the package (or -1 if the compiler doesn't think a
    96  // hard-coded ID is needed), and 'cmode'/'cgran' are the coverage
    97  // counter mode and granularity requested by the user. Return value is
    98  // the ID for the package for use by the package code itself.
    99  func AddCovMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkpath string, pkgid int, cmode uint8, cgran uint8) uint32 {
   100  	slot := len(covMeta.metaList)
   101  	covMeta.metaList = append(covMeta.metaList,
   102  		CovMetaBlob{
   103  			P:                  (*byte)(p),
   104  			Len:                dlen,
   105  			Hash:               hash,
   106  			PkgPath:            pkpath,
   107  			PkgID:              pkgid,
   108  			CounterMode:        cmode,
   109  			CounterGranularity: cgran,
   110  		},
   111  	)
   112  	if pkgid != -1 {
   113  		if covMeta.pkgMap == nil {
   114  			covMeta.pkgMap = make(map[int]int)
   115  		}
   116  		if _, ok := covMeta.pkgMap[pkgid]; ok {
   117  			assert.Throw("runtime.addCovMeta:", "coverage", "package", "map", "collision")
   118  		}
   119  		// Record the real slot (position on meta-list) for this
   120  		// package; we'll use the map to fix things up later on.
   121  		covMeta.pkgMap[pkgid] = slot
   122  	}
   123  
   124  	// ID zero is reserved as invalid.
   125  	return uint32(slot + 1)
   126  }