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 5 package 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 47 var 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. 69 const 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. 74 func 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