xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h (revision 0c47338023d44ff130cf69465bd1b2e75ff0bb39)
1  //===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file contains support for reading coverage mapping data for
10  // instrumentation based coverage.
11  //
12  //===----------------------------------------------------------------------===//
13  
14  #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
15  #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
16  
17  #include "llvm/ADT/ArrayRef.h"
18  #include "llvm/ADT/StringRef.h"
19  #include "llvm/ProfileData/Coverage/CoverageMapping.h"
20  #include "llvm/ProfileData/InstrProf.h"
21  #include "llvm/Support/Error.h"
22  #include "llvm/Support/MemoryBuffer.h"
23  #include <cstddef>
24  #include <cstdint>
25  #include <iterator>
26  #include <memory>
27  #include <vector>
28  
29  namespace llvm {
30  namespace coverage {
31  
32  class CoverageMappingReader;
33  
34  /// Coverage mapping information for a single function.
35  struct CoverageMappingRecord {
36    StringRef FunctionName;
37    uint64_t FunctionHash;
38    ArrayRef<StringRef> Filenames;
39    ArrayRef<CounterExpression> Expressions;
40    ArrayRef<CounterMappingRegion> MappingRegions;
41  };
42  
43  /// A file format agnostic iterator over coverage mapping data.
44  class CoverageMappingIterator
45      : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
46    CoverageMappingReader *Reader;
47    CoverageMappingRecord Record;
48    coveragemap_error ReadErr;
49  
50    void increment();
51  
52  public:
53    CoverageMappingIterator()
54        : Reader(nullptr), Record(), ReadErr(coveragemap_error::success) {}
55  
56    CoverageMappingIterator(CoverageMappingReader *Reader)
57        : Reader(Reader), Record(), ReadErr(coveragemap_error::success) {
58      increment();
59    }
60  
61    ~CoverageMappingIterator() {
62      if (ReadErr != coveragemap_error::success)
63        llvm_unreachable("Unexpected error in coverage mapping iterator");
64    }
65  
66    CoverageMappingIterator &operator++() {
67      increment();
68      return *this;
69    }
70    bool operator==(const CoverageMappingIterator &RHS) const {
71      return Reader == RHS.Reader;
72    }
73    bool operator!=(const CoverageMappingIterator &RHS) const {
74      return Reader != RHS.Reader;
75    }
76    Expected<CoverageMappingRecord &> operator*() {
77      if (ReadErr != coveragemap_error::success) {
78        auto E = make_error<CoverageMapError>(ReadErr);
79        ReadErr = coveragemap_error::success;
80        return std::move(E);
81      }
82      return Record;
83    }
84    Expected<CoverageMappingRecord *> operator->() {
85      if (ReadErr != coveragemap_error::success) {
86        auto E = make_error<CoverageMapError>(ReadErr);
87        ReadErr = coveragemap_error::success;
88        return std::move(E);
89      }
90      return &Record;
91    }
92  };
93  
94  class CoverageMappingReader {
95  public:
96    virtual ~CoverageMappingReader() = default;
97  
98    virtual Error readNextRecord(CoverageMappingRecord &Record) = 0;
99    CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
100    CoverageMappingIterator end() { return CoverageMappingIterator(); }
101  };
102  
103  /// Base class for the raw coverage mapping and filenames data readers.
104  class RawCoverageReader {
105  protected:
106    StringRef Data;
107  
108    RawCoverageReader(StringRef Data) : Data(Data) {}
109  
110    Error readULEB128(uint64_t &Result);
111    Error readIntMax(uint64_t &Result, uint64_t MaxPlus1);
112    Error readSize(uint64_t &Result);
113    Error readString(StringRef &Result);
114  };
115  
116  /// Checks if the given coverage mapping data is exported for
117  /// an unused function.
118  class RawCoverageMappingDummyChecker : public RawCoverageReader {
119  public:
120    RawCoverageMappingDummyChecker(StringRef MappingData)
121        : RawCoverageReader(MappingData) {}
122  
123    Expected<bool> isDummy();
124  };
125  
126  /// Reader for the raw coverage mapping data.
127  class RawCoverageMappingReader : public RawCoverageReader {
128    ArrayRef<StringRef> TranslationUnitFilenames;
129    std::vector<StringRef> &Filenames;
130    std::vector<CounterExpression> &Expressions;
131    std::vector<CounterMappingRegion> &MappingRegions;
132  
133  public:
134    RawCoverageMappingReader(StringRef MappingData,
135                             ArrayRef<StringRef> TranslationUnitFilenames,
136                             std::vector<StringRef> &Filenames,
137                             std::vector<CounterExpression> &Expressions,
138                             std::vector<CounterMappingRegion> &MappingRegions)
139        : RawCoverageReader(MappingData),
140          TranslationUnitFilenames(TranslationUnitFilenames),
141          Filenames(Filenames), Expressions(Expressions),
142          MappingRegions(MappingRegions) {}
143    RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
144    RawCoverageMappingReader &
145    operator=(const RawCoverageMappingReader &) = delete;
146  
147    Error read();
148  
149  private:
150    Error decodeCounter(unsigned Value, Counter &C);
151    Error readCounter(Counter &C);
152    Error
153    readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions,
154                               unsigned InferredFileID, size_t NumFileIDs);
155  };
156  
157  /// Reader for the coverage mapping data that is emitted by the
158  /// frontend and stored in an object file.
159  class BinaryCoverageReader : public CoverageMappingReader {
160  public:
161    struct ProfileMappingRecord {
162      CovMapVersion Version;
163      StringRef FunctionName;
164      uint64_t FunctionHash;
165      StringRef CoverageMapping;
166      size_t FilenamesBegin;
167      size_t FilenamesSize;
168  
169      ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName,
170                           uint64_t FunctionHash, StringRef CoverageMapping,
171                           size_t FilenamesBegin, size_t FilenamesSize)
172          : Version(Version), FunctionName(FunctionName),
173            FunctionHash(FunctionHash), CoverageMapping(CoverageMapping),
174            FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {}
175    };
176  
177    using DecompressedData = std::vector<std::unique_ptr<SmallVector<char, 0>>>;
178  
179  private:
180    std::vector<StringRef> Filenames;
181    std::vector<ProfileMappingRecord> MappingRecords;
182    InstrProfSymtab ProfileNames;
183    size_t CurrentRecord = 0;
184    std::vector<StringRef> FunctionsFilenames;
185    std::vector<CounterExpression> Expressions;
186    std::vector<CounterMappingRegion> MappingRegions;
187  
188    // Used to tie the lifetimes of coverage function records to the lifetime of
189    // this BinaryCoverageReader instance. Needed to support the format change in
190    // D69471, which can split up function records into multiple sections on ELF.
191    std::string FuncRecords;
192  
193    // Used to tie the lifetimes of decompressed strings to the lifetime of this
194    // BinaryCoverageReader instance.
195    DecompressedData Decompressed;
196  
197    BinaryCoverageReader(std::string &&FuncRecords)
198        : FuncRecords(std::move(FuncRecords)) {}
199  
200  public:
201    BinaryCoverageReader(const BinaryCoverageReader &) = delete;
202    BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
203  
204    static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
205    create(MemoryBufferRef ObjectBuffer, StringRef Arch,
206           SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers);
207  
208    static Expected<std::unique_ptr<BinaryCoverageReader>>
209    createCoverageReaderFromBuffer(StringRef Coverage, std::string &&FuncRecords,
210                                   InstrProfSymtab &&ProfileNames,
211                                   uint8_t BytesInAddress,
212                                   support::endianness Endian);
213  
214    Error readNextRecord(CoverageMappingRecord &Record) override;
215  };
216  
217  /// Reader for the raw coverage filenames.
218  class RawCoverageFilenamesReader : public RawCoverageReader {
219    std::vector<StringRef> &Filenames;
220  
221    // Read an uncompressed sequence of filenames.
222    Error readUncompressed(uint64_t NumFilenames);
223  
224  public:
225    RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
226        : RawCoverageReader(Data), Filenames(Filenames) {}
227    RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
228    RawCoverageFilenamesReader &
229    operator=(const RawCoverageFilenamesReader &) = delete;
230  
231    Error read(CovMapVersion Version,
232               BinaryCoverageReader::DecompressedData &Decompressed);
233  };
234  
235  } // end namespace coverage
236  } // end namespace llvm
237  
238  #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
239