blob: 8ddd44d6bbc08ec77666dc356ea11902b6eaf4e0 [file] [log] [blame]
// 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
}