| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package rtcov |
| |
| import "unsafe" |
| |
| // This package contains types whose structure is shared between |
| // the runtime package and the "runtime/coverage" implementation. |
| |
| // CovMetaBlob is a container for holding the meta-data symbol (an |
| // RODATA variable) for an instrumented Go package. Here "p" points to |
| // the symbol itself, "len" is the length of the sym in bytes, and |
| // "hash" is an md5sum for the sym computed by the compiler. When |
| // the init function for a coverage-instrumented package executes, it |
| // will make a call into the runtime which will create a covMetaBlob |
| // object for the package and chain it onto a global list. |
| type CovMetaBlob struct { |
| P *byte |
| Len uint32 |
| Hash [16]byte |
| PkgPath string |
| PkgID int |
| CounterMode uint8 // coverage.CounterMode |
| CounterGranularity uint8 // coverage.CounterGranularity |
| } |
| |
| // CovCounterBlob is a container for encapsulating a counter section |
| // (BSS variable) for an instrumented Go module. Here "counters" |
| // points to the counter payload and "len" is the number of uint32 |
| // entries in the section. |
| type CovCounterBlob struct { |
| Counters *uint32 |
| Len uint64 |
| } |
| |
| // Meta is the top-level container for bits of state related to |
| // code coverage meta-data in the runtime. |
| var Meta struct { |
| // List contains the list of currently registered meta-data |
| // blobs for the running program. |
| List []CovMetaBlob |
| |
| // PkgMap records mappings from hard-coded package IDs to |
| // slots in the List above. |
| PkgMap map[int]int |
| |
| // Set to true if we discover a package mapping glitch. |
| hardCodedListNeedsUpdating bool |
| } |
| |
| // AddMeta is invoked during package "init" functions by the |
| // compiler when compiling for coverage instrumentation; here 'p' is a |
| // meta-data blob of length 'dlen' for the package in question, 'hash' |
| // is a compiler-computed md5.sum for the blob, 'pkpath' is the |
| // package path, 'pkid' is the hard-coded ID that the compiler is |
| // using for the package (or -1 if the compiler doesn't think a |
| // hard-coded ID is needed), and 'cmode'/'cgran' are the coverage |
| // counter mode and granularity requested by the user. Return value is |
| // the ID for the package for use by the package code itself, |
| // or 0 for impossible errors. |
| func AddMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkgpath string, pkgid int, cmode uint8, cgran uint8) uint32 { |
| slot := len(Meta.List) |
| Meta.List = append(Meta.List, CovMetaBlob{ |
| P: (*byte)(p), |
| Len: dlen, |
| Hash: hash, |
| PkgPath: pkgpath, |
| PkgID: pkgid, |
| CounterMode: cmode, |
| CounterGranularity: cgran, |
| }) |
| if pkgid != -1 { |
| if Meta.PkgMap == nil { |
| Meta.PkgMap = make(map[int]int) |
| } |
| if _, ok := Meta.PkgMap[pkgid]; ok { |
| return 0 |
| } |
| // Record the real slot (position on meta-list) for this |
| // package; we'll use the map to fix things up later on. |
| Meta.PkgMap[pkgid] = slot |
| } |
| |
| // ID zero is reserved as invalid. |
| return uint32(slot + 1) |
| } |