blob: 9e30d679007dbdb42166dc4c8589dc9b049140d5 [file] [log] [blame]
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rtcov
import "unsafe"
// This package contains types whose structure is shared between
// the runtime package and the "runtime/coverage" implementation.
// CovMetaBlob is a container for holding the meta-data symbol (an
// RODATA variable) for an instrumented Go package. Here "p" points to
// the symbol itself, "len" is the length of the sym in bytes, and
// "hash" is an md5sum for the sym computed by the compiler. When
// the init function for a coverage-instrumented package executes, it
// will make a call into the runtime which will create a covMetaBlob
// object for the package and chain it onto a global list.
type CovMetaBlob struct {
P *byte
Len uint32
Hash [16]byte
PkgPath string
PkgID int
CounterMode uint8 // coverage.CounterMode
CounterGranularity uint8 // coverage.CounterGranularity
}
// CovCounterBlob is a container for encapsulating a counter section
// (BSS variable) for an instrumented Go module. Here "counters"
// points to the counter payload and "len" is the number of uint32
// entries in the section.
type CovCounterBlob struct {
Counters *uint32
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)
}