github.com/bir3/gocompiler@v0.9.2202/src/internal/fuzz/coverage.go (about) 1 // Copyright 2021 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 fuzz 6 7 import ( 8 "fmt" 9 "math/bits" 10 ) 11 12 // ResetCoverage sets all of the counters for each edge of the instrumented 13 // source code to 0. 14 func ResetCoverage() { 15 cov := coverage() 16 for i := range cov { 17 cov[i] = 0 18 } 19 } 20 21 // SnapshotCoverage copies the current counter values into coverageSnapshot, 22 // preserving them for later inspection. SnapshotCoverage also rounds each 23 // counter down to the nearest power of two. This lets the coordinator store 24 // multiple values for each counter by OR'ing them together. 25 func SnapshotCoverage() { 26 cov := coverage() 27 for i, b := range cov { 28 b |= b >> 1 29 b |= b >> 2 30 b |= b >> 4 31 b -= b >> 1 32 coverageSnapshot[i] = b 33 } 34 } 35 36 // diffCoverage returns a set of bits set in snapshot but not in base. 37 // If there are no new bits set, diffCoverage returns nil. 38 func diffCoverage(base, snapshot []byte) []byte { 39 if len(base) != len(snapshot) { 40 panic(fmt.Sprintf("the number of coverage bits changed: before=%d, after=%d", len(base), len(snapshot))) 41 } 42 found := false 43 for i := range snapshot { 44 if snapshot[i]&^base[i] != 0 { 45 found = true 46 break 47 } 48 } 49 if !found { 50 return nil 51 } 52 diff := make([]byte, len(snapshot)) 53 for i := range diff { 54 diff[i] = snapshot[i] &^ base[i] 55 } 56 return diff 57 } 58 59 // countNewCoverageBits returns the number of bits set in snapshot that are not 60 // set in base. 61 func countNewCoverageBits(base, snapshot []byte) int { 62 n := 0 63 for i := range snapshot { 64 n += bits.OnesCount8(snapshot[i] &^ base[i]) 65 } 66 return n 67 } 68 69 // isCoverageSubset returns true if all the base coverage bits are set in 70 // snapshot. 71 func isCoverageSubset(base, snapshot []byte) bool { 72 for i, v := range base { 73 if v&snapshot[i] != v { 74 return false 75 } 76 } 77 return true 78 } 79 80 // hasCoverageBit returns true if snapshot has at least one bit set that is 81 // also set in base. 82 func hasCoverageBit(base, snapshot []byte) bool { 83 for i := range snapshot { 84 if snapshot[i]&base[i] != 0 { 85 return true 86 } 87 } 88 return false 89 } 90 91 func countBits(cov []byte) int { 92 n := 0 93 for _, c := range cov { 94 n += bits.OnesCount8(c) 95 } 96 return n 97 } 98 99 var ( 100 coverageEnabled = len(coverage()) > 0 101 coverageSnapshot = make([]byte, len(coverage())) 102 103 // _counters and _ecounters mark the start and end, respectively, of where 104 // the 8-bit coverage counters reside in memory. They're known to cmd/link, 105 // which specially assigns their addresses for this purpose. 106 _counters, _ecounters [0]byte 107 )