github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/trace/v2/raw/writer.go (about) 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 raw 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 12 "github.com/go-asm/go/trace/v2/event" 13 "github.com/go-asm/go/trace/v2/version" 14 ) 15 16 // Writer emits the wire format of a trace. 17 // 18 // It may not produce a byte-for-byte compatible trace from what is 19 // produced by the runtime, because it may be missing extra padding 20 // in the LEB128 encoding that the runtime adds but isn't necessary 21 // when you know the data up-front. 22 type Writer struct { 23 w io.Writer 24 buf []byte 25 v version.Version 26 specs []event.Spec 27 } 28 29 // NewWriter creates a new byte format writer. 30 func NewWriter(w io.Writer, v version.Version) (*Writer, error) { 31 _, err := version.WriteHeader(w, v) 32 return &Writer{w: w, v: v, specs: v.Specs()}, err 33 } 34 35 // WriteEvent writes a single event to the trace wire format stream. 36 func (w *Writer) WriteEvent(e Event) error { 37 // Check version. 38 if e.Version != w.v { 39 return fmt.Errorf("mismatched version between writer (go 1.%d) and event (go 1.%d)", w.v, e.Version) 40 } 41 42 // Write event header byte. 43 w.buf = append(w.buf, uint8(e.Ev)) 44 45 // Write out all arguments. 46 spec := w.specs[e.Ev] 47 for _, arg := range e.Args[:len(spec.Args)] { 48 w.buf = binary.AppendUvarint(w.buf, arg) 49 } 50 if spec.IsStack { 51 frameArgs := e.Args[len(spec.Args):] 52 for i := 0; i < len(frameArgs); i++ { 53 w.buf = binary.AppendUvarint(w.buf, frameArgs[i]) 54 } 55 } 56 57 // Write out the length of the data. 58 if spec.HasData { 59 w.buf = binary.AppendUvarint(w.buf, uint64(len(e.Data))) 60 } 61 62 // Write out varint events. 63 _, err := w.w.Write(w.buf) 64 w.buf = w.buf[:0] 65 if err != nil { 66 return err 67 } 68 69 // Write out data. 70 if spec.HasData { 71 _, err := w.w.Write(e.Data) 72 return err 73 } 74 return nil 75 }