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" 23ba7a92c0SNico Weber #include "llvm/Object/COFF.h" 24e78d131aSEugene Zelenko #include "llvm/Object/Error.h" 25dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h" 26dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.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" 36ba7a92c0SNico Weber #include "llvm/Support/Path.h" 37dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 38e78d131aSEugene Zelenko #include <vector> 39dc707122SEaswaran Raman 40dc707122SEaswaran Raman using namespace llvm; 41dc707122SEaswaran Raman using namespace coverage; 42dc707122SEaswaran Raman using namespace object; 43dc707122SEaswaran Raman 44dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 45dc707122SEaswaran Raman 46dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records"); 47dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records"); 48dd1ea9deSVedant Kumar 49dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 50bae83970SVedant Kumar if (ReadErr != coveragemap_error::success) 51bae83970SVedant Kumar return; 52bae83970SVedant Kumar 53dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 54dc707122SEaswaran Raman // the next record. 55bae83970SVedant Kumar if (auto E = Reader->readNextRecord(Record)) 569152fd17SVedant Kumar handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 579152fd17SVedant Kumar if (CME.get() == coveragemap_error::eof) 58dc707122SEaswaran Raman *this = CoverageMappingIterator(); 599152fd17SVedant Kumar else 60bae83970SVedant Kumar ReadErr = CME.get(); 619152fd17SVedant Kumar }); 629152fd17SVedant Kumar } 63dc707122SEaswaran Raman 649152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) { 6572208a82SEugene Zelenko if (Data.empty()) 669152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 67dc707122SEaswaran Raman unsigned N = 0; 686a0746a9SFangrui Song Result = decodeULEB128(Data.bytes_begin(), &N); 69dc707122SEaswaran Raman if (N > Data.size()) 709152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 71dc707122SEaswaran Raman Data = Data.substr(N); 729152fd17SVedant Kumar return Error::success(); 73dc707122SEaswaran Raman } 74dc707122SEaswaran Raman 759152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { 76dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 77dc707122SEaswaran Raman return Err; 78dc707122SEaswaran Raman if (Result >= MaxPlus1) 799152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 809152fd17SVedant Kumar return Error::success(); 81dc707122SEaswaran Raman } 82dc707122SEaswaran Raman 839152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) { 84dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 85dc707122SEaswaran Raman return Err; 86dc707122SEaswaran Raman // Sanity check the number. 87dc707122SEaswaran Raman if (Result > Data.size()) 889152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 899152fd17SVedant Kumar return Error::success(); 90dc707122SEaswaran Raman } 91dc707122SEaswaran Raman 929152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) { 93dc707122SEaswaran Raman uint64_t Length; 94dc707122SEaswaran Raman if (auto Err = readSize(Length)) 95dc707122SEaswaran Raman return Err; 96dc707122SEaswaran Raman Result = Data.substr(0, Length); 97dc707122SEaswaran Raman Data = Data.substr(Length); 989152fd17SVedant Kumar return Error::success(); 99dc707122SEaswaran Raman } 100dc707122SEaswaran Raman 1015fbd1a33SPetr Hosek Error RawCoverageFilenamesReader::read(CovMapVersion Version) { 102dc707122SEaswaran Raman uint64_t NumFilenames; 103dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 104dc707122SEaswaran Raman return Err; 105dd1ea9deSVedant Kumar if (!NumFilenames) 106dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 107dd1ea9deSVedant Kumar 108dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 1095fbd1a33SPetr Hosek return readUncompressed(Version, NumFilenames); 110dd1ea9deSVedant Kumar 111dd1ea9deSVedant Kumar // The uncompressed length may exceed the size of the encoded filenames. 112dd1ea9deSVedant Kumar // Skip size validation. 113dd1ea9deSVedant Kumar uint64_t UncompressedLen; 114dd1ea9deSVedant Kumar if (auto Err = readULEB128(UncompressedLen)) 115dd1ea9deSVedant Kumar return Err; 116dd1ea9deSVedant Kumar 117dd1ea9deSVedant Kumar uint64_t CompressedLen; 118dd1ea9deSVedant Kumar if (auto Err = readSize(CompressedLen)) 119dd1ea9deSVedant Kumar return Err; 120dd1ea9deSVedant Kumar 121dd1ea9deSVedant Kumar if (CompressedLen > 0) { 122dd1ea9deSVedant Kumar if (!zlib::isAvailable()) 123dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 124dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 125dd1ea9deSVedant Kumar 1265fbd1a33SPetr Hosek // Allocate memory for the decompressed filenames. 1275fbd1a33SPetr Hosek SmallVector<char, 0> StorageBuf; 128dd1ea9deSVedant Kumar 129dd1ea9deSVedant Kumar // Read compressed filenames. 130dd1ea9deSVedant Kumar StringRef CompressedFilenames = Data.substr(0, CompressedLen); 131dd1ea9deSVedant Kumar Data = Data.substr(CompressedLen); 132dd1ea9deSVedant Kumar auto Err = 133dd1ea9deSVedant Kumar zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen); 134dd1ea9deSVedant Kumar if (Err) { 135dd1ea9deSVedant Kumar consumeError(std::move(Err)); 136dd1ea9deSVedant Kumar return make_error<CoverageMapError>( 137dd1ea9deSVedant Kumar coveragemap_error::decompression_failed); 138dd1ea9deSVedant Kumar } 139dd1ea9deSVedant Kumar 140dd1ea9deSVedant Kumar StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size()); 141dd1ea9deSVedant Kumar RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames); 1425fbd1a33SPetr Hosek return Delegate.readUncompressed(Version, NumFilenames); 143dd1ea9deSVedant Kumar } 144dd1ea9deSVedant Kumar 1455fbd1a33SPetr Hosek return readUncompressed(Version, NumFilenames); 146dd1ea9deSVedant Kumar } 147dd1ea9deSVedant Kumar 1485fbd1a33SPetr Hosek Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version, 1495fbd1a33SPetr Hosek uint64_t NumFilenames) { 150dd1ea9deSVedant Kumar // Read uncompressed filenames. 1515fbd1a33SPetr Hosek if (Version < CovMapVersion::Version6) { 152dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 153dc707122SEaswaran Raman StringRef Filename; 154dc707122SEaswaran Raman if (auto Err = readString(Filename)) 155dc707122SEaswaran Raman return Err; 1565fbd1a33SPetr Hosek Filenames.push_back(Filename.str()); 1575fbd1a33SPetr Hosek } 1585fbd1a33SPetr Hosek } else { 1595fbd1a33SPetr Hosek StringRef CWD; 1605fbd1a33SPetr Hosek if (auto Err = readString(CWD)) 1615fbd1a33SPetr Hosek return Err; 1625fbd1a33SPetr Hosek Filenames.push_back(CWD.str()); 1635fbd1a33SPetr Hosek 1645fbd1a33SPetr Hosek for (size_t I = 1; I < NumFilenames; ++I) { 1655fbd1a33SPetr Hosek StringRef Filename; 1665fbd1a33SPetr Hosek if (auto Err = readString(Filename)) 1675fbd1a33SPetr Hosek return Err; 1685fbd1a33SPetr Hosek if (sys::path::is_absolute(Filename)) { 1695fbd1a33SPetr Hosek Filenames.push_back(Filename.str()); 1705fbd1a33SPetr Hosek } else { 1715fbd1a33SPetr Hosek SmallString<256> P(CWD); 1725fbd1a33SPetr Hosek llvm::sys::path::append(P, Filename); 1735fbd1a33SPetr Hosek Filenames.push_back(static_cast<std::string>(P)); 1745fbd1a33SPetr Hosek } 1755fbd1a33SPetr Hosek } 176dc707122SEaswaran Raman } 1779152fd17SVedant Kumar return Error::success(); 178dc707122SEaswaran Raman } 179dc707122SEaswaran Raman 1809152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 181dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 182dc707122SEaswaran Raman switch (Tag) { 183dc707122SEaswaran Raman case Counter::Zero: 184dc707122SEaswaran Raman C = Counter::getZero(); 1859152fd17SVedant Kumar return Error::success(); 186dc707122SEaswaran Raman case Counter::CounterValueReference: 187dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 1889152fd17SVedant Kumar return Error::success(); 189dc707122SEaswaran Raman default: 190dc707122SEaswaran Raman break; 191dc707122SEaswaran Raman } 192dc707122SEaswaran Raman Tag -= Counter::Expression; 193dc707122SEaswaran Raman switch (Tag) { 194dc707122SEaswaran Raman case CounterExpression::Subtract: 195dc707122SEaswaran Raman case CounterExpression::Add: { 196dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 197dc707122SEaswaran Raman if (ID >= Expressions.size()) 1989152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 199dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 200dc707122SEaswaran Raman C = Counter::getExpression(ID); 201dc707122SEaswaran Raman break; 202dc707122SEaswaran Raman } 203dc707122SEaswaran Raman default: 2049152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 205dc707122SEaswaran Raman } 2069152fd17SVedant Kumar return Error::success(); 207dc707122SEaswaran Raman } 208dc707122SEaswaran Raman 2099152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 210dc707122SEaswaran Raman uint64_t EncodedCounter; 211dc707122SEaswaran Raman if (auto Err = 212dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 213dc707122SEaswaran Raman return Err; 214dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 215dc707122SEaswaran Raman return Err; 2169152fd17SVedant Kumar return Error::success(); 217dc707122SEaswaran Raman } 218dc707122SEaswaran Raman 219dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 220dc707122SEaswaran Raman << Counter::EncodingTagBits; 221dc707122SEaswaran Raman 2225f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id. 223dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 224dc707122SEaswaran Raman /// function. 2259152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 226dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 227dc707122SEaswaran Raman size_t NumFileIDs) { 228dc707122SEaswaran Raman uint64_t NumRegions; 229dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 230dc707122SEaswaran Raman return Err; 231dc707122SEaswaran Raman unsigned LineStart = 0; 232dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 2339f2967bcSAlan Phipps Counter C, C2; 234dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 235dc707122SEaswaran Raman 236dc707122SEaswaran Raman // Read the combined counter + region kind. 237dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 238dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 239dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 240dc707122SEaswaran Raman return Err; 241dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 242dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 2439f2967bcSAlan Phipps 2449f2967bcSAlan Phipps // If Tag does not represent a ZeroCounter, then it is understood to refer 2459f2967bcSAlan Phipps // to a counter or counter expression with region kind assumed to be 2469f2967bcSAlan Phipps // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the 2479f2967bcSAlan Phipps // referenced counter or counter expression (and nothing else). 2489f2967bcSAlan Phipps // 2499f2967bcSAlan Phipps // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set, 2509f2967bcSAlan Phipps // then EncodedCounterAndRegion is interpreted to represent an 2519f2967bcSAlan Phipps // ExpansionRegion. In all other cases, EncodedCounterAndRegion is 2529f2967bcSAlan Phipps // interpreted to refer to a specific region kind, after which additional 2539f2967bcSAlan Phipps // fields may be read (e.g. BranchRegions have two encoded counters that 2549f2967bcSAlan Phipps // follow an encoded region kind value). 255dc707122SEaswaran Raman if (Tag != Counter::Zero) { 256dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 257dc707122SEaswaran Raman return Err; 258dc707122SEaswaran Raman } else { 259dc707122SEaswaran Raman // Is it an expansion region? 260dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 261dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 262dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 263dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 264dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 2659152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 266dc707122SEaswaran Raman } else { 267dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 268dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 269dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 270dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 271dc707122SEaswaran Raman break; 272dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 273dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 274dc707122SEaswaran Raman break; 2759f2967bcSAlan Phipps case CounterMappingRegion::BranchRegion: 2769f2967bcSAlan Phipps // For a Branch Region, read two successive counters. 2779f2967bcSAlan Phipps Kind = CounterMappingRegion::BranchRegion; 2789f2967bcSAlan Phipps if (auto Err = readCounter(C)) 2799f2967bcSAlan Phipps return Err; 2809f2967bcSAlan Phipps if (auto Err = readCounter(C2)) 2819f2967bcSAlan Phipps return Err; 2829f2967bcSAlan Phipps break; 283dc707122SEaswaran Raman default: 2849152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 285dc707122SEaswaran Raman } 286dc707122SEaswaran Raman } 287dc707122SEaswaran Raman } 288dc707122SEaswaran Raman 289dc707122SEaswaran Raman // Read the source range. 290dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 291dc707122SEaswaran Raman if (auto Err = 292dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 293dc707122SEaswaran Raman return Err; 294dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 295dc707122SEaswaran Raman return Err; 296dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 2979152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 298dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 299dc707122SEaswaran Raman return Err; 300dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 301dc707122SEaswaran Raman return Err; 302dc707122SEaswaran Raman LineStart += LineStartDelta; 303ad8f637bSVedant Kumar 304ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 305ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 306ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 307ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 308ad8f637bSVedant Kumar } 309ad8f637bSVedant Kumar 310dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 311dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 312dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 313dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 314dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 315dc707122SEaswaran Raman // column end take up one byte each. 316dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 317dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 318dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 319dc707122SEaswaran Raman ColumnStart = 1; 320dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 321dc707122SEaswaran Raman } 322dc707122SEaswaran Raman 323d34e60caSNicola Zaghen LLVM_DEBUG({ 324dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 325dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 326dc707122SEaswaran Raman << ColumnEnd << ", "; 327dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 328dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 329dc707122SEaswaran Raman else 330dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 331dc707122SEaswaran Raman dbgs() << "\n"; 332dc707122SEaswaran Raman }); 333dc707122SEaswaran Raman 3349f2967bcSAlan Phipps auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID, 335bae83970SVedant Kumar LineStart, ColumnStart, 336bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 337bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 338bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 339bae83970SVedant Kumar MappingRegions.push_back(CMR); 340dc707122SEaswaran Raman } 3419152fd17SVedant Kumar return Error::success(); 342dc707122SEaswaran Raman } 343dc707122SEaswaran Raman 3449152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 345dc707122SEaswaran Raman // Read the virtual file mapping. 346e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 347dc707122SEaswaran Raman uint64_t NumFileMappings; 348dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 349dc707122SEaswaran Raman return Err; 350dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 351dc707122SEaswaran Raman uint64_t FilenameIndex; 352dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 353dc707122SEaswaran Raman return Err; 354dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 355dc707122SEaswaran Raman } 356dc707122SEaswaran Raman 357dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 358dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 359dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 360dc707122SEaswaran Raman } 361dc707122SEaswaran Raman 362dc707122SEaswaran Raman // Read the expressions. 363dc707122SEaswaran Raman uint64_t NumExpressions; 364dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 365dc707122SEaswaran Raman return Err; 366dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 367dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 368dc707122SEaswaran Raman // are decoded. 369dc707122SEaswaran Raman Expressions.resize( 370dc707122SEaswaran Raman NumExpressions, 371dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 372dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 373dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 374dc707122SEaswaran Raman return Err; 375dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 376dc707122SEaswaran Raman return Err; 377dc707122SEaswaran Raman } 378dc707122SEaswaran Raman 379dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 380dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 381dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 382dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 383dc707122SEaswaran Raman VirtualFileMapping.size())) 384dc707122SEaswaran Raman return Err; 385dc707122SEaswaran Raman } 386dc707122SEaswaran Raman 387dc707122SEaswaran Raman // Set the counters for the expansion regions. 388dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 389dc707122SEaswaran Raman // from the expanded file. 390dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 391dc707122SEaswaran Raman // all the nested expansion regions. 392dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 393dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 394dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 395dc707122SEaswaran Raman for (auto &R : MappingRegions) { 396dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 397dc707122SEaswaran Raman continue; 398dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 399dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 400dc707122SEaswaran Raman } 401dc707122SEaswaran Raman for (auto &R : MappingRegions) { 402dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 403dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 404dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 405dc707122SEaswaran Raman } 406dc707122SEaswaran Raman } 407dc707122SEaswaran Raman } 408dc707122SEaswaran Raman 4099152fd17SVedant Kumar return Error::success(); 410dc707122SEaswaran Raman } 411dc707122SEaswaran Raman 412ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 413ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 414ac40e819SIgor Kudrin uint64_t NumFileMappings; 415ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 416c55cf4afSBill Wendling return std::move(Err); 417ac40e819SIgor Kudrin if (NumFileMappings != 1) 418ac40e819SIgor Kudrin return false; 419ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 420ac40e819SIgor Kudrin uint64_t FilenameIndex; 421ac40e819SIgor Kudrin if (Error Err = 422ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 423c55cf4afSBill Wendling return std::move(Err); 424ac40e819SIgor Kudrin uint64_t NumExpressions; 425ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 426c55cf4afSBill Wendling return std::move(Err); 427ac40e819SIgor Kudrin if (NumExpressions != 0) 428ac40e819SIgor Kudrin return false; 429ac40e819SIgor Kudrin uint64_t NumRegions; 430ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 431c55cf4afSBill Wendling return std::move(Err); 432ac40e819SIgor Kudrin if (NumRegions != 1) 433ac40e819SIgor Kudrin return false; 434ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 435ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 436ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 437c55cf4afSBill Wendling return std::move(Err); 438ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 439ac40e819SIgor Kudrin return Tag == Counter::Zero; 440ac40e819SIgor Kudrin } 441ac40e819SIgor Kudrin 4429152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 443e183340cSFangrui Song Expected<StringRef> DataOrErr = Section.getContents(); 444e183340cSFangrui Song if (!DataOrErr) 445e183340cSFangrui Song return DataOrErr.takeError(); 446e183340cSFangrui Song Data = *DataOrErr; 447dc707122SEaswaran Raman Address = Section.getAddress(); 4488b6af001SReid Kleckner 4498b6af001SReid Kleckner // If this is a linked PE/COFF file, then we have to skip over the null byte 4508b6af001SReid Kleckner // that is allocated in the .lprfn$A section in the LLVM profiling runtime. 4518b6af001SReid Kleckner const ObjectFile *Obj = Section.getObject(); 4528b6af001SReid Kleckner if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) 4538b6af001SReid Kleckner Data = Data.drop_front(1); 4548b6af001SReid Kleckner 4559152fd17SVedant Kumar return Error::success(); 456dc707122SEaswaran Raman } 457dc707122SEaswaran Raman 458dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 459dc707122SEaswaran Raman if (Pointer < Address) 460dc707122SEaswaran Raman return StringRef(); 461dc707122SEaswaran Raman auto Offset = Pointer - Address; 462dc707122SEaswaran Raman if (Offset + Size > Data.size()) 463dc707122SEaswaran Raman return StringRef(); 464dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 465dc707122SEaswaran Raman } 466dc707122SEaswaran Raman 467ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 468ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 469ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 470ac40e819SIgor Kudrin if (Hash) 471ac40e819SIgor Kudrin return false; 472ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 473ac40e819SIgor Kudrin } 474ac40e819SIgor Kudrin 475dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of 476dd1ea9deSVedant Kumar /// filenames in a vector-like container. 477dd1ea9deSVedant Kumar struct FilenameRange { 478dd1ea9deSVedant Kumar unsigned StartingIndex; 479dd1ea9deSVedant Kumar unsigned Length; 480dd1ea9deSVedant Kumar 481dd1ea9deSVedant Kumar FilenameRange(unsigned StartingIndex, unsigned Length) 482dd1ea9deSVedant Kumar : StartingIndex(StartingIndex), Length(Length) {} 483dd1ea9deSVedant Kumar 484dd1ea9deSVedant Kumar void markInvalid() { Length = 0; } 485dd1ea9deSVedant Kumar bool isInvalid() const { return Length == 0; } 486dd1ea9deSVedant Kumar }; 487dd1ea9deSVedant Kumar 488dc707122SEaswaran Raman namespace { 489e78d131aSEugene Zelenko 490dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module. 491dc707122SEaswaran Raman struct CovMapFuncRecordReader { 492e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 493e78d131aSEugene Zelenko 494dd1ea9deSVedant Kumar // Read a coverage header. 4953739b95dSVedant Kumar // 496dd1ea9deSVedant Kumar // \p CovBuf points to the buffer containing the \c CovHeader of the coverage 4973739b95dSVedant Kumar // mapping data associated with the module. 4983739b95dSVedant Kumar // 499dd1ea9deSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or to an address 500dd1ea9deSVedant Kumar // greater than \p CovEnd if not. 5015fbd1a33SPetr Hosek virtual Expected<const char *> readCoverageHeader(const char *CovBuf, 5025fbd1a33SPetr Hosek const char *CovBufEnd) = 0; 503dd1ea9deSVedant Kumar 504dd1ea9deSVedant Kumar // Read function records. 505dd1ea9deSVedant Kumar // 506dd1ea9deSVedant Kumar // \p FuncRecBuf points to the buffer containing a batch of function records. 507dd1ea9deSVedant Kumar // \p FuncRecBufEnd points past the end of the batch of records. 508dd1ea9deSVedant Kumar // 509dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 510dd1ea9deSVedant Kumar // associated with the function records. It is unused in Version4. 511dd1ea9deSVedant Kumar // 512dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 513dd1ea9deSVedant Kumar // mappings associated with the function records. It is unused in Version4. 514dd1ea9deSVedant Kumar virtual Error readFunctionRecords(const char *FuncRecBuf, 515dd1ea9deSVedant Kumar const char *FuncRecBufEnd, 516dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 517dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 518dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) = 0; 519e78d131aSEugene Zelenko 520dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 5219152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 522e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 523dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 5245fbd1a33SPetr Hosek std::vector<std::string> &F); 525dc707122SEaswaran Raman }; 526dc707122SEaswaran Raman 527dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 528e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 529dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 53072208a82SEugene Zelenko using FuncRecordType = 53172208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 53272208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 533dc707122SEaswaran Raman 534ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 535ac40e819SIgor Kudrin // in \c Records. 536e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 537dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 5385fbd1a33SPetr Hosek std::vector<std::string> &Filenames; 539dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 540dc707122SEaswaran Raman 541dd1ea9deSVedant Kumar // Maps a hash of the filenames in a TU to a \c FileRange. The range 542dd1ea9deSVedant Kumar // specifies the location of the hashed filenames in \c Filenames. 543dd1ea9deSVedant Kumar DenseMap<uint64_t, FilenameRange> FileRangeMap; 544dd1ea9deSVedant Kumar 545ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 546ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 547ac40e819SIgor Kudrin // records for the functions with ODR linkage. 548ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 549ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 550ac40e819SIgor Kudrin // not used in the corresponding translation unit. 551ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 552dd1ea9deSVedant Kumar StringRef Mapping, 553dd1ea9deSVedant Kumar FilenameRange FileRange) { 554dd1ea9deSVedant Kumar ++CovMapNumRecords; 555ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 556ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 557ac40e819SIgor Kudrin auto InsertResult = 558ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 559ac40e819SIgor Kudrin if (InsertResult.second) { 560ac40e819SIgor Kudrin StringRef FuncName; 561ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 562ac40e819SIgor Kudrin return Err; 563b5794ca9SVedant Kumar if (FuncName.empty()) 564b5794ca9SVedant Kumar return make_error<InstrProfError>(instrprof_error::malformed); 565dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 566dd1ea9deSVedant Kumar Records.emplace_back(Version, FuncName, FuncHash, Mapping, 567dd1ea9deSVedant Kumar FileRange.StartingIndex, FileRange.Length); 568ac40e819SIgor Kudrin return Error::success(); 569ac40e819SIgor Kudrin } 570ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 571ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 572ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 573ac40e819SIgor Kudrin Records[OldRecordIndex]; 574ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 575ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 576ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 577ac40e819SIgor Kudrin return Err; 578ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 579ac40e819SIgor Kudrin return Error::success(); 580ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 581ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 582ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 583ac40e819SIgor Kudrin return Err; 584ac40e819SIgor Kudrin if (*NewIsDummyExpected) 585ac40e819SIgor Kudrin return Error::success(); 586dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 587ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 588ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 589dd1ea9deSVedant Kumar OldRecord.FilenamesBegin = FileRange.StartingIndex; 590dd1ea9deSVedant Kumar OldRecord.FilenamesSize = FileRange.Length; 591ac40e819SIgor Kudrin return Error::success(); 592ac40e819SIgor Kudrin } 593ac40e819SIgor Kudrin 594dc707122SEaswaran Raman public: 595dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 596dc707122SEaswaran Raman InstrProfSymtab &P, 597dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 5985fbd1a33SPetr Hosek std::vector<std::string> &F) 599dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 600e78d131aSEugene Zelenko 601e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 602dc707122SEaswaran Raman 6035fbd1a33SPetr Hosek Expected<const char *> readCoverageHeader(const char *CovBuf, 6045fbd1a33SPetr Hosek const char *CovBufEnd) override { 605dc707122SEaswaran Raman using namespace support; 606e78d131aSEugene Zelenko 607dd1ea9deSVedant Kumar if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) 6089152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 609dd1ea9deSVedant Kumar auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); 610dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 611dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 612dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 613dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 614dd1ea9deSVedant Kumar CovBuf = reinterpret_cast<const char *>(CovHeader + 1); 615dc707122SEaswaran Raman 616dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 617dd1ea9deSVedant Kumar // This is a no-op in Version4 (function records are read after all headers 618dd1ea9deSVedant Kumar // are read). 619dd1ea9deSVedant Kumar const char *FuncRecBuf = nullptr; 620dd1ea9deSVedant Kumar const char *FuncRecBufEnd = nullptr; 621dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 622dd1ea9deSVedant Kumar FuncRecBuf = CovBuf; 623dd1ea9deSVedant Kumar CovBuf += NRecords * sizeof(FuncRecordType); 624dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 625dd1ea9deSVedant Kumar FuncRecBufEnd = CovBuf; 626dc707122SEaswaran Raman 627dc707122SEaswaran Raman // Get the filenames. 628dd1ea9deSVedant Kumar if (CovBuf + FilenamesSize > CovBufEnd) 6299152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 630dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 631dd1ea9deSVedant Kumar StringRef FilenameRegion(CovBuf, FilenamesSize); 632dd1ea9deSVedant Kumar RawCoverageFilenamesReader Reader(FilenameRegion, Filenames); 6335fbd1a33SPetr Hosek if (auto Err = Reader.read(Version)) 634c55cf4afSBill Wendling return std::move(Err); 635dd1ea9deSVedant Kumar CovBuf += FilenamesSize; 636dd1ea9deSVedant Kumar FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin); 637dd1ea9deSVedant Kumar 6389f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) { 639dd1ea9deSVedant Kumar // Map a hash of the filenames region to the filename range associated 640dd1ea9deSVedant Kumar // with this coverage header. 641dd1ea9deSVedant Kumar int64_t FilenamesRef = 642dd1ea9deSVedant Kumar llvm::IndexedInstrProf::ComputeHash(FilenameRegion); 643dd1ea9deSVedant Kumar auto Insert = 644dd1ea9deSVedant Kumar FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange)); 645dd1ea9deSVedant Kumar if (!Insert.second) { 646dd1ea9deSVedant Kumar // The same filenames ref was encountered twice. It's possible that 647dd1ea9deSVedant Kumar // the associated filenames are the same. 648dd1ea9deSVedant Kumar auto It = Filenames.begin(); 649dd1ea9deSVedant Kumar FilenameRange &OrigRange = Insert.first->getSecond(); 650dd1ea9deSVedant Kumar if (std::equal(It + OrigRange.StartingIndex, 651dd1ea9deSVedant Kumar It + OrigRange.StartingIndex + OrigRange.Length, 652dd1ea9deSVedant Kumar It + FileRange.StartingIndex, 653dd1ea9deSVedant Kumar It + FileRange.StartingIndex + FileRange.Length)) 654dd1ea9deSVedant Kumar // Map the new range to the original one. 655dd1ea9deSVedant Kumar FileRange = OrigRange; 656dd1ea9deSVedant Kumar else 657dd1ea9deSVedant Kumar // This is a hash collision. Mark the filenames ref invalid. 658dd1ea9deSVedant Kumar OrigRange.markInvalid(); 659dd1ea9deSVedant Kumar } 660dd1ea9deSVedant Kumar } 661dc707122SEaswaran Raman 662dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 663dd1ea9deSVedant Kumar // This is a no-op in Version4 (coverage mappings are not affixed to the 664dd1ea9deSVedant Kumar // coverage header). 665dd1ea9deSVedant Kumar const char *MappingBuf = CovBuf; 6669f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && CoverageSize != 0) 6679152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 668dd1ea9deSVedant Kumar CovBuf += CoverageSize; 669dd1ea9deSVedant Kumar const char *MappingEnd = CovBuf; 670dd1ea9deSVedant Kumar 671dd1ea9deSVedant Kumar if (CovBuf > CovBufEnd) 672dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 673dd1ea9deSVedant Kumar 674dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 675dd1ea9deSVedant Kumar // Read each function record. 676dd1ea9deSVedant Kumar if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange, 677dd1ea9deSVedant Kumar MappingBuf, MappingEnd)) 678dd1ea9deSVedant Kumar return std::move(E); 679dd1ea9deSVedant Kumar } 680dd1ea9deSVedant Kumar 681dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 682dc707122SEaswaran Raman // before reading the next map. 683dd1ea9deSVedant Kumar CovBuf += offsetToAlignedAddr(CovBuf, Align(8)); 684dc707122SEaswaran Raman 685dd1ea9deSVedant Kumar return CovBuf; 68699317124SVedant Kumar } 687dd1ea9deSVedant Kumar 688dd1ea9deSVedant Kumar Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd, 689dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 690dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 691dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) override { 692dd1ea9deSVedant Kumar auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf); 693dd1ea9deSVedant Kumar while ((const char *)CFR < FuncRecBufEnd) { 694dd1ea9deSVedant Kumar // Validate the length of the coverage mapping for this function. 695dd1ea9deSVedant Kumar const char *NextMappingBuf; 696dd1ea9deSVedant Kumar const FuncRecordType *NextCFR; 697dd1ea9deSVedant Kumar std::tie(NextMappingBuf, NextCFR) = 698dd1ea9deSVedant Kumar CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); 699dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 700dd1ea9deSVedant Kumar if (NextMappingBuf > OutOfLineMappingBufEnd) 701dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 702dd1ea9deSVedant Kumar 703dd1ea9deSVedant Kumar // Look up the set of filenames associated with this function record. 704dd1ea9deSVedant Kumar Optional<FilenameRange> FileRange; 705dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 706dd1ea9deSVedant Kumar FileRange = OutOfLineFileRange; 707dd1ea9deSVedant Kumar } else { 708dd1ea9deSVedant Kumar uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); 709dd1ea9deSVedant Kumar auto It = FileRangeMap.find(FilenamesRef); 710dd1ea9deSVedant Kumar if (It == FileRangeMap.end()) 711dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 712dd1ea9deSVedant Kumar else 713dd1ea9deSVedant Kumar FileRange = It->getSecond(); 714dd1ea9deSVedant Kumar } 715dd1ea9deSVedant Kumar 716dd1ea9deSVedant Kumar // Now, read the coverage data. 717dd1ea9deSVedant Kumar if (FileRange && !FileRange->isInvalid()) { 718dd1ea9deSVedant Kumar StringRef Mapping = 719dd1ea9deSVedant Kumar CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); 7209f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && 721dd1ea9deSVedant Kumar Mapping.data() + Mapping.size() > FuncRecBufEnd) 722dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 723dd1ea9deSVedant Kumar if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) 724dd1ea9deSVedant Kumar return Err; 725dd1ea9deSVedant Kumar } 726dd1ea9deSVedant Kumar 727dd1ea9deSVedant Kumar std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR); 728dd1ea9deSVedant Kumar } 729dd1ea9deSVedant Kumar return Error::success(); 730dc707122SEaswaran Raman } 731dc707122SEaswaran Raman }; 732e78d131aSEugene Zelenko 733dc707122SEaswaran Raman } // end anonymous namespace 734dc707122SEaswaran Raman 735dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 7369152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 737e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 738dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 7395fbd1a33SPetr Hosek std::vector<std::string> &F) { 740dc707122SEaswaran Raman using namespace coverage; 741e78d131aSEugene Zelenko 742dc707122SEaswaran Raman switch (Version) { 743dc707122SEaswaran Raman case CovMapVersion::Version1: 7440eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 745dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 746dc707122SEaswaran Raman case CovMapVersion::Version2: 747ad8f637bSVedant Kumar case CovMapVersion::Version3: 748dd1ea9deSVedant Kumar case CovMapVersion::Version4: 7499f2967bcSAlan Phipps case CovMapVersion::Version5: 7505fbd1a33SPetr Hosek case CovMapVersion::Version6: 751dc707122SEaswaran Raman // Decompress the name data. 7529152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 753c55cf4afSBill Wendling return std::move(E); 754ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 7550eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 756dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 757dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version3) 7580eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 759ad8f637bSVedant Kumar CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); 760dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version4) 761dd1ea9deSVedant Kumar return std::make_unique<VersionedCovMapFuncRecordReader< 762dd1ea9deSVedant Kumar CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F); 7639f2967bcSAlan Phipps else if (Version == CovMapVersion::Version5) 7649f2967bcSAlan Phipps return std::make_unique<VersionedCovMapFuncRecordReader< 7659f2967bcSAlan Phipps CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F); 7665fbd1a33SPetr Hosek else if (Version == CovMapVersion::Version6) 7675fbd1a33SPetr Hosek return std::make_unique<VersionedCovMapFuncRecordReader< 7685fbd1a33SPetr Hosek CovMapVersion::Version6, IntPtrT, Endian>>(P, R, F); 769dc707122SEaswaran Raman } 770dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 771dc707122SEaswaran Raman } 772dc707122SEaswaran Raman 773dc707122SEaswaran Raman template <typename T, support::endianness Endian> 7749152fd17SVedant Kumar static Error readCoverageMappingData( 775dd1ea9deSVedant Kumar InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, 776dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 7775fbd1a33SPetr Hosek std::vector<std::string> &Filenames) { 778dc707122SEaswaran Raman using namespace coverage; 779e78d131aSEugene Zelenko 780dc707122SEaswaran Raman // Read the records in the coverage data section. 781dc707122SEaswaran Raman auto CovHeader = 782dd1ea9deSVedant Kumar reinterpret_cast<const CovMapHeader *>(CovMap.data()); 783dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 784e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 7859152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 7869152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 787dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 788dc707122SEaswaran Raman Filenames); 7899152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 7909152fd17SVedant Kumar return E; 7919152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 792dd1ea9deSVedant Kumar const char *CovBuf = CovMap.data(); 793dd1ea9deSVedant Kumar const char *CovBufEnd = CovBuf + CovMap.size(); 794dd1ea9deSVedant Kumar const char *FuncRecBuf = FuncRecords.data(); 795dd1ea9deSVedant Kumar const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size(); 796dd1ea9deSVedant Kumar while (CovBuf < CovBufEnd) { 797dd1ea9deSVedant Kumar // Read the current coverage header & filename data. 798dd1ea9deSVedant Kumar // 799dd1ea9deSVedant Kumar // Prior to Version4, this also reads all function records affixed to the 800dd1ea9deSVedant Kumar // header. 801dd1ea9deSVedant Kumar // 802dd1ea9deSVedant Kumar // Return a pointer to the next coverage header. 8035fbd1a33SPetr Hosek auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd); 804dd1ea9deSVedant Kumar if (auto E = NextOrErr.takeError()) 8059152fd17SVedant Kumar return E; 806dd1ea9deSVedant Kumar CovBuf = NextOrErr.get(); 807dc707122SEaswaran Raman } 808dd1ea9deSVedant Kumar // In Version4, function records are not affixed to coverage headers. Read 809dd1ea9deSVedant Kumar // the records from their dedicated section. 8109f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) 811dd1ea9deSVedant Kumar return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr, 812dd1ea9deSVedant Kumar nullptr); 8139152fd17SVedant Kumar return Error::success(); 814dc707122SEaswaran Raman } 815e78d131aSEugene Zelenko 816dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 817dc707122SEaswaran Raman 818901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 819901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer( 82080cd518bSVedant Kumar StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames, 821dd1ea9deSVedant Kumar uint8_t BytesInAddress, support::endianness Endian) { 82280cd518bSVedant Kumar std::unique_ptr<BinaryCoverageReader> Reader( 82380cd518bSVedant Kumar new BinaryCoverageReader(std::move(FuncRecords))); 824901d04fcSVedant Kumar Reader->ProfileNames = std::move(ProfileNames); 82580cd518bSVedant Kumar StringRef FuncRecordsRef = Reader->FuncRecords; 826901d04fcSVedant Kumar if (BytesInAddress == 4 && Endian == support::endianness::little) { 827901d04fcSVedant Kumar if (Error E = 828901d04fcSVedant Kumar readCoverageMappingData<uint32_t, support::endianness::little>( 82980cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8305fbd1a33SPetr Hosek Reader->MappingRecords, Reader->Filenames)) 831c55cf4afSBill Wendling return std::move(E); 832901d04fcSVedant Kumar } else if (BytesInAddress == 4 && Endian == support::endianness::big) { 833901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( 83480cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8355fbd1a33SPetr Hosek Reader->MappingRecords, Reader->Filenames)) 836c55cf4afSBill Wendling return std::move(E); 837901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::little) { 838901d04fcSVedant Kumar if (Error E = 839901d04fcSVedant Kumar readCoverageMappingData<uint64_t, support::endianness::little>( 84080cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8415fbd1a33SPetr Hosek Reader->MappingRecords, Reader->Filenames)) 842c55cf4afSBill Wendling return std::move(E); 843901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::big) { 844901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( 84580cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8465fbd1a33SPetr Hosek Reader->MappingRecords, Reader->Filenames)) 847c55cf4afSBill Wendling return std::move(E); 848901d04fcSVedant Kumar } else 849901d04fcSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 850c55cf4afSBill Wendling return std::move(Reader); 851901d04fcSVedant Kumar } 852901d04fcSVedant Kumar 853901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 854901d04fcSVedant Kumar loadTestingFormat(StringRef Data) { 855901d04fcSVedant Kumar uint8_t BytesInAddress = 8; 856901d04fcSVedant Kumar support::endianness Endian = support::endianness::little; 857dc707122SEaswaran Raman 858dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 85972208a82SEugene Zelenko if (Data.empty()) 8609152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 861dc707122SEaswaran Raman unsigned N = 0; 8626a0746a9SFangrui Song uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); 863dc707122SEaswaran Raman if (N > Data.size()) 8649152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 865dc707122SEaswaran Raman Data = Data.substr(N); 86672208a82SEugene Zelenko if (Data.empty()) 8679152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 868dc707122SEaswaran Raman N = 0; 8696a0746a9SFangrui Song uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); 870dc707122SEaswaran Raman if (N > Data.size()) 8719152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 872dc707122SEaswaran Raman Data = Data.substr(N); 873dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 8749152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 875901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 8769152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 877c55cf4afSBill Wendling return std::move(E); 878*489a3531SPetr Hosek Data = Data.substr(ProfileNamesSize); 879eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 880*489a3531SPetr Hosek size_t Pad = offsetToAlignedAddr(Data.data(), Align(8)); 881*489a3531SPetr Hosek if (Data.size() < Pad) 882*489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 883*489a3531SPetr Hosek Data = Data.substr(Pad); 884*489a3531SPetr Hosek if (Data.size() < sizeof(CovMapHeader)) 885*489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 886*489a3531SPetr Hosek auto const *CovHeader = reinterpret_cast<const CovMapHeader *>( 887*489a3531SPetr Hosek Data.substr(0, sizeof(CovMapHeader)).data()); 888*489a3531SPetr Hosek CovMapVersion Version = 889*489a3531SPetr Hosek (CovMapVersion)CovHeader->getVersion<support::endianness::little>(); 890*489a3531SPetr Hosek StringRef CoverageMapping, CoverageRecords; 891*489a3531SPetr Hosek if (Version < CovMapVersion::Version4) { 892*489a3531SPetr Hosek CoverageMapping = Data; 89372208a82SEugene Zelenko if (CoverageMapping.empty()) 8949152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 895*489a3531SPetr Hosek } else { 896*489a3531SPetr Hosek uint32_t FilenamesSize = 897*489a3531SPetr Hosek CovHeader->getFilenamesSize<support::endianness::little>(); 898*489a3531SPetr Hosek uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; 899*489a3531SPetr Hosek CoverageMapping = Data.substr(0, CoverageMappingSize); 900*489a3531SPetr Hosek if (CoverageMapping.empty()) 901*489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 902*489a3531SPetr Hosek Data = Data.substr(CoverageMappingSize); 903*489a3531SPetr Hosek // Skip the padding bytes because coverage records data has an alignment 904*489a3531SPetr Hosek // of 8. 905*489a3531SPetr Hosek Pad = offsetToAlignedAddr(Data.data(), Align(8)); 906*489a3531SPetr Hosek if (Data.size() < Pad) 9079152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 908*489a3531SPetr Hosek CoverageRecords = Data.substr(Pad); 909*489a3531SPetr Hosek if (CoverageRecords.empty()) 910*489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 911*489a3531SPetr Hosek } 912901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 913*489a3531SPetr Hosek CoverageMapping, CoverageRecords.str(), std::move(ProfileNames), 914*489a3531SPetr Hosek BytesInAddress, Endian); 915dc707122SEaswaran Raman } 916dc707122SEaswaran Raman 91780cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats 91880cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF. 91980cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, 92080cd518bSVedant Kumar StringRef Name) { 9218b6af001SReid Kleckner // On COFF, the object file section name may end in "$M". This tells the 9228b6af001SReid Kleckner // linker to sort these sections between "$A" and "$Z". The linker removes the 9238b6af001SReid Kleckner // dollar and everything after it in the final binary. Do the same to match. 9248b6af001SReid Kleckner bool IsCOFF = isa<COFFObjectFile>(OF); 9258b6af001SReid Kleckner auto stripSuffix = [IsCOFF](StringRef N) { 9268b6af001SReid Kleckner return IsCOFF ? N.split('$').first : N; 9278b6af001SReid Kleckner }; 9288b6af001SReid Kleckner Name = stripSuffix(Name); 9298b6af001SReid Kleckner 93080cd518bSVedant Kumar std::vector<SectionRef> Sections; 931dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 932bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 933bcc00e1aSGeorge Rimar if (!NameOrErr) 934bcc00e1aSGeorge Rimar return NameOrErr.takeError(); 935bcc00e1aSGeorge Rimar if (stripSuffix(*NameOrErr) == Name) 93680cd518bSVedant Kumar Sections.push_back(Section); 937dc707122SEaswaran Raman } 93880cd518bSVedant Kumar if (Sections.empty()) 9399152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 94080cd518bSVedant Kumar return Sections; 941dc707122SEaswaran Raman } 942dc707122SEaswaran Raman 943901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 944901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) { 945dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 946e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 947dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 948dc707122SEaswaran Raman // appropriate architecture. 9494fd11c1eSAlexander Shaposhnikov auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); 9509acb1099SKevin Enderby if (!ObjectFileOrErr) 9519acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 952dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 953e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 954dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 955e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 956dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 957dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 9589152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 959dc707122SEaswaran Raman } else 960dc707122SEaswaran Raman // We can only handle object files. 9619152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 962dc707122SEaswaran Raman 963dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 964901d04fcSVedant Kumar uint8_t BytesInAddress = OF->getBytesInAddress(); 965901d04fcSVedant Kumar support::endianness Endian = OF->isLittleEndian() 966901d04fcSVedant Kumar ? support::endianness::little 967dc707122SEaswaran Raman : support::endianness::big; 968dc707122SEaswaran Raman 969dc707122SEaswaran Raman // Look for the sections that we are interested in. 9701a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 9714a5ddf80SXinliang David Li auto NamesSection = 97280cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 9731a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9749152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 975c55cf4afSBill Wendling return std::move(E); 9764a5ddf80SXinliang David Li auto CoverageSection = 97780cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 9781a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9799152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 980c55cf4afSBill Wendling return std::move(E); 98180cd518bSVedant Kumar std::vector<SectionRef> CoverageSectionRefs = *CoverageSection; 98280cd518bSVedant Kumar if (CoverageSectionRefs.size() != 1) 98380cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 98480cd518bSVedant Kumar auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); 985901d04fcSVedant Kumar if (!CoverageMappingOrErr) 986901d04fcSVedant Kumar return CoverageMappingOrErr.takeError(); 987dd1ea9deSVedant Kumar StringRef CoverageMapping = CoverageMappingOrErr.get(); 988e183340cSFangrui Song 989901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 99080cd518bSVedant Kumar std::vector<SectionRef> NamesSectionRefs = *NamesSection; 99180cd518bSVedant Kumar if (NamesSectionRefs.size() != 1) 99280cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 99380cd518bSVedant Kumar if (Error E = ProfileNames.create(NamesSectionRefs.back())) 994c55cf4afSBill Wendling return std::move(E); 995dc707122SEaswaran Raman 996dd1ea9deSVedant Kumar // Look for the coverage records section (Version4 only). 99780cd518bSVedant Kumar std::string FuncRecords; 99880cd518bSVedant Kumar auto CoverageRecordsSections = 99980cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, 1000dd1ea9deSVedant Kumar /*AddSegmentInfo=*/false)); 100180cd518bSVedant Kumar if (auto E = CoverageRecordsSections.takeError()) 1002dd1ea9deSVedant Kumar consumeError(std::move(E)); 1003dd1ea9deSVedant Kumar else { 100480cd518bSVedant Kumar for (SectionRef Section : *CoverageRecordsSections) { 100580cd518bSVedant Kumar auto CoverageRecordsOrErr = Section.getContents(); 1006dd1ea9deSVedant Kumar if (!CoverageRecordsOrErr) 1007dd1ea9deSVedant Kumar return CoverageRecordsOrErr.takeError(); 100880cd518bSVedant Kumar FuncRecords += CoverageRecordsOrErr.get(); 100980cd518bSVedant Kumar while (FuncRecords.size() % 8 != 0) 101080cd518bSVedant Kumar FuncRecords += '\0'; 101180cd518bSVedant Kumar } 1012dd1ea9deSVedant Kumar } 1013dd1ea9deSVedant Kumar 1014901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 101580cd518bSVedant Kumar CoverageMapping, std::move(FuncRecords), std::move(ProfileNames), 101680cd518bSVedant Kumar BytesInAddress, Endian); 1017dc707122SEaswaran Raman } 1018dc707122SEaswaran Raman 10197fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin. 10207fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) { 10217fafaa07SVedant Kumar // If we have a universal binary and Arch doesn't identify any of its slices, 10227fafaa07SVedant Kumar // it's user error. 10237fafaa07SVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) { 10247fafaa07SVedant Kumar for (auto &ObjForArch : Universal->objects()) 10257fafaa07SVedant Kumar if (Arch == ObjForArch.getArchFlagName()) 10267fafaa07SVedant Kumar return false; 10277fafaa07SVedant Kumar return true; 10287fafaa07SVedant Kumar } 10297fafaa07SVedant Kumar return false; 10307fafaa07SVedant Kumar } 10317fafaa07SVedant Kumar 1032901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 1033901d04fcSVedant Kumar BinaryCoverageReader::create( 1034901d04fcSVedant Kumar MemoryBufferRef ObjectBuffer, StringRef Arch, 1035901d04fcSVedant Kumar SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) { 1036901d04fcSVedant Kumar std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; 1037dc707122SEaswaran Raman 1038901d04fcSVedant Kumar if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { 1039dc707122SEaswaran Raman // This is a special format used for testing. 1040901d04fcSVedant Kumar auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer()); 1041901d04fcSVedant Kumar if (!ReaderOrErr) 1042901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1043901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1044c55cf4afSBill Wendling return std::move(Readers); 1045901d04fcSVedant Kumar } 1046dc707122SEaswaran Raman 1047901d04fcSVedant Kumar auto BinOrErr = createBinary(ObjectBuffer); 1048901d04fcSVedant Kumar if (!BinOrErr) 1049901d04fcSVedant Kumar return BinOrErr.takeError(); 1050901d04fcSVedant Kumar std::unique_ptr<Binary> Bin = std::move(BinOrErr.get()); 1051901d04fcSVedant Kumar 10527fafaa07SVedant Kumar if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch)) 10537fafaa07SVedant Kumar return make_error<CoverageMapError>( 10547fafaa07SVedant Kumar coveragemap_error::invalid_or_missing_arch_specifier); 10557fafaa07SVedant Kumar 1056901d04fcSVedant Kumar // MachO universal binaries which contain archives need to be treated as 1057901d04fcSVedant Kumar // archives, not as regular binaries. 1058901d04fcSVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 1059901d04fcSVedant Kumar for (auto &ObjForArch : Universal->objects()) { 1060901d04fcSVedant Kumar // Skip slices within the universal binary which target the wrong arch. 1061901d04fcSVedant Kumar std::string ObjArch = ObjForArch.getArchFlagName(); 1062901d04fcSVedant Kumar if (Arch != ObjArch) 1063901d04fcSVedant Kumar continue; 1064901d04fcSVedant Kumar 1065901d04fcSVedant Kumar auto ArchiveOrErr = ObjForArch.getAsArchive(); 1066901d04fcSVedant Kumar if (!ArchiveOrErr) { 1067901d04fcSVedant Kumar // If this is not an archive, try treating it as a regular object. 1068901d04fcSVedant Kumar consumeError(ArchiveOrErr.takeError()); 1069901d04fcSVedant Kumar break; 1070901d04fcSVedant Kumar } 1071901d04fcSVedant Kumar 1072901d04fcSVedant Kumar return BinaryCoverageReader::create( 1073901d04fcSVedant Kumar ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers); 1074901d04fcSVedant Kumar } 1075901d04fcSVedant Kumar } 1076901d04fcSVedant Kumar 1077901d04fcSVedant Kumar // Load coverage out of archive members. 1078901d04fcSVedant Kumar if (auto *Ar = dyn_cast<Archive>(Bin.get())) { 1079901d04fcSVedant Kumar Error Err = Error::success(); 1080901d04fcSVedant Kumar for (auto &Child : Ar->children(Err)) { 1081901d04fcSVedant Kumar Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef(); 1082901d04fcSVedant Kumar if (!ChildBufOrErr) 1083901d04fcSVedant Kumar return ChildBufOrErr.takeError(); 1084901d04fcSVedant Kumar 1085901d04fcSVedant Kumar auto ChildReadersOrErr = BinaryCoverageReader::create( 1086901d04fcSVedant Kumar ChildBufOrErr.get(), Arch, ObjectFileBuffers); 1087901d04fcSVedant Kumar if (!ChildReadersOrErr) 1088901d04fcSVedant Kumar return ChildReadersOrErr.takeError(); 1089901d04fcSVedant Kumar for (auto &Reader : ChildReadersOrErr.get()) 1090901d04fcSVedant Kumar Readers.push_back(std::move(Reader)); 1091901d04fcSVedant Kumar } 1092901d04fcSVedant Kumar if (Err) 1093c55cf4afSBill Wendling return std::move(Err); 1094901d04fcSVedant Kumar 1095901d04fcSVedant Kumar // Thin archives reference object files outside of the archive file, i.e. 1096901d04fcSVedant Kumar // files which reside in memory not owned by the caller. Transfer ownership 1097901d04fcSVedant Kumar // to the caller. 1098901d04fcSVedant Kumar if (Ar->isThin()) 1099901d04fcSVedant Kumar for (auto &Buffer : Ar->takeThinBuffers()) 1100901d04fcSVedant Kumar ObjectFileBuffers.push_back(std::move(Buffer)); 1101901d04fcSVedant Kumar 1102c55cf4afSBill Wendling return std::move(Readers); 1103901d04fcSVedant Kumar } 1104901d04fcSVedant Kumar 1105901d04fcSVedant Kumar auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch); 1106901d04fcSVedant Kumar if (!ReaderOrErr) 1107901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1108901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1109c55cf4afSBill Wendling return std::move(Readers); 1110dc707122SEaswaran Raman } 1111dc707122SEaswaran Raman 11129152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 1113dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 11149152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 1115dc707122SEaswaran Raman 1116dc707122SEaswaran Raman FunctionsFilenames.clear(); 1117dc707122SEaswaran Raman Expressions.clear(); 1118dc707122SEaswaran Raman MappingRegions.clear(); 1119dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 11205fbd1a33SPetr Hosek auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize); 11215fbd1a33SPetr Hosek RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames, 11225fbd1a33SPetr Hosek Expressions, MappingRegions); 1123dc707122SEaswaran Raman if (auto Err = Reader.read()) 1124dc707122SEaswaran Raman return Err; 1125dc707122SEaswaran Raman 1126dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 1127dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 1128dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 1129dc707122SEaswaran Raman Record.Expressions = Expressions; 1130dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 1131dc707122SEaswaran Raman 1132dc707122SEaswaran Raman ++CurrentRecord; 11339152fd17SVedant Kumar return Error::success(); 1134dc707122SEaswaran Raman } 1135