aboutsummaryrefslogtreecommitdiff
path: root/src/internal/coverage
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/internal/coverage
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/internal/coverage')
-rw-r--r--src/internal/coverage/pkid.go80
-rw-r--r--src/internal/coverage/rtcov/rtcov.go25
2 files changed, 105 insertions, 0 deletions
diff --git a/src/internal/coverage/pkid.go b/src/internal/coverage/pkid.go
new file mode 100644
index 0000000000..2b4ac2ee56
--- /dev/null
+++ b/src/internal/coverage/pkid.go
@@ -0,0 +1,80 @@
+// 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 coverage
+
+// Building the runtime package with coverage instrumentation enabled
+// is tricky. For all other packages, you can be guaranteed that
+// the package init function is run before any functions are executed,
+// but this invariant is not maintained for packages such as "runtime",
+// "internal/cpu", etc. To handle this, hard-code the package ID for
+// the set of packages whose functions may be running before the
+// init function of the package is complete.
+//
+// Hardcoding is unfortunate because it means that the tool that does
+// coverage instrumentation has to keep a list of runtime packages,
+// meaning that if someone makes changes to the pkg "runtime"
+// dependencies, unexpected behavior will result for coverage builds.
+// The coverage runtime will detect and report the unexpected
+// behavior; look for an error of this form:
+//
+// internal error in coverage meta-data tracking:
+// list of hard-coded runtime package IDs needs revising.
+// registered list:
+// slot: 0 path='internal/cpu' hard-coded id: 1
+// slot: 1 path='internal/goarch' hard-coded id: 2
+// slot: 2 path='runtime/internal/atomic' hard-coded id: 3
+// slot: 3 path='internal/goos'
+// slot: 4 path='runtime/internal/sys' hard-coded id: 5
+// slot: 5 path='internal/abi' hard-coded id: 4
+// slot: 6 path='runtime/internal/math' hard-coded id: 6
+// slot: 7 path='internal/bytealg' hard-coded id: 7
+// slot: 8 path='internal/goexperiment'
+// slot: 9 path='runtime/internal/syscall' hard-coded id: 8
+// slot: 10 path='runtime' hard-coded id: 9
+// fatal error: runtime.addCovMeta
+//
+// For the error above, the hard-coded list is missing "internal/goos"
+// and "internal/goexperiment" ; the developer in question will need
+// to copy the list above into "rtPkgs" below.
+//
+// Note: this strategy assumes that the list of dependencies of
+// package runtime is fixed, and doesn't vary depending on OS/arch. If
+// this were to be the case, we would need a table of some sort below
+// as opposed to a fixed list.
+
+var rtPkgs = [...]string{
+ "internal/cpu",
+ "internal/goarch",
+ "runtime/internal/atomic",
+ "internal/goos",
+ "runtime/internal/sys",
+ "internal/abi",
+ "runtime/internal/math",
+ "internal/bytealg",
+ "internal/goexperiment",
+ "runtime/internal/syscall",
+ "runtime",
+}
+
+// Scoping note: the constants and apis in this file are internal
+// only, not expected to ever be exposed outside of the runtime (unlike
+// other coverage file formats and APIs, which will likely be shared
+// at some point).
+
+// NotHardCoded is a package pseudo-ID indicating that a given package
+// is not part of the runtime and doesn't require a hard-coded ID.
+const NotHardCoded = -1
+
+// HardCodedPkgId returns the hard-coded ID for the specified package
+// path, or -1 if we don't use a hard-coded ID. Hard-coded IDs start
+// at -2 and decrease as we go down the list.
+func HardCodedPkgID(pkgpath string) int {
+ for k, p := range rtPkgs {
+ if p == pkgpath {
+ return (0 - k) - 2
+ }
+ }
+ return NotHardCoded
+}
diff --git a/src/internal/coverage/rtcov/rtcov.go b/src/internal/coverage/rtcov/rtcov.go
new file mode 100644
index 0000000000..38dbae6c82
--- /dev/null
+++ b/src/internal/coverage/rtcov/rtcov.go
@@ -0,0 +1,25 @@
+// 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
+
+// This package contains types whose structure is shared between
+// the runtime package and the "runtime/coverage" package.
+
+// 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
+}