1// Copyright 2022 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package coverage 6 7// Building the runtime package with coverage instrumentation enabled 8// is tricky. For all other packages, you can be guaranteed that 9// the package init function is run before any functions are executed, 10// but this invariant is not maintained for packages such as "runtime", 11// "internal/cpu", etc. To handle this, hard-code the package ID for 12// the set of packages whose functions may be running before the 13// init function of the package is complete. 14// 15// Hardcoding is unfortunate because it means that the tool that does 16// coverage instrumentation has to keep a list of runtime packages, 17// meaning that if someone makes changes to the pkg "runtime" 18// dependencies, unexpected behavior will result for coverage builds. 19// The coverage runtime will detect and report the unexpected 20// behavior; look for an error of this form: 21// 22// internal error in coverage meta-data tracking: 23// list of hard-coded runtime package IDs needs revising. 24// registered list: 25// slot: 0 path='internal/cpu' hard-coded id: 1 26// slot: 1 path='internal/goarch' hard-coded id: 2 27// slot: 2 path='internal/runtime/atomic' hard-coded id: 3 28// slot: 3 path='internal/goos' 29// slot: 4 path='runtime/internal/sys' hard-coded id: 5 30// slot: 5 path='internal/abi' hard-coded id: 4 31// slot: 6 path='runtime/internal/math' hard-coded id: 6 32// slot: 7 path='internal/bytealg' hard-coded id: 7 33// slot: 8 path='internal/goexperiment' 34// slot: 9 path='internal/runtime/syscall' hard-coded id: 8 35// slot: 10 path='runtime' hard-coded id: 9 36// fatal error: runtime.addCovMeta 37// 38// For the error above, the hard-coded list is missing "internal/goos" 39// and "internal/goexperiment" ; the developer in question will need 40// to copy the list above into "rtPkgs" below. 41// 42// Note: this strategy assumes that the list of dependencies of 43// package runtime is fixed, and doesn't vary depending on OS/arch. If 44// this were to be the case, we would need a table of some sort below 45// as opposed to a fixed list. 46 47var rtPkgs = [...]string{ 48 "internal/cpu", 49 "internal/goarch", 50 "internal/runtime/atomic", 51 "internal/goos", 52 "internal/chacha8rand", 53 "runtime/internal/sys", 54 "internal/abi", 55 "runtime/internal/math", 56 "internal/bytealg", 57 "internal/goexperiment", 58 "internal/runtime/syscall", 59 "runtime", 60} 61 62// Scoping note: the constants and apis in this file are internal 63// only, not expected to ever be exposed outside of the runtime (unlike 64// other coverage file formats and APIs, which will likely be shared 65// at some point). 66 67// NotHardCoded is a package pseudo-ID indicating that a given package 68// is not part of the runtime and doesn't require a hard-coded ID. 69const NotHardCoded = -1 70 71// HardCodedPkgID returns the hard-coded ID for the specified package 72// path, or -1 if we don't use a hard-coded ID. Hard-coded IDs start 73// at -2 and decrease as we go down the list. 74func HardCodedPkgID(pkgpath string) int { 75 for k, p := range rtPkgs { 76 if p == pkgpath { 77 return (0 - k) - 2 78 } 79 } 80 return NotHardCoded 81} 82