1
2
3
4
5 package decodemeta
6
7
8
9
10
11 import (
12 "encoding/binary"
13 "fmt"
14 "internal/coverage"
15 "internal/coverage/slicereader"
16 "internal/coverage/stringtab"
17 "io"
18 "os"
19 )
20
21
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
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
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
86
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
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
100 if foff < uint32(funcOffsetLocation) || foff > d.hdr.Length {
101 return fmt.Errorf("malformed func offset %d", foff)
102 }
103
104
105 floc := int64(foff)
106 if _, err := d.r.Seek(floc, io.SeekStart); err != nil {
107 return err
108 }
109
110
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
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 }
137
View as plain text