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 5package raw 6 7import ( 8 "bufio" 9 "encoding/binary" 10 "fmt" 11 "io" 12 13 "internal/trace/event" 14 "internal/trace/version" 15) 16 17// Reader parses trace bytes with only very basic validation 18// into an event stream. 19type Reader struct { 20 r *bufio.Reader 21 v version.Version 22 specs []event.Spec 23} 24 25// NewReader creates a new reader for the trace wire format. 26func NewReader(r io.Reader) (*Reader, error) { 27 br := bufio.NewReader(r) 28 v, err := version.ReadHeader(br) 29 if err != nil { 30 return nil, err 31 } 32 return &Reader{r: br, v: v, specs: v.Specs()}, nil 33} 34 35// Version returns the version of the trace that we're reading. 36func (r *Reader) Version() version.Version { 37 return r.v 38} 39 40// ReadEvent reads and returns the next trace event in the byte stream. 41func (r *Reader) ReadEvent() (Event, error) { 42 evb, err := r.r.ReadByte() 43 if err == io.EOF { 44 return Event{}, io.EOF 45 } 46 if err != nil { 47 return Event{}, err 48 } 49 if int(evb) >= len(r.specs) || evb == 0 { 50 return Event{}, fmt.Errorf("invalid event type: %d", evb) 51 } 52 ev := event.Type(evb) 53 spec := r.specs[ev] 54 args, err := r.readArgs(len(spec.Args)) 55 if err != nil { 56 return Event{}, err 57 } 58 if spec.IsStack { 59 len := int(args[1]) 60 for i := 0; i < len; i++ { 61 // Each stack frame has four args: pc, func ID, file ID, line number. 62 frame, err := r.readArgs(4) 63 if err != nil { 64 return Event{}, err 65 } 66 args = append(args, frame...) 67 } 68 } 69 var data []byte 70 if spec.HasData { 71 data, err = r.readData() 72 if err != nil { 73 return Event{}, err 74 } 75 } 76 return Event{ 77 Version: r.v, 78 Ev: ev, 79 Args: args, 80 Data: data, 81 }, nil 82} 83 84func (r *Reader) readArgs(n int) ([]uint64, error) { 85 var args []uint64 86 for i := 0; i < n; i++ { 87 val, err := binary.ReadUvarint(r.r) 88 if err != nil { 89 return nil, err 90 } 91 args = append(args, val) 92 } 93 return args, nil 94} 95 96func (r *Reader) readData() ([]byte, error) { 97 len, err := binary.ReadUvarint(r.r) 98 if err != nil { 99 return nil, err 100 } 101 var data []byte 102 for i := 0; i < int(len); i++ { 103 b, err := r.r.ReadByte() 104 if err != nil { 105 return nil, err 106 } 107 data = append(data, b) 108 } 109 return data, nil 110} 111