1
0
mirror of https://github.com/golang/go synced 2024-11-15 02:40:32 -07:00

internal/coverage/cfile: remove more //go:linkname usage

Move code so that basic imports work instead
of //go:linkname for metadata lists.

For #67401.

Change-Id: Id02075570befc45a9426559aad2137ab540928b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/585915
Reviewed-by: Than McIntosh <thanm@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Russ Cox 2024-05-15 18:39:01 -04:00
parent c96159c252
commit df4e49366c
6 changed files with 111 additions and 112 deletions

View File

@ -39,23 +39,34 @@ import (
var depsRules = ` var depsRules = `
# No dependencies allowed for any of these packages. # No dependencies allowed for any of these packages.
NONE NONE
< cmp, container/list, container/ring, < unsafe
internal/cfg, internal/coverage, internal/coverage/rtcov, < cmp,
internal/coverage/uleb128, internal/coverage/calloc, container/list,
internal/goarch, internal/godebugs, container/ring,
internal/goexperiment, internal/goos, internal/byteorder, internal/byteorder,
internal/goversion, internal/nettrace, internal/platform, internal/cfg,
internal/profilerecord, internal/trace/traceviewer/format, internal/coverage,
internal/coverage/rtcov,
internal/coverage/uleb128,
internal/coverage/calloc,
internal/cpu,
internal/goarch,
internal/godebugs,
internal/goexperiment,
internal/goos,
internal/goversion,
internal/nettrace,
internal/platform,
internal/profilerecord,
internal/trace/traceviewer/format,
log/internal, log/internal,
unicode/utf8, unicode/utf16, unicode, math/bits,
unsafe; unicode,
unicode/utf8,
unicode/utf16;
# internal/abi depends only on internal/goarch and unsafe. internal/goarch < internal/abi;
internal/goarch, unsafe < internal/abi; internal/byteorder, internal/goarch < internal/chacha8rand;
internal/byteorder, internal/goarch, unsafe < internal/chacha8rand;
unsafe < internal/cpu;
# RUNTIME is the core runtime group of packages, all of them very light-weight. # RUNTIME is the core runtime group of packages, all of them very light-weight.
internal/abi, internal/abi,
@ -66,7 +77,8 @@ var depsRules = `
internal/godebugs, internal/godebugs,
internal/goexperiment, internal/goexperiment,
internal/goos, internal/goos,
internal/profilerecord internal/profilerecord,
math/bits
< internal/bytealg < internal/bytealg
< internal/stringslite < internal/stringslite
< internal/itoa < internal/itoa
@ -86,22 +98,17 @@ var depsRules = `
< internal/godebug < internal/godebug
< internal/reflectlite < internal/reflectlite
< errors < errors
< internal/oserror, math/bits < internal/oserror;
cmp, internal/race, math/bits
< iter < iter
< maps, slices;
internal/oserror, maps, slices
< RUNTIME; < RUNTIME;
RUNTIME, unsafe RUNTIME
< maps; < sort
# slices depends on unsafe for overlapping check, cmp for comparison
# semantics, and math/bits for # calculating bitlength of numbers.
RUNTIME, unsafe, cmp, math/bits
< slices;
RUNTIME, slices
< sort;
sort
< container/heap; < container/heap;
RUNTIME RUNTIME
@ -663,7 +670,7 @@ var depsRules = `
< internal/trace/traceviewer; < internal/trace/traceviewer;
# Coverage. # Coverage.
FMT, crypto/md5, encoding/binary, regexp, sort, text/tabwriter, unsafe, FMT, crypto/md5, encoding/binary, regexp, sort, text/tabwriter,
internal/coverage, internal/coverage/uleb128 internal/coverage, internal/coverage/uleb128
< internal/coverage/cmerge, < internal/coverage/cmerge,
internal/coverage/pods, internal/coverage/pods,

View File

@ -7,6 +7,7 @@ package cfile
import ( import (
"fmt" "fmt"
"internal/coverage" "internal/coverage"
"internal/coverage/rtcov"
"io" "io"
"sync/atomic" "sync/atomic"
"unsafe" "unsafe"
@ -17,7 +18,7 @@ func WriteMetaDir(dir string) error {
if !finalHashComputed { if !finalHashComputed {
return fmt.Errorf("error: no meta-data available (binary not built with -cover?)") return fmt.Errorf("error: no meta-data available (binary not built with -cover?)")
} }
return emitMetaDataToDirectory(dir, getCovMetaList()) return emitMetaDataToDirectory(dir, rtcov.Meta.List)
} }
// WriteMeta implements [runtime/coverage.WriteMeta]. // WriteMeta implements [runtime/coverage.WriteMeta].
@ -28,7 +29,7 @@ func WriteMeta(w io.Writer) error {
if !finalHashComputed { if !finalHashComputed {
return fmt.Errorf("error: no meta-data available (binary not built with -cover?)") return fmt.Errorf("error: no meta-data available (binary not built with -cover?)")
} }
ml := getCovMetaList() ml := rtcov.Meta.List
return writeMetaData(w, ml, cmode, cgran, finalHash) return writeMetaData(w, ml, cmode, cgran, finalHash)
} }
@ -57,7 +58,7 @@ func WriteCounters(w io.Writer) error {
return fmt.Errorf("meta-data not written yet, unable to write counter data") return fmt.Errorf("meta-data not written yet, unable to write counter data")
} }
pm := getCovPkgMap() pm := rtcov.Meta.PkgMap
s := &emitState{ s := &emitState{
counterlist: cl, counterlist: cl,
pkgmap: pm, pkgmap: pm,

View File

@ -29,25 +29,13 @@ import (
// emitted at the end of code coverage testing runs, from instrumented // emitted at the end of code coverage testing runs, from instrumented
// executables. // executables.
// getCovMetaList returns a list of meta-data blobs registered
// for the currently executing instrumented program. It is defined in the
// runtime.
//go:linkname getCovMetaList
func getCovMetaList() []rtcov.CovMetaBlob
// getCovCounterList returns a list of counter-data blobs registered // getCovCounterList returns a list of counter-data blobs registered
// for the currently executing instrumented program. It is defined in the // for the currently executing instrumented program. It is defined in the
// runtime. // runtime.
//
//go:linkname getCovCounterList //go:linkname getCovCounterList
func getCovCounterList() []rtcov.CovCounterBlob func getCovCounterList() []rtcov.CovCounterBlob
// getCovPkgMap returns a map storing the remapped package IDs for
// hard-coded runtime packages (see internal/coverage/pkgid.go for
// more on why hard-coded package IDs are needed). This function
// is defined in the runtime.
//go:linkname getCovPkgMap
func getCovPkgMap() map[int]int
// emitState holds useful state information during the emit process. // emitState holds useful state information during the emit process.
// //
// When an instrumented program finishes execution and starts the // When an instrumented program finishes execution and starts the
@ -180,7 +168,7 @@ func granClash(g coverage.CounterGranularity) bool {
// all meta-data blobs and capturing os args. // all meta-data blobs and capturing os args.
func prepareForMetaEmit() ([]rtcov.CovMetaBlob, error) { func prepareForMetaEmit() ([]rtcov.CovMetaBlob, error) {
// Ask the runtime for the list of coverage meta-data symbols. // Ask the runtime for the list of coverage meta-data symbols.
ml := getCovMetaList() ml := rtcov.Meta.List
// In the normal case (go build -o prog.exe ... ; ./prog.exe) // In the normal case (go build -o prog.exe ... ; ./prog.exe)
// len(ml) will always be non-zero, but we check here since at // len(ml) will always be non-zero, but we check here since at
@ -210,7 +198,7 @@ func prepareForMetaEmit() ([]rtcov.CovMetaBlob, error) {
} }
fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "\n")
} }
pm := getCovPkgMap() pm := rtcov.Meta.PkgMap
fmt.Fprintf(os.Stderr, "=+= remap table:\n") fmt.Fprintf(os.Stderr, "=+= remap table:\n")
for from, to := range pm { for from, to := range pm {
fmt.Fprintf(os.Stderr, "=+= from %d to %d\n", fmt.Fprintf(os.Stderr, "=+= from %d to %d\n",
@ -310,7 +298,7 @@ func emitCounterDataToDirectory(outdir string) error {
} }
// Ask the runtime for the list of coverage counter symbols. // Ask the runtime for the list of coverage counter symbols.
pm := getCovPkgMap() pm := rtcov.Meta.PkgMap
s := &emitState{ s := &emitState{
counterlist: cl, counterlist: cl,
pkgmap: pm, pkgmap: pm,
@ -591,8 +579,8 @@ func MarkProfileEmitted(val bool) {
} }
func reportErrorInHardcodedList(slot, pkgID int32, fnID, nCtrs uint32) { func reportErrorInHardcodedList(slot, pkgID int32, fnID, nCtrs uint32) {
metaList := getCovMetaList() metaList := rtcov.Meta.List
pkgMap := getCovPkgMap() pkgMap := rtcov.Meta.PkgMap
println("internal error in coverage meta-data tracking:") println("internal error in coverage meta-data tracking:")
println("encountered bad pkgID:", pkgID, " at slot:", slot, println("encountered bad pkgID:", pkgID, " at slot:", slot,

View File

@ -14,6 +14,7 @@ import (
"internal/coverage/decodecounter" "internal/coverage/decodecounter"
"internal/coverage/decodemeta" "internal/coverage/decodemeta"
"internal/coverage/pods" "internal/coverage/pods"
"internal/coverage/rtcov"
"internal/runtime/atomic" "internal/runtime/atomic"
"io" "io"
"os" "os"
@ -33,7 +34,7 @@ func ProcessCoverTestDir(dir string, cfile string, cm string, cpkg string, w io.
} }
// Emit meta-data and counter data. // Emit meta-data and counter data.
ml := getCovMetaList() ml := rtcov.Meta.List
if len(ml) == 0 { if len(ml) == 0 {
// This corresponds to the case where we have a package that // This corresponds to the case where we have a package that
// contains test code but no functions (which is fine). In this // contains test code but no functions (which is fine). In this

View File

@ -4,8 +4,10 @@
package rtcov package rtcov
import "unsafe"
// This package contains types whose structure is shared between // This package contains types whose structure is shared between
// the runtime package and the "runtime/coverage" package. // the runtime package and the "runtime/coverage" implementation.
// CovMetaBlob is a container for holding the meta-data symbol (an // CovMetaBlob is a container for holding the meta-data symbol (an
// RODATA variable) for an instrumented Go package. Here "p" points to // RODATA variable) for an instrumented Go package. Here "p" points to
@ -32,3 +34,55 @@ type CovCounterBlob struct {
Counters *uint32 Counters *uint32
Len uint64 Len uint64
} }
// Meta is the top-level container for bits of state related to
// code coverage meta-data in the runtime.
var Meta struct {
// List contains the list of currently registered meta-data
// blobs for the running program.
List []CovMetaBlob
// PkgMap records mappings from hard-coded package IDs to
// slots in the List above.
PkgMap map[int]int
// Set to true if we discover a package mapping glitch.
hardCodedListNeedsUpdating bool
}
// AddMeta is invoked during package "init" functions by the
// compiler when compiling for coverage instrumentation; here 'p' is a
// meta-data blob of length 'dlen' for the package in question, 'hash'
// is a compiler-computed md5.sum for the blob, 'pkpath' is the
// package path, 'pkid' is the hard-coded ID that the compiler is
// using for the package (or -1 if the compiler doesn't think a
// hard-coded ID is needed), and 'cmode'/'cgran' are the coverage
// counter mode and granularity requested by the user. Return value is
// the ID for the package for use by the package code itself,
// or 0 for impossible errors.
func AddMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkgpath string, pkgid int, cmode uint8, cgran uint8) uint32 {
slot := len(Meta.List)
Meta.List = append(Meta.List, CovMetaBlob{
P: (*byte)(p),
Len: dlen,
Hash: hash,
PkgPath: pkgpath,
PkgID: pkgid,
CounterMode: cmode,
CounterGranularity: cgran,
})
if pkgid != -1 {
if Meta.PkgMap == nil {
Meta.PkgMap = make(map[int]int)
}
if _, ok := Meta.PkgMap[pkgid]; ok {
return 0
}
// Record the real slot (position on meta-list) for this
// package; we'll use the map to fix things up later on.
Meta.PkgMap[pkgid] = slot
}
// ID zero is reserved as invalid.
return uint32(slot + 1)
}

View File

@ -9,64 +9,12 @@ import (
"unsafe" "unsafe"
) )
// covMeta is the top-level container for bits of state related to // The compiler emits calls to runtime.addCovMeta
// code coverage meta-data in the runtime. // but this code has moved to rtcov.AddMeta.
var covMeta struct { func addCovMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkgpath string, pkgid int, cmode uint8, cgran uint8) uint32 {
// metaList contains the list of currently registered meta-data id := rtcov.AddMeta(p, dlen, hash, pkgpath, pkgid, cmode, cgran)
// blobs for the running program. if id == 0 {
metaList []rtcov.CovMetaBlob throw("runtime.addCovMeta: coverage package map collision")
// pkgMap records mappings from hard-coded package IDs to
// slots in the covMetaList above.
pkgMap map[int]int
// Set to true if we discover a package mapping glitch.
hardCodedListNeedsUpdating bool
}
// addCovMeta is invoked during package "init" functions by the
// compiler when compiling for coverage instrumentation; here 'p' is a
// meta-data blob of length 'dlen' for the package in question, 'hash'
// is a compiler-computed md5.sum for the blob, 'pkpath' is the
// package path, 'pkid' is the hard-coded ID that the compiler is
// using for the package (or -1 if the compiler doesn't think a
// hard-coded ID is needed), and 'cmode'/'cgran' are the coverage
// counter mode and granularity requested by the user. Return value is
// the ID for the package for use by the package code itself.
func addCovMeta(p unsafe.Pointer, dlen uint32, hash [16]byte, pkpath string, pkid int, cmode uint8, cgran uint8) uint32 {
slot := len(covMeta.metaList)
covMeta.metaList = append(covMeta.metaList,
rtcov.CovMetaBlob{
P: (*byte)(p),
Len: dlen,
Hash: hash,
PkgPath: pkpath,
PkgID: pkid,
CounterMode: cmode,
CounterGranularity: cgran,
})
if pkid != -1 {
if covMeta.pkgMap == nil {
covMeta.pkgMap = make(map[int]int)
}
if _, ok := covMeta.pkgMap[pkid]; ok {
throw("runtime.addCovMeta: coverage package map collision")
}
// Record the real slot (position on meta-list) for this
// package; we'll use the map to fix things up later on.
covMeta.pkgMap[pkid] = slot
} }
return id
// ID zero is reserved as invalid.
return uint32(slot + 1)
}
//go:linkname coverage_getCovMetaList internal/coverage/cfile.getCovMetaList
func coverage_getCovMetaList() []rtcov.CovMetaBlob {
return covMeta.metaList
}
//go:linkname coverage_getCovPkgMap internal/coverage/cfile.getCovPkgMap
func coverage_getCovPkgMap() map[int]int {
return covMeta.pkgMap
} }