1dc707122SEaswaran Raman //=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// 2dc707122SEaswaran Raman // 3dc707122SEaswaran Raman // The LLVM Compiler Infrastructure 4dc707122SEaswaran Raman // 5dc707122SEaswaran Raman // This file is distributed under the University of Illinois Open Source 6dc707122SEaswaran Raman // License. See LICENSE.TXT for details. 7dc707122SEaswaran Raman // 8dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 9dc707122SEaswaran Raman // 10dc707122SEaswaran Raman // This file contains support for reading coverage mapping data for 11dc707122SEaswaran Raman // instrumentation based coverage. 12dc707122SEaswaran Raman // 13dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 14dc707122SEaswaran Raman 15dc707122SEaswaran Raman #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 16dc707122SEaswaran Raman #include "llvm/ADT/DenseSet.h" 17dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h" 18dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.h" 19dc707122SEaswaran Raman #include "llvm/Support/Debug.h" 20dc707122SEaswaran Raman #include "llvm/Support/Endian.h" 21dc707122SEaswaran Raman #include "llvm/Support/LEB128.h" 22dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h" 23dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 24dc707122SEaswaran Raman 25dc707122SEaswaran Raman using namespace llvm; 26dc707122SEaswaran Raman using namespace coverage; 27dc707122SEaswaran Raman using namespace object; 28dc707122SEaswaran Raman 29dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 30dc707122SEaswaran Raman 31dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 32dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 33dc707122SEaswaran Raman // the next record. 3485c973d3SVedant Kumar if (Reader->readNextRecord(Record)) 35dc707122SEaswaran Raman *this = CoverageMappingIterator(); 36dc707122SEaswaran Raman } 37dc707122SEaswaran Raman 3885c973d3SVedant Kumar std::error_code RawCoverageReader::readULEB128(uint64_t &Result) { 39dc707122SEaswaran Raman if (Data.size() < 1) 4085c973d3SVedant Kumar return coveragemap_error::truncated; 41dc707122SEaswaran Raman unsigned N = 0; 42dc707122SEaswaran Raman Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 43dc707122SEaswaran Raman if (N > Data.size()) 4485c973d3SVedant Kumar return coveragemap_error::malformed; 45dc707122SEaswaran Raman Data = Data.substr(N); 4685c973d3SVedant Kumar return std::error_code(); 47dc707122SEaswaran Raman } 48dc707122SEaswaran Raman 4985c973d3SVedant Kumar std::error_code RawCoverageReader::readIntMax(uint64_t &Result, 5085c973d3SVedant Kumar uint64_t MaxPlus1) { 51dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 52dc707122SEaswaran Raman return Err; 53dc707122SEaswaran Raman if (Result >= MaxPlus1) 5485c973d3SVedant Kumar return coveragemap_error::malformed; 5585c973d3SVedant Kumar return std::error_code(); 56dc707122SEaswaran Raman } 57dc707122SEaswaran Raman 5885c973d3SVedant Kumar std::error_code RawCoverageReader::readSize(uint64_t &Result) { 59dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 60dc707122SEaswaran Raman return Err; 61dc707122SEaswaran Raman // Sanity check the number. 62dc707122SEaswaran Raman if (Result > Data.size()) 6385c973d3SVedant Kumar return coveragemap_error::malformed; 6485c973d3SVedant Kumar return std::error_code(); 65dc707122SEaswaran Raman } 66dc707122SEaswaran Raman 6785c973d3SVedant Kumar std::error_code RawCoverageReader::readString(StringRef &Result) { 68dc707122SEaswaran Raman uint64_t Length; 69dc707122SEaswaran Raman if (auto Err = readSize(Length)) 70dc707122SEaswaran Raman return Err; 71dc707122SEaswaran Raman Result = Data.substr(0, Length); 72dc707122SEaswaran Raman Data = Data.substr(Length); 7385c973d3SVedant Kumar return std::error_code(); 74dc707122SEaswaran Raman } 75dc707122SEaswaran Raman 7685c973d3SVedant Kumar std::error_code RawCoverageFilenamesReader::read() { 77dc707122SEaswaran Raman uint64_t NumFilenames; 78dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 79dc707122SEaswaran Raman return Err; 80dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 81dc707122SEaswaran Raman StringRef Filename; 82dc707122SEaswaran Raman if (auto Err = readString(Filename)) 83dc707122SEaswaran Raman return Err; 84dc707122SEaswaran Raman Filenames.push_back(Filename); 85dc707122SEaswaran Raman } 8685c973d3SVedant Kumar return std::error_code(); 87dc707122SEaswaran Raman } 88dc707122SEaswaran Raman 8985c973d3SVedant Kumar std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value, 9085c973d3SVedant Kumar Counter &C) { 91dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 92dc707122SEaswaran Raman switch (Tag) { 93dc707122SEaswaran Raman case Counter::Zero: 94dc707122SEaswaran Raman C = Counter::getZero(); 9585c973d3SVedant Kumar return std::error_code(); 96dc707122SEaswaran Raman case Counter::CounterValueReference: 97dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 9885c973d3SVedant Kumar return std::error_code(); 99dc707122SEaswaran Raman default: 100dc707122SEaswaran Raman break; 101dc707122SEaswaran Raman } 102dc707122SEaswaran Raman Tag -= Counter::Expression; 103dc707122SEaswaran Raman switch (Tag) { 104dc707122SEaswaran Raman case CounterExpression::Subtract: 105dc707122SEaswaran Raman case CounterExpression::Add: { 106dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 107dc707122SEaswaran Raman if (ID >= Expressions.size()) 10885c973d3SVedant Kumar return coveragemap_error::malformed; 109dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 110dc707122SEaswaran Raman C = Counter::getExpression(ID); 111dc707122SEaswaran Raman break; 112dc707122SEaswaran Raman } 113dc707122SEaswaran Raman default: 11485c973d3SVedant Kumar return coveragemap_error::malformed; 115dc707122SEaswaran Raman } 11685c973d3SVedant Kumar return std::error_code(); 117dc707122SEaswaran Raman } 118dc707122SEaswaran Raman 11985c973d3SVedant Kumar std::error_code RawCoverageMappingReader::readCounter(Counter &C) { 120dc707122SEaswaran Raman uint64_t EncodedCounter; 121dc707122SEaswaran Raman if (auto Err = 122dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 123dc707122SEaswaran Raman return Err; 124dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 125dc707122SEaswaran Raman return Err; 12685c973d3SVedant Kumar return std::error_code(); 127dc707122SEaswaran Raman } 128dc707122SEaswaran Raman 129dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 130dc707122SEaswaran Raman << Counter::EncodingTagBits; 131dc707122SEaswaran Raman 132dc707122SEaswaran Raman /// \brief Read the sub-array of regions for the given inferred file id. 133dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 134dc707122SEaswaran Raman /// function. 13585c973d3SVedant Kumar std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( 136dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 137dc707122SEaswaran Raman size_t NumFileIDs) { 138dc707122SEaswaran Raman uint64_t NumRegions; 139dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 140dc707122SEaswaran Raman return Err; 141dc707122SEaswaran Raman unsigned LineStart = 0; 142dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 143dc707122SEaswaran Raman Counter C; 144dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 145dc707122SEaswaran Raman 146dc707122SEaswaran Raman // Read the combined counter + region kind. 147dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 148dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 149dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 150dc707122SEaswaran Raman return Err; 151dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 152dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 153dc707122SEaswaran Raman if (Tag != Counter::Zero) { 154dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 155dc707122SEaswaran Raman return Err; 156dc707122SEaswaran Raman } else { 157dc707122SEaswaran Raman // Is it an expansion region? 158dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 159dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 160dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 161dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 162dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 16385c973d3SVedant Kumar return coveragemap_error::malformed; 164dc707122SEaswaran Raman } else { 165dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 166dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 167dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 168dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 169dc707122SEaswaran Raman break; 170dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 171dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 172dc707122SEaswaran Raman break; 173dc707122SEaswaran Raman default: 17485c973d3SVedant Kumar return coveragemap_error::malformed; 175dc707122SEaswaran Raman } 176dc707122SEaswaran Raman } 177dc707122SEaswaran Raman } 178dc707122SEaswaran Raman 179dc707122SEaswaran Raman // Read the source range. 180dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 181dc707122SEaswaran Raman if (auto Err = 182dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 183dc707122SEaswaran Raman return Err; 184dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 185dc707122SEaswaran Raman return Err; 186dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 18785c973d3SVedant Kumar return coveragemap_error::malformed; 188dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 189dc707122SEaswaran Raman return Err; 190dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 191dc707122SEaswaran Raman return Err; 192dc707122SEaswaran Raman LineStart += LineStartDelta; 193dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 194dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 195dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 196dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 197dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 198dc707122SEaswaran Raman // column end take up one byte each. 199dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 200dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 201dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 202dc707122SEaswaran Raman ColumnStart = 1; 203dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 204dc707122SEaswaran Raman } 205dc707122SEaswaran Raman 206dc707122SEaswaran Raman DEBUG({ 207dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 208dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 209dc707122SEaswaran Raman << ColumnEnd << ", "; 210dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 211dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 212dc707122SEaswaran Raman else 213dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 214dc707122SEaswaran Raman dbgs() << "\n"; 215dc707122SEaswaran Raman }); 216dc707122SEaswaran Raman 217dc707122SEaswaran Raman MappingRegions.push_back(CounterMappingRegion( 218dc707122SEaswaran Raman C, InferredFileID, ExpandedFileID, LineStart, ColumnStart, 219dc707122SEaswaran Raman LineStart + NumLines, ColumnEnd, Kind)); 220dc707122SEaswaran Raman } 22185c973d3SVedant Kumar return std::error_code(); 222dc707122SEaswaran Raman } 223dc707122SEaswaran Raman 22485c973d3SVedant Kumar std::error_code RawCoverageMappingReader::read() { 225dc707122SEaswaran Raman 226dc707122SEaswaran Raman // Read the virtual file mapping. 227dc707122SEaswaran Raman llvm::SmallVector<unsigned, 8> VirtualFileMapping; 228dc707122SEaswaran Raman uint64_t NumFileMappings; 229dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 230dc707122SEaswaran Raman return Err; 231dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 232dc707122SEaswaran Raman uint64_t FilenameIndex; 233dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 234dc707122SEaswaran Raman return Err; 235dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 236dc707122SEaswaran Raman } 237dc707122SEaswaran Raman 238dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 239dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 240dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 241dc707122SEaswaran Raman } 242dc707122SEaswaran Raman 243dc707122SEaswaran Raman // Read the expressions. 244dc707122SEaswaran Raman uint64_t NumExpressions; 245dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 246dc707122SEaswaran Raman return Err; 247dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 248dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 249dc707122SEaswaran Raman // are decoded. 250dc707122SEaswaran Raman Expressions.resize( 251dc707122SEaswaran Raman NumExpressions, 252dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 253dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 254dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 255dc707122SEaswaran Raman return Err; 256dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 257dc707122SEaswaran Raman return Err; 258dc707122SEaswaran Raman } 259dc707122SEaswaran Raman 260dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 261dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 262dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 263dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 264dc707122SEaswaran Raman VirtualFileMapping.size())) 265dc707122SEaswaran Raman return Err; 266dc707122SEaswaran Raman } 267dc707122SEaswaran Raman 268dc707122SEaswaran Raman // Set the counters for the expansion regions. 269dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 270dc707122SEaswaran Raman // from the expanded file. 271dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 272dc707122SEaswaran Raman // all the nested expansion regions. 273dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 274dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 275dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 276dc707122SEaswaran Raman for (auto &R : MappingRegions) { 277dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 278dc707122SEaswaran Raman continue; 279dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 280dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 281dc707122SEaswaran Raman } 282dc707122SEaswaran Raman for (auto &R : MappingRegions) { 283dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 284dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 285dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 286dc707122SEaswaran Raman } 287dc707122SEaswaran Raman } 288dc707122SEaswaran Raman } 289dc707122SEaswaran Raman 29085c973d3SVedant Kumar return std::error_code(); 291dc707122SEaswaran Raman } 292dc707122SEaswaran Raman 29385c973d3SVedant Kumar std::error_code InstrProfSymtab::create(SectionRef &Section) { 29485c973d3SVedant Kumar if (auto Err = Section.getContents(Data)) 29585c973d3SVedant Kumar return Err; 296dc707122SEaswaran Raman Address = Section.getAddress(); 29785c973d3SVedant Kumar return std::error_code(); 298dc707122SEaswaran Raman } 299dc707122SEaswaran Raman 300dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 301dc707122SEaswaran Raman if (Pointer < Address) 302dc707122SEaswaran Raman return StringRef(); 303dc707122SEaswaran Raman auto Offset = Pointer - Address; 304dc707122SEaswaran Raman if (Offset + Size > Data.size()) 305dc707122SEaswaran Raman return StringRef(); 306dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 307dc707122SEaswaran Raman } 308dc707122SEaswaran Raman 309dc707122SEaswaran Raman namespace { 310dc707122SEaswaran Raman struct CovMapFuncRecordReader { 311dc707122SEaswaran Raman // The interface to read coverage mapping function records for 312dc707122SEaswaran Raman // a module. \p Buf is a reference to the buffer pointer pointing 313dc707122SEaswaran Raman // to the \c CovHeader of coverage mapping data associated with 314dc707122SEaswaran Raman // the module. 31585c973d3SVedant Kumar virtual std::error_code readFunctionRecords(const char *&Buf, 31685c973d3SVedant Kumar const char *End) = 0; 317dc707122SEaswaran Raman virtual ~CovMapFuncRecordReader() {} 318dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 31985c973d3SVedant Kumar static ErrorOr<std::unique_ptr<CovMapFuncRecordReader>> 320dc707122SEaswaran Raman get(coverage::CovMapVersion Version, InstrProfSymtab &P, 321dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 322dc707122SEaswaran Raman std::vector<StringRef> &F); 323dc707122SEaswaran Raman }; 324dc707122SEaswaran Raman 325dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 326dc707122SEaswaran Raman template <coverage::CovMapVersion Version, class IntPtrT, 327dc707122SEaswaran Raman support::endianness Endian> 328dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 329dc707122SEaswaran Raman typedef typename coverage::CovMapTraits< 330dc707122SEaswaran Raman Version, IntPtrT>::CovMapFuncRecordType FuncRecordType; 331dc707122SEaswaran Raman typedef typename coverage::CovMapTraits<Version, IntPtrT>::NameRefType 332dc707122SEaswaran Raman NameRefType; 333dc707122SEaswaran Raman 334dc707122SEaswaran Raman llvm::DenseSet<NameRefType> UniqueFunctionMappingData; 335dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 336dc707122SEaswaran Raman std::vector<StringRef> &Filenames; 337dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 338dc707122SEaswaran Raman 339dc707122SEaswaran Raman public: 340dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 341dc707122SEaswaran Raman InstrProfSymtab &P, 342dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 343dc707122SEaswaran Raman std::vector<StringRef> &F) 344dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 345dc707122SEaswaran Raman ~VersionedCovMapFuncRecordReader() override {} 346dc707122SEaswaran Raman 34785c973d3SVedant Kumar std::error_code readFunctionRecords(const char *&Buf, 34885c973d3SVedant Kumar const char *End) override { 349dc707122SEaswaran Raman using namespace support; 350dc707122SEaswaran Raman if (Buf + sizeof(CovMapHeader) > End) 35185c973d3SVedant Kumar return coveragemap_error::malformed; 352dc707122SEaswaran Raman auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf); 353dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 354dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 355dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 356dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 357dc707122SEaswaran Raman Buf = reinterpret_cast<const char *>(CovHeader + 1); 358dc707122SEaswaran Raman 359dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 360dc707122SEaswaran Raman const char *FunBuf = Buf; 361dc707122SEaswaran Raman Buf += NRecords * sizeof(FuncRecordType); 362dc707122SEaswaran Raman const char *FunEnd = Buf; 363dc707122SEaswaran Raman 364dc707122SEaswaran Raman // Get the filenames. 365dc707122SEaswaran Raman if (Buf + FilenamesSize > End) 36685c973d3SVedant Kumar return coveragemap_error::malformed; 367dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 368dc707122SEaswaran Raman RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); 369dc707122SEaswaran Raman if (auto Err = Reader.read()) 370dc707122SEaswaran Raman return Err; 371dc707122SEaswaran Raman Buf += FilenamesSize; 372dc707122SEaswaran Raman 373dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 374dc707122SEaswaran Raman const char *CovBuf = Buf; 375dc707122SEaswaran Raman Buf += CoverageSize; 376dc707122SEaswaran Raman const char *CovEnd = Buf; 377dc707122SEaswaran Raman 378dc707122SEaswaran Raman if (Buf > End) 37985c973d3SVedant Kumar return coveragemap_error::malformed; 380dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 381dc707122SEaswaran Raman // before reading the next map. 382dc707122SEaswaran Raman Buf += alignmentAdjustment(Buf, 8); 383dc707122SEaswaran Raman 384dc707122SEaswaran Raman auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf); 385dc707122SEaswaran Raman while ((const char *)CFR < FunEnd) { 386dc707122SEaswaran Raman // Read the function information 387dc707122SEaswaran Raman uint32_t DataSize = CFR->template getDataSize<Endian>(); 388dc707122SEaswaran Raman uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 389dc707122SEaswaran Raman 390dc707122SEaswaran Raman // Now use that to read the coverage data. 391dc707122SEaswaran Raman if (CovBuf + DataSize > CovEnd) 39285c973d3SVedant Kumar return coveragemap_error::malformed; 393dc707122SEaswaran Raman auto Mapping = StringRef(CovBuf, DataSize); 394dc707122SEaswaran Raman CovBuf += DataSize; 395dc707122SEaswaran Raman 396dc707122SEaswaran Raman // Ignore this record if we already have a record that points to the same 397dc707122SEaswaran Raman // function name. This is useful to ignore the redundant records for the 398dc707122SEaswaran Raman // functions with ODR linkage. 399dc707122SEaswaran Raman NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 400dc707122SEaswaran Raman if (!UniqueFunctionMappingData.insert(NameRef).second) { 401dc707122SEaswaran Raman CFR++; 402dc707122SEaswaran Raman continue; 403dc707122SEaswaran Raman } 404dc707122SEaswaran Raman 405dc707122SEaswaran Raman StringRef FuncName; 40685c973d3SVedant Kumar if (std::error_code EC = 40785c973d3SVedant Kumar CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 40885c973d3SVedant Kumar return EC; 409dc707122SEaswaran Raman Records.push_back(BinaryCoverageReader::ProfileMappingRecord( 410dc707122SEaswaran Raman Version, FuncName, FuncHash, Mapping, FilenamesBegin, 411dc707122SEaswaran Raman Filenames.size() - FilenamesBegin)); 412dc707122SEaswaran Raman CFR++; 413dc707122SEaswaran Raman } 41485c973d3SVedant Kumar return std::error_code(); 415dc707122SEaswaran Raman } 416dc707122SEaswaran Raman }; 417dc707122SEaswaran Raman } // end anonymous namespace 418dc707122SEaswaran Raman 419dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 42085c973d3SVedant Kumar ErrorOr<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 421dc707122SEaswaran Raman coverage::CovMapVersion Version, InstrProfSymtab &P, 422dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 423dc707122SEaswaran Raman std::vector<StringRef> &F) { 424dc707122SEaswaran Raman using namespace coverage; 425dc707122SEaswaran Raman switch (Version) { 426dc707122SEaswaran Raman case CovMapVersion::Version1: 427dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 428dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 429dc707122SEaswaran Raman case CovMapVersion::Version2: 430dc707122SEaswaran Raman // Decompress the name data. 43185c973d3SVedant Kumar if (auto EC = P.create(P.getNameData())) 43285c973d3SVedant Kumar return EC; 433dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 434dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 435dc707122SEaswaran Raman } 436dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 437dc707122SEaswaran Raman } 438dc707122SEaswaran Raman 439dc707122SEaswaran Raman template <typename T, support::endianness Endian> 44085c973d3SVedant Kumar static std::error_code readCoverageMappingData( 441dc707122SEaswaran Raman InstrProfSymtab &ProfileNames, StringRef Data, 442dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 443dc707122SEaswaran Raman std::vector<StringRef> &Filenames) { 444dc707122SEaswaran Raman using namespace coverage; 445dc707122SEaswaran Raman // Read the records in the coverage data section. 446dc707122SEaswaran Raman auto CovHeader = 447dc707122SEaswaran Raman reinterpret_cast<const coverage::CovMapHeader *>(Data.data()); 448dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 449dc707122SEaswaran Raman if (Version > coverage::CovMapVersion::CurrentVersion) 45085c973d3SVedant Kumar return coveragemap_error::unsupported_version; 45185c973d3SVedant Kumar ErrorOr<std::unique_ptr<CovMapFuncRecordReader>> ReaderErrorOr = 452dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 453dc707122SEaswaran Raman Filenames); 45485c973d3SVedant Kumar if (auto EC = ReaderErrorOr.getError()) 45585c973d3SVedant Kumar return EC; 45685c973d3SVedant Kumar auto Reader = std::move(ReaderErrorOr.get()); 457dc707122SEaswaran Raman for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { 45885c973d3SVedant Kumar if (std::error_code EC = Reader->readFunctionRecords(Buf, End)) 45985c973d3SVedant Kumar return EC; 460dc707122SEaswaran Raman } 46185c973d3SVedant Kumar return std::error_code(); 462dc707122SEaswaran Raman } 463dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 464dc707122SEaswaran Raman 46585c973d3SVedant Kumar static std::error_code loadTestingFormat(StringRef Data, 46685c973d3SVedant Kumar InstrProfSymtab &ProfileNames, 467dc707122SEaswaran Raman StringRef &CoverageMapping, 468dc707122SEaswaran Raman uint8_t &BytesInAddress, 469dc707122SEaswaran Raman support::endianness &Endian) { 470dc707122SEaswaran Raman BytesInAddress = 8; 471dc707122SEaswaran Raman Endian = support::endianness::little; 472dc707122SEaswaran Raman 473dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 474dc707122SEaswaran Raman if (Data.size() < 1) 47585c973d3SVedant Kumar return coveragemap_error::truncated; 476dc707122SEaswaran Raman unsigned N = 0; 477dc707122SEaswaran Raman auto ProfileNamesSize = 478dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 479dc707122SEaswaran Raman if (N > Data.size()) 48085c973d3SVedant Kumar return coveragemap_error::malformed; 481dc707122SEaswaran Raman Data = Data.substr(N); 482dc707122SEaswaran Raman if (Data.size() < 1) 48385c973d3SVedant Kumar return coveragemap_error::truncated; 484dc707122SEaswaran Raman N = 0; 485dc707122SEaswaran Raman uint64_t Address = 486dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 487dc707122SEaswaran Raman if (N > Data.size()) 48885c973d3SVedant Kumar return coveragemap_error::malformed; 489dc707122SEaswaran Raman Data = Data.substr(N); 490dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 49185c973d3SVedant Kumar return coveragemap_error::malformed; 49285c973d3SVedant Kumar ProfileNames.create(Data.substr(0, ProfileNamesSize), Address); 493dc707122SEaswaran Raman CoverageMapping = Data.substr(ProfileNamesSize); 494*eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 495*eb103073SIgor Kudrin if (CoverageMapping.size() < 1) 496*eb103073SIgor Kudrin return coveragemap_error::truncated; 497*eb103073SIgor Kudrin size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8); 498*eb103073SIgor Kudrin if (CoverageMapping.size() < Pad) 499*eb103073SIgor Kudrin return coveragemap_error::malformed; 500*eb103073SIgor Kudrin CoverageMapping = CoverageMapping.substr(Pad); 50185c973d3SVedant Kumar return std::error_code(); 502dc707122SEaswaran Raman } 503dc707122SEaswaran Raman 50485c973d3SVedant Kumar static ErrorOr<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { 505dc707122SEaswaran Raman StringRef FoundName; 506dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 507dc707122SEaswaran Raman if (auto EC = Section.getName(FoundName)) 50885c973d3SVedant Kumar return EC; 509dc707122SEaswaran Raman if (FoundName == Name) 510dc707122SEaswaran Raman return Section; 511dc707122SEaswaran Raman } 51285c973d3SVedant Kumar return coveragemap_error::no_data_found; 513dc707122SEaswaran Raman } 514dc707122SEaswaran Raman 51585c973d3SVedant Kumar static std::error_code 51685c973d3SVedant Kumar loadBinaryFormat(MemoryBufferRef ObjectBuffer, InstrProfSymtab &ProfileNames, 51785c973d3SVedant Kumar StringRef &CoverageMapping, uint8_t &BytesInAddress, 518dc707122SEaswaran Raman support::endianness &Endian, StringRef Arch) { 519dc707122SEaswaran Raman auto BinOrErr = object::createBinary(ObjectBuffer); 520dc707122SEaswaran Raman if (!BinOrErr) 52185c973d3SVedant Kumar return errorToErrorCode(BinOrErr.takeError()); 522dc707122SEaswaran Raman auto Bin = std::move(BinOrErr.get()); 523dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 524dc707122SEaswaran Raman if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) { 525dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 526dc707122SEaswaran Raman // appropriate architecture. 527dc707122SEaswaran Raman auto ObjectFileOrErr = Universal->getObjectForArch(Arch); 52885c973d3SVedant Kumar if (std::error_code EC = ObjectFileOrErr.getError()) 52985c973d3SVedant Kumar return EC; 530dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 531dc707122SEaswaran Raman } else if (isa<object::ObjectFile>(Bin.get())) { 532dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 533dc707122SEaswaran Raman OF.reset(cast<object::ObjectFile>(Bin.release())); 534dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 535dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 53685c973d3SVedant Kumar return object_error::arch_not_found; 537dc707122SEaswaran Raman } else 538dc707122SEaswaran Raman // We can only handle object files. 53985c973d3SVedant Kumar return coveragemap_error::malformed; 540dc707122SEaswaran Raman 541dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 542dc707122SEaswaran Raman BytesInAddress = OF->getBytesInAddress(); 543dc707122SEaswaran Raman Endian = OF->isLittleEndian() ? support::endianness::little 544dc707122SEaswaran Raman : support::endianness::big; 545dc707122SEaswaran Raman 546dc707122SEaswaran Raman // Look for the sections that we are interested in. 547dc707122SEaswaran Raman auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false)); 54885c973d3SVedant Kumar if (auto EC = NamesSection.getError()) 54985c973d3SVedant Kumar return EC; 550dc707122SEaswaran Raman auto CoverageSection = 551dc707122SEaswaran Raman lookupSection(*OF, getInstrProfCoverageSectionName(false)); 55285c973d3SVedant Kumar if (auto EC = CoverageSection.getError()) 55385c973d3SVedant Kumar return EC; 554dc707122SEaswaran Raman 555dc707122SEaswaran Raman // Get the contents of the given sections. 55685c973d3SVedant Kumar if (std::error_code EC = CoverageSection->getContents(CoverageMapping)) 55785c973d3SVedant Kumar return EC; 55885c973d3SVedant Kumar if (std::error_code EC = ProfileNames.create(*NamesSection)) 55985c973d3SVedant Kumar return EC; 560dc707122SEaswaran Raman 56185c973d3SVedant Kumar return std::error_code(); 562dc707122SEaswaran Raman } 563dc707122SEaswaran Raman 56485c973d3SVedant Kumar ErrorOr<std::unique_ptr<BinaryCoverageReader>> 565dc707122SEaswaran Raman BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, 566dc707122SEaswaran Raman StringRef Arch) { 567dc707122SEaswaran Raman std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); 568dc707122SEaswaran Raman 569dc707122SEaswaran Raman StringRef Coverage; 570dc707122SEaswaran Raman uint8_t BytesInAddress; 571dc707122SEaswaran Raman support::endianness Endian; 57285c973d3SVedant Kumar std::error_code EC; 573dc707122SEaswaran Raman if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) 574dc707122SEaswaran Raman // This is a special format used for testing. 57585c973d3SVedant Kumar EC = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames, 576dc707122SEaswaran Raman Coverage, BytesInAddress, Endian); 577dc707122SEaswaran Raman else 57885c973d3SVedant Kumar EC = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames, 579dc707122SEaswaran Raman Coverage, BytesInAddress, Endian, Arch); 58085c973d3SVedant Kumar if (EC) 58185c973d3SVedant Kumar return EC; 582dc707122SEaswaran Raman 583dc707122SEaswaran Raman if (BytesInAddress == 4 && Endian == support::endianness::little) 58485c973d3SVedant Kumar EC = readCoverageMappingData<uint32_t, support::endianness::little>( 585dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 586dc707122SEaswaran Raman Reader->Filenames); 587dc707122SEaswaran Raman else if (BytesInAddress == 4 && Endian == support::endianness::big) 58885c973d3SVedant Kumar EC = readCoverageMappingData<uint32_t, support::endianness::big>( 589dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 590dc707122SEaswaran Raman Reader->Filenames); 591dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::little) 59285c973d3SVedant Kumar EC = readCoverageMappingData<uint64_t, support::endianness::little>( 593dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 594dc707122SEaswaran Raman Reader->Filenames); 595dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::big) 59685c973d3SVedant Kumar EC = readCoverageMappingData<uint64_t, support::endianness::big>( 597dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 598dc707122SEaswaran Raman Reader->Filenames); 599dc707122SEaswaran Raman else 60085c973d3SVedant Kumar return coveragemap_error::malformed; 60185c973d3SVedant Kumar if (EC) 60285c973d3SVedant Kumar return EC; 603dc707122SEaswaran Raman return std::move(Reader); 604dc707122SEaswaran Raman } 605dc707122SEaswaran Raman 60685c973d3SVedant Kumar std::error_code 60785c973d3SVedant Kumar BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 608dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 60985c973d3SVedant Kumar return coveragemap_error::eof; 610dc707122SEaswaran Raman 611dc707122SEaswaran Raman FunctionsFilenames.clear(); 612dc707122SEaswaran Raman Expressions.clear(); 613dc707122SEaswaran Raman MappingRegions.clear(); 614dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 615dc707122SEaswaran Raman RawCoverageMappingReader Reader( 616dc707122SEaswaran Raman R.CoverageMapping, 617dc707122SEaswaran Raman makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), 618dc707122SEaswaran Raman FunctionsFilenames, Expressions, MappingRegions); 619dc707122SEaswaran Raman if (auto Err = Reader.read()) 620dc707122SEaswaran Raman return Err; 621dc707122SEaswaran Raman 622dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 623dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 624dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 625dc707122SEaswaran Raman Record.Expressions = Expressions; 626dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 627dc707122SEaswaran Raman 628dc707122SEaswaran Raman ++CurrentRecord; 62985c973d3SVedant Kumar return std::error_code(); 630dc707122SEaswaran Raman } 631