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
5package coverage
6
7// Types and constants related to the output files written
8// by code coverage tooling. When a coverage-instrumented binary
9// is run, it emits two output files: a meta-data output file, and
10// a counter data output file.
11
12//.....................................................................
13//
14// Meta-data definitions:
15//
16// The meta-data file is composed of a file header, a series of
17// meta-data blobs/sections (one per instrumented package), and an offsets
18// area storing the offsets of each section. Format of the meta-data
19// file looks like:
20//
21// --header----------
22//  | magic: [4]byte magic string
23//  | version
24//  | total length of meta-data file in bytes
25//  | numPkgs: number of package entries in file
26//  | hash: [16]byte hash of entire meta-data payload
27//  | offset to string table section
28//  | length of string table
29//  | number of entries in string table
30//  | counter mode
31//  | counter granularity
32//  --package offsets table------
33//  <offset to pkg 0>
34//  <offset to pkg 1>
35//  ...
36//  --package lengths table------
37//  <length of pkg 0>
38//  <length of pkg 1>
39//  ...
40//  --string table------
41//  <uleb128 len> 8
42//  <data> "somestring"
43//  ...
44//  --package payloads------
45//  <meta-symbol for pkg 0>
46//  <meta-symbol for pkg 1>
47//  ...
48//
49// Each package payload is a stand-alone blob emitted by the compiler,
50// and does not depend on anything else in the meta-data file. In
51// particular, each blob has it's own string table. Note that the
52// file-level string table is expected to be very short (most strings
53// will be in the meta-data blobs themselves).
54
55// CovMetaMagic holds the magic string for a meta-data file.
56var CovMetaMagic = [4]byte{'\x00', '\x63', '\x76', '\x6d'}
57
58// MetaFilePref is a prefix used when emitting meta-data files; these
59// files are of the form "covmeta.<hash>", where hash is a hash
60// computed from the hashes of all the package meta-data symbols in
61// the program.
62const MetaFilePref = "covmeta"
63
64// MetaFileVersion contains the current (most recent) meta-data file version.
65const MetaFileVersion = 1
66
67// MetaFileHeader stores file header information for a meta-data file.
68type MetaFileHeader struct {
69	Magic        [4]byte
70	Version      uint32
71	TotalLength  uint64
72	Entries      uint64
73	MetaFileHash [16]byte
74	StrTabOffset uint32
75	StrTabLength uint32
76	CMode        CounterMode
77	CGranularity CounterGranularity
78	_            [6]byte // padding
79}
80
81// MetaSymbolHeader stores header information for a single
82// meta-data blob, e.g. the coverage meta-data payload
83// computed for a given Go package.
84type MetaSymbolHeader struct {
85	Length     uint32 // size of meta-symbol payload in bytes
86	PkgName    uint32 // string table index
87	PkgPath    uint32 // string table index
88	ModulePath uint32 // string table index
89	MetaHash   [16]byte
90	_          byte    // currently unused
91	_          [3]byte // padding
92	NumFiles   uint32
93	NumFuncs   uint32
94}
95
96const CovMetaHeaderSize = 16 + 4 + 4 + 4 + 4 + 4 + 4 + 4 // keep in sync with above
97
98// As an example, consider the following Go package:
99//
100// 01: package p
101// 02:
102// 03: var v, w, z int
103// 04:
104// 05: func small(x, y int) int {
105// 06:   v++
106// 07:   // comment
107// 08:   if y == 0 {
108// 09:     return x
109// 10:   }
110// 11:   return (x << 1) ^ (9 / y)
111// 12: }
112// 13:
113// 14: func Medium(q, r int) int {
114// 15:   s1 := small(q, r)
115// 16:   z += s1
116// 17:   s2 := small(r, q)
117// 18:   w -= s2
118// 19:   return w + z
119// 20: }
120//
121// The meta-data blob for the single package above might look like the
122// following:
123//
124// -- MetaSymbolHeader header----------
125//  | size: size of this blob in bytes
126//  | packagepath: <path to p>
127//  | modulepath: <modpath for p>
128//  | nfiles: 1
129//  | nfunctions: 2
130//  --func offsets table------
131//  <offset to func 0>
132//  <offset to func 1>
133//  --string table (contains all files and functions)------
134//  | <uleb128 len> 4
135//  | <data> "p.go"
136//  | <uleb128 len> 5
137//  | <data> "small"
138//  | <uleb128 len> 6
139//  | <data> "Medium"
140//  --func 0------
141//  | <uleb128> num units: 3
142//  | <uleb128> func name: S1 (index into string table)
143//  | <uleb128> file: S0 (index into string table)
144//  | <unit 0>:  S0   L6     L8    2
145//  | <unit 1>:  S0   L9     L9    1
146//  | <unit 2>:  S0   L11    L11   1
147//  --func 1------
148//  | <uleb128> num units: 1
149//  | <uleb128> func name: S2 (index into string table)
150//  | <uleb128> file: S0 (index into string table)
151//  | <unit 0>:  S0   L15    L19   5
152//  ---end-----------
153
154// The following types and constants used by the meta-data encoder/decoder.
155
156// FuncDesc encapsulates the meta-data definitions for a single Go function.
157// This version assumes that we're looking at a function before inlining;
158// if we want to capture a post-inlining view of the world, the
159// representations of source positions would need to be a good deal more
160// complicated.
161type FuncDesc struct {
162	Funcname string
163	Srcfile  string
164	Units    []CoverableUnit
165	Lit      bool // true if this is a function literal
166}
167
168// CoverableUnit describes the source characteristics of a single
169// program unit for which we want to gather coverage info. Coverable
170// units are either "simple" or "intraline"; a "simple" coverable unit
171// corresponds to a basic block (region of straight-line code with no
172// jumps or control transfers). An "intraline" unit corresponds to a
173// logical clause nested within some other simple unit. A simple unit
174// will have a zero Parent value; for an intraline unit NxStmts will
175// be zero and Parent will be set to 1 plus the index of the
176// containing simple statement. Example:
177//
178//	L7:   q := 1
179//	L8:   x := (y == 101 || launch() == false)
180//	L9:   r := x * 2
181//
182// For the code above we would have three simple units (one for each
183// line), then an intraline unit describing the "launch() == false"
184// clause in line 8, with Parent pointing to the index of the line 8
185// unit in the units array.
186//
187// Note: in the initial version of the coverage revamp, only simple
188// units will be in use.
189type CoverableUnit struct {
190	StLine, StCol uint32
191	EnLine, EnCol uint32
192	NxStmts       uint32
193	Parent        uint32
194}
195
196// CounterMode tracks the "flavor" of the coverage counters being
197// used in a given coverage-instrumented program.
198type CounterMode uint8
199
200const (
201	CtrModeInvalid  CounterMode = iota
202	CtrModeSet                  // "set" mode
203	CtrModeCount                // "count" mode
204	CtrModeAtomic               // "atomic" mode
205	CtrModeRegOnly              // registration-only pseudo-mode
206	CtrModeTestMain             // testmain pseudo-mode
207)
208
209func (cm CounterMode) String() string {
210	switch cm {
211	case CtrModeSet:
212		return "set"
213	case CtrModeCount:
214		return "count"
215	case CtrModeAtomic:
216		return "atomic"
217	case CtrModeRegOnly:
218		return "regonly"
219	case CtrModeTestMain:
220		return "testmain"
221	}
222	return "<invalid>"
223}
224
225func ParseCounterMode(mode string) CounterMode {
226	var cm CounterMode
227	switch mode {
228	case "set":
229		cm = CtrModeSet
230	case "count":
231		cm = CtrModeCount
232	case "atomic":
233		cm = CtrModeAtomic
234	case "regonly":
235		cm = CtrModeRegOnly
236	case "testmain":
237		cm = CtrModeTestMain
238	default:
239		cm = CtrModeInvalid
240	}
241	return cm
242}
243
244// CounterGranularity tracks the granularity of the coverage counters being
245// used in a given coverage-instrumented program.
246type CounterGranularity uint8
247
248const (
249	CtrGranularityInvalid CounterGranularity = iota
250	CtrGranularityPerBlock
251	CtrGranularityPerFunc
252)
253
254func (cm CounterGranularity) String() string {
255	switch cm {
256	case CtrGranularityPerBlock:
257		return "perblock"
258	case CtrGranularityPerFunc:
259		return "perfunc"
260	}
261	return "<invalid>"
262}
263
264// Name of file within the "go test -cover" temp coverdir directory
265// containing a list of meta-data files for packages being tested
266// in a "go test -coverpkg=... ..." run. This constant is shared
267// by the Go command and by the coverage runtime.
268const MetaFilesFileName = "metafiles.txt"
269
270// MetaFileCollection contains information generated by the Go command and
271// the read in by coverage test support functions within an executing
272// "go test -cover" binary.
273type MetaFileCollection struct {
274	ImportPaths       []string
275	MetaFileFragments []string
276}
277
278//.....................................................................
279//
280// Counter data definitions:
281//
282
283// A counter data file is composed of a file header followed by one or
284// more "segments" (each segment representing a given run or partial
285// run of a give binary) followed by a footer.
286
287// CovCounterMagic holds the magic string for a coverage counter-data file.
288var CovCounterMagic = [4]byte{'\x00', '\x63', '\x77', '\x6d'}
289
290// CounterFileVersion stores the most recent counter data file version.
291const CounterFileVersion = 1
292
293// CounterFileHeader stores files header information for a counter-data file.
294type CounterFileHeader struct {
295	Magic     [4]byte
296	Version   uint32
297	MetaHash  [16]byte
298	CFlavor   CounterFlavor
299	BigEndian bool
300	_         [6]byte // padding
301}
302
303// CounterSegmentHeader encapsulates information about a specific
304// segment in a counter data file, which at the moment contains
305// counters data from a single execution of a coverage-instrumented
306// program. Following the segment header will be the string table and
307// args table, and then (possibly) padding bytes to bring the byte
308// size of the preamble up to a multiple of 4. Immediately following
309// that will be the counter payloads.
310//
311// The "args" section of a segment is used to store annotations
312// describing where the counter data came from; this section is
313// basically a series of key-value pairs (can be thought of as an
314// encoded 'map[string]string'). At the moment we only write os.Args()
315// data to this section, using pairs of the form "argc=<integer>",
316// "argv0=<os.Args[0]>", "argv1=<os.Args[1]>", and so on. In the
317// future the args table may also include things like GOOS/GOARCH
318// values, and/or tags indicating which tests were run to generate the
319// counter data.
320type CounterSegmentHeader struct {
321	FcnEntries uint64
322	StrTabLen  uint32
323	ArgsLen    uint32
324}
325
326// CounterFileFooter appears at the tail end of a counter data file,
327// and stores the number of segments it contains.
328type CounterFileFooter struct {
329	Magic       [4]byte
330	_           [4]byte // padding
331	NumSegments uint32
332	_           [4]byte // padding
333}
334
335// CounterFilePref is the file prefix used when emitting coverage data
336// output files. CounterFileTemplate describes the format of the file
337// name: prefix followed by meta-file hash followed by process ID
338// followed by emit UnixNanoTime.
339const CounterFilePref = "covcounters"
340const CounterFileTempl = "%s.%x.%d.%d"
341const CounterFileRegexp = `^%s\.(\S+)\.(\d+)\.(\d+)+$`
342
343// CounterFlavor describes how function and counters are
344// stored/represented in the counter section of the file.
345type CounterFlavor uint8
346
347const (
348	// "Raw" representation: all values (pkg ID, func ID, num counters,
349	// and counters themselves) are stored as uint32's.
350	CtrRaw CounterFlavor = iota + 1
351
352	// "ULeb" representation: all values (pkg ID, func ID, num counters,
353	// and counters themselves) are stored with ULEB128 encoding.
354	CtrULeb128
355)
356
357func Round4(x int) int {
358	return (x + 3) &^ 3
359}
360
361//.....................................................................
362//
363// Runtime counter data definitions.
364//
365
366// At runtime within a coverage-instrumented program, the "counters"
367// object we associated with instrumented function can be thought of
368// as a struct of the following form:
369//
370// struct {
371//     numCtrs uint32
372//     pkgid uint32
373//     funcid uint32
374//     counterArray [numBlocks]uint32
375// }
376//
377// where "numCtrs" is the number of blocks / coverable units within the
378// function, "pkgid" is the unique index assigned to this package by
379// the runtime, "funcid" is the index of this function within its containing
380// package, and "counterArray" stores the actual counters.
381//
382// The counter variable itself is created not as a struct but as a flat
383// array of uint32's; we then use the offsets below to index into it.
384
385const NumCtrsOffset = 0
386const PkgIdOffset = 1
387const FuncIdOffset = 2
388const FirstCtrOffset = 3
389