Home | History | Annotate | Line # | Download | only in Coverage
      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   CoverageMappingReader *Reader;
     46   CoverageMappingRecord Record;
     47   coveragemap_error ReadErr;
     48 
     49   void increment();
     50 
     51 public:
     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), Record(), ReadErr(coveragemap_error::success) {}
     60 
     61   CoverageMappingIterator(CoverageMappingReader *Reader)
     62       : Reader(Reader), Record(), 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>(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>(ReadErr);
     92       ReadErr = coveragemap_error::success;
     93       return std::move(E);
     94     }
     95     return &Record;
     96   }
     97 };
     98 
     99 class CoverageMappingReader {
    100 public:
    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.
    109 class RawCoverageReader {
    110 protected:
    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.
    123 class RawCoverageMappingDummyChecker : public RawCoverageReader {
    124 public:
    125   RawCoverageMappingDummyChecker(StringRef MappingData)
    126       : RawCoverageReader(MappingData) {}
    127 
    128   Expected<bool> isDummy();
    129 };
    130 
    131 /// Reader for the raw coverage mapping data.
    132 class RawCoverageMappingReader : public RawCoverageReader {
    133   ArrayRef<std::string> &TranslationUnitFilenames;
    134   std::vector<StringRef> &Filenames;
    135   std::vector<CounterExpression> &Expressions;
    136   std::vector<CounterMappingRegion> &MappingRegions;
    137 
    138 public:
    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 
    154 private:
    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.
    164 class BinaryCoverageReader : public CoverageMappingReader {
    165 public:
    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 private:
    183   std::vector<std::string> Filenames;
    184   std::vector<ProfileMappingRecord> MappingRecords;
    185   InstrProfSymtab ProfileNames;
    186   size_t CurrentRecord = 0;
    187   std::vector<StringRef> FunctionsFilenames;
    188   std::vector<CounterExpression> Expressions;
    189   std::vector<CounterMappingRegion> MappingRegions;
    190 
    191   // Used to tie the lifetimes of coverage function records to the lifetime of
    192   // this BinaryCoverageReader instance. Needed to support the format change in
    193   // D69471, which can split up function records into multiple sections on ELF.
    194   std::string FuncRecords;
    195 
    196   BinaryCoverageReader(std::string &&FuncRecords)
    197       : FuncRecords(std::move(FuncRecords)) {}
    198 
    199 public:
    200   BinaryCoverageReader(const BinaryCoverageReader &) = delete;
    201   BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
    202 
    203   static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
    204   create(MemoryBufferRef ObjectBuffer, StringRef Arch,
    205          SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
    206          StringRef CompilationDir = "");
    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                                  StringRef CompilationDir = "");
    214 
    215   Error readNextRecord(CoverageMappingRecord &Record) override;
    216 };
    217 
    218 /// Reader for the raw coverage filenames.
    219 class RawCoverageFilenamesReader : public RawCoverageReader {
    220   std::vector<std::string> &Filenames;
    221   StringRef CompilationDir;
    222 
    223   // Read an uncompressed sequence of filenames.
    224   Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
    225 
    226 public:
    227   RawCoverageFilenamesReader(StringRef Data,
    228                              std::vector<std::string> &Filenames,
    229                              StringRef CompilationDir = "")
    230       : RawCoverageReader(Data), Filenames(Filenames),
    231         CompilationDir(CompilationDir) {}
    232   RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
    233   RawCoverageFilenamesReader &
    234   operator=(const RawCoverageFilenamesReader &) = delete;
    235 
    236   Error read(CovMapVersion Version);
    237 };
    238 
    239 } // end namespace coverage
    240 } // end namespace llvm
    241 
    242 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
    243