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