10b57cec5SDimitry Andric //===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains support for reading coverage mapping data for 100b57cec5SDimitry Andric // instrumentation based coverage. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 150b57cec5SDimitry Andric #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 190b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h" 200b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 210b57cec5SDimitry Andric #include "llvm/Support/Error.h" 220b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 230b57cec5SDimitry Andric #include <cstddef> 240b57cec5SDimitry Andric #include <cstdint> 250b57cec5SDimitry Andric #include <iterator> 260b57cec5SDimitry Andric #include <memory> 270b57cec5SDimitry Andric #include <vector> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace llvm { 300b57cec5SDimitry Andric namespace coverage { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class CoverageMappingReader; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric /// Coverage mapping information for a single function. 350b57cec5SDimitry Andric struct CoverageMappingRecord { 360b57cec5SDimitry Andric StringRef FunctionName; 370b57cec5SDimitry Andric uint64_t FunctionHash; 380b57cec5SDimitry Andric ArrayRef<StringRef> Filenames; 390b57cec5SDimitry Andric ArrayRef<CounterExpression> Expressions; 400b57cec5SDimitry Andric ArrayRef<CounterMappingRegion> MappingRegions; 410b57cec5SDimitry Andric }; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// A file format agnostic iterator over coverage mapping data. 44fe6060f1SDimitry Andric class CoverageMappingIterator { 450b57cec5SDimitry Andric CoverageMappingReader *Reader; 460b57cec5SDimitry Andric CoverageMappingRecord Record; 470b57cec5SDimitry Andric coveragemap_error ReadErr; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void increment(); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric public: 52fe6060f1SDimitry Andric using iterator_category = std::input_iterator_tag; 53fe6060f1SDimitry Andric using value_type = CoverageMappingRecord; 54fe6060f1SDimitry Andric using difference_type = std::ptrdiff_t; 55fe6060f1SDimitry Andric using pointer = value_type *; 56fe6060f1SDimitry Andric using reference = value_type &; 57fe6060f1SDimitry Andric CoverageMappingIterator()580b57cec5SDimitry Andric CoverageMappingIterator() 5904eeddc0SDimitry Andric : Reader(nullptr), ReadErr(coveragemap_error::success) {} 600b57cec5SDimitry Andric CoverageMappingIterator(CoverageMappingReader * Reader)610b57cec5SDimitry Andric CoverageMappingIterator(CoverageMappingReader *Reader) 6204eeddc0SDimitry Andric : Reader(Reader), ReadErr(coveragemap_error::success) { 630b57cec5SDimitry Andric increment(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric ~CoverageMappingIterator()660b57cec5SDimitry Andric ~CoverageMappingIterator() { 670b57cec5SDimitry Andric if (ReadErr != coveragemap_error::success) 680b57cec5SDimitry Andric llvm_unreachable("Unexpected error in coverage mapping iterator"); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric CoverageMappingIterator &operator++() { 720b57cec5SDimitry Andric increment(); 730b57cec5SDimitry Andric return *this; 740b57cec5SDimitry Andric } 75e8d8bef9SDimitry Andric bool operator==(const CoverageMappingIterator &RHS) const { 760b57cec5SDimitry Andric return Reader == RHS.Reader; 770b57cec5SDimitry Andric } 78e8d8bef9SDimitry Andric bool operator!=(const CoverageMappingIterator &RHS) const { 790b57cec5SDimitry Andric return Reader != RHS.Reader; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric Expected<CoverageMappingRecord &> operator*() { 820b57cec5SDimitry Andric if (ReadErr != coveragemap_error::success) { 830b57cec5SDimitry Andric auto E = make_error<CoverageMapError>(ReadErr); 840b57cec5SDimitry Andric ReadErr = coveragemap_error::success; 850b57cec5SDimitry Andric return std::move(E); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric return Record; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric Expected<CoverageMappingRecord *> operator->() { 900b57cec5SDimitry Andric if (ReadErr != coveragemap_error::success) { 910b57cec5SDimitry Andric auto E = make_error<CoverageMapError>(ReadErr); 920b57cec5SDimitry Andric ReadErr = coveragemap_error::success; 930b57cec5SDimitry Andric return std::move(E); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric return &Record; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric }; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric class CoverageMappingReader { 1000b57cec5SDimitry Andric public: 1010b57cec5SDimitry Andric virtual ~CoverageMappingReader() = default; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; begin()1040b57cec5SDimitry Andric CoverageMappingIterator begin() { return CoverageMappingIterator(this); } end()1050b57cec5SDimitry Andric CoverageMappingIterator end() { return CoverageMappingIterator(); } 1060b57cec5SDimitry Andric }; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /// Base class for the raw coverage mapping and filenames data readers. 1090b57cec5SDimitry Andric class RawCoverageReader { 1100b57cec5SDimitry Andric protected: 1110b57cec5SDimitry Andric StringRef Data; 1120b57cec5SDimitry Andric RawCoverageReader(StringRef Data)1130b57cec5SDimitry Andric RawCoverageReader(StringRef Data) : Data(Data) {} 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric Error readULEB128(uint64_t &Result); 1160b57cec5SDimitry Andric Error readIntMax(uint64_t &Result, uint64_t MaxPlus1); 1170b57cec5SDimitry Andric Error readSize(uint64_t &Result); 1180b57cec5SDimitry Andric Error readString(StringRef &Result); 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric /// Checks if the given coverage mapping data is exported for 1220b57cec5SDimitry Andric /// an unused function. 1230b57cec5SDimitry Andric class RawCoverageMappingDummyChecker : public RawCoverageReader { 1240b57cec5SDimitry Andric public: RawCoverageMappingDummyChecker(StringRef MappingData)1250b57cec5SDimitry Andric RawCoverageMappingDummyChecker(StringRef MappingData) 1260b57cec5SDimitry Andric : RawCoverageReader(MappingData) {} 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric Expected<bool> isDummy(); 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// Reader for the raw coverage mapping data. 1320b57cec5SDimitry Andric class RawCoverageMappingReader : public RawCoverageReader { 133fe6060f1SDimitry Andric ArrayRef<std::string> &TranslationUnitFilenames; 1340b57cec5SDimitry Andric std::vector<StringRef> &Filenames; 1350b57cec5SDimitry Andric std::vector<CounterExpression> &Expressions; 1360b57cec5SDimitry Andric std::vector<CounterMappingRegion> &MappingRegions; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric public: RawCoverageMappingReader(StringRef MappingData,ArrayRef<std::string> & TranslationUnitFilenames,std::vector<StringRef> & Filenames,std::vector<CounterExpression> & Expressions,std::vector<CounterMappingRegion> & MappingRegions)1390b57cec5SDimitry Andric RawCoverageMappingReader(StringRef MappingData, 140fe6060f1SDimitry Andric ArrayRef<std::string> &TranslationUnitFilenames, 1410b57cec5SDimitry Andric std::vector<StringRef> &Filenames, 1420b57cec5SDimitry Andric std::vector<CounterExpression> &Expressions, 1430b57cec5SDimitry Andric std::vector<CounterMappingRegion> &MappingRegions) 1440b57cec5SDimitry Andric : RawCoverageReader(MappingData), 1450b57cec5SDimitry Andric TranslationUnitFilenames(TranslationUnitFilenames), 1460b57cec5SDimitry Andric Filenames(Filenames), Expressions(Expressions), 1470b57cec5SDimitry Andric MappingRegions(MappingRegions) {} 1480b57cec5SDimitry Andric RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; 1490b57cec5SDimitry Andric RawCoverageMappingReader & 1500b57cec5SDimitry Andric operator=(const RawCoverageMappingReader &) = delete; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric Error read(); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric private: 1550b57cec5SDimitry Andric Error decodeCounter(unsigned Value, Counter &C); 1560b57cec5SDimitry Andric Error readCounter(Counter &C); 1570b57cec5SDimitry Andric Error 1580b57cec5SDimitry Andric readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions, 1590b57cec5SDimitry Andric unsigned InferredFileID, size_t NumFileIDs); 1600b57cec5SDimitry Andric }; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// Reader for the coverage mapping data that is emitted by the 1630b57cec5SDimitry Andric /// frontend and stored in an object file. 1640b57cec5SDimitry Andric class BinaryCoverageReader : public CoverageMappingReader { 1650b57cec5SDimitry Andric public: 1660b57cec5SDimitry Andric struct ProfileMappingRecord { 1670b57cec5SDimitry Andric CovMapVersion Version; 1680b57cec5SDimitry Andric StringRef FunctionName; 1690b57cec5SDimitry Andric uint64_t FunctionHash; 1700b57cec5SDimitry Andric StringRef CoverageMapping; 1710b57cec5SDimitry Andric size_t FilenamesBegin; 1720b57cec5SDimitry Andric size_t FilenamesSize; 1730b57cec5SDimitry Andric ProfileMappingRecordProfileMappingRecord1740b57cec5SDimitry Andric ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName, 1750b57cec5SDimitry Andric uint64_t FunctionHash, StringRef CoverageMapping, 1760b57cec5SDimitry Andric size_t FilenamesBegin, size_t FilenamesSize) 1770b57cec5SDimitry Andric : Version(Version), FunctionName(FunctionName), 1780b57cec5SDimitry Andric FunctionHash(FunctionHash), CoverageMapping(CoverageMapping), 1790b57cec5SDimitry Andric FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} 1800b57cec5SDimitry Andric }; 1810b57cec5SDimitry Andric 182fe6060f1SDimitry Andric using FuncRecordsStorage = std::unique_ptr<MemoryBuffer>; 1835ffd83dbSDimitry Andric 1840b57cec5SDimitry Andric private: 185fe6060f1SDimitry Andric std::vector<std::string> Filenames; 1860b57cec5SDimitry Andric std::vector<ProfileMappingRecord> MappingRecords; 187*0fca6ea1SDimitry Andric std::unique_ptr<InstrProfSymtab> ProfileNames; 1880b57cec5SDimitry Andric size_t CurrentRecord = 0; 1890b57cec5SDimitry Andric std::vector<StringRef> FunctionsFilenames; 1900b57cec5SDimitry Andric std::vector<CounterExpression> Expressions; 1910b57cec5SDimitry Andric std::vector<CounterMappingRegion> MappingRegions; 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric // Used to tie the lifetimes of coverage function records to the lifetime of 1945ffd83dbSDimitry Andric // this BinaryCoverageReader instance. Needed to support the format change in 1955ffd83dbSDimitry Andric // D69471, which can split up function records into multiple sections on ELF. 196fe6060f1SDimitry Andric FuncRecordsStorage FuncRecords; 1975ffd83dbSDimitry Andric BinaryCoverageReader(std::unique_ptr<InstrProfSymtab> Symtab,FuncRecordsStorage && FuncRecords)198*0fca6ea1SDimitry Andric BinaryCoverageReader(std::unique_ptr<InstrProfSymtab> Symtab, 199*0fca6ea1SDimitry Andric FuncRecordsStorage &&FuncRecords) 200*0fca6ea1SDimitry Andric : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)) {} 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric public: 2030b57cec5SDimitry Andric BinaryCoverageReader(const BinaryCoverageReader &) = delete; 2040b57cec5SDimitry Andric BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 2070b57cec5SDimitry Andric create(MemoryBufferRef ObjectBuffer, StringRef Arch, 208fe6060f1SDimitry Andric SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers, 2091ac55f4cSDimitry Andric StringRef CompilationDir = "", 2101ac55f4cSDimitry Andric SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric static Expected<std::unique_ptr<BinaryCoverageReader>> 213*0fca6ea1SDimitry Andric createCoverageReaderFromBuffer( 214*0fca6ea1SDimitry Andric StringRef Coverage, FuncRecordsStorage &&FuncRecords, 215*0fca6ea1SDimitry Andric std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress, 216*0fca6ea1SDimitry Andric llvm::endianness Endian, StringRef CompilationDir = ""); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric Error readNextRecord(CoverageMappingRecord &Record) override; 2190b57cec5SDimitry Andric }; 2200b57cec5SDimitry Andric 2215ffd83dbSDimitry Andric /// Reader for the raw coverage filenames. 2225ffd83dbSDimitry Andric class RawCoverageFilenamesReader : public RawCoverageReader { 223fe6060f1SDimitry Andric std::vector<std::string> &Filenames; 224fe6060f1SDimitry Andric StringRef CompilationDir; 2255ffd83dbSDimitry Andric 2265ffd83dbSDimitry Andric // Read an uncompressed sequence of filenames. 227fe6060f1SDimitry Andric Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames); 2285ffd83dbSDimitry Andric 2295ffd83dbSDimitry Andric public: 230fe6060f1SDimitry Andric RawCoverageFilenamesReader(StringRef Data, 231fe6060f1SDimitry Andric std::vector<std::string> &Filenames, 232fe6060f1SDimitry Andric StringRef CompilationDir = "") RawCoverageReader(Data)233fe6060f1SDimitry Andric : RawCoverageReader(Data), Filenames(Filenames), 234fe6060f1SDimitry Andric CompilationDir(CompilationDir) {} 2355ffd83dbSDimitry Andric RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; 2365ffd83dbSDimitry Andric RawCoverageFilenamesReader & 2375ffd83dbSDimitry Andric operator=(const RawCoverageFilenamesReader &) = delete; 2385ffd83dbSDimitry Andric 239fe6060f1SDimitry Andric Error read(CovMapVersion Version); 2405ffd83dbSDimitry Andric }; 2415ffd83dbSDimitry Andric 2420b57cec5SDimitry Andric } // end namespace coverage 2430b57cec5SDimitry Andric } // end namespace llvm 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 246