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" 19dd1ea9deSVedant 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" 29dd1ea9deSVedant 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 45dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records"); 46dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records"); 47dd1ea9deSVedant 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 100dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::read( 101dd1ea9deSVedant Kumar CovMapVersion Version, 102dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) { 103dc707122SEaswaran Raman uint64_t NumFilenames; 104dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 105dc707122SEaswaran Raman return Err; 106dd1ea9deSVedant Kumar if (!NumFilenames) 107dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 108dd1ea9deSVedant Kumar 109dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 110dd1ea9deSVedant Kumar return readUncompressed(NumFilenames); 111dd1ea9deSVedant Kumar 112dd1ea9deSVedant Kumar // The uncompressed length may exceed the size of the encoded filenames. 113dd1ea9deSVedant Kumar // Skip size validation. 114dd1ea9deSVedant Kumar uint64_t UncompressedLen; 115dd1ea9deSVedant Kumar if (auto Err = readULEB128(UncompressedLen)) 116dd1ea9deSVedant Kumar return Err; 117dd1ea9deSVedant Kumar 118dd1ea9deSVedant Kumar uint64_t CompressedLen; 119dd1ea9deSVedant Kumar if (auto Err = readSize(CompressedLen)) 120dd1ea9deSVedant Kumar return Err; 121dd1ea9deSVedant Kumar 122dd1ea9deSVedant Kumar if (CompressedLen > 0) { 123dd1ea9deSVedant Kumar if (!zlib::isAvailable()) 124dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 125dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 126dd1ea9deSVedant Kumar 127dd1ea9deSVedant Kumar // Allocate memory for the decompressed filenames. Transfer ownership of 128dd1ea9deSVedant Kumar // the memory to BinaryCoverageReader. 129dd1ea9deSVedant Kumar auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>(); 130dd1ea9deSVedant Kumar SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get(); 131dd1ea9deSVedant Kumar Decompressed.push_back(std::move(DecompressedStorage)); 132dd1ea9deSVedant Kumar 133dd1ea9deSVedant Kumar // Read compressed filenames. 134dd1ea9deSVedant Kumar StringRef CompressedFilenames = Data.substr(0, CompressedLen); 135dd1ea9deSVedant Kumar Data = Data.substr(CompressedLen); 136dd1ea9deSVedant Kumar auto Err = 137dd1ea9deSVedant Kumar zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen); 138dd1ea9deSVedant Kumar if (Err) { 139dd1ea9deSVedant Kumar consumeError(std::move(Err)); 140dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 141dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 142dd1ea9deSVedant Kumar } 143dd1ea9deSVedant Kumar 144dd1ea9deSVedant Kumar StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size()); 145dd1ea9deSVedant Kumar RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames); 146dd1ea9deSVedant Kumar return Delegate.readUncompressed(NumFilenames); 147dd1ea9deSVedant Kumar } 148dd1ea9deSVedant Kumar 149dd1ea9deSVedant Kumar return readUncompressed(NumFilenames); 150dd1ea9deSVedant Kumar } 151dd1ea9deSVedant Kumar 152dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) { 153dd1ea9deSVedant 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) { 216*9f2967bcSAlan Phipps Counter C, C2; 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; 226*9f2967bcSAlan Phipps 227*9f2967bcSAlan Phipps // If Tag does not represent a ZeroCounter, then it is understood to refer 228*9f2967bcSAlan Phipps // to a counter or counter expression with region kind assumed to be 229*9f2967bcSAlan Phipps // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the 230*9f2967bcSAlan Phipps // referenced counter or counter expression (and nothing else). 231*9f2967bcSAlan Phipps // 232*9f2967bcSAlan Phipps // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set, 233*9f2967bcSAlan Phipps // then EncodedCounterAndRegion is interpreted to represent an 234*9f2967bcSAlan Phipps // ExpansionRegion. In all other cases, EncodedCounterAndRegion is 235*9f2967bcSAlan Phipps // interpreted to refer to a specific region kind, after which additional 236*9f2967bcSAlan Phipps // fields may be read (e.g. BranchRegions have two encoded counters that 237*9f2967bcSAlan Phipps // follow an encoded region kind value). 238dc707122SEaswaran Raman if (Tag != Counter::Zero) { 239dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 240dc707122SEaswaran Raman return Err; 241dc707122SEaswaran Raman } else { 242dc707122SEaswaran Raman // Is it an expansion region? 243dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 244dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 245dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 246dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 247dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 2489152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 249dc707122SEaswaran Raman } else { 250dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 251dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 252dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 253dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 254dc707122SEaswaran Raman break; 255dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 256dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 257dc707122SEaswaran Raman break; 258*9f2967bcSAlan Phipps case CounterMappingRegion::BranchRegion: 259*9f2967bcSAlan Phipps // For a Branch Region, read two successive counters. 260*9f2967bcSAlan Phipps Kind = CounterMappingRegion::BranchRegion; 261*9f2967bcSAlan Phipps if (auto Err = readCounter(C)) 262*9f2967bcSAlan Phipps return Err; 263*9f2967bcSAlan Phipps if (auto Err = readCounter(C2)) 264*9f2967bcSAlan Phipps return Err; 265*9f2967bcSAlan Phipps break; 266dc707122SEaswaran Raman default: 2679152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 268dc707122SEaswaran Raman } 269dc707122SEaswaran Raman } 270dc707122SEaswaran Raman } 271dc707122SEaswaran Raman 272dc707122SEaswaran Raman // Read the source range. 273dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 274dc707122SEaswaran Raman if (auto Err = 275dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 276dc707122SEaswaran Raman return Err; 277dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 278dc707122SEaswaran Raman return Err; 279dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 2809152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 281dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 282dc707122SEaswaran Raman return Err; 283dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 284dc707122SEaswaran Raman return Err; 285dc707122SEaswaran Raman LineStart += LineStartDelta; 286ad8f637bSVedant Kumar 287ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 288ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 289ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 290ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 291ad8f637bSVedant Kumar } 292ad8f637bSVedant Kumar 293dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 294dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 295dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 296dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 297dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 298dc707122SEaswaran Raman // column end take up one byte each. 299dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 300dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 301dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 302dc707122SEaswaran Raman ColumnStart = 1; 303dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 304dc707122SEaswaran Raman } 305dc707122SEaswaran Raman 306d34e60caSNicola Zaghen LLVM_DEBUG({ 307dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 308dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 309dc707122SEaswaran Raman << ColumnEnd << ", "; 310dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 311dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 312dc707122SEaswaran Raman else 313dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 314dc707122SEaswaran Raman dbgs() << "\n"; 315dc707122SEaswaran Raman }); 316dc707122SEaswaran Raman 317*9f2967bcSAlan Phipps auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID, 318bae83970SVedant Kumar LineStart, ColumnStart, 319bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 320bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 321bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 322bae83970SVedant Kumar MappingRegions.push_back(CMR); 323dc707122SEaswaran Raman } 3249152fd17SVedant Kumar return Error::success(); 325dc707122SEaswaran Raman } 326dc707122SEaswaran Raman 3279152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 328dc707122SEaswaran Raman // Read the virtual file mapping. 329e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 330dc707122SEaswaran Raman uint64_t NumFileMappings; 331dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 332dc707122SEaswaran Raman return Err; 333dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 334dc707122SEaswaran Raman uint64_t FilenameIndex; 335dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 336dc707122SEaswaran Raman return Err; 337dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 338dc707122SEaswaran Raman } 339dc707122SEaswaran Raman 340dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 341dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 342dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 343dc707122SEaswaran Raman } 344dc707122SEaswaran Raman 345dc707122SEaswaran Raman // Read the expressions. 346dc707122SEaswaran Raman uint64_t NumExpressions; 347dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 348dc707122SEaswaran Raman return Err; 349dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 350dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 351dc707122SEaswaran Raman // are decoded. 352dc707122SEaswaran Raman Expressions.resize( 353dc707122SEaswaran Raman NumExpressions, 354dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 355dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 356dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 357dc707122SEaswaran Raman return Err; 358dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 359dc707122SEaswaran Raman return Err; 360dc707122SEaswaran Raman } 361dc707122SEaswaran Raman 362dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 363dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 364dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 365dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 366dc707122SEaswaran Raman VirtualFileMapping.size())) 367dc707122SEaswaran Raman return Err; 368dc707122SEaswaran Raman } 369dc707122SEaswaran Raman 370dc707122SEaswaran Raman // Set the counters for the expansion regions. 371dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 372dc707122SEaswaran Raman // from the expanded file. 373dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 374dc707122SEaswaran Raman // all the nested expansion regions. 375dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 376dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 377dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 378dc707122SEaswaran Raman for (auto &R : MappingRegions) { 379dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 380dc707122SEaswaran Raman continue; 381dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 382dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 383dc707122SEaswaran Raman } 384dc707122SEaswaran Raman for (auto &R : MappingRegions) { 385dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 386dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 387dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 388dc707122SEaswaran Raman } 389dc707122SEaswaran Raman } 390dc707122SEaswaran Raman } 391dc707122SEaswaran Raman 3929152fd17SVedant Kumar return Error::success(); 393dc707122SEaswaran Raman } 394dc707122SEaswaran Raman 395ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 396ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 397ac40e819SIgor Kudrin uint64_t NumFileMappings; 398ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 399c55cf4afSBill Wendling return std::move(Err); 400ac40e819SIgor Kudrin if (NumFileMappings != 1) 401ac40e819SIgor Kudrin return false; 402ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 403ac40e819SIgor Kudrin uint64_t FilenameIndex; 404ac40e819SIgor Kudrin if (Error Err = 405ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 406c55cf4afSBill Wendling return std::move(Err); 407ac40e819SIgor Kudrin uint64_t NumExpressions; 408ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 409c55cf4afSBill Wendling return std::move(Err); 410ac40e819SIgor Kudrin if (NumExpressions != 0) 411ac40e819SIgor Kudrin return false; 412ac40e819SIgor Kudrin uint64_t NumRegions; 413ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 414c55cf4afSBill Wendling return std::move(Err); 415ac40e819SIgor Kudrin if (NumRegions != 1) 416ac40e819SIgor Kudrin return false; 417ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 418ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 419ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 420c55cf4afSBill Wendling return std::move(Err); 421ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 422ac40e819SIgor Kudrin return Tag == Counter::Zero; 423ac40e819SIgor Kudrin } 424ac40e819SIgor Kudrin 4259152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 426e183340cSFangrui Song Expected<StringRef> DataOrErr = Section.getContents(); 427e183340cSFangrui Song if (!DataOrErr) 428e183340cSFangrui Song return DataOrErr.takeError(); 429e183340cSFangrui Song Data = *DataOrErr; 430dc707122SEaswaran Raman Address = Section.getAddress(); 4318b6af001SReid Kleckner 4328b6af001SReid Kleckner // If this is a linked PE/COFF file, then we have to skip over the null byte 4338b6af001SReid Kleckner // that is allocated in the .lprfn$A section in the LLVM profiling runtime. 4348b6af001SReid Kleckner const ObjectFile *Obj = Section.getObject(); 4358b6af001SReid Kleckner if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) 4368b6af001SReid Kleckner Data = Data.drop_front(1); 4378b6af001SReid Kleckner 4389152fd17SVedant Kumar return Error::success(); 439dc707122SEaswaran Raman } 440dc707122SEaswaran Raman 441dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 442dc707122SEaswaran Raman if (Pointer < Address) 443dc707122SEaswaran Raman return StringRef(); 444dc707122SEaswaran Raman auto Offset = Pointer - Address; 445dc707122SEaswaran Raman if (Offset + Size > Data.size()) 446dc707122SEaswaran Raman return StringRef(); 447dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 448dc707122SEaswaran Raman } 449dc707122SEaswaran Raman 450ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 451ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 452ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 453ac40e819SIgor Kudrin if (Hash) 454ac40e819SIgor Kudrin return false; 455ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 456ac40e819SIgor Kudrin } 457ac40e819SIgor Kudrin 458dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of 459dd1ea9deSVedant Kumar /// filenames in a vector-like container. 460dd1ea9deSVedant Kumar struct FilenameRange { 461dd1ea9deSVedant Kumar unsigned StartingIndex; 462dd1ea9deSVedant Kumar unsigned Length; 463dd1ea9deSVedant Kumar 464dd1ea9deSVedant Kumar FilenameRange(unsigned StartingIndex, unsigned Length) 465dd1ea9deSVedant Kumar : StartingIndex(StartingIndex), Length(Length) {} 466dd1ea9deSVedant Kumar 467dd1ea9deSVedant Kumar void markInvalid() { Length = 0; } 468dd1ea9deSVedant Kumar bool isInvalid() const { return Length == 0; } 469dd1ea9deSVedant Kumar }; 470dd1ea9deSVedant Kumar 471dc707122SEaswaran Raman namespace { 472e78d131aSEugene Zelenko 473dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module. 474dc707122SEaswaran Raman struct CovMapFuncRecordReader { 475e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 476e78d131aSEugene Zelenko 477dd1ea9deSVedant Kumar // Read a coverage header. 4783739b95dSVedant Kumar // 479dd1ea9deSVedant Kumar // \p CovBuf points to the buffer containing the \c CovHeader of the coverage 4803739b95dSVedant Kumar // mapping data associated with the module. 4813739b95dSVedant Kumar // 482dd1ea9deSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or to an address 483dd1ea9deSVedant Kumar // greater than \p CovEnd if not. 484dd1ea9deSVedant Kumar virtual Expected<const char *> 485dd1ea9deSVedant Kumar readCoverageHeader(const char *CovBuf, const char *CovBufEnd, 486dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) = 0; 487dd1ea9deSVedant Kumar 488dd1ea9deSVedant Kumar // Read function records. 489dd1ea9deSVedant Kumar // 490dd1ea9deSVedant Kumar // \p FuncRecBuf points to the buffer containing a batch of function records. 491dd1ea9deSVedant Kumar // \p FuncRecBufEnd points past the end of the batch of records. 492dd1ea9deSVedant Kumar // 493dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 494dd1ea9deSVedant Kumar // associated with the function records. It is unused in Version4. 495dd1ea9deSVedant Kumar // 496dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 497dd1ea9deSVedant Kumar // mappings associated with the function records. It is unused in Version4. 498dd1ea9deSVedant Kumar virtual Error readFunctionRecords(const char *FuncRecBuf, 499dd1ea9deSVedant Kumar const char *FuncRecBufEnd, 500dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 501dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 502dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) = 0; 503e78d131aSEugene Zelenko 504dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 5059152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 506e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 507dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 508dc707122SEaswaran Raman std::vector<StringRef> &F); 509dc707122SEaswaran Raman }; 510dc707122SEaswaran Raman 511dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 512e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 513dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 51472208a82SEugene Zelenko using FuncRecordType = 51572208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 51672208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 517dc707122SEaswaran Raman 518ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 519ac40e819SIgor Kudrin // in \c Records. 520e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 521dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 522dc707122SEaswaran Raman std::vector<StringRef> &Filenames; 523dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 524dc707122SEaswaran Raman 525dd1ea9deSVedant Kumar // Maps a hash of the filenames in a TU to a \c FileRange. The range 526dd1ea9deSVedant Kumar // specifies the location of the hashed filenames in \c Filenames. 527dd1ea9deSVedant Kumar DenseMap<uint64_t, FilenameRange> FileRangeMap; 528dd1ea9deSVedant Kumar 529ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 530ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 531ac40e819SIgor Kudrin // records for the functions with ODR linkage. 532ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 533ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 534ac40e819SIgor Kudrin // not used in the corresponding translation unit. 535ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 536dd1ea9deSVedant Kumar StringRef Mapping, 537dd1ea9deSVedant Kumar FilenameRange FileRange) { 538dd1ea9deSVedant Kumar ++CovMapNumRecords; 539ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 540ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 541ac40e819SIgor Kudrin auto InsertResult = 542ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 543ac40e819SIgor Kudrin if (InsertResult.second) { 544ac40e819SIgor Kudrin StringRef FuncName; 545ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 546ac40e819SIgor Kudrin return Err; 547b5794ca9SVedant Kumar if (FuncName.empty()) 548b5794ca9SVedant Kumar return make_error<InstrProfError>(instrprof_error::malformed); 549dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 550dd1ea9deSVedant Kumar Records.emplace_back(Version, FuncName, FuncHash, Mapping, 551dd1ea9deSVedant Kumar FileRange.StartingIndex, FileRange.Length); 552ac40e819SIgor Kudrin return Error::success(); 553ac40e819SIgor Kudrin } 554ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 555ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 556ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 557ac40e819SIgor Kudrin Records[OldRecordIndex]; 558ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 559ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 560ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 561ac40e819SIgor Kudrin return Err; 562ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 563ac40e819SIgor Kudrin return Error::success(); 564ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 565ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 566ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 567ac40e819SIgor Kudrin return Err; 568ac40e819SIgor Kudrin if (*NewIsDummyExpected) 569ac40e819SIgor Kudrin return Error::success(); 570dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 571ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 572ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 573dd1ea9deSVedant Kumar OldRecord.FilenamesBegin = FileRange.StartingIndex; 574dd1ea9deSVedant Kumar OldRecord.FilenamesSize = FileRange.Length; 575ac40e819SIgor Kudrin return Error::success(); 576ac40e819SIgor Kudrin } 577ac40e819SIgor Kudrin 578dc707122SEaswaran Raman public: 579dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 580dc707122SEaswaran Raman InstrProfSymtab &P, 581dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 582dc707122SEaswaran Raman std::vector<StringRef> &F) 583dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 584e78d131aSEugene Zelenko 585e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 586dc707122SEaswaran Raman 587dd1ea9deSVedant Kumar Expected<const char *> readCoverageHeader( 588dd1ea9deSVedant Kumar const char *CovBuf, const char *CovBufEnd, 589dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) override { 590dc707122SEaswaran Raman using namespace support; 591e78d131aSEugene Zelenko 592dd1ea9deSVedant Kumar if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) 5939152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 594dd1ea9deSVedant Kumar auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); 595dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 596dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 597dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 598dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 599dd1ea9deSVedant Kumar CovBuf = reinterpret_cast<const char *>(CovHeader + 1); 600dc707122SEaswaran Raman 601dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 602dd1ea9deSVedant Kumar // This is a no-op in Version4 (function records are read after all headers 603dd1ea9deSVedant Kumar // are read). 604dd1ea9deSVedant Kumar const char *FuncRecBuf = nullptr; 605dd1ea9deSVedant Kumar const char *FuncRecBufEnd = nullptr; 606dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 607dd1ea9deSVedant Kumar FuncRecBuf = CovBuf; 608dd1ea9deSVedant Kumar CovBuf += NRecords * sizeof(FuncRecordType); 609dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 610dd1ea9deSVedant Kumar FuncRecBufEnd = CovBuf; 611dc707122SEaswaran Raman 612dc707122SEaswaran Raman // Get the filenames. 613dd1ea9deSVedant Kumar if (CovBuf + FilenamesSize > CovBufEnd) 6149152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 615dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 616dd1ea9deSVedant Kumar StringRef FilenameRegion(CovBuf, FilenamesSize); 617dd1ea9deSVedant Kumar RawCoverageFilenamesReader Reader(FilenameRegion, Filenames); 618dd1ea9deSVedant Kumar if (auto Err = Reader.read(Version, Decompressed)) 619c55cf4afSBill Wendling return std::move(Err); 620dd1ea9deSVedant Kumar CovBuf += FilenamesSize; 621dd1ea9deSVedant Kumar FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin); 622dd1ea9deSVedant Kumar 623*9f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) { 624dd1ea9deSVedant Kumar // Map a hash of the filenames region to the filename range associated 625dd1ea9deSVedant Kumar // with this coverage header. 626dd1ea9deSVedant Kumar int64_t FilenamesRef = 627dd1ea9deSVedant Kumar llvm::IndexedInstrProf::ComputeHash(FilenameRegion); 628dd1ea9deSVedant Kumar auto Insert = 629dd1ea9deSVedant Kumar FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange)); 630dd1ea9deSVedant Kumar if (!Insert.second) { 631dd1ea9deSVedant Kumar // The same filenames ref was encountered twice. It's possible that 632dd1ea9deSVedant Kumar // the associated filenames are the same. 633dd1ea9deSVedant Kumar auto It = Filenames.begin(); 634dd1ea9deSVedant Kumar FilenameRange &OrigRange = Insert.first->getSecond(); 635dd1ea9deSVedant Kumar if (std::equal(It + OrigRange.StartingIndex, 636dd1ea9deSVedant Kumar It + OrigRange.StartingIndex + OrigRange.Length, 637dd1ea9deSVedant Kumar It + FileRange.StartingIndex, 638dd1ea9deSVedant Kumar It + FileRange.StartingIndex + FileRange.Length)) 639dd1ea9deSVedant Kumar // Map the new range to the original one. 640dd1ea9deSVedant Kumar FileRange = OrigRange; 641dd1ea9deSVedant Kumar else 642dd1ea9deSVedant Kumar // This is a hash collision. Mark the filenames ref invalid. 643dd1ea9deSVedant Kumar OrigRange.markInvalid(); 644dd1ea9deSVedant Kumar } 645dd1ea9deSVedant Kumar } 646dc707122SEaswaran Raman 647dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 648dd1ea9deSVedant Kumar // This is a no-op in Version4 (coverage mappings are not affixed to the 649dd1ea9deSVedant Kumar // coverage header). 650dd1ea9deSVedant Kumar const char *MappingBuf = CovBuf; 651*9f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && CoverageSize != 0) 6529152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 653dd1ea9deSVedant Kumar CovBuf += CoverageSize; 654dd1ea9deSVedant Kumar const char *MappingEnd = CovBuf; 655dd1ea9deSVedant Kumar 656dd1ea9deSVedant Kumar if (CovBuf > CovBufEnd) 657dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 658dd1ea9deSVedant Kumar 659dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 660dd1ea9deSVedant Kumar // Read each function record. 661dd1ea9deSVedant Kumar if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange, 662dd1ea9deSVedant Kumar MappingBuf, MappingEnd)) 663dd1ea9deSVedant Kumar return std::move(E); 664dd1ea9deSVedant Kumar } 665dd1ea9deSVedant Kumar 666dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 667dc707122SEaswaran Raman // before reading the next map. 668dd1ea9deSVedant Kumar CovBuf += offsetToAlignedAddr(CovBuf, Align(8)); 669dc707122SEaswaran Raman 670dd1ea9deSVedant Kumar return CovBuf; 67199317124SVedant Kumar } 672dd1ea9deSVedant Kumar 673dd1ea9deSVedant Kumar Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd, 674dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 675dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 676dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) override { 677dd1ea9deSVedant Kumar auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf); 678dd1ea9deSVedant Kumar while ((const char *)CFR < FuncRecBufEnd) { 679dd1ea9deSVedant Kumar // Validate the length of the coverage mapping for this function. 680dd1ea9deSVedant Kumar const char *NextMappingBuf; 681dd1ea9deSVedant Kumar const FuncRecordType *NextCFR; 682dd1ea9deSVedant Kumar std::tie(NextMappingBuf, NextCFR) = 683dd1ea9deSVedant Kumar CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); 684dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 685dd1ea9deSVedant Kumar if (NextMappingBuf > OutOfLineMappingBufEnd) 686dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 687dd1ea9deSVedant Kumar 688dd1ea9deSVedant Kumar // Look up the set of filenames associated with this function record. 689dd1ea9deSVedant Kumar Optional<FilenameRange> FileRange; 690dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 691dd1ea9deSVedant Kumar FileRange = OutOfLineFileRange; 692dd1ea9deSVedant Kumar } else { 693dd1ea9deSVedant Kumar uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); 694dd1ea9deSVedant Kumar auto It = FileRangeMap.find(FilenamesRef); 695dd1ea9deSVedant Kumar if (It == FileRangeMap.end()) 696dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 697dd1ea9deSVedant Kumar else 698dd1ea9deSVedant Kumar FileRange = It->getSecond(); 699dd1ea9deSVedant Kumar } 700dd1ea9deSVedant Kumar 701dd1ea9deSVedant Kumar // Now, read the coverage data. 702dd1ea9deSVedant Kumar if (FileRange && !FileRange->isInvalid()) { 703dd1ea9deSVedant Kumar StringRef Mapping = 704dd1ea9deSVedant Kumar CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); 705*9f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && 706dd1ea9deSVedant Kumar Mapping.data() + Mapping.size() > FuncRecBufEnd) 707dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 708dd1ea9deSVedant Kumar if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) 709dd1ea9deSVedant Kumar return Err; 710dd1ea9deSVedant Kumar } 711dd1ea9deSVedant Kumar 712dd1ea9deSVedant Kumar std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR); 713dd1ea9deSVedant Kumar } 714dd1ea9deSVedant Kumar return Error::success(); 715dc707122SEaswaran Raman } 716dc707122SEaswaran Raman }; 717e78d131aSEugene Zelenko 718dc707122SEaswaran Raman } // end anonymous namespace 719dc707122SEaswaran Raman 720dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 7219152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 722e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 723dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 724dc707122SEaswaran Raman std::vector<StringRef> &F) { 725dc707122SEaswaran Raman using namespace coverage; 726e78d131aSEugene Zelenko 727dc707122SEaswaran Raman switch (Version) { 728dc707122SEaswaran Raman case CovMapVersion::Version1: 7290eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 730dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 731dc707122SEaswaran Raman case CovMapVersion::Version2: 732ad8f637bSVedant Kumar case CovMapVersion::Version3: 733dd1ea9deSVedant Kumar case CovMapVersion::Version4: 734*9f2967bcSAlan Phipps case CovMapVersion::Version5: 735dc707122SEaswaran Raman // Decompress the name data. 7369152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 737c55cf4afSBill Wendling return std::move(E); 738ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 7390eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 740dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 741dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version3) 7420eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 743ad8f637bSVedant Kumar CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); 744dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version4) 745dd1ea9deSVedant Kumar return std::make_unique<VersionedCovMapFuncRecordReader< 746dd1ea9deSVedant Kumar CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F); 747*9f2967bcSAlan Phipps else if (Version == CovMapVersion::Version5) 748*9f2967bcSAlan Phipps return std::make_unique<VersionedCovMapFuncRecordReader< 749*9f2967bcSAlan Phipps CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F); 750dc707122SEaswaran Raman } 751dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 752dc707122SEaswaran Raman } 753dc707122SEaswaran Raman 754dc707122SEaswaran Raman template <typename T, support::endianness Endian> 7559152fd17SVedant Kumar static Error readCoverageMappingData( 756dd1ea9deSVedant Kumar InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, 757dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 758dd1ea9deSVedant Kumar std::vector<StringRef> &Filenames, 759dd1ea9deSVedant Kumar BinaryCoverageReader::DecompressedData &Decompressed) { 760dc707122SEaswaran Raman using namespace coverage; 761e78d131aSEugene Zelenko 762dc707122SEaswaran Raman // Read the records in the coverage data section. 763dc707122SEaswaran Raman auto CovHeader = 764dd1ea9deSVedant Kumar reinterpret_cast<const CovMapHeader *>(CovMap.data()); 765dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 766e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 7679152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 7689152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 769dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 770dc707122SEaswaran Raman Filenames); 7719152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 7729152fd17SVedant Kumar return E; 7739152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 774dd1ea9deSVedant Kumar const char *CovBuf = CovMap.data(); 775dd1ea9deSVedant Kumar const char *CovBufEnd = CovBuf + CovMap.size(); 776dd1ea9deSVedant Kumar const char *FuncRecBuf = FuncRecords.data(); 777dd1ea9deSVedant Kumar const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size(); 778dd1ea9deSVedant Kumar while (CovBuf < CovBufEnd) { 779dd1ea9deSVedant Kumar // Read the current coverage header & filename data. 780dd1ea9deSVedant Kumar // 781dd1ea9deSVedant Kumar // Prior to Version4, this also reads all function records affixed to the 782dd1ea9deSVedant Kumar // header. 783dd1ea9deSVedant Kumar // 784dd1ea9deSVedant Kumar // Return a pointer to the next coverage header. 785dd1ea9deSVedant Kumar auto NextOrErr = 786dd1ea9deSVedant Kumar Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed); 787dd1ea9deSVedant Kumar if (auto E = NextOrErr.takeError()) 7889152fd17SVedant Kumar return E; 789dd1ea9deSVedant Kumar CovBuf = NextOrErr.get(); 790dc707122SEaswaran Raman } 791dd1ea9deSVedant Kumar // In Version4, function records are not affixed to coverage headers. Read 792dd1ea9deSVedant Kumar // the records from their dedicated section. 793*9f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) 794dd1ea9deSVedant Kumar return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr, 795dd1ea9deSVedant Kumar nullptr); 7969152fd17SVedant Kumar return Error::success(); 797dc707122SEaswaran Raman } 798e78d131aSEugene Zelenko 799dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 800dc707122SEaswaran Raman 801901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 802901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer( 80380cd518bSVedant Kumar StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames, 804dd1ea9deSVedant Kumar uint8_t BytesInAddress, support::endianness Endian) { 80580cd518bSVedant Kumar std::unique_ptr<BinaryCoverageReader> Reader( 80680cd518bSVedant Kumar new BinaryCoverageReader(std::move(FuncRecords))); 807901d04fcSVedant Kumar Reader->ProfileNames = std::move(ProfileNames); 80880cd518bSVedant Kumar StringRef FuncRecordsRef = Reader->FuncRecords; 809901d04fcSVedant Kumar if (BytesInAddress == 4 && Endian == support::endianness::little) { 810901d04fcSVedant Kumar if (Error E = 811901d04fcSVedant Kumar readCoverageMappingData<uint32_t, support::endianness::little>( 81280cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 813dd1ea9deSVedant Kumar Reader->MappingRecords, Reader->Filenames, 814dd1ea9deSVedant Kumar Reader->Decompressed)) 815c55cf4afSBill Wendling return std::move(E); 816901d04fcSVedant Kumar } else if (BytesInAddress == 4 && Endian == support::endianness::big) { 817901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( 81880cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 81980cd518bSVedant Kumar Reader->MappingRecords, Reader->Filenames, Reader->Decompressed)) 820c55cf4afSBill Wendling return std::move(E); 821901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::little) { 822901d04fcSVedant Kumar if (Error E = 823901d04fcSVedant Kumar readCoverageMappingData<uint64_t, support::endianness::little>( 82480cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 825dd1ea9deSVedant Kumar Reader->MappingRecords, Reader->Filenames, 826dd1ea9deSVedant Kumar Reader->Decompressed)) 827c55cf4afSBill Wendling return std::move(E); 828901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::big) { 829901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( 83080cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 83180cd518bSVedant Kumar Reader->MappingRecords, Reader->Filenames, Reader->Decompressed)) 832c55cf4afSBill Wendling return std::move(E); 833901d04fcSVedant Kumar } else 834901d04fcSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 835c55cf4afSBill Wendling return std::move(Reader); 836901d04fcSVedant Kumar } 837901d04fcSVedant Kumar 838901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 839901d04fcSVedant Kumar loadTestingFormat(StringRef Data) { 840901d04fcSVedant Kumar uint8_t BytesInAddress = 8; 841901d04fcSVedant Kumar support::endianness Endian = support::endianness::little; 842dc707122SEaswaran Raman 843dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 84472208a82SEugene Zelenko if (Data.empty()) 8459152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 846dc707122SEaswaran Raman unsigned N = 0; 8476a0746a9SFangrui Song uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); 848dc707122SEaswaran Raman if (N > Data.size()) 8499152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 850dc707122SEaswaran Raman Data = Data.substr(N); 85172208a82SEugene Zelenko if (Data.empty()) 8529152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 853dc707122SEaswaran Raman N = 0; 8546a0746a9SFangrui Song uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); 855dc707122SEaswaran Raman if (N > Data.size()) 8569152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 857dc707122SEaswaran Raman Data = Data.substr(N); 858dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 8599152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 860901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 8619152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 862c55cf4afSBill Wendling return std::move(E); 863901d04fcSVedant Kumar StringRef CoverageMapping = Data.substr(ProfileNamesSize); 864eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 86572208a82SEugene Zelenko if (CoverageMapping.empty()) 8669152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 867ce56e1a1SGuillaume Chatelet size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8)); 868eb103073SIgor Kudrin if (CoverageMapping.size() < Pad) 8699152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 870eb103073SIgor Kudrin CoverageMapping = CoverageMapping.substr(Pad); 871901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 872dd1ea9deSVedant Kumar CoverageMapping, "", std::move(ProfileNames), BytesInAddress, Endian); 873dc707122SEaswaran Raman } 874dc707122SEaswaran Raman 87580cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats 87680cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF. 87780cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, 87880cd518bSVedant Kumar StringRef Name) { 8798b6af001SReid Kleckner // On COFF, the object file section name may end in "$M". This tells the 8808b6af001SReid Kleckner // linker to sort these sections between "$A" and "$Z". The linker removes the 8818b6af001SReid Kleckner // dollar and everything after it in the final binary. Do the same to match. 8828b6af001SReid Kleckner bool IsCOFF = isa<COFFObjectFile>(OF); 8838b6af001SReid Kleckner auto stripSuffix = [IsCOFF](StringRef N) { 8848b6af001SReid Kleckner return IsCOFF ? N.split('$').first : N; 8858b6af001SReid Kleckner }; 8868b6af001SReid Kleckner Name = stripSuffix(Name); 8878b6af001SReid Kleckner 88880cd518bSVedant Kumar std::vector<SectionRef> Sections; 889dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 890bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 891bcc00e1aSGeorge Rimar if (!NameOrErr) 892bcc00e1aSGeorge Rimar return NameOrErr.takeError(); 893bcc00e1aSGeorge Rimar if (stripSuffix(*NameOrErr) == Name) 89480cd518bSVedant Kumar Sections.push_back(Section); 895dc707122SEaswaran Raman } 89680cd518bSVedant Kumar if (Sections.empty()) 8979152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 89880cd518bSVedant Kumar return Sections; 899dc707122SEaswaran Raman } 900dc707122SEaswaran Raman 901901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 902901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) { 903dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 904e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 905dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 906dc707122SEaswaran Raman // appropriate architecture. 9074fd11c1eSAlexander Shaposhnikov auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); 9089acb1099SKevin Enderby if (!ObjectFileOrErr) 9099acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 910dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 911e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 912dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 913e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 914dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 915dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 9169152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 917dc707122SEaswaran Raman } else 918dc707122SEaswaran Raman // We can only handle object files. 9199152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 920dc707122SEaswaran Raman 921dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 922901d04fcSVedant Kumar uint8_t BytesInAddress = OF->getBytesInAddress(); 923901d04fcSVedant Kumar support::endianness Endian = OF->isLittleEndian() 924901d04fcSVedant Kumar ? support::endianness::little 925dc707122SEaswaran Raman : support::endianness::big; 926dc707122SEaswaran Raman 927dc707122SEaswaran Raman // Look for the sections that we are interested in. 9281a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 9294a5ddf80SXinliang David Li auto NamesSection = 93080cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 9311a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9329152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 933c55cf4afSBill Wendling return std::move(E); 9344a5ddf80SXinliang David Li auto CoverageSection = 93580cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 9361a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9379152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 938c55cf4afSBill Wendling return std::move(E); 93980cd518bSVedant Kumar std::vector<SectionRef> CoverageSectionRefs = *CoverageSection; 94080cd518bSVedant Kumar if (CoverageSectionRefs.size() != 1) 94180cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 94280cd518bSVedant Kumar auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); 943901d04fcSVedant Kumar if (!CoverageMappingOrErr) 944901d04fcSVedant Kumar return CoverageMappingOrErr.takeError(); 945dd1ea9deSVedant Kumar StringRef CoverageMapping = CoverageMappingOrErr.get(); 946e183340cSFangrui Song 947901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 94880cd518bSVedant Kumar std::vector<SectionRef> NamesSectionRefs = *NamesSection; 94980cd518bSVedant Kumar if (NamesSectionRefs.size() != 1) 95080cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 95180cd518bSVedant Kumar if (Error E = ProfileNames.create(NamesSectionRefs.back())) 952c55cf4afSBill Wendling return std::move(E); 953dc707122SEaswaran Raman 954dd1ea9deSVedant Kumar // Look for the coverage records section (Version4 only). 95580cd518bSVedant Kumar std::string FuncRecords; 95680cd518bSVedant Kumar auto CoverageRecordsSections = 95780cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, 958dd1ea9deSVedant Kumar /*AddSegmentInfo=*/false)); 95980cd518bSVedant Kumar if (auto E = CoverageRecordsSections.takeError()) 960dd1ea9deSVedant Kumar consumeError(std::move(E)); 961dd1ea9deSVedant Kumar else { 96280cd518bSVedant Kumar for (SectionRef Section : *CoverageRecordsSections) { 96380cd518bSVedant Kumar auto CoverageRecordsOrErr = Section.getContents(); 964dd1ea9deSVedant Kumar if (!CoverageRecordsOrErr) 965dd1ea9deSVedant Kumar return CoverageRecordsOrErr.takeError(); 96680cd518bSVedant Kumar FuncRecords += CoverageRecordsOrErr.get(); 96780cd518bSVedant Kumar while (FuncRecords.size() % 8 != 0) 96880cd518bSVedant Kumar FuncRecords += '\0'; 96980cd518bSVedant Kumar } 970dd1ea9deSVedant Kumar } 971dd1ea9deSVedant Kumar 972901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 97380cd518bSVedant Kumar CoverageMapping, std::move(FuncRecords), std::move(ProfileNames), 97480cd518bSVedant Kumar BytesInAddress, Endian); 975dc707122SEaswaran Raman } 976dc707122SEaswaran Raman 9777fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin. 9787fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) { 9797fafaa07SVedant Kumar // If we have a universal binary and Arch doesn't identify any of its slices, 9807fafaa07SVedant Kumar // it's user error. 9817fafaa07SVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) { 9827fafaa07SVedant Kumar for (auto &ObjForArch : Universal->objects()) 9837fafaa07SVedant Kumar if (Arch == ObjForArch.getArchFlagName()) 9847fafaa07SVedant Kumar return false; 9857fafaa07SVedant Kumar return true; 9867fafaa07SVedant Kumar } 9877fafaa07SVedant Kumar return false; 9887fafaa07SVedant Kumar } 9897fafaa07SVedant Kumar 990901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 991901d04fcSVedant Kumar BinaryCoverageReader::create( 992901d04fcSVedant Kumar MemoryBufferRef ObjectBuffer, StringRef Arch, 993901d04fcSVedant Kumar SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) { 994901d04fcSVedant Kumar std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; 995dc707122SEaswaran Raman 996901d04fcSVedant Kumar if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { 997dc707122SEaswaran Raman // This is a special format used for testing. 998901d04fcSVedant Kumar auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer()); 999901d04fcSVedant Kumar if (!ReaderOrErr) 1000901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1001901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1002c55cf4afSBill Wendling return std::move(Readers); 1003901d04fcSVedant Kumar } 1004dc707122SEaswaran Raman 1005901d04fcSVedant Kumar auto BinOrErr = createBinary(ObjectBuffer); 1006901d04fcSVedant Kumar if (!BinOrErr) 1007901d04fcSVedant Kumar return BinOrErr.takeError(); 1008901d04fcSVedant Kumar std::unique_ptr<Binary> Bin = std::move(BinOrErr.get()); 1009901d04fcSVedant Kumar 10107fafaa07SVedant Kumar if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch)) 10117fafaa07SVedant Kumar return make_error<CoverageMapError>( 10127fafaa07SVedant Kumar coveragemap_error::invalid_or_missing_arch_specifier); 10137fafaa07SVedant Kumar 1014901d04fcSVedant Kumar // MachO universal binaries which contain archives need to be treated as 1015901d04fcSVedant Kumar // archives, not as regular binaries. 1016901d04fcSVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 1017901d04fcSVedant Kumar for (auto &ObjForArch : Universal->objects()) { 1018901d04fcSVedant Kumar // Skip slices within the universal binary which target the wrong arch. 1019901d04fcSVedant Kumar std::string ObjArch = ObjForArch.getArchFlagName(); 1020901d04fcSVedant Kumar if (Arch != ObjArch) 1021901d04fcSVedant Kumar continue; 1022901d04fcSVedant Kumar 1023901d04fcSVedant Kumar auto ArchiveOrErr = ObjForArch.getAsArchive(); 1024901d04fcSVedant Kumar if (!ArchiveOrErr) { 1025901d04fcSVedant Kumar // If this is not an archive, try treating it as a regular object. 1026901d04fcSVedant Kumar consumeError(ArchiveOrErr.takeError()); 1027901d04fcSVedant Kumar break; 1028901d04fcSVedant Kumar } 1029901d04fcSVedant Kumar 1030901d04fcSVedant Kumar return BinaryCoverageReader::create( 1031901d04fcSVedant Kumar ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers); 1032901d04fcSVedant Kumar } 1033901d04fcSVedant Kumar } 1034901d04fcSVedant Kumar 1035901d04fcSVedant Kumar // Load coverage out of archive members. 1036901d04fcSVedant Kumar if (auto *Ar = dyn_cast<Archive>(Bin.get())) { 1037901d04fcSVedant Kumar Error Err = Error::success(); 1038901d04fcSVedant Kumar for (auto &Child : Ar->children(Err)) { 1039901d04fcSVedant Kumar Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef(); 1040901d04fcSVedant Kumar if (!ChildBufOrErr) 1041901d04fcSVedant Kumar return ChildBufOrErr.takeError(); 1042901d04fcSVedant Kumar 1043901d04fcSVedant Kumar auto ChildReadersOrErr = BinaryCoverageReader::create( 1044901d04fcSVedant Kumar ChildBufOrErr.get(), Arch, ObjectFileBuffers); 1045901d04fcSVedant Kumar if (!ChildReadersOrErr) 1046901d04fcSVedant Kumar return ChildReadersOrErr.takeError(); 1047901d04fcSVedant Kumar for (auto &Reader : ChildReadersOrErr.get()) 1048901d04fcSVedant Kumar Readers.push_back(std::move(Reader)); 1049901d04fcSVedant Kumar } 1050901d04fcSVedant Kumar if (Err) 1051c55cf4afSBill Wendling return std::move(Err); 1052901d04fcSVedant Kumar 1053901d04fcSVedant Kumar // Thin archives reference object files outside of the archive file, i.e. 1054901d04fcSVedant Kumar // files which reside in memory not owned by the caller. Transfer ownership 1055901d04fcSVedant Kumar // to the caller. 1056901d04fcSVedant Kumar if (Ar->isThin()) 1057901d04fcSVedant Kumar for (auto &Buffer : Ar->takeThinBuffers()) 1058901d04fcSVedant Kumar ObjectFileBuffers.push_back(std::move(Buffer)); 1059901d04fcSVedant Kumar 1060c55cf4afSBill Wendling return std::move(Readers); 1061901d04fcSVedant Kumar } 1062901d04fcSVedant Kumar 1063901d04fcSVedant Kumar auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch); 1064901d04fcSVedant Kumar if (!ReaderOrErr) 1065901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1066901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1067c55cf4afSBill Wendling return std::move(Readers); 1068dc707122SEaswaran Raman } 1069dc707122SEaswaran Raman 10709152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 1071dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 10729152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 1073dc707122SEaswaran Raman 1074dc707122SEaswaran Raman FunctionsFilenames.clear(); 1075dc707122SEaswaran Raman Expressions.clear(); 1076dc707122SEaswaran Raman MappingRegions.clear(); 1077dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 1078dc707122SEaswaran Raman RawCoverageMappingReader Reader( 1079dc707122SEaswaran Raman R.CoverageMapping, 1080dc707122SEaswaran Raman makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), 1081dc707122SEaswaran Raman FunctionsFilenames, Expressions, MappingRegions); 1082dc707122SEaswaran Raman if (auto Err = Reader.read()) 1083dc707122SEaswaran Raman return Err; 1084dc707122SEaswaran Raman 1085dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 1086dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 1087dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 1088dc707122SEaswaran Raman Record.Expressions = Expressions; 1089dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 1090dc707122SEaswaran Raman 1091dc707122SEaswaran Raman ++CurrentRecord; 10929152fd17SVedant Kumar return Error::success(); 1093dc707122SEaswaran Raman } 1094