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
29namespace llvm {
30namespace coverage {
31
32class CoverageMappingReader;
33
34/// Coverage mapping information for a single function.
35struct 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.
44class CoverageMappingIterator {
45 CoverageMappingReader *Reader;
46 CoverageMappingRecord Record;
47 coveragemap_error ReadErr;
48
49 void increment();
50
51public:
52 using iterator_category = std::input_iterator_tag;
53 using value_type = CoverageMappingRecord;
54 using difference_type = std::ptrdiff_t;
55 using pointer = value_type *;
56 using reference = value_type &;
57
58 CoverageMappingIterator()
59 : Reader(nullptr), ReadErr(coveragemap_error::success) {}
60
61 CoverageMappingIterator(CoverageMappingReader *Reader)
62 : Reader(Reader), ReadErr(coveragemap_error::success) {
63 increment();
64 }
65
66 ~CoverageMappingIterator() {
67 if (ReadErr != coveragemap_error::success)
68 llvm_unreachable("Unexpected error in coverage mapping iterator");
69 }
70
71 CoverageMappingIterator &operator++() {
72 increment();
73 return *this;
74 }
75 bool operator==(const CoverageMappingIterator &RHS) const {
76 return Reader == RHS.Reader;
77 }
78 bool operator!=(const CoverageMappingIterator &RHS) const {
79 return Reader != RHS.Reader;
80 }
81 Expected<CoverageMappingRecord &> operator*() {
82 if (ReadErr != coveragemap_error::success) {
83 auto E = make_error<CoverageMapError>(Args&: ReadErr);
84 ReadErr = coveragemap_error::success;
85 return std::move(E);
86 }
87 return Record;
88 }
89 Expected<CoverageMappingRecord *> operator->() {
90 if (ReadErr != coveragemap_error::success) {
91 auto E = make_error<CoverageMapError>(Args&: ReadErr);
92 ReadErr = coveragemap_error::success;
93 return std::move(E);
94 }
95 return &Record;
96 }
97};
98
99class CoverageMappingReader {
100public:
101 virtual ~CoverageMappingReader() = default;
102
103 virtual Error readNextRecord(CoverageMappingRecord &Record) = 0;
104 CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
105 CoverageMappingIterator end() { return CoverageMappingIterator(); }
106};
107
108/// Base class for the raw coverage mapping and filenames data readers.
109class RawCoverageReader {
110protected:
111 StringRef Data;
112
113 RawCoverageReader(StringRef Data) : Data(Data) {}
114
115 Error readULEB128(uint64_t &Result);
116 Error readIntMax(uint64_t &Result, uint64_t MaxPlus1);
117 Error readSize(uint64_t &Result);
118 Error readString(StringRef &Result);
119};
120
121/// Checks if the given coverage mapping data is exported for
122/// an unused function.
123class RawCoverageMappingDummyChecker : public RawCoverageReader {
124public:
125 RawCoverageMappingDummyChecker(StringRef MappingData)
126 : RawCoverageReader(MappingData) {}
127
128 Expected<bool> isDummy();
129};
130
131/// Reader for the raw coverage mapping data.
132class RawCoverageMappingReader : public RawCoverageReader {
133 ArrayRef<std::string> &TranslationUnitFilenames;
134 std::vector<StringRef> &Filenames;
135 std::vector<CounterExpression> &Expressions;
136 std::vector<CounterMappingRegion> &MappingRegions;
137
138public:
139 RawCoverageMappingReader(StringRef MappingData,
140 ArrayRef<std::string> &TranslationUnitFilenames,
141 std::vector<StringRef> &Filenames,
142 std::vector<CounterExpression> &Expressions,
143 std::vector<CounterMappingRegion> &MappingRegions)
144 : RawCoverageReader(MappingData),
145 TranslationUnitFilenames(TranslationUnitFilenames),
146 Filenames(Filenames), Expressions(Expressions),
147 MappingRegions(MappingRegions) {}
148 RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
149 RawCoverageMappingReader &
150 operator=(const RawCoverageMappingReader &) = delete;
151
152 Error read();
153
154private:
155 Error decodeCounter(unsigned Value, Counter &C);
156 Error readCounter(Counter &C);
157 Error
158 readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions,
159 unsigned InferredFileID, size_t NumFileIDs);
160};
161
162/// Reader for the coverage mapping data that is emitted by the
163/// frontend and stored in an object file.
164class BinaryCoverageReader : public CoverageMappingReader {
165public:
166 struct ProfileMappingRecord {
167 CovMapVersion Version;
168 StringRef FunctionName;
169 uint64_t FunctionHash;
170 StringRef CoverageMapping;
171 size_t FilenamesBegin;
172 size_t FilenamesSize;
173
174 ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName,
175 uint64_t FunctionHash, StringRef CoverageMapping,
176 size_t FilenamesBegin, size_t FilenamesSize)
177 : Version(Version), FunctionName(FunctionName),
178 FunctionHash(FunctionHash), CoverageMapping(CoverageMapping),
179 FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {}
180 };
181
182 using FuncRecordsStorage = std::unique_ptr<MemoryBuffer>;
183
184private:
185 std::vector<std::string> Filenames;
186 std::vector<ProfileMappingRecord> MappingRecords;
187 InstrProfSymtab ProfileNames;
188 size_t CurrentRecord = 0;
189 std::vector<StringRef> FunctionsFilenames;
190 std::vector<CounterExpression> Expressions;
191 std::vector<CounterMappingRegion> MappingRegions;
192
193 // Used to tie the lifetimes of coverage function records to the lifetime of
194 // this BinaryCoverageReader instance. Needed to support the format change in
195 // D69471, which can split up function records into multiple sections on ELF.
196 FuncRecordsStorage FuncRecords;
197
198 BinaryCoverageReader(FuncRecordsStorage &&FuncRecords)
199 : FuncRecords(std::move(FuncRecords)) {}
200
201public:
202 BinaryCoverageReader(const BinaryCoverageReader &) = delete;
203 BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
204
205 static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
206 create(MemoryBufferRef ObjectBuffer, StringRef Arch,
207 SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
208 StringRef CompilationDir = "",
209 SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr);
210
211 static Expected<std::unique_ptr<BinaryCoverageReader>>
212 createCoverageReaderFromBuffer(StringRef Coverage,
213 FuncRecordsStorage &&FuncRecords,
214 InstrProfSymtab &&ProfileNames,
215 uint8_t BytesInAddress,
216 llvm::endianness Endian,
217 StringRef CompilationDir = "");
218
219 Error readNextRecord(CoverageMappingRecord &Record) override;
220};
221
222/// Reader for the raw coverage filenames.
223class RawCoverageFilenamesReader : public RawCoverageReader {
224 std::vector<std::string> &Filenames;
225 StringRef CompilationDir;
226
227 // Read an uncompressed sequence of filenames.
228 Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
229
230public:
231 RawCoverageFilenamesReader(StringRef Data,
232 std::vector<std::string> &Filenames,
233 StringRef CompilationDir = "")
234 : RawCoverageReader(Data), Filenames(Filenames),
235 CompilationDir(CompilationDir) {}
236 RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
237 RawCoverageFilenamesReader &
238 operator=(const RawCoverageFilenamesReader &) = delete;
239
240 Error read(CovMapVersion Version);
241};
242
243} // end namespace coverage
244} // end namespace llvm
245
246#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
247

source code of llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h