diff options
| author | Than McIntosh <thanm@google.com> | 2022-04-19 18:45:06 -0400 |
|---|---|---|
| committer | Than McIntosh <thanm@google.com> | 2022-09-26 21:48:50 +0000 |
| commit | cf83a490e495e5bfa7065cd97811e689101a687e (patch) | |
| tree | 59ddb5355c3332e27433d90f011a0b970fa54e18 /src/runtime | |
| parent | efa3f1749fabe3b3062edff7651baa8cb1f574ab (diff) | |
| download | go-cf83a490e495e5bfa7065cd97811e689101a687e.tar.xz | |
runtime: add hook to register coverage-instrumented packages
Add support to the runtime for registering coverage-instrumented
packages, using a new hook that can be called from the init function
of an instrumented package. The hook records the meta-data symbol for
the package (chaining it onto a list), and returns a package ID to be
used to identify functions in the package. This new hook is not yet
called; that will be added in a subsequent patch. The list of
registered meta-data objects will be used (again in a future patch) as
part of coverage data file writing.
Special handling is required for packages such as "runtime" or
"internal/cpu", where functions in the package execute before the
package "init" func runs. For these packages hard-code the package ID,
then record the position of the package in the overall list so that we
can fix things up later on.
Updates #51430.
Change-Id: I6ca3ddf535197442a2603c6d7a0a9798b8496f40
Reviewed-on: https://go-review.googlesource.com/c/go/+/401234
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/covermeta.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/runtime/covermeta.go b/src/runtime/covermeta.go new file mode 100644 index 0000000000..90bc20f45b --- /dev/null +++ b/src/runtime/covermeta.go @@ -0,0 +1,82 @@ +// 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 runtime + +import ( + "internal/coverage/rtcov" + "unsafe" +) + +// covMeta is the top-level container for bits of state related to +// code coverage meta-data in the runtime. +var covMeta struct { + // metaList contains the list of currently registered meta-data + // blobs for the running program. + metaList []rtcov.CovMetaBlob + + // pkgMap records mappings from hard-coded package IDs to + // slots in the covMetaList above. + pkgMap map[int]int + + // Set to true if we discover a package mapping glitch. + hardCodedListNeedsUpdating bool +} + +func reportErrorInHardcodedList(slot int32, pkgId int32) { + println("internal error in coverage meta-data tracking:") + println("encountered bad pkg ID ", pkgId, " at slot ", slot) + println("list of hard-coded runtime package IDs needs revising.") + println("[see the comment on the 'rtPkgs' var in ") + println(" <goroot>/src/internal/coverage/pkid.go]") + println("registered list:") + for k, b := range covMeta.metaList { + print("slot: ", k, " path='", b.PkgPath, "' ") + if b.PkgID != -1 { + print(" hard-coded id: ", b.PkgID) + } + println("") + } + println("remap table:") + for from, to := range covMeta.pkgMap { + println("from ", from, " to ", to) + } +} + +// addCovMeta 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. +func addCovMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkpath string, pkid int, cmode uint8, cgran uint8) uint32 { + slot := len(covMeta.metaList) + covMeta.metaList = append(covMeta.metaList, + rtcov.CovMetaBlob{ + P: (*byte)(p), + Len: dlen, + Hash: hash, + PkgPath: pkpath, + PkgID: pkid, + CounterMode: cmode, + CounterGranularity: cgran, + }) + if pkid != -1 { + if covMeta.pkgMap == nil { + covMeta.pkgMap = make(map[int]int) + } + if _, ok := covMeta.pkgMap[pkid]; ok { + throw("runtime.addCovMeta: coverage package map collision") + } + // Record the real slot (position on meta-list) for this + // package; we'll use the map to fix things up later on. + covMeta.pkgMap[pkid] = slot + } + + // ID zero is reserved as invalid. + return uint32(slot + 1) +} |
