1 // Copyright 2023 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 version
6 7 import (
8 "fmt"
9 "io"
10 11 "internal/trace/tracev2"
12 )
13 14 // Version represents the version of a trace file.
15 type Version uint32
16 17 const (
18 Go111 Version = 11 // v1
19 Go119 Version = 19 // v1
20 Go121 Version = 21 // v1
21 Go122 Version = 22 // v2
22 Go123 Version = 23 // v2
23 Go125 Version = 25 // v2
24 Current = Go125
25 )
26 27 var versions = map[Version][]tracev2.EventSpec{
28 // Go 1.11–1.21 use a different parser and are only set here for the sake of
29 // Version.Valid.
30 Go111: nil,
31 Go119: nil,
32 Go121: nil,
33 34 Go122: tracev2.Specs()[:tracev2.EvUserLog+1], // All events after are Go 1.23+.
35 Go123: tracev2.Specs()[:tracev2.EvExperimentalBatch+1], // All events after are Go 1.25+.
36 Go125: tracev2.Specs(),
37 }
38 39 // Specs returns the set of event.Specs for this version.
40 func (v Version) Specs() []tracev2.EventSpec {
41 return versions[v]
42 }
43 44 // EventName returns a string name of a wire format event
45 // for a particular trace version.
46 func (v Version) EventName(typ tracev2.EventType) []byte {
47 if !v.Valid() {
48 return "<invalid trace version>"
49 }
50 s := v.Specs()
51 if len(s) == 0 {
52 return "<v1 trace event type>"
53 }
54 if int(typ) < len(s) && s[typ].Name != "" {
55 return s[typ].Name
56 }
57 return fmt.Sprintf("Invalid(%d)", typ)
58 }
59 60 func (v Version) Valid() bool {
61 _, ok := versions[v]
62 return ok
63 }
64 65 // headerFmt is the format of the header of all Go execution traces.
66 const headerFmt = "go 1.%d trace\x00\x00\x00"
67 68 // ReadHeader reads the version of the trace out of the trace file's
69 // header, whose prefix must be present in v.
70 func ReadHeader(r io.Reader) (Version, error) {
71 var v Version
72 _, err := fmt.Fscanf(r, headerFmt, &v)
73 if err != nil {
74 return v, fmt.Errorf("bad file format: not a Go execution trace?")
75 }
76 if !v.Valid() {
77 return v, fmt.Errorf("unknown or unsupported trace version go 1.%d", v)
78 }
79 return v, nil
80 }
81 82 // WriteHeader writes a header for a trace version v to w.
83 func WriteHeader(w io.Writer, v Version) (int, error) {
84 return fmt.Fprintf(w, headerFmt, v)
85 }
86