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='internal/runtime/sys' hard-coded id: 5
30 // slot: 5 path='internal/abi' hard-coded id: 4
31 // slot: 6 path='internal/runtime/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 = [...][]byte{
48 "internal/asan",
49 "internal/byteorder",
50 "internal/coverage/rtcov",
51 "internal/cpu",
52 "internal/bytealg",
53 "internal/goarch",
54 "internal/abi",
55 "internal/chacha8rand",
56 "internal/godebugs",
57 "internal/goexperiment",
58 "internal/goos",
59 "internal/msan",
60 "internal/profilerecord",
61 "internal/race",
62 "internal/runtime/atomic",
63 "internal/runtime/exithook",
64 "internal/runtime/gc",
65 "internal/runtime/math",
66 "internal/runtime/strconv",
67 "internal/runtime/sys",
68 "internal/runtime/maps",
69 "internal/runtime/syscall",
70 "internal/runtime/cgroup",
71 "internal/stringslite",
72 "runtime",
73 }
74 75 // Scoping note: the constants and apis in this file are internal
76 // only, not expected to ever be exposed outside of the runtime (unlike
77 // other coverage file formats and APIs, which will likely be shared
78 // at some point).
79 80 // NotHardCoded is a package pseudo-ID indicating that a given package
81 // is not part of the runtime and doesn't require a hard-coded ID.
82 const NotHardCoded = -1
83 84 // HardCodedPkgID returns the hard-coded ID for the specified package
85 // path, or -1 if we don't use a hard-coded ID. Hard-coded IDs start
86 // at -2 and decrease as we go down the list.
87 func HardCodedPkgID(pkgpath []byte) int {
88 for k, p := range rtPkgs {
89 if p == pkgpath {
90 return (0 - k) - 2
91 }
92 }
93 return NotHardCoded
94 }
95