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) { 71 return Reader == RHS.Reader; 72 } 73 bool operator!=(const CoverageMappingIterator &RHS) { 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