aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2022-04-19 18:45:06 -0400
committerThan McIntosh <thanm@google.com>2022-09-26 21:48:50 +0000
commitcf83a490e495e5bfa7065cd97811e689101a687e (patch)
tree59ddb5355c3332e27433d90f011a0b970fa54e18 /src/runtime
parentefa3f1749fabe3b3062edff7651baa8cb1f574ab (diff)
downloadgo-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.go82
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)
+}