diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:19:13 +0000 |
commit | ccd992355df7192993c666236047820244914598 (patch) | |
tree | f00fea65147227b7743083c6148396f74cd66935 /src/internal/coverage/decodemeta/decode.go | |
parent | Initial commit. (diff) | |
download | golang-1.21-ccd992355df7192993c666236047820244914598.tar.xz golang-1.21-ccd992355df7192993c666236047820244914598.zip |
Adding upstream version 1.21.8.upstream/1.21.8
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/internal/coverage/decodemeta/decode.go')
-rw-r--r-- | src/internal/coverage/decodemeta/decode.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/internal/coverage/decodemeta/decode.go b/src/internal/coverage/decodemeta/decode.go new file mode 100644 index 0000000..fa047c7 --- /dev/null +++ b/src/internal/coverage/decodemeta/decode.go @@ -0,0 +1,136 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package decodemeta + +// This package contains APIs and helpers for decoding a single package's +// meta data "blob" emitted by the compiler when coverage instrumentation +// is turned on. + +import ( + "encoding/binary" + "fmt" + "internal/coverage" + "internal/coverage/slicereader" + "internal/coverage/stringtab" + "io" + "os" +) + +// See comments in the encodecovmeta package for details on the format. + +type CoverageMetaDataDecoder struct { + r *slicereader.Reader + hdr coverage.MetaSymbolHeader + strtab *stringtab.Reader + tmp []byte + debug bool +} + +func NewCoverageMetaDataDecoder(b []byte, readonly bool) (*CoverageMetaDataDecoder, error) { + slr := slicereader.NewReader(b, readonly) + x := &CoverageMetaDataDecoder{ + r: slr, + tmp: make([]byte, 0, 256), + } + if err := x.readHeader(); err != nil { + return nil, err + } + if err := x.readStringTable(); err != nil { + return nil, err + } + return x, nil +} + +func (d *CoverageMetaDataDecoder) readHeader() error { + if err := binary.Read(d.r, binary.LittleEndian, &d.hdr); err != nil { + return err + } + if d.debug { + fmt.Fprintf(os.Stderr, "=-= after readHeader: %+v\n", d.hdr) + } + return nil +} + +func (d *CoverageMetaDataDecoder) readStringTable() error { + // Seek to the correct location to read the string table. + stringTableLocation := int64(coverage.CovMetaHeaderSize + 4*d.hdr.NumFuncs) + if _, err := d.r.Seek(stringTableLocation, io.SeekStart); err != nil { + return err + } + + // Read the table itself. + d.strtab = stringtab.NewReader(d.r) + d.strtab.Read() + return nil +} + +func (d *CoverageMetaDataDecoder) PackagePath() string { + return d.strtab.Get(d.hdr.PkgPath) +} + +func (d *CoverageMetaDataDecoder) PackageName() string { + return d.strtab.Get(d.hdr.PkgName) +} + +func (d *CoverageMetaDataDecoder) ModulePath() string { + return d.strtab.Get(d.hdr.ModulePath) +} + +func (d *CoverageMetaDataDecoder) NumFuncs() uint32 { + return d.hdr.NumFuncs +} + +// ReadFunc reads the coverage meta-data for the function with index +// 'findex', filling it into the FuncDesc pointed to by 'f'. +func (d *CoverageMetaDataDecoder) ReadFunc(fidx uint32, f *coverage.FuncDesc) error { + if fidx >= d.hdr.NumFuncs { + return fmt.Errorf("illegal function index") + } + + // Seek to the correct location to read the function offset and read it. + funcOffsetLocation := int64(coverage.CovMetaHeaderSize + 4*fidx) + if _, err := d.r.Seek(funcOffsetLocation, io.SeekStart); err != nil { + return err + } + foff := d.r.ReadUint32() + + // Check assumptions + if foff < uint32(funcOffsetLocation) || foff > d.hdr.Length { + return fmt.Errorf("malformed func offset %d", foff) + } + + // Seek to the correct location to read the function. + floc := int64(foff) + if _, err := d.r.Seek(floc, io.SeekStart); err != nil { + return err + } + + // Preamble containing number of units, file, and function. + numUnits := uint32(d.r.ReadULEB128()) + fnameidx := uint32(d.r.ReadULEB128()) + fileidx := uint32(d.r.ReadULEB128()) + + f.Srcfile = d.strtab.Get(fileidx) + f.Funcname = d.strtab.Get(fnameidx) + + // Now the units + f.Units = f.Units[:0] + if cap(f.Units) < int(numUnits) { + f.Units = make([]coverage.CoverableUnit, 0, numUnits) + } + for k := uint32(0); k < numUnits; k++ { + f.Units = append(f.Units, + coverage.CoverableUnit{ + StLine: uint32(d.r.ReadULEB128()), + StCol: uint32(d.r.ReadULEB128()), + EnLine: uint32(d.r.ReadULEB128()), + EnCol: uint32(d.r.ReadULEB128()), + NxStmts: uint32(d.r.ReadULEB128()), + }) + } + lit := d.r.ReadULEB128() + f.Lit = lit != 0 + return nil +} |