172208a82SEugene Zelenko //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===// 2dc707122SEaswaran Raman // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6dc707122SEaswaran Raman // 7dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 8dc707122SEaswaran Raman // 9dc707122SEaswaran Raman // This file contains support for reading coverage mapping data for 10dc707122SEaswaran Raman // instrumentation based coverage. 11dc707122SEaswaran Raman // 12dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 13dc707122SEaswaran Raman 144a5ddf80SXinliang David Li #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 15e78d131aSEugene Zelenko #include "llvm/ADT/ArrayRef.h" 16ac40e819SIgor Kudrin #include "llvm/ADT/DenseMap.h" 17e78d131aSEugene Zelenko #include "llvm/ADT/STLExtras.h" 184a5ddf80SXinliang David Li #include "llvm/ADT/SmallVector.h" 19*dd1ea9deSVedant Kumar #include "llvm/ADT/Statistic.h" 20e78d131aSEugene Zelenko #include "llvm/ADT/StringRef.h" 21e78d131aSEugene Zelenko #include "llvm/ADT/Triple.h" 22e78d131aSEugene Zelenko #include "llvm/Object/Binary.h" 23e78d131aSEugene Zelenko #include "llvm/Object/Error.h" 24dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h" 25dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.h" 268b6af001SReid Kleckner #include "llvm/Object/COFF.h" 27e78d131aSEugene Zelenko #include "llvm/ProfileData/InstrProf.h" 28e78d131aSEugene Zelenko #include "llvm/Support/Casting.h" 29*dd1ea9deSVedant Kumar #include "llvm/Support/Compression.h" 30dc707122SEaswaran Raman #include "llvm/Support/Debug.h" 314a5ddf80SXinliang David Li #include "llvm/Support/Endian.h" 32e78d131aSEugene Zelenko #include "llvm/Support/Error.h" 33e78d131aSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 34dc707122SEaswaran Raman #include "llvm/Support/LEB128.h" 35dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h" 36dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 37e78d131aSEugene Zelenko #include <vector> 38dc707122SEaswaran Raman 39dc707122SEaswaran Raman using namespace llvm; 40dc707122SEaswaran Raman using namespace coverage; 41dc707122SEaswaran Raman using namespace object; 42dc707122SEaswaran Raman 43dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 44dc707122SEaswaran Raman 45*dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records"); 46*dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records"); 47*dd1ea9deSVedant Kumar 48dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 49bae83970SVedant Kumar if (ReadErr != coveragemap_error::success) 50bae83970SVedant Kumar return; 51bae83970SVedant Kumar 52dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 53dc707122SEaswaran Raman // the next record. 54bae83970SVedant Kumar if (auto E = Reader->readNextRecord(Record)) 559152fd17SVedant Kumar handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 569152fd17SVedant Kumar if (CME.get() == coveragemap_error::eof) 57dc707122SEaswaran Raman *this = CoverageMappingIterator(); 589152fd17SVedant Kumar else 59bae83970SVedant Kumar ReadErr = CME.get(); 609152fd17SVedant Kumar }); 619152fd17SVedant Kumar } 62dc707122SEaswaran Raman 639152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) { 6472208a82SEugene Zelenko if (Data.empty()) 659152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 66dc707122SEaswaran Raman unsigned N = 0; 676a0746a9SFangrui Song Result = decodeULEB128(Data.bytes_begin(), &N); 68dc707122SEaswaran Raman if (N > Data.size()) 699152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 70dc707122SEaswaran Raman Data = Data.substr(N); 719152fd17SVedant Kumar return Error::success(); 72dc707122SEaswaran Raman } 73dc707122SEaswaran Raman 749152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { 75dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 76dc707122SEaswaran Raman return Err; 77dc707122SEaswaran Raman if (Result >= MaxPlus1) 789152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 799152fd17SVedant Kumar return Error::success(); 80dc707122SEaswaran Raman } 81dc707122SEaswaran Raman 829152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) { 83dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 84dc707122SEaswaran Raman return Err; 85dc707122SEaswaran Raman // Sanity check the number. 86dc707122SEaswaran Raman if (Result > Data.size()) 879152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 889152fd17SVedant Kumar return Error::success(); 89dc707122SEaswaran Raman } 90dc707122SEaswaran Raman 919152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) { 92dc707122SEaswaran Raman uint64_t Length; 93dc707122SEaswaran Raman if (auto Err = readSize(Length)) 94dc707122SEaswaran Raman return Err; 95dc707122SEaswaran Raman Result = Data.substr(0, Length); 96dc707122SEaswaran Raman Data = Data.substr(Length); 979152fd17SVedant Kumar return Error::success(); 98dc707122SEaswaran Raman } 99dc707122SEaswaran Raman 100*dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::read( 101*dd1ea9deSVedant Kumar CovMapVersion Version, 102*dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) { 103dc707122SEaswaran Raman uint64_t NumFilenames; 104dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 105dc707122SEaswaran Raman return Err; 106*dd1ea9deSVedant Kumar if (!NumFilenames) 107*dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 108*dd1ea9deSVedant Kumar 109*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 110*dd1ea9deSVedant Kumar return readUncompressed(NumFilenames); 111*dd1ea9deSVedant Kumar 112*dd1ea9deSVedant Kumar // The uncompressed length may exceed the size of the encoded filenames. 113*dd1ea9deSVedant Kumar // Skip size validation. 114*dd1ea9deSVedant Kumar uint64_t UncompressedLen; 115*dd1ea9deSVedant Kumar if (auto Err = readULEB128(UncompressedLen)) 116*dd1ea9deSVedant Kumar return Err; 117*dd1ea9deSVedant Kumar 118*dd1ea9deSVedant Kumar uint64_t CompressedLen; 119*dd1ea9deSVedant Kumar if (auto Err = readSize(CompressedLen)) 120*dd1ea9deSVedant Kumar return Err; 121*dd1ea9deSVedant Kumar 122*dd1ea9deSVedant Kumar if (CompressedLen > 0) { 123*dd1ea9deSVedant Kumar if (!zlib::isAvailable()) 124*dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 125*dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 126*dd1ea9deSVedant Kumar 127*dd1ea9deSVedant Kumar // Allocate memory for the decompressed filenames. Transfer ownership of 128*dd1ea9deSVedant Kumar // the memory to BinaryCoverageReader. 129*dd1ea9deSVedant Kumar auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>(); 130*dd1ea9deSVedant Kumar SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get(); 131*dd1ea9deSVedant Kumar Decompressed.push_back(std::move(DecompressedStorage)); 132*dd1ea9deSVedant Kumar 133*dd1ea9deSVedant Kumar // Read compressed filenames. 134*dd1ea9deSVedant Kumar StringRef CompressedFilenames = Data.substr(0, CompressedLen); 135*dd1ea9deSVedant Kumar Data = Data.substr(CompressedLen); 136*dd1ea9deSVedant Kumar auto Err = 137*dd1ea9deSVedant Kumar zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen); 138*dd1ea9deSVedant Kumar if (Err) { 139*dd1ea9deSVedant Kumar consumeError(std::move(Err)); 140*dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 141*dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 142*dd1ea9deSVedant Kumar } 143*dd1ea9deSVedant Kumar 144*dd1ea9deSVedant Kumar StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size()); 145*dd1ea9deSVedant Kumar RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames); 146*dd1ea9deSVedant Kumar return Delegate.readUncompressed(NumFilenames); 147*dd1ea9deSVedant Kumar } 148*dd1ea9deSVedant Kumar 149*dd1ea9deSVedant Kumar return readUncompressed(NumFilenames); 150*dd1ea9deSVedant Kumar } 151*dd1ea9deSVedant Kumar 152*dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) { 153*dd1ea9deSVedant Kumar // Read uncompressed filenames. 154dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 155dc707122SEaswaran Raman StringRef Filename; 156dc707122SEaswaran Raman if (auto Err = readString(Filename)) 157dc707122SEaswaran Raman return Err; 158dc707122SEaswaran Raman Filenames.push_back(Filename); 159dc707122SEaswaran Raman } 1609152fd17SVedant Kumar return Error::success(); 161dc707122SEaswaran Raman } 162dc707122SEaswaran Raman 1639152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 164dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 165dc707122SEaswaran Raman switch (Tag) { 166dc707122SEaswaran Raman case Counter::Zero: 167dc707122SEaswaran Raman C = Counter::getZero(); 1689152fd17SVedant Kumar return Error::success(); 169dc707122SEaswaran Raman case Counter::CounterValueReference: 170dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 1719152fd17SVedant Kumar return Error::success(); 172dc707122SEaswaran Raman default: 173dc707122SEaswaran Raman break; 174dc707122SEaswaran Raman } 175dc707122SEaswaran Raman Tag -= Counter::Expression; 176dc707122SEaswaran Raman switch (Tag) { 177dc707122SEaswaran Raman case CounterExpression::Subtract: 178dc707122SEaswaran Raman case CounterExpression::Add: { 179dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 180dc707122SEaswaran Raman if (ID >= Expressions.size()) 1819152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 182dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 183dc707122SEaswaran Raman C = Counter::getExpression(ID); 184dc707122SEaswaran Raman break; 185dc707122SEaswaran Raman } 186dc707122SEaswaran Raman default: 1879152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 188dc707122SEaswaran Raman } 1899152fd17SVedant Kumar return Error::success(); 190dc707122SEaswaran Raman } 191dc707122SEaswaran Raman 1929152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 193dc707122SEaswaran Raman uint64_t EncodedCounter; 194dc707122SEaswaran Raman if (auto Err = 195dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 196dc707122SEaswaran Raman return Err; 197dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 198dc707122SEaswaran Raman return Err; 1999152fd17SVedant Kumar return Error::success(); 200dc707122SEaswaran Raman } 201dc707122SEaswaran Raman 202dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 203dc707122SEaswaran Raman << Counter::EncodingTagBits; 204dc707122SEaswaran Raman 2055f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id. 206dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 207dc707122SEaswaran Raman /// function. 2089152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 209dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 210dc707122SEaswaran Raman size_t NumFileIDs) { 211dc707122SEaswaran Raman uint64_t NumRegions; 212dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 213dc707122SEaswaran Raman return Err; 214dc707122SEaswaran Raman unsigned LineStart = 0; 215dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 216dc707122SEaswaran Raman Counter C; 217dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 218dc707122SEaswaran Raman 219dc707122SEaswaran Raman // Read the combined counter + region kind. 220dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 221dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 222dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 223dc707122SEaswaran Raman return Err; 224dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 225dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 226dc707122SEaswaran Raman if (Tag != Counter::Zero) { 227dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 228dc707122SEaswaran Raman return Err; 229dc707122SEaswaran Raman } else { 230dc707122SEaswaran Raman // Is it an expansion region? 231dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 232dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 233dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 234dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 235dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 2369152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 237dc707122SEaswaran Raman } else { 238dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 239dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 240dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 241dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 242dc707122SEaswaran Raman break; 243dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 244dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 245dc707122SEaswaran Raman break; 246dc707122SEaswaran Raman default: 2479152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 248dc707122SEaswaran Raman } 249dc707122SEaswaran Raman } 250dc707122SEaswaran Raman } 251dc707122SEaswaran Raman 252dc707122SEaswaran Raman // Read the source range. 253dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 254dc707122SEaswaran Raman if (auto Err = 255dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 256dc707122SEaswaran Raman return Err; 257dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 258dc707122SEaswaran Raman return Err; 259dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 2609152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 261dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 262dc707122SEaswaran Raman return Err; 263dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 264dc707122SEaswaran Raman return Err; 265dc707122SEaswaran Raman LineStart += LineStartDelta; 266ad8f637bSVedant Kumar 267ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 268ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 269ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 270ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 271ad8f637bSVedant Kumar } 272ad8f637bSVedant Kumar 273dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 274dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 275dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 276dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 277dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 278dc707122SEaswaran Raman // column end take up one byte each. 279dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 280dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 281dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 282dc707122SEaswaran Raman ColumnStart = 1; 283dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 284dc707122SEaswaran Raman } 285dc707122SEaswaran Raman 286d34e60caSNicola Zaghen LLVM_DEBUG({ 287dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 288dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 289dc707122SEaswaran Raman << ColumnEnd << ", "; 290dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 291dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 292dc707122SEaswaran Raman else 293dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 294dc707122SEaswaran Raman dbgs() << "\n"; 295dc707122SEaswaran Raman }); 296dc707122SEaswaran Raman 297bae83970SVedant Kumar auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID, 298bae83970SVedant Kumar LineStart, ColumnStart, 299bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 300bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 301bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 302bae83970SVedant Kumar MappingRegions.push_back(CMR); 303dc707122SEaswaran Raman } 3049152fd17SVedant Kumar return Error::success(); 305dc707122SEaswaran Raman } 306dc707122SEaswaran Raman 3079152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 308dc707122SEaswaran Raman // Read the virtual file mapping. 309e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 310dc707122SEaswaran Raman uint64_t NumFileMappings; 311dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 312dc707122SEaswaran Raman return Err; 313dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 314dc707122SEaswaran Raman uint64_t FilenameIndex; 315dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 316dc707122SEaswaran Raman return Err; 317dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 318dc707122SEaswaran Raman } 319dc707122SEaswaran Raman 320dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 321dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 322dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 323dc707122SEaswaran Raman } 324dc707122SEaswaran Raman 325dc707122SEaswaran Raman // Read the expressions. 326dc707122SEaswaran Raman uint64_t NumExpressions; 327dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 328dc707122SEaswaran Raman return Err; 329dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 330dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 331dc707122SEaswaran Raman // are decoded. 332dc707122SEaswaran Raman Expressions.resize( 333dc707122SEaswaran Raman NumExpressions, 334dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 335dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 336dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 337dc707122SEaswaran Raman return Err; 338dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 339dc707122SEaswaran Raman return Err; 340dc707122SEaswaran Raman } 341dc707122SEaswaran Raman 342dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 343dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 344dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 345dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 346dc707122SEaswaran Raman VirtualFileMapping.size())) 347dc707122SEaswaran Raman return Err; 348dc707122SEaswaran Raman } 349dc707122SEaswaran Raman 350dc707122SEaswaran Raman // Set the counters for the expansion regions. 351dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 352dc707122SEaswaran Raman // from the expanded file. 353dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 354dc707122SEaswaran Raman // all the nested expansion regions. 355dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 356dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 357dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 358dc707122SEaswaran Raman for (auto &R : MappingRegions) { 359dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 360dc707122SEaswaran Raman continue; 361dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 362dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 363dc707122SEaswaran Raman } 364dc707122SEaswaran Raman for (auto &R : MappingRegions) { 365dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 366dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 367dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 368dc707122SEaswaran Raman } 369dc707122SEaswaran Raman } 370dc707122SEaswaran Raman } 371dc707122SEaswaran Raman 3729152fd17SVedant Kumar return Error::success(); 373dc707122SEaswaran Raman } 374dc707122SEaswaran Raman 375ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 376ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 377ac40e819SIgor Kudrin uint64_t NumFileMappings; 378ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 379c55cf4afSBill Wendling return std::move(Err); 380ac40e819SIgor Kudrin if (NumFileMappings != 1) 381ac40e819SIgor Kudrin return false; 382ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 383ac40e819SIgor Kudrin uint64_t FilenameIndex; 384ac40e819SIgor Kudrin if (Error Err = 385ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 386c55cf4afSBill Wendling return std::move(Err); 387ac40e819SIgor Kudrin uint64_t NumExpressions; 388ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 389c55cf4afSBill Wendling return std::move(Err); 390ac40e819SIgor Kudrin if (NumExpressions != 0) 391ac40e819SIgor Kudrin return false; 392ac40e819SIgor Kudrin uint64_t NumRegions; 393ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 394c55cf4afSBill Wendling return std::move(Err); 395ac40e819SIgor Kudrin if (NumRegions != 1) 396ac40e819SIgor Kudrin return false; 397ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 398ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 399ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 400c55cf4afSBill Wendling return std::move(Err); 401ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 402ac40e819SIgor Kudrin return Tag == Counter::Zero; 403ac40e819SIgor Kudrin } 404ac40e819SIgor Kudrin 4059152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 406e183340cSFangrui Song Expected<StringRef> DataOrErr = Section.getContents(); 407e183340cSFangrui Song if (!DataOrErr) 408e183340cSFangrui Song return DataOrErr.takeError(); 409e183340cSFangrui Song Data = *DataOrErr; 410dc707122SEaswaran Raman Address = Section.getAddress(); 4118b6af001SReid Kleckner 4128b6af001SReid Kleckner // If this is a linked PE/COFF file, then we have to skip over the null byte 4138b6af001SReid Kleckner // that is allocated in the .lprfn$A section in the LLVM profiling runtime. 4148b6af001SReid Kleckner const ObjectFile *Obj = Section.getObject(); 4158b6af001SReid Kleckner if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) 4168b6af001SReid Kleckner Data = Data.drop_front(1); 4178b6af001SReid Kleckner 4189152fd17SVedant Kumar return Error::success(); 419dc707122SEaswaran Raman } 420dc707122SEaswaran Raman 421dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 422dc707122SEaswaran Raman if (Pointer < Address) 423dc707122SEaswaran Raman return StringRef(); 424dc707122SEaswaran Raman auto Offset = Pointer - Address; 425dc707122SEaswaran Raman if (Offset + Size > Data.size()) 426dc707122SEaswaran Raman return StringRef(); 427dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 428dc707122SEaswaran Raman } 429dc707122SEaswaran Raman 430ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 431ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 432ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 433ac40e819SIgor Kudrin if (Hash) 434ac40e819SIgor Kudrin return false; 435ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 436ac40e819SIgor Kudrin } 437ac40e819SIgor Kudrin 438*dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of 439*dd1ea9deSVedant Kumar /// filenames in a vector-like container. 440*dd1ea9deSVedant Kumar struct FilenameRange { 441*dd1ea9deSVedant Kumar unsigned StartingIndex; 442*dd1ea9deSVedant Kumar unsigned Length; 443*dd1ea9deSVedant Kumar 444*dd1ea9deSVedant Kumar FilenameRange(unsigned StartingIndex, unsigned Length) 445*dd1ea9deSVedant Kumar : StartingIndex(StartingIndex), Length(Length) {} 446*dd1ea9deSVedant Kumar 447*dd1ea9deSVedant Kumar void markInvalid() { Length = 0; } 448*dd1ea9deSVedant Kumar bool isInvalid() const { return Length == 0; } 449*dd1ea9deSVedant Kumar }; 450*dd1ea9deSVedant Kumar 451dc707122SEaswaran Raman namespace { 452e78d131aSEugene Zelenko 453*dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module. 454dc707122SEaswaran Raman struct CovMapFuncRecordReader { 455e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 456e78d131aSEugene Zelenko 457*dd1ea9deSVedant Kumar // Read a coverage header. 4583739b95dSVedant Kumar // 459*dd1ea9deSVedant Kumar // \p CovBuf points to the buffer containing the \c CovHeader of the coverage 4603739b95dSVedant Kumar // mapping data associated with the module. 4613739b95dSVedant Kumar // 462*dd1ea9deSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or to an address 463*dd1ea9deSVedant Kumar // greater than \p CovEnd if not. 464*dd1ea9deSVedant Kumar virtual Expected<const char *> 465*dd1ea9deSVedant Kumar readCoverageHeader(const char *CovBuf, const char *CovBufEnd, 466*dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) = 0; 467*dd1ea9deSVedant Kumar 468*dd1ea9deSVedant Kumar // Read function records. 469*dd1ea9deSVedant Kumar // 470*dd1ea9deSVedant Kumar // \p FuncRecBuf points to the buffer containing a batch of function records. 471*dd1ea9deSVedant Kumar // \p FuncRecBufEnd points past the end of the batch of records. 472*dd1ea9deSVedant Kumar // 473*dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 474*dd1ea9deSVedant Kumar // associated with the function records. It is unused in Version4. 475*dd1ea9deSVedant Kumar // 476*dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 477*dd1ea9deSVedant Kumar // mappings associated with the function records. It is unused in Version4. 478*dd1ea9deSVedant Kumar virtual Error readFunctionRecords(const char *FuncRecBuf, 479*dd1ea9deSVedant Kumar const char *FuncRecBufEnd, 480*dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 481*dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 482*dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) = 0; 483e78d131aSEugene Zelenko 484dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 4859152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 486e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 487dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 488dc707122SEaswaran Raman std::vector<StringRef> &F); 489dc707122SEaswaran Raman }; 490dc707122SEaswaran Raman 491dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 492e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 493dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 49472208a82SEugene Zelenko using FuncRecordType = 49572208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 49672208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 497dc707122SEaswaran Raman 498ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 499ac40e819SIgor Kudrin // in \c Records. 500e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 501dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 502dc707122SEaswaran Raman std::vector<StringRef> &Filenames; 503dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 504dc707122SEaswaran Raman 505*dd1ea9deSVedant Kumar // Maps a hash of the filenames in a TU to a \c FileRange. The range 506*dd1ea9deSVedant Kumar // specifies the location of the hashed filenames in \c Filenames. 507*dd1ea9deSVedant Kumar DenseMap<uint64_t, FilenameRange> FileRangeMap; 508*dd1ea9deSVedant Kumar 509ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 510ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 511ac40e819SIgor Kudrin // records for the functions with ODR linkage. 512ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 513ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 514ac40e819SIgor Kudrin // not used in the corresponding translation unit. 515ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 516*dd1ea9deSVedant Kumar StringRef Mapping, 517*dd1ea9deSVedant Kumar FilenameRange FileRange) { 518*dd1ea9deSVedant Kumar ++CovMapNumRecords; 519ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 520ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 521ac40e819SIgor Kudrin auto InsertResult = 522ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 523ac40e819SIgor Kudrin if (InsertResult.second) { 524ac40e819SIgor Kudrin StringRef FuncName; 525ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 526ac40e819SIgor Kudrin return Err; 527b5794ca9SVedant Kumar if (FuncName.empty()) 528b5794ca9SVedant Kumar return make_error<InstrProfError>(instrprof_error::malformed); 529*dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 530*dd1ea9deSVedant Kumar Records.emplace_back(Version, FuncName, FuncHash, Mapping, 531*dd1ea9deSVedant Kumar FileRange.StartingIndex, FileRange.Length); 532ac40e819SIgor Kudrin return Error::success(); 533ac40e819SIgor Kudrin } 534ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 535ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 536ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 537ac40e819SIgor Kudrin Records[OldRecordIndex]; 538ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 539ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 540ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 541ac40e819SIgor Kudrin return Err; 542ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 543ac40e819SIgor Kudrin return Error::success(); 544ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 545ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 546ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 547ac40e819SIgor Kudrin return Err; 548ac40e819SIgor Kudrin if (*NewIsDummyExpected) 549ac40e819SIgor Kudrin return Error::success(); 550*dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 551ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 552ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 553*dd1ea9deSVedant Kumar OldRecord.FilenamesBegin = FileRange.StartingIndex; 554*dd1ea9deSVedant Kumar OldRecord.FilenamesSize = FileRange.Length; 555ac40e819SIgor Kudrin return Error::success(); 556ac40e819SIgor Kudrin } 557ac40e819SIgor Kudrin 558dc707122SEaswaran Raman public: 559dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 560dc707122SEaswaran Raman InstrProfSymtab &P, 561dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 562dc707122SEaswaran Raman std::vector<StringRef> &F) 563dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 564e78d131aSEugene Zelenko 565e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 566dc707122SEaswaran Raman 567*dd1ea9deSVedant Kumar Expected<const char *> readCoverageHeader( 568*dd1ea9deSVedant Kumar const char *CovBuf, const char *CovBufEnd, 569*dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) override { 570dc707122SEaswaran Raman using namespace support; 571e78d131aSEugene Zelenko 572*dd1ea9deSVedant Kumar if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) 5739152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 574*dd1ea9deSVedant Kumar auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); 575dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 576dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 577dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 578dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 579*dd1ea9deSVedant Kumar CovBuf = reinterpret_cast<const char *>(CovHeader + 1); 580dc707122SEaswaran Raman 581dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 582*dd1ea9deSVedant Kumar // This is a no-op in Version4 (function records are read after all headers 583*dd1ea9deSVedant Kumar // are read). 584*dd1ea9deSVedant Kumar const char *FuncRecBuf = nullptr; 585*dd1ea9deSVedant Kumar const char *FuncRecBufEnd = nullptr; 586*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 587*dd1ea9deSVedant Kumar FuncRecBuf = CovBuf; 588*dd1ea9deSVedant Kumar CovBuf += NRecords * sizeof(FuncRecordType); 589*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 590*dd1ea9deSVedant Kumar FuncRecBufEnd = CovBuf; 591dc707122SEaswaran Raman 592dc707122SEaswaran Raman // Get the filenames. 593*dd1ea9deSVedant Kumar if (CovBuf + FilenamesSize > CovBufEnd) 5949152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 595dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 596*dd1ea9deSVedant Kumar StringRef FilenameRegion(CovBuf, FilenamesSize); 597*dd1ea9deSVedant Kumar RawCoverageFilenamesReader Reader(FilenameRegion, Filenames); 598*dd1ea9deSVedant Kumar if (auto Err = Reader.read(Version, Decompressed)) 599c55cf4afSBill Wendling return std::move(Err); 600*dd1ea9deSVedant Kumar CovBuf += FilenamesSize; 601*dd1ea9deSVedant Kumar FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin); 602*dd1ea9deSVedant Kumar 603*dd1ea9deSVedant Kumar if (Version == CovMapVersion::Version4) { 604*dd1ea9deSVedant Kumar // Map a hash of the filenames region to the filename range associated 605*dd1ea9deSVedant Kumar // with this coverage header. 606*dd1ea9deSVedant Kumar int64_t FilenamesRef = 607*dd1ea9deSVedant Kumar llvm::IndexedInstrProf::ComputeHash(FilenameRegion); 608*dd1ea9deSVedant Kumar auto Insert = 609*dd1ea9deSVedant Kumar FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange)); 610*dd1ea9deSVedant Kumar if (!Insert.second) { 611*dd1ea9deSVedant Kumar // The same filenames ref was encountered twice. It's possible that 612*dd1ea9deSVedant Kumar // the associated filenames are the same. 613*dd1ea9deSVedant Kumar auto It = Filenames.begin(); 614*dd1ea9deSVedant Kumar FilenameRange &OrigRange = Insert.first->getSecond(); 615*dd1ea9deSVedant Kumar if (std::equal(It + OrigRange.StartingIndex, 616*dd1ea9deSVedant Kumar It + OrigRange.StartingIndex + OrigRange.Length, 617*dd1ea9deSVedant Kumar It + FileRange.StartingIndex, 618*dd1ea9deSVedant Kumar It + FileRange.StartingIndex + FileRange.Length)) 619*dd1ea9deSVedant Kumar // Map the new range to the original one. 620*dd1ea9deSVedant Kumar FileRange = OrigRange; 621*dd1ea9deSVedant Kumar else 622*dd1ea9deSVedant Kumar // This is a hash collision. Mark the filenames ref invalid. 623*dd1ea9deSVedant Kumar OrigRange.markInvalid(); 624*dd1ea9deSVedant Kumar } 625*dd1ea9deSVedant Kumar } 626dc707122SEaswaran Raman 627dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 628*dd1ea9deSVedant Kumar // This is a no-op in Version4 (coverage mappings are not affixed to the 629*dd1ea9deSVedant Kumar // coverage header). 630*dd1ea9deSVedant Kumar const char *MappingBuf = CovBuf; 631*dd1ea9deSVedant Kumar if (Version == CovMapVersion::Version4 && CoverageSize != 0) 6329152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 633*dd1ea9deSVedant Kumar CovBuf += CoverageSize; 634*dd1ea9deSVedant Kumar const char *MappingEnd = CovBuf; 635*dd1ea9deSVedant Kumar 636*dd1ea9deSVedant Kumar if (CovBuf > CovBufEnd) 637*dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 638*dd1ea9deSVedant Kumar 639*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 640*dd1ea9deSVedant Kumar // Read each function record. 641*dd1ea9deSVedant Kumar if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange, 642*dd1ea9deSVedant Kumar MappingBuf, MappingEnd)) 643*dd1ea9deSVedant Kumar return std::move(E); 644*dd1ea9deSVedant Kumar } 645*dd1ea9deSVedant Kumar 646dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 647dc707122SEaswaran Raman // before reading the next map. 648*dd1ea9deSVedant Kumar CovBuf += offsetToAlignedAddr(CovBuf, Align(8)); 649dc707122SEaswaran Raman 650*dd1ea9deSVedant Kumar return CovBuf; 65199317124SVedant Kumar } 652*dd1ea9deSVedant Kumar 653*dd1ea9deSVedant Kumar Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd, 654*dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 655*dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 656*dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) override { 657*dd1ea9deSVedant Kumar auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf); 658*dd1ea9deSVedant Kumar while ((const char *)CFR < FuncRecBufEnd) { 659*dd1ea9deSVedant Kumar // Validate the length of the coverage mapping for this function. 660*dd1ea9deSVedant Kumar const char *NextMappingBuf; 661*dd1ea9deSVedant Kumar const FuncRecordType *NextCFR; 662*dd1ea9deSVedant Kumar std::tie(NextMappingBuf, NextCFR) = 663*dd1ea9deSVedant Kumar CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); 664*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 665*dd1ea9deSVedant Kumar if (NextMappingBuf > OutOfLineMappingBufEnd) 666*dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 667*dd1ea9deSVedant Kumar 668*dd1ea9deSVedant Kumar // Look up the set of filenames associated with this function record. 669*dd1ea9deSVedant Kumar Optional<FilenameRange> FileRange; 670*dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 671*dd1ea9deSVedant Kumar FileRange = OutOfLineFileRange; 672*dd1ea9deSVedant Kumar } else { 673*dd1ea9deSVedant Kumar uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); 674*dd1ea9deSVedant Kumar auto It = FileRangeMap.find(FilenamesRef); 675*dd1ea9deSVedant Kumar if (It == FileRangeMap.end()) 676*dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 677*dd1ea9deSVedant Kumar else 678*dd1ea9deSVedant Kumar FileRange = It->getSecond(); 679*dd1ea9deSVedant Kumar } 680*dd1ea9deSVedant Kumar 681*dd1ea9deSVedant Kumar // Now, read the coverage data. 682*dd1ea9deSVedant Kumar if (FileRange && !FileRange->isInvalid()) { 683*dd1ea9deSVedant Kumar StringRef Mapping = 684*dd1ea9deSVedant Kumar CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); 685*dd1ea9deSVedant Kumar if (Version == CovMapVersion::Version4 && 686*dd1ea9deSVedant Kumar Mapping.data() + Mapping.size() > FuncRecBufEnd) 687*dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 688*dd1ea9deSVedant Kumar if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) 689*dd1ea9deSVedant Kumar return Err; 690*dd1ea9deSVedant Kumar } 691*dd1ea9deSVedant Kumar 692*dd1ea9deSVedant Kumar std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR); 693*dd1ea9deSVedant Kumar } 694*dd1ea9deSVedant Kumar return Error::success(); 695dc707122SEaswaran Raman } 696dc707122SEaswaran Raman }; 697e78d131aSEugene Zelenko 698dc707122SEaswaran Raman } // end anonymous namespace 699dc707122SEaswaran Raman 700dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 7019152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 702e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 703dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 704dc707122SEaswaran Raman std::vector<StringRef> &F) { 705dc707122SEaswaran Raman using namespace coverage; 706e78d131aSEugene Zelenko 707dc707122SEaswaran Raman switch (Version) { 708dc707122SEaswaran Raman case CovMapVersion::Version1: 7090eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 710dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 711dc707122SEaswaran Raman case CovMapVersion::Version2: 712ad8f637bSVedant Kumar case CovMapVersion::Version3: 713*dd1ea9deSVedant Kumar case CovMapVersion::Version4: 714dc707122SEaswaran Raman // Decompress the name data. 7159152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 716c55cf4afSBill Wendling return std::move(E); 717ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 7180eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 719dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 720*dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version3) 7210eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 722ad8f637bSVedant Kumar CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); 723*dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version4) 724*dd1ea9deSVedant Kumar return std::make_unique<VersionedCovMapFuncRecordReader< 725*dd1ea9deSVedant Kumar CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F); 726dc707122SEaswaran Raman } 727dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 728dc707122SEaswaran Raman } 729dc707122SEaswaran Raman 730dc707122SEaswaran Raman template <typename T, support::endianness Endian> 7319152fd17SVedant Kumar static Error readCoverageMappingData( 732*dd1ea9deSVedant Kumar InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, 733dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 734*dd1ea9deSVedant Kumar std::vector<StringRef> &Filenames, 735*dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) { 736dc707122SEaswaran Raman using namespace coverage; 737e78d131aSEugene Zelenko 738dc707122SEaswaran Raman // Read the records in the coverage data section. 739dc707122SEaswaran Raman auto CovHeader = 740*dd1ea9deSVedant Kumar reinterpret_cast<const CovMapHeader *>(CovMap.data()); 741dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 742e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 7439152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 7449152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 745dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 746dc707122SEaswaran Raman Filenames); 7479152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 7489152fd17SVedant Kumar return E; 7499152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 750*dd1ea9deSVedant Kumar const char *CovBuf = CovMap.data(); 751*dd1ea9deSVedant Kumar const char *CovBufEnd = CovBuf + CovMap.size(); 752*dd1ea9deSVedant Kumar const char *FuncRecBuf = FuncRecords.data(); 753*dd1ea9deSVedant Kumar const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size(); 754*dd1ea9deSVedant Kumar while (CovBuf < CovBufEnd) { 755*dd1ea9deSVedant Kumar // Read the current coverage header & filename data. 756*dd1ea9deSVedant Kumar // 757*dd1ea9deSVedant Kumar // Prior to Version4, this also reads all function records affixed to the 758*dd1ea9deSVedant Kumar // header. 759*dd1ea9deSVedant Kumar // 760*dd1ea9deSVedant Kumar // Return a pointer to the next coverage header. 761*dd1ea9deSVedant Kumar auto NextOrErr = 762*dd1ea9deSVedant Kumar Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed); 763*dd1ea9deSVedant Kumar if (auto E = NextOrErr.takeError()) 7649152fd17SVedant Kumar return E; 765*dd1ea9deSVedant Kumar CovBuf = NextOrErr.get(); 766dc707122SEaswaran Raman } 767*dd1ea9deSVedant Kumar // In Version4, function records are not affixed to coverage headers. Read 768*dd1ea9deSVedant Kumar // the records from their dedicated section. 769*dd1ea9deSVedant Kumar if (Version == CovMapVersion::Version4) 770*dd1ea9deSVedant Kumar return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr, 771*dd1ea9deSVedant Kumar nullptr); 7729152fd17SVedant Kumar return Error::success(); 773dc707122SEaswaran Raman } 774e78d131aSEugene Zelenko 775dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 776dc707122SEaswaran Raman 777901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 778901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer( 779*dd1ea9deSVedant Kumar StringRef Coverage, StringRef FuncRecords, InstrProfSymtab &&ProfileNames, 780*dd1ea9deSVedant Kumar uint8_t BytesInAddress, support::endianness Endian) { 781901d04fcSVedant Kumar std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); 782901d04fcSVedant Kumar Reader->ProfileNames = std::move(ProfileNames); 783901d04fcSVedant Kumar if (BytesInAddress == 4 && Endian == support::endianness::little) { 784901d04fcSVedant Kumar if (Error E = 785901d04fcSVedant Kumar readCoverageMappingData<uint32_t, support::endianness::little>( 786*dd1ea9deSVedant Kumar Reader->ProfileNames, Coverage, FuncRecords, 787*dd1ea9deSVedant Kumar Reader->MappingRecords, Reader->Filenames, 788*dd1ea9deSVedant Kumar Reader->Decompressed)) 789c55cf4afSBill Wendling return std::move(E); 790901d04fcSVedant Kumar } else if (BytesInAddress == 4 && Endian == support::endianness::big) { 791901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( 792*dd1ea9deSVedant Kumar Reader->ProfileNames, Coverage, FuncRecords, Reader->MappingRecords, 793*dd1ea9deSVedant Kumar Reader->Filenames, Reader->Decompressed)) 794c55cf4afSBill Wendling return std::move(E); 795901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::little) { 796901d04fcSVedant Kumar if (Error E = 797901d04fcSVedant Kumar readCoverageMappingData<uint64_t, support::endianness::little>( 798*dd1ea9deSVedant Kumar Reader->ProfileNames, Coverage, FuncRecords, 799*dd1ea9deSVedant Kumar Reader->MappingRecords, Reader->Filenames, 800*dd1ea9deSVedant Kumar Reader->Decompressed)) 801c55cf4afSBill Wendling return std::move(E); 802901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::big) { 803901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( 804*dd1ea9deSVedant Kumar Reader->ProfileNames, Coverage, FuncRecords, Reader->MappingRecords, 805*dd1ea9deSVedant Kumar Reader->Filenames, Reader->Decompressed)) 806c55cf4afSBill Wendling return std::move(E); 807901d04fcSVedant Kumar } else 808901d04fcSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 809c55cf4afSBill Wendling return std::move(Reader); 810901d04fcSVedant Kumar } 811901d04fcSVedant Kumar 812901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 813901d04fcSVedant Kumar loadTestingFormat(StringRef Data) { 814901d04fcSVedant Kumar uint8_t BytesInAddress = 8; 815901d04fcSVedant Kumar support::endianness Endian = support::endianness::little; 816dc707122SEaswaran Raman 817dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 81872208a82SEugene Zelenko if (Data.empty()) 8199152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 820dc707122SEaswaran Raman unsigned N = 0; 8216a0746a9SFangrui Song uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); 822dc707122SEaswaran Raman if (N > Data.size()) 8239152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 824dc707122SEaswaran Raman Data = Data.substr(N); 82572208a82SEugene Zelenko if (Data.empty()) 8269152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 827dc707122SEaswaran Raman N = 0; 8286a0746a9SFangrui Song uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); 829dc707122SEaswaran Raman if (N > Data.size()) 8309152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 831dc707122SEaswaran Raman Data = Data.substr(N); 832dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 8339152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 834901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 8359152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 836c55cf4afSBill Wendling return std::move(E); 837901d04fcSVedant Kumar StringRef CoverageMapping = Data.substr(ProfileNamesSize); 838eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 83972208a82SEugene Zelenko if (CoverageMapping.empty()) 8409152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 841ce56e1a1SGuillaume Chatelet size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8)); 842eb103073SIgor Kudrin if (CoverageMapping.size() < Pad) 8439152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 844eb103073SIgor Kudrin CoverageMapping = CoverageMapping.substr(Pad); 845901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 846*dd1ea9deSVedant Kumar CoverageMapping, "", std::move(ProfileNames), BytesInAddress, Endian); 847dc707122SEaswaran Raman } 848dc707122SEaswaran Raman 8499152fd17SVedant Kumar static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { 8508b6af001SReid Kleckner // On COFF, the object file section name may end in "$M". This tells the 8518b6af001SReid Kleckner // linker to sort these sections between "$A" and "$Z". The linker removes the 8528b6af001SReid Kleckner // dollar and everything after it in the final binary. Do the same to match. 8538b6af001SReid Kleckner bool IsCOFF = isa<COFFObjectFile>(OF); 8548b6af001SReid Kleckner auto stripSuffix = [IsCOFF](StringRef N) { 8558b6af001SReid Kleckner return IsCOFF ? N.split('$').first : N; 8568b6af001SReid Kleckner }; 8578b6af001SReid Kleckner Name = stripSuffix(Name); 8588b6af001SReid Kleckner 859dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 860bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 861bcc00e1aSGeorge Rimar if (!NameOrErr) 862bcc00e1aSGeorge Rimar return NameOrErr.takeError(); 863bcc00e1aSGeorge Rimar if (stripSuffix(*NameOrErr) == Name) 864dc707122SEaswaran Raman return Section; 865dc707122SEaswaran Raman } 8669152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 867dc707122SEaswaran Raman } 868dc707122SEaswaran Raman 869901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 870901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) { 871dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 872e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 873dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 874dc707122SEaswaran Raman // appropriate architecture. 8754fd11c1eSAlexander Shaposhnikov auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); 8769acb1099SKevin Enderby if (!ObjectFileOrErr) 8779acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 878dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 879e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 880dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 881e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 882dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 883dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 8849152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 885dc707122SEaswaran Raman } else 886dc707122SEaswaran Raman // We can only handle object files. 8879152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 888dc707122SEaswaran Raman 889dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 890901d04fcSVedant Kumar uint8_t BytesInAddress = OF->getBytesInAddress(); 891901d04fcSVedant Kumar support::endianness Endian = OF->isLittleEndian() 892901d04fcSVedant Kumar ? support::endianness::little 893dc707122SEaswaran Raman : support::endianness::big; 894dc707122SEaswaran Raman 895dc707122SEaswaran Raman // Look for the sections that we are interested in. 8961a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 8974a5ddf80SXinliang David Li auto NamesSection = 8981a6a2b64SVedant Kumar lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 8991a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9009152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 901c55cf4afSBill Wendling return std::move(E); 9024a5ddf80SXinliang David Li auto CoverageSection = 9031a6a2b64SVedant Kumar lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 9041a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9059152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 906c55cf4afSBill Wendling return std::move(E); 907901d04fcSVedant Kumar auto CoverageMappingOrErr = CoverageSection->getContents(); 908901d04fcSVedant Kumar if (!CoverageMappingOrErr) 909901d04fcSVedant Kumar return CoverageMappingOrErr.takeError(); 910*dd1ea9deSVedant Kumar StringRef CoverageMapping = CoverageMappingOrErr.get(); 911e183340cSFangrui Song 912901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 9139152fd17SVedant Kumar if (Error E = ProfileNames.create(*NamesSection)) 914c55cf4afSBill Wendling return std::move(E); 915dc707122SEaswaran Raman 916*dd1ea9deSVedant Kumar // Look for the coverage records section (Version4 only). 917*dd1ea9deSVedant Kumar StringRef FuncRecords; 918*dd1ea9deSVedant Kumar auto CoverageRecordsSection = 919*dd1ea9deSVedant Kumar lookupSection(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, 920*dd1ea9deSVedant Kumar /*AddSegmentInfo=*/false)); 921*dd1ea9deSVedant Kumar if (auto E = CoverageRecordsSection.takeError()) 922*dd1ea9deSVedant Kumar consumeError(std::move(E)); 923*dd1ea9deSVedant Kumar else { 924*dd1ea9deSVedant Kumar auto CoverageRecordsOrErr = CoverageRecordsSection->getContents(); 925*dd1ea9deSVedant Kumar if (!CoverageRecordsOrErr) 926*dd1ea9deSVedant Kumar return CoverageRecordsOrErr.takeError(); 927*dd1ea9deSVedant Kumar FuncRecords = CoverageRecordsOrErr.get(); 928*dd1ea9deSVedant Kumar } 929*dd1ea9deSVedant Kumar 930901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 931*dd1ea9deSVedant Kumar CoverageMapping, FuncRecords, std::move(ProfileNames), BytesInAddress, 932901d04fcSVedant Kumar Endian); 933dc707122SEaswaran Raman } 934dc707122SEaswaran Raman 935901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 936901d04fcSVedant Kumar BinaryCoverageReader::create( 937901d04fcSVedant Kumar MemoryBufferRef ObjectBuffer, StringRef Arch, 938901d04fcSVedant Kumar SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) { 939901d04fcSVedant Kumar std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; 940dc707122SEaswaran Raman 941901d04fcSVedant Kumar if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { 942dc707122SEaswaran Raman // This is a special format used for testing. 943901d04fcSVedant Kumar auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer()); 944901d04fcSVedant Kumar if (!ReaderOrErr) 945901d04fcSVedant Kumar return ReaderOrErr.takeError(); 946901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 947c55cf4afSBill Wendling return std::move(Readers); 948901d04fcSVedant Kumar } 949dc707122SEaswaran Raman 950901d04fcSVedant Kumar auto BinOrErr = createBinary(ObjectBuffer); 951901d04fcSVedant Kumar if (!BinOrErr) 952901d04fcSVedant Kumar return BinOrErr.takeError(); 953901d04fcSVedant Kumar std::unique_ptr<Binary> Bin = std::move(BinOrErr.get()); 954901d04fcSVedant Kumar 955901d04fcSVedant Kumar // MachO universal binaries which contain archives need to be treated as 956901d04fcSVedant Kumar // archives, not as regular binaries. 957901d04fcSVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 958901d04fcSVedant Kumar for (auto &ObjForArch : Universal->objects()) { 959901d04fcSVedant Kumar // Skip slices within the universal binary which target the wrong arch. 960901d04fcSVedant Kumar std::string ObjArch = ObjForArch.getArchFlagName(); 961901d04fcSVedant Kumar if (Arch != ObjArch) 962901d04fcSVedant Kumar continue; 963901d04fcSVedant Kumar 964901d04fcSVedant Kumar auto ArchiveOrErr = ObjForArch.getAsArchive(); 965901d04fcSVedant Kumar if (!ArchiveOrErr) { 966901d04fcSVedant Kumar // If this is not an archive, try treating it as a regular object. 967901d04fcSVedant Kumar consumeError(ArchiveOrErr.takeError()); 968901d04fcSVedant Kumar break; 969901d04fcSVedant Kumar } 970901d04fcSVedant Kumar 971901d04fcSVedant Kumar return BinaryCoverageReader::create( 972901d04fcSVedant Kumar ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers); 973901d04fcSVedant Kumar } 974901d04fcSVedant Kumar } 975901d04fcSVedant Kumar 976901d04fcSVedant Kumar // Load coverage out of archive members. 977901d04fcSVedant Kumar if (auto *Ar = dyn_cast<Archive>(Bin.get())) { 978901d04fcSVedant Kumar Error Err = Error::success(); 979901d04fcSVedant Kumar for (auto &Child : Ar->children(Err)) { 980901d04fcSVedant Kumar Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef(); 981901d04fcSVedant Kumar if (!ChildBufOrErr) 982901d04fcSVedant Kumar return ChildBufOrErr.takeError(); 983901d04fcSVedant Kumar 984901d04fcSVedant Kumar auto ChildReadersOrErr = BinaryCoverageReader::create( 985901d04fcSVedant Kumar ChildBufOrErr.get(), Arch, ObjectFileBuffers); 986901d04fcSVedant Kumar if (!ChildReadersOrErr) 987901d04fcSVedant Kumar return ChildReadersOrErr.takeError(); 988901d04fcSVedant Kumar for (auto &Reader : ChildReadersOrErr.get()) 989901d04fcSVedant Kumar Readers.push_back(std::move(Reader)); 990901d04fcSVedant Kumar } 991901d04fcSVedant Kumar if (Err) 992c55cf4afSBill Wendling return std::move(Err); 993901d04fcSVedant Kumar 994901d04fcSVedant Kumar // Thin archives reference object files outside of the archive file, i.e. 995901d04fcSVedant Kumar // files which reside in memory not owned by the caller. Transfer ownership 996901d04fcSVedant Kumar // to the caller. 997901d04fcSVedant Kumar if (Ar->isThin()) 998901d04fcSVedant Kumar for (auto &Buffer : Ar->takeThinBuffers()) 999901d04fcSVedant Kumar ObjectFileBuffers.push_back(std::move(Buffer)); 1000901d04fcSVedant Kumar 1001c55cf4afSBill Wendling return std::move(Readers); 1002901d04fcSVedant Kumar } 1003901d04fcSVedant Kumar 1004901d04fcSVedant Kumar auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch); 1005901d04fcSVedant Kumar if (!ReaderOrErr) 1006901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1007901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1008c55cf4afSBill Wendling return std::move(Readers); 1009dc707122SEaswaran Raman } 1010dc707122SEaswaran Raman 10119152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 1012dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 10139152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 1014dc707122SEaswaran Raman 1015dc707122SEaswaran Raman FunctionsFilenames.clear(); 1016dc707122SEaswaran Raman Expressions.clear(); 1017dc707122SEaswaran Raman MappingRegions.clear(); 1018dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 1019dc707122SEaswaran Raman RawCoverageMappingReader Reader( 1020dc707122SEaswaran Raman R.CoverageMapping, 1021dc707122SEaswaran Raman makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), 1022dc707122SEaswaran Raman FunctionsFilenames, Expressions, MappingRegions); 1023dc707122SEaswaran Raman if (auto Err = Reader.read()) 1024dc707122SEaswaran Raman return Err; 1025dc707122SEaswaran Raman 1026dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 1027dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 1028dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 1029dc707122SEaswaran Raman Record.Expressions = Expressions; 1030dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 1031dc707122SEaswaran Raman 1032dc707122SEaswaran Raman ++CurrentRecord; 10339152fd17SVedant Kumar return Error::success(); 1034dc707122SEaswaran Raman } 1035