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 }