github.com/bir3/gocompiler@v0.9.2202/src/internal/coverage/decodemeta/decode.go (about) 1 // Copyright 2021 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 decodemeta 6 7 // This package contains APIs and helpers for decoding a single package's 8 // meta data "blob" emitted by the compiler when coverage instrumentation 9 // is turned on. 10 11 import ( 12 "encoding/binary" 13 "fmt" 14 "github.com/bir3/gocompiler/src/internal/coverage" 15 "github.com/bir3/gocompiler/src/internal/coverage/slicereader" 16 "github.com/bir3/gocompiler/src/internal/coverage/stringtab" 17 "io" 18 "os" 19 ) 20 21 // See comments in the encodecovmeta package for details on the format. 22 23 type CoverageMetaDataDecoder struct { 24 r *slicereader.Reader 25 hdr coverage.MetaSymbolHeader 26 strtab *stringtab.Reader 27 tmp []byte 28 debug bool 29 } 30 31 func NewCoverageMetaDataDecoder(b []byte, readonly bool) (*CoverageMetaDataDecoder, error) { 32 slr := slicereader.NewReader(b, readonly) 33 x := &CoverageMetaDataDecoder{ 34 r: slr, 35 tmp: make([]byte, 0, 256), 36 } 37 if err := x.readHeader(); err != nil { 38 return nil, err 39 } 40 if err := x.readStringTable(); err != nil { 41 return nil, err 42 } 43 return x, nil 44 } 45 46 func (d *CoverageMetaDataDecoder) readHeader() error { 47 if err := binary.Read(d.r, binary.LittleEndian, &d.hdr); err != nil { 48 return err 49 } 50 if d.debug { 51 fmt.Fprintf(os.Stderr, "=-= after readHeader: %+v\n", d.hdr) 52 } 53 return nil 54 } 55 56 func (d *CoverageMetaDataDecoder) readStringTable() error { 57 // Seek to the correct location to read the string table. 58 stringTableLocation := int64(coverage.CovMetaHeaderSize + 4*d.hdr.NumFuncs) 59 if _, err := d.r.Seek(stringTableLocation, io.SeekStart); err != nil { 60 return err 61 } 62 63 // Read the table itself. 64 d.strtab = stringtab.NewReader(d.r) 65 d.strtab.Read() 66 return nil 67 } 68 69 func (d *CoverageMetaDataDecoder) PackagePath() string { 70 return d.strtab.Get(d.hdr.PkgPath) 71 } 72 73 func (d *CoverageMetaDataDecoder) PackageName() string { 74 return d.strtab.Get(d.hdr.PkgName) 75 } 76 77 func (d *CoverageMetaDataDecoder) ModulePath() string { 78 return d.strtab.Get(d.hdr.ModulePath) 79 } 80 81 func (d *CoverageMetaDataDecoder) NumFuncs() uint32 { 82 return d.hdr.NumFuncs 83 } 84 85 // ReadFunc reads the coverage meta-data for the function with index 86 // 'findex', filling it into the FuncDesc pointed to by 'f'. 87 func (d *CoverageMetaDataDecoder) ReadFunc(fidx uint32, f *coverage.FuncDesc) error { 88 if fidx >= d.hdr.NumFuncs { 89 return fmt.Errorf("illegal function index") 90 } 91 92 // Seek to the correct location to read the function offset and read it. 93 funcOffsetLocation := int64(coverage.CovMetaHeaderSize + 4*fidx) 94 if _, err := d.r.Seek(funcOffsetLocation, io.SeekStart); err != nil { 95 return err 96 } 97 foff := d.r.ReadUint32() 98 99 // Check assumptions 100 if foff < uint32(funcOffsetLocation) || foff > d.hdr.Length { 101 return fmt.Errorf("malformed func offset %d", foff) 102 } 103 104 // Seek to the correct location to read the function. 105 floc := int64(foff) 106 if _, err := d.r.Seek(floc, io.SeekStart); err != nil { 107 return err 108 } 109 110 // Preamble containing number of units, file, and function. 111 numUnits := uint32(d.r.ReadULEB128()) 112 fnameidx := uint32(d.r.ReadULEB128()) 113 fileidx := uint32(d.r.ReadULEB128()) 114 115 f.Srcfile = d.strtab.Get(fileidx) 116 f.Funcname = d.strtab.Get(fnameidx) 117 118 // Now the units 119 f.Units = f.Units[:0] 120 if cap(f.Units) < int(numUnits) { 121 f.Units = make([]coverage.CoverableUnit, 0, numUnits) 122 } 123 for k := uint32(0); k < numUnits; k++ { 124 f.Units = append(f.Units, 125 coverage.CoverableUnit{ 126 StLine: uint32(d.r.ReadULEB128()), 127 StCol: uint32(d.r.ReadULEB128()), 128 EnLine: uint32(d.r.ReadULEB128()), 129 EnCol: uint32(d.r.ReadULEB128()), 130 NxStmts: uint32(d.r.ReadULEB128()), 131 }) 132 } 133 lit := d.r.ReadULEB128() 134 f.Lit = lit != 0 135 return nil 136 }