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 string 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 string, 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 = make(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