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()); 141*8280ece0SPetr Hosek RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames, 142*8280ece0SPetr Hosek CompilationDir); 1435fbd1a33SPetr Hosek return Delegate.readUncompressed(Version, NumFilenames); 144dd1ea9deSVedant Kumar } 145dd1ea9deSVedant Kumar 1465fbd1a33SPetr Hosek return readUncompressed(Version, NumFilenames); 147dd1ea9deSVedant Kumar } 148dd1ea9deSVedant Kumar 1495fbd1a33SPetr Hosek Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version, 1505fbd1a33SPetr Hosek uint64_t NumFilenames) { 151dd1ea9deSVedant Kumar // Read uncompressed filenames. 1525fbd1a33SPetr Hosek if (Version < CovMapVersion::Version6) { 153dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 154dc707122SEaswaran Raman StringRef Filename; 155dc707122SEaswaran Raman if (auto Err = readString(Filename)) 156dc707122SEaswaran Raman return Err; 1575fbd1a33SPetr Hosek Filenames.push_back(Filename.str()); 1585fbd1a33SPetr Hosek } 1595fbd1a33SPetr Hosek } else { 1605fbd1a33SPetr Hosek StringRef CWD; 1615fbd1a33SPetr Hosek if (auto Err = readString(CWD)) 1625fbd1a33SPetr Hosek return Err; 1635fbd1a33SPetr Hosek Filenames.push_back(CWD.str()); 1645fbd1a33SPetr Hosek 1655fbd1a33SPetr Hosek for (size_t I = 1; I < NumFilenames; ++I) { 1665fbd1a33SPetr Hosek StringRef Filename; 1675fbd1a33SPetr Hosek if (auto Err = readString(Filename)) 1685fbd1a33SPetr Hosek return Err; 1695fbd1a33SPetr Hosek if (sys::path::is_absolute(Filename)) { 1705fbd1a33SPetr Hosek Filenames.push_back(Filename.str()); 1715fbd1a33SPetr Hosek } else { 172*8280ece0SPetr Hosek SmallString<256> P; 173*8280ece0SPetr Hosek if (!CompilationDir.empty()) 174*8280ece0SPetr Hosek P.assign(CompilationDir); 175*8280ece0SPetr Hosek else 176*8280ece0SPetr Hosek P.assign(CWD); 1775fbd1a33SPetr Hosek llvm::sys::path::append(P, Filename); 1785fbd1a33SPetr Hosek Filenames.push_back(static_cast<std::string>(P)); 1795fbd1a33SPetr Hosek } 1805fbd1a33SPetr Hosek } 181dc707122SEaswaran Raman } 1829152fd17SVedant Kumar return Error::success(); 183dc707122SEaswaran Raman } 184dc707122SEaswaran Raman 1859152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 186dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 187dc707122SEaswaran Raman switch (Tag) { 188dc707122SEaswaran Raman case Counter::Zero: 189dc707122SEaswaran Raman C = Counter::getZero(); 1909152fd17SVedant Kumar return Error::success(); 191dc707122SEaswaran Raman case Counter::CounterValueReference: 192dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 1939152fd17SVedant Kumar return Error::success(); 194dc707122SEaswaran Raman default: 195dc707122SEaswaran Raman break; 196dc707122SEaswaran Raman } 197dc707122SEaswaran Raman Tag -= Counter::Expression; 198dc707122SEaswaran Raman switch (Tag) { 199dc707122SEaswaran Raman case CounterExpression::Subtract: 200dc707122SEaswaran Raman case CounterExpression::Add: { 201dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 202dc707122SEaswaran Raman if (ID >= Expressions.size()) 2039152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 204dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 205dc707122SEaswaran Raman C = Counter::getExpression(ID); 206dc707122SEaswaran Raman break; 207dc707122SEaswaran Raman } 208dc707122SEaswaran Raman default: 2099152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 210dc707122SEaswaran Raman } 2119152fd17SVedant Kumar return Error::success(); 212dc707122SEaswaran Raman } 213dc707122SEaswaran Raman 2149152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 215dc707122SEaswaran Raman uint64_t EncodedCounter; 216dc707122SEaswaran Raman if (auto Err = 217dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 218dc707122SEaswaran Raman return Err; 219dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 220dc707122SEaswaran Raman return Err; 2219152fd17SVedant Kumar return Error::success(); 222dc707122SEaswaran Raman } 223dc707122SEaswaran Raman 224dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 225dc707122SEaswaran Raman << Counter::EncodingTagBits; 226dc707122SEaswaran Raman 2275f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id. 228dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 229dc707122SEaswaran Raman /// function. 2309152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 231dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 232dc707122SEaswaran Raman size_t NumFileIDs) { 233dc707122SEaswaran Raman uint64_t NumRegions; 234dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 235dc707122SEaswaran Raman return Err; 236dc707122SEaswaran Raman unsigned LineStart = 0; 237dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 2389f2967bcSAlan Phipps Counter C, C2; 239dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 240dc707122SEaswaran Raman 241dc707122SEaswaran Raman // Read the combined counter + region kind. 242dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 243dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 244dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 245dc707122SEaswaran Raman return Err; 246dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 247dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 2489f2967bcSAlan Phipps 2499f2967bcSAlan Phipps // If Tag does not represent a ZeroCounter, then it is understood to refer 2509f2967bcSAlan Phipps // to a counter or counter expression with region kind assumed to be 2519f2967bcSAlan Phipps // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the 2529f2967bcSAlan Phipps // referenced counter or counter expression (and nothing else). 2539f2967bcSAlan Phipps // 2549f2967bcSAlan Phipps // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set, 2559f2967bcSAlan Phipps // then EncodedCounterAndRegion is interpreted to represent an 2569f2967bcSAlan Phipps // ExpansionRegion. In all other cases, EncodedCounterAndRegion is 2579f2967bcSAlan Phipps // interpreted to refer to a specific region kind, after which additional 2589f2967bcSAlan Phipps // fields may be read (e.g. BranchRegions have two encoded counters that 2599f2967bcSAlan Phipps // follow an encoded region kind value). 260dc707122SEaswaran Raman if (Tag != Counter::Zero) { 261dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 262dc707122SEaswaran Raman return Err; 263dc707122SEaswaran Raman } else { 264dc707122SEaswaran Raman // Is it an expansion region? 265dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 266dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 267dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 268dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 269dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 2709152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 271dc707122SEaswaran Raman } else { 272dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 273dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 274dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 275dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 276dc707122SEaswaran Raman break; 277dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 278dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 279dc707122SEaswaran Raman break; 2809f2967bcSAlan Phipps case CounterMappingRegion::BranchRegion: 2819f2967bcSAlan Phipps // For a Branch Region, read two successive counters. 2829f2967bcSAlan Phipps Kind = CounterMappingRegion::BranchRegion; 2839f2967bcSAlan Phipps if (auto Err = readCounter(C)) 2849f2967bcSAlan Phipps return Err; 2859f2967bcSAlan Phipps if (auto Err = readCounter(C2)) 2869f2967bcSAlan Phipps return Err; 2879f2967bcSAlan Phipps break; 288dc707122SEaswaran Raman default: 2899152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 290dc707122SEaswaran Raman } 291dc707122SEaswaran Raman } 292dc707122SEaswaran Raman } 293dc707122SEaswaran Raman 294dc707122SEaswaran Raman // Read the source range. 295dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 296dc707122SEaswaran Raman if (auto Err = 297dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 298dc707122SEaswaran Raman return Err; 299dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 300dc707122SEaswaran Raman return Err; 301dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 3029152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 303dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 304dc707122SEaswaran Raman return Err; 305dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 306dc707122SEaswaran Raman return Err; 307dc707122SEaswaran Raman LineStart += LineStartDelta; 308ad8f637bSVedant Kumar 309ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 310ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 311ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 312ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 313ad8f637bSVedant Kumar } 314ad8f637bSVedant Kumar 315dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 316dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 317dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 318dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 319dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 320dc707122SEaswaran Raman // column end take up one byte each. 321dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 322dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 323dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 324dc707122SEaswaran Raman ColumnStart = 1; 325dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 326dc707122SEaswaran Raman } 327dc707122SEaswaran Raman 328d34e60caSNicola Zaghen LLVM_DEBUG({ 329dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 330dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 331dc707122SEaswaran Raman << ColumnEnd << ", "; 332dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 333dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 334dc707122SEaswaran Raman else 335dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 336dc707122SEaswaran Raman dbgs() << "\n"; 337dc707122SEaswaran Raman }); 338dc707122SEaswaran Raman 3399f2967bcSAlan Phipps auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID, 340bae83970SVedant Kumar LineStart, ColumnStart, 341bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 342bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 343bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 344bae83970SVedant Kumar MappingRegions.push_back(CMR); 345dc707122SEaswaran Raman } 3469152fd17SVedant Kumar return Error::success(); 347dc707122SEaswaran Raman } 348dc707122SEaswaran Raman 3499152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 350dc707122SEaswaran Raman // Read the virtual file mapping. 351e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 352dc707122SEaswaran Raman uint64_t NumFileMappings; 353dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 354dc707122SEaswaran Raman return Err; 355dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 356dc707122SEaswaran Raman uint64_t FilenameIndex; 357dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 358dc707122SEaswaran Raman return Err; 359dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 360dc707122SEaswaran Raman } 361dc707122SEaswaran Raman 362dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 363dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 364dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 365dc707122SEaswaran Raman } 366dc707122SEaswaran Raman 367dc707122SEaswaran Raman // Read the expressions. 368dc707122SEaswaran Raman uint64_t NumExpressions; 369dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 370dc707122SEaswaran Raman return Err; 371dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 372dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 373dc707122SEaswaran Raman // are decoded. 374dc707122SEaswaran Raman Expressions.resize( 375dc707122SEaswaran Raman NumExpressions, 376dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 377dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 378dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 379dc707122SEaswaran Raman return Err; 380dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 381dc707122SEaswaran Raman return Err; 382dc707122SEaswaran Raman } 383dc707122SEaswaran Raman 384dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 385dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 386dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 387dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 388dc707122SEaswaran Raman VirtualFileMapping.size())) 389dc707122SEaswaran Raman return Err; 390dc707122SEaswaran Raman } 391dc707122SEaswaran Raman 392dc707122SEaswaran Raman // Set the counters for the expansion regions. 393dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 394dc707122SEaswaran Raman // from the expanded file. 395dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 396dc707122SEaswaran Raman // all the nested expansion regions. 397dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 398dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 399dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 400dc707122SEaswaran Raman for (auto &R : MappingRegions) { 401dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 402dc707122SEaswaran Raman continue; 403dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 404dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 405dc707122SEaswaran Raman } 406dc707122SEaswaran Raman for (auto &R : MappingRegions) { 407dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 408dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 409dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 410dc707122SEaswaran Raman } 411dc707122SEaswaran Raman } 412dc707122SEaswaran Raman } 413dc707122SEaswaran Raman 4149152fd17SVedant Kumar return Error::success(); 415dc707122SEaswaran Raman } 416dc707122SEaswaran Raman 417ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 418ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 419ac40e819SIgor Kudrin uint64_t NumFileMappings; 420ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 421c55cf4afSBill Wendling return std::move(Err); 422ac40e819SIgor Kudrin if (NumFileMappings != 1) 423ac40e819SIgor Kudrin return false; 424ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 425ac40e819SIgor Kudrin uint64_t FilenameIndex; 426ac40e819SIgor Kudrin if (Error Err = 427ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 428c55cf4afSBill Wendling return std::move(Err); 429ac40e819SIgor Kudrin uint64_t NumExpressions; 430ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 431c55cf4afSBill Wendling return std::move(Err); 432ac40e819SIgor Kudrin if (NumExpressions != 0) 433ac40e819SIgor Kudrin return false; 434ac40e819SIgor Kudrin uint64_t NumRegions; 435ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 436c55cf4afSBill Wendling return std::move(Err); 437ac40e819SIgor Kudrin if (NumRegions != 1) 438ac40e819SIgor Kudrin return false; 439ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 440ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 441ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 442c55cf4afSBill Wendling return std::move(Err); 443ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 444ac40e819SIgor Kudrin return Tag == Counter::Zero; 445ac40e819SIgor Kudrin } 446ac40e819SIgor Kudrin 4479152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 448e183340cSFangrui Song Expected<StringRef> DataOrErr = Section.getContents(); 449e183340cSFangrui Song if (!DataOrErr) 450e183340cSFangrui Song return DataOrErr.takeError(); 451e183340cSFangrui Song Data = *DataOrErr; 452dc707122SEaswaran Raman Address = Section.getAddress(); 4538b6af001SReid Kleckner 4548b6af001SReid Kleckner // If this is a linked PE/COFF file, then we have to skip over the null byte 4558b6af001SReid Kleckner // that is allocated in the .lprfn$A section in the LLVM profiling runtime. 4568b6af001SReid Kleckner const ObjectFile *Obj = Section.getObject(); 4578b6af001SReid Kleckner if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) 4588b6af001SReid Kleckner Data = Data.drop_front(1); 4598b6af001SReid Kleckner 4609152fd17SVedant Kumar return Error::success(); 461dc707122SEaswaran Raman } 462dc707122SEaswaran Raman 463dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 464dc707122SEaswaran Raman if (Pointer < Address) 465dc707122SEaswaran Raman return StringRef(); 466dc707122SEaswaran Raman auto Offset = Pointer - Address; 467dc707122SEaswaran Raman if (Offset + Size > Data.size()) 468dc707122SEaswaran Raman return StringRef(); 469dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 470dc707122SEaswaran Raman } 471dc707122SEaswaran Raman 472ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 473ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 474ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 475ac40e819SIgor Kudrin if (Hash) 476ac40e819SIgor Kudrin return false; 477ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 478ac40e819SIgor Kudrin } 479ac40e819SIgor Kudrin 480dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of 481dd1ea9deSVedant Kumar /// filenames in a vector-like container. 482dd1ea9deSVedant Kumar struct FilenameRange { 483dd1ea9deSVedant Kumar unsigned StartingIndex; 484dd1ea9deSVedant Kumar unsigned Length; 485dd1ea9deSVedant Kumar 486dd1ea9deSVedant Kumar FilenameRange(unsigned StartingIndex, unsigned Length) 487dd1ea9deSVedant Kumar : StartingIndex(StartingIndex), Length(Length) {} 488dd1ea9deSVedant Kumar 489dd1ea9deSVedant Kumar void markInvalid() { Length = 0; } 490dd1ea9deSVedant Kumar bool isInvalid() const { return Length == 0; } 491dd1ea9deSVedant Kumar }; 492dd1ea9deSVedant Kumar 493dc707122SEaswaran Raman namespace { 494e78d131aSEugene Zelenko 495dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module. 496dc707122SEaswaran Raman struct CovMapFuncRecordReader { 497e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 498e78d131aSEugene Zelenko 499dd1ea9deSVedant Kumar // Read a coverage header. 5003739b95dSVedant Kumar // 501dd1ea9deSVedant Kumar // \p CovBuf points to the buffer containing the \c CovHeader of the coverage 5023739b95dSVedant Kumar // mapping data associated with the module. 5033739b95dSVedant Kumar // 504dd1ea9deSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or to an address 505dd1ea9deSVedant Kumar // greater than \p CovEnd if not. 5065fbd1a33SPetr Hosek virtual Expected<const char *> readCoverageHeader(const char *CovBuf, 5075fbd1a33SPetr Hosek const char *CovBufEnd) = 0; 508dd1ea9deSVedant Kumar 509dd1ea9deSVedant Kumar // Read function records. 510dd1ea9deSVedant Kumar // 511dd1ea9deSVedant Kumar // \p FuncRecBuf points to the buffer containing a batch of function records. 512dd1ea9deSVedant Kumar // \p FuncRecBufEnd points past the end of the batch of records. 513dd1ea9deSVedant Kumar // 514dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 515dd1ea9deSVedant Kumar // associated with the function records. It is unused in Version4. 516dd1ea9deSVedant Kumar // 517dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 518dd1ea9deSVedant Kumar // mappings associated with the function records. It is unused in Version4. 519dd1ea9deSVedant Kumar virtual Error readFunctionRecords(const char *FuncRecBuf, 520dd1ea9deSVedant Kumar const char *FuncRecBufEnd, 521dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 522dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 523dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) = 0; 524e78d131aSEugene Zelenko 525dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 5269152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 527e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 528*8280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 5295fbd1a33SPetr Hosek std::vector<std::string> &F); 530dc707122SEaswaran Raman }; 531dc707122SEaswaran Raman 532dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 533e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 534dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 53572208a82SEugene Zelenko using FuncRecordType = 53672208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 53772208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 538dc707122SEaswaran Raman 539ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 540ac40e819SIgor Kudrin // in \c Records. 541e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 542dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 543*8280ece0SPetr Hosek StringRef CompilationDir; 5445fbd1a33SPetr Hosek std::vector<std::string> &Filenames; 545dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 546dc707122SEaswaran Raman 547dd1ea9deSVedant Kumar // Maps a hash of the filenames in a TU to a \c FileRange. The range 548dd1ea9deSVedant Kumar // specifies the location of the hashed filenames in \c Filenames. 549dd1ea9deSVedant Kumar DenseMap<uint64_t, FilenameRange> FileRangeMap; 550dd1ea9deSVedant Kumar 551ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 552ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 553ac40e819SIgor Kudrin // records for the functions with ODR linkage. 554ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 555ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 556ac40e819SIgor Kudrin // not used in the corresponding translation unit. 557ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 558dd1ea9deSVedant Kumar StringRef Mapping, 559dd1ea9deSVedant Kumar FilenameRange FileRange) { 560dd1ea9deSVedant Kumar ++CovMapNumRecords; 561ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 562ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 563ac40e819SIgor Kudrin auto InsertResult = 564ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 565ac40e819SIgor Kudrin if (InsertResult.second) { 566ac40e819SIgor Kudrin StringRef FuncName; 567ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 568ac40e819SIgor Kudrin return Err; 569b5794ca9SVedant Kumar if (FuncName.empty()) 570b5794ca9SVedant Kumar return make_error<InstrProfError>(instrprof_error::malformed); 571dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 572dd1ea9deSVedant Kumar Records.emplace_back(Version, FuncName, FuncHash, Mapping, 573dd1ea9deSVedant Kumar FileRange.StartingIndex, FileRange.Length); 574ac40e819SIgor Kudrin return Error::success(); 575ac40e819SIgor Kudrin } 576ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 577ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 578ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 579ac40e819SIgor Kudrin Records[OldRecordIndex]; 580ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 581ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 582ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 583ac40e819SIgor Kudrin return Err; 584ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 585ac40e819SIgor Kudrin return Error::success(); 586ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 587ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 588ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 589ac40e819SIgor Kudrin return Err; 590ac40e819SIgor Kudrin if (*NewIsDummyExpected) 591ac40e819SIgor Kudrin return Error::success(); 592dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 593ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 594ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 595dd1ea9deSVedant Kumar OldRecord.FilenamesBegin = FileRange.StartingIndex; 596dd1ea9deSVedant Kumar OldRecord.FilenamesSize = FileRange.Length; 597ac40e819SIgor Kudrin return Error::success(); 598ac40e819SIgor Kudrin } 599ac40e819SIgor Kudrin 600dc707122SEaswaran Raman public: 601dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 602dc707122SEaswaran Raman InstrProfSymtab &P, 603*8280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 6045fbd1a33SPetr Hosek std::vector<std::string> &F) 605*8280ece0SPetr Hosek : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {} 606e78d131aSEugene Zelenko 607e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 608dc707122SEaswaran Raman 6095fbd1a33SPetr Hosek Expected<const char *> readCoverageHeader(const char *CovBuf, 6105fbd1a33SPetr Hosek const char *CovBufEnd) override { 611dc707122SEaswaran Raman using namespace support; 612e78d131aSEugene Zelenko 613dd1ea9deSVedant Kumar if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) 6149152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 615dd1ea9deSVedant Kumar auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); 616dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 617dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 618dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 619dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 620dd1ea9deSVedant Kumar CovBuf = reinterpret_cast<const char *>(CovHeader + 1); 621dc707122SEaswaran Raman 622dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 623dd1ea9deSVedant Kumar // This is a no-op in Version4 (function records are read after all headers 624dd1ea9deSVedant Kumar // are read). 625dd1ea9deSVedant Kumar const char *FuncRecBuf = nullptr; 626dd1ea9deSVedant Kumar const char *FuncRecBufEnd = nullptr; 627dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 628dd1ea9deSVedant Kumar FuncRecBuf = CovBuf; 629dd1ea9deSVedant Kumar CovBuf += NRecords * sizeof(FuncRecordType); 630dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 631dd1ea9deSVedant Kumar FuncRecBufEnd = CovBuf; 632dc707122SEaswaran Raman 633dc707122SEaswaran Raman // Get the filenames. 634dd1ea9deSVedant Kumar if (CovBuf + FilenamesSize > CovBufEnd) 6359152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 636dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 637dd1ea9deSVedant Kumar StringRef FilenameRegion(CovBuf, FilenamesSize); 638*8280ece0SPetr Hosek RawCoverageFilenamesReader Reader(FilenameRegion, Filenames, 639*8280ece0SPetr Hosek CompilationDir); 6405fbd1a33SPetr Hosek if (auto Err = Reader.read(Version)) 641c55cf4afSBill Wendling return std::move(Err); 642dd1ea9deSVedant Kumar CovBuf += FilenamesSize; 643dd1ea9deSVedant Kumar FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin); 644dd1ea9deSVedant Kumar 6459f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) { 646dd1ea9deSVedant Kumar // Map a hash of the filenames region to the filename range associated 647dd1ea9deSVedant Kumar // with this coverage header. 648dd1ea9deSVedant Kumar int64_t FilenamesRef = 649dd1ea9deSVedant Kumar llvm::IndexedInstrProf::ComputeHash(FilenameRegion); 650dd1ea9deSVedant Kumar auto Insert = 651dd1ea9deSVedant Kumar FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange)); 652dd1ea9deSVedant Kumar if (!Insert.second) { 653dd1ea9deSVedant Kumar // The same filenames ref was encountered twice. It's possible that 654dd1ea9deSVedant Kumar // the associated filenames are the same. 655dd1ea9deSVedant Kumar auto It = Filenames.begin(); 656dd1ea9deSVedant Kumar FilenameRange &OrigRange = Insert.first->getSecond(); 657dd1ea9deSVedant Kumar if (std::equal(It + OrigRange.StartingIndex, 658dd1ea9deSVedant Kumar It + OrigRange.StartingIndex + OrigRange.Length, 659dd1ea9deSVedant Kumar It + FileRange.StartingIndex, 660dd1ea9deSVedant Kumar It + FileRange.StartingIndex + FileRange.Length)) 661dd1ea9deSVedant Kumar // Map the new range to the original one. 662dd1ea9deSVedant Kumar FileRange = OrigRange; 663dd1ea9deSVedant Kumar else 664dd1ea9deSVedant Kumar // This is a hash collision. Mark the filenames ref invalid. 665dd1ea9deSVedant Kumar OrigRange.markInvalid(); 666dd1ea9deSVedant Kumar } 667dd1ea9deSVedant Kumar } 668dc707122SEaswaran Raman 669dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 670dd1ea9deSVedant Kumar // This is a no-op in Version4 (coverage mappings are not affixed to the 671dd1ea9deSVedant Kumar // coverage header). 672dd1ea9deSVedant Kumar const char *MappingBuf = CovBuf; 6739f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && CoverageSize != 0) 6749152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 675dd1ea9deSVedant Kumar CovBuf += CoverageSize; 676dd1ea9deSVedant Kumar const char *MappingEnd = CovBuf; 677dd1ea9deSVedant Kumar 678dd1ea9deSVedant Kumar if (CovBuf > CovBufEnd) 679dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 680dd1ea9deSVedant Kumar 681dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 682dd1ea9deSVedant Kumar // Read each function record. 683dd1ea9deSVedant Kumar if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange, 684dd1ea9deSVedant Kumar MappingBuf, MappingEnd)) 685dd1ea9deSVedant Kumar return std::move(E); 686dd1ea9deSVedant Kumar } 687dd1ea9deSVedant Kumar 688dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 689dc707122SEaswaran Raman // before reading the next map. 690dd1ea9deSVedant Kumar CovBuf += offsetToAlignedAddr(CovBuf, Align(8)); 691dc707122SEaswaran Raman 692dd1ea9deSVedant Kumar return CovBuf; 69399317124SVedant Kumar } 694dd1ea9deSVedant Kumar 695dd1ea9deSVedant Kumar Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd, 696dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 697dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 698dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) override { 699dd1ea9deSVedant Kumar auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf); 700dd1ea9deSVedant Kumar while ((const char *)CFR < FuncRecBufEnd) { 701dd1ea9deSVedant Kumar // Validate the length of the coverage mapping for this function. 702dd1ea9deSVedant Kumar const char *NextMappingBuf; 703dd1ea9deSVedant Kumar const FuncRecordType *NextCFR; 704dd1ea9deSVedant Kumar std::tie(NextMappingBuf, NextCFR) = 705dd1ea9deSVedant Kumar CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); 706dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 707dd1ea9deSVedant Kumar if (NextMappingBuf > OutOfLineMappingBufEnd) 708dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 709dd1ea9deSVedant Kumar 710dd1ea9deSVedant Kumar // Look up the set of filenames associated with this function record. 711dd1ea9deSVedant Kumar Optional<FilenameRange> FileRange; 712dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 713dd1ea9deSVedant Kumar FileRange = OutOfLineFileRange; 714dd1ea9deSVedant Kumar } else { 715dd1ea9deSVedant Kumar uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); 716dd1ea9deSVedant Kumar auto It = FileRangeMap.find(FilenamesRef); 717dd1ea9deSVedant Kumar if (It == FileRangeMap.end()) 718dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 719dd1ea9deSVedant Kumar else 720dd1ea9deSVedant Kumar FileRange = It->getSecond(); 721dd1ea9deSVedant Kumar } 722dd1ea9deSVedant Kumar 723dd1ea9deSVedant Kumar // Now, read the coverage data. 724dd1ea9deSVedant Kumar if (FileRange && !FileRange->isInvalid()) { 725dd1ea9deSVedant Kumar StringRef Mapping = 726dd1ea9deSVedant Kumar CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); 7279f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && 728dd1ea9deSVedant Kumar Mapping.data() + Mapping.size() > FuncRecBufEnd) 729dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 730dd1ea9deSVedant Kumar if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) 731dd1ea9deSVedant Kumar return Err; 732dd1ea9deSVedant Kumar } 733dd1ea9deSVedant Kumar 734dd1ea9deSVedant Kumar std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR); 735dd1ea9deSVedant Kumar } 736dd1ea9deSVedant Kumar return Error::success(); 737dc707122SEaswaran Raman } 738dc707122SEaswaran Raman }; 739e78d131aSEugene Zelenko 740dc707122SEaswaran Raman } // end anonymous namespace 741dc707122SEaswaran Raman 742dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 7439152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 744e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 745*8280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 7465fbd1a33SPetr Hosek std::vector<std::string> &F) { 747dc707122SEaswaran Raman using namespace coverage; 748e78d131aSEugene Zelenko 749dc707122SEaswaran Raman switch (Version) { 750dc707122SEaswaran Raman case CovMapVersion::Version1: 7510eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 752*8280ece0SPetr Hosek CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F); 753dc707122SEaswaran Raman case CovMapVersion::Version2: 754ad8f637bSVedant Kumar case CovMapVersion::Version3: 755dd1ea9deSVedant Kumar case CovMapVersion::Version4: 7569f2967bcSAlan Phipps case CovMapVersion::Version5: 7575fbd1a33SPetr Hosek case CovMapVersion::Version6: 758dc707122SEaswaran Raman // Decompress the name data. 7599152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 760c55cf4afSBill Wendling return std::move(E); 761ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 7620eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 763*8280ece0SPetr Hosek CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F); 764dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version3) 7650eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 766*8280ece0SPetr Hosek CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F); 767dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version4) 768dd1ea9deSVedant Kumar return std::make_unique<VersionedCovMapFuncRecordReader< 769*8280ece0SPetr Hosek CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F); 7709f2967bcSAlan Phipps else if (Version == CovMapVersion::Version5) 7719f2967bcSAlan Phipps return std::make_unique<VersionedCovMapFuncRecordReader< 772*8280ece0SPetr Hosek CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F); 7735fbd1a33SPetr Hosek else if (Version == CovMapVersion::Version6) 7745fbd1a33SPetr Hosek return std::make_unique<VersionedCovMapFuncRecordReader< 775*8280ece0SPetr Hosek CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F); 776dc707122SEaswaran Raman } 777dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 778dc707122SEaswaran Raman } 779dc707122SEaswaran Raman 780dc707122SEaswaran Raman template <typename T, support::endianness Endian> 7819152fd17SVedant Kumar static Error readCoverageMappingData( 782dd1ea9deSVedant Kumar InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, 783dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 784*8280ece0SPetr Hosek StringRef CompilationDir, std::vector<std::string> &Filenames) { 785dc707122SEaswaran Raman using namespace coverage; 786e78d131aSEugene Zelenko 787dc707122SEaswaran Raman // Read the records in the coverage data section. 788dc707122SEaswaran Raman auto CovHeader = 789dd1ea9deSVedant Kumar reinterpret_cast<const CovMapHeader *>(CovMap.data()); 790dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 791e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 7929152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 7939152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 794dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 795*8280ece0SPetr Hosek CompilationDir, Filenames); 7969152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 7979152fd17SVedant Kumar return E; 7989152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 799dd1ea9deSVedant Kumar const char *CovBuf = CovMap.data(); 800dd1ea9deSVedant Kumar const char *CovBufEnd = CovBuf + CovMap.size(); 801dd1ea9deSVedant Kumar const char *FuncRecBuf = FuncRecords.data(); 802dd1ea9deSVedant Kumar const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size(); 803dd1ea9deSVedant Kumar while (CovBuf < CovBufEnd) { 804dd1ea9deSVedant Kumar // Read the current coverage header & filename data. 805dd1ea9deSVedant Kumar // 806dd1ea9deSVedant Kumar // Prior to Version4, this also reads all function records affixed to the 807dd1ea9deSVedant Kumar // header. 808dd1ea9deSVedant Kumar // 809dd1ea9deSVedant Kumar // Return a pointer to the next coverage header. 8105fbd1a33SPetr Hosek auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd); 811dd1ea9deSVedant Kumar if (auto E = NextOrErr.takeError()) 8129152fd17SVedant Kumar return E; 813dd1ea9deSVedant Kumar CovBuf = NextOrErr.get(); 814dc707122SEaswaran Raman } 815dd1ea9deSVedant Kumar // In Version4, function records are not affixed to coverage headers. Read 816dd1ea9deSVedant Kumar // the records from their dedicated section. 8179f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) 818dd1ea9deSVedant Kumar return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr, 819dd1ea9deSVedant Kumar nullptr); 8209152fd17SVedant Kumar return Error::success(); 821dc707122SEaswaran Raman } 822e78d131aSEugene Zelenko 823dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 824dc707122SEaswaran Raman 825901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 826901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer( 827*8280ece0SPetr Hosek StringRef Coverage, std::string &&FuncRecords, 828*8280ece0SPetr Hosek InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, 829*8280ece0SPetr Hosek support::endianness Endian, StringRef CompilationDir) { 83080cd518bSVedant Kumar std::unique_ptr<BinaryCoverageReader> Reader( 83180cd518bSVedant Kumar new BinaryCoverageReader(std::move(FuncRecords))); 832901d04fcSVedant Kumar Reader->ProfileNames = std::move(ProfileNames); 83380cd518bSVedant Kumar StringRef FuncRecordsRef = Reader->FuncRecords; 834901d04fcSVedant Kumar if (BytesInAddress == 4 && Endian == support::endianness::little) { 835901d04fcSVedant Kumar if (Error E = 836901d04fcSVedant Kumar readCoverageMappingData<uint32_t, support::endianness::little>( 83780cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 838*8280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 839c55cf4afSBill Wendling return std::move(E); 840901d04fcSVedant Kumar } else if (BytesInAddress == 4 && Endian == support::endianness::big) { 841901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( 84280cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 843*8280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 844c55cf4afSBill Wendling return std::move(E); 845901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::little) { 846901d04fcSVedant Kumar if (Error E = 847901d04fcSVedant Kumar readCoverageMappingData<uint64_t, support::endianness::little>( 84880cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 849*8280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 850c55cf4afSBill Wendling return std::move(E); 851901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::big) { 852901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( 85380cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 854*8280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 855c55cf4afSBill Wendling return std::move(E); 856901d04fcSVedant Kumar } else 857901d04fcSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 858c55cf4afSBill Wendling return std::move(Reader); 859901d04fcSVedant Kumar } 860901d04fcSVedant Kumar 861901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 862*8280ece0SPetr Hosek loadTestingFormat(StringRef Data, StringRef CompilationDir) { 863901d04fcSVedant Kumar uint8_t BytesInAddress = 8; 864901d04fcSVedant Kumar support::endianness Endian = support::endianness::little; 865dc707122SEaswaran Raman 866dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 86772208a82SEugene Zelenko if (Data.empty()) 8689152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 869dc707122SEaswaran Raman unsigned N = 0; 8706a0746a9SFangrui Song uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); 871dc707122SEaswaran Raman if (N > Data.size()) 8729152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 873dc707122SEaswaran Raman Data = Data.substr(N); 87472208a82SEugene Zelenko if (Data.empty()) 8759152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 876dc707122SEaswaran Raman N = 0; 8776a0746a9SFangrui Song uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); 878dc707122SEaswaran Raman if (N > Data.size()) 8799152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 880dc707122SEaswaran Raman Data = Data.substr(N); 881dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 8829152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 883901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 8849152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 885c55cf4afSBill Wendling return std::move(E); 886489a3531SPetr Hosek Data = Data.substr(ProfileNamesSize); 887eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 888489a3531SPetr Hosek size_t Pad = offsetToAlignedAddr(Data.data(), Align(8)); 889489a3531SPetr Hosek if (Data.size() < Pad) 890489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 891489a3531SPetr Hosek Data = Data.substr(Pad); 892489a3531SPetr Hosek if (Data.size() < sizeof(CovMapHeader)) 893489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 894489a3531SPetr Hosek auto const *CovHeader = reinterpret_cast<const CovMapHeader *>( 895489a3531SPetr Hosek Data.substr(0, sizeof(CovMapHeader)).data()); 896489a3531SPetr Hosek CovMapVersion Version = 897489a3531SPetr Hosek (CovMapVersion)CovHeader->getVersion<support::endianness::little>(); 898489a3531SPetr Hosek StringRef CoverageMapping, CoverageRecords; 899489a3531SPetr Hosek if (Version < CovMapVersion::Version4) { 900489a3531SPetr Hosek CoverageMapping = Data; 90172208a82SEugene Zelenko if (CoverageMapping.empty()) 9029152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 903489a3531SPetr Hosek } else { 904489a3531SPetr Hosek uint32_t FilenamesSize = 905489a3531SPetr Hosek CovHeader->getFilenamesSize<support::endianness::little>(); 906489a3531SPetr Hosek uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; 907489a3531SPetr Hosek CoverageMapping = Data.substr(0, CoverageMappingSize); 908489a3531SPetr Hosek if (CoverageMapping.empty()) 909489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 910489a3531SPetr Hosek Data = Data.substr(CoverageMappingSize); 911489a3531SPetr Hosek // Skip the padding bytes because coverage records data has an alignment 912489a3531SPetr Hosek // of 8. 913489a3531SPetr Hosek Pad = offsetToAlignedAddr(Data.data(), Align(8)); 914489a3531SPetr Hosek if (Data.size() < Pad) 9159152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 916489a3531SPetr Hosek CoverageRecords = Data.substr(Pad); 917489a3531SPetr Hosek if (CoverageRecords.empty()) 918489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 919489a3531SPetr Hosek } 920901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 921489a3531SPetr Hosek CoverageMapping, CoverageRecords.str(), std::move(ProfileNames), 922*8280ece0SPetr Hosek BytesInAddress, Endian, CompilationDir); 923dc707122SEaswaran Raman } 924dc707122SEaswaran Raman 92580cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats 92680cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF. 92780cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, 92880cd518bSVedant Kumar StringRef Name) { 9298b6af001SReid Kleckner // On COFF, the object file section name may end in "$M". This tells the 9308b6af001SReid Kleckner // linker to sort these sections between "$A" and "$Z". The linker removes the 9318b6af001SReid Kleckner // dollar and everything after it in the final binary. Do the same to match. 9328b6af001SReid Kleckner bool IsCOFF = isa<COFFObjectFile>(OF); 9338b6af001SReid Kleckner auto stripSuffix = [IsCOFF](StringRef N) { 9348b6af001SReid Kleckner return IsCOFF ? N.split('$').first : N; 9358b6af001SReid Kleckner }; 9368b6af001SReid Kleckner Name = stripSuffix(Name); 9378b6af001SReid Kleckner 93880cd518bSVedant Kumar std::vector<SectionRef> Sections; 939dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 940bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 941bcc00e1aSGeorge Rimar if (!NameOrErr) 942bcc00e1aSGeorge Rimar return NameOrErr.takeError(); 943bcc00e1aSGeorge Rimar if (stripSuffix(*NameOrErr) == Name) 94480cd518bSVedant Kumar Sections.push_back(Section); 945dc707122SEaswaran Raman } 94680cd518bSVedant Kumar if (Sections.empty()) 9479152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 94880cd518bSVedant Kumar return Sections; 949dc707122SEaswaran Raman } 950dc707122SEaswaran Raman 951901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 952*8280ece0SPetr Hosek loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, 953*8280ece0SPetr Hosek StringRef CompilationDir = "") { 954dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 955e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 956dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 957dc707122SEaswaran Raman // appropriate architecture. 9584fd11c1eSAlexander Shaposhnikov auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); 9599acb1099SKevin Enderby if (!ObjectFileOrErr) 9609acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 961dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 962e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 963dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 964e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 965dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 966dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 9679152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 968dc707122SEaswaran Raman } else 969dc707122SEaswaran Raman // We can only handle object files. 9709152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 971dc707122SEaswaran Raman 972dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 973901d04fcSVedant Kumar uint8_t BytesInAddress = OF->getBytesInAddress(); 974901d04fcSVedant Kumar support::endianness Endian = OF->isLittleEndian() 975901d04fcSVedant Kumar ? support::endianness::little 976dc707122SEaswaran Raman : support::endianness::big; 977dc707122SEaswaran Raman 978dc707122SEaswaran Raman // Look for the sections that we are interested in. 9791a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 9804a5ddf80SXinliang David Li auto NamesSection = 98180cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 9821a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9839152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 984c55cf4afSBill Wendling return std::move(E); 9854a5ddf80SXinliang David Li auto CoverageSection = 98680cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 9871a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9889152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 989c55cf4afSBill Wendling return std::move(E); 99080cd518bSVedant Kumar std::vector<SectionRef> CoverageSectionRefs = *CoverageSection; 99180cd518bSVedant Kumar if (CoverageSectionRefs.size() != 1) 99280cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 99380cd518bSVedant Kumar auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); 994901d04fcSVedant Kumar if (!CoverageMappingOrErr) 995901d04fcSVedant Kumar return CoverageMappingOrErr.takeError(); 996dd1ea9deSVedant Kumar StringRef CoverageMapping = CoverageMappingOrErr.get(); 997e183340cSFangrui Song 998901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 99980cd518bSVedant Kumar std::vector<SectionRef> NamesSectionRefs = *NamesSection; 100080cd518bSVedant Kumar if (NamesSectionRefs.size() != 1) 100180cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 100280cd518bSVedant Kumar if (Error E = ProfileNames.create(NamesSectionRefs.back())) 1003c55cf4afSBill Wendling return std::move(E); 1004dc707122SEaswaran Raman 1005dd1ea9deSVedant Kumar // Look for the coverage records section (Version4 only). 100680cd518bSVedant Kumar std::string FuncRecords; 100780cd518bSVedant Kumar auto CoverageRecordsSections = 100880cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, 1009dd1ea9deSVedant Kumar /*AddSegmentInfo=*/false)); 101080cd518bSVedant Kumar if (auto E = CoverageRecordsSections.takeError()) 1011dd1ea9deSVedant Kumar consumeError(std::move(E)); 1012dd1ea9deSVedant Kumar else { 101380cd518bSVedant Kumar for (SectionRef Section : *CoverageRecordsSections) { 101480cd518bSVedant Kumar auto CoverageRecordsOrErr = Section.getContents(); 1015dd1ea9deSVedant Kumar if (!CoverageRecordsOrErr) 1016dd1ea9deSVedant Kumar return CoverageRecordsOrErr.takeError(); 101780cd518bSVedant Kumar FuncRecords += CoverageRecordsOrErr.get(); 101880cd518bSVedant Kumar while (FuncRecords.size() % 8 != 0) 101980cd518bSVedant Kumar FuncRecords += '\0'; 102080cd518bSVedant Kumar } 1021dd1ea9deSVedant Kumar } 1022dd1ea9deSVedant Kumar 1023901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 102480cd518bSVedant Kumar CoverageMapping, std::move(FuncRecords), std::move(ProfileNames), 1025*8280ece0SPetr Hosek BytesInAddress, Endian, CompilationDir); 1026dc707122SEaswaran Raman } 1027dc707122SEaswaran Raman 10287fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin. 10297fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) { 10307fafaa07SVedant Kumar // If we have a universal binary and Arch doesn't identify any of its slices, 10317fafaa07SVedant Kumar // it's user error. 10327fafaa07SVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) { 10337fafaa07SVedant Kumar for (auto &ObjForArch : Universal->objects()) 10347fafaa07SVedant Kumar if (Arch == ObjForArch.getArchFlagName()) 10357fafaa07SVedant Kumar return false; 10367fafaa07SVedant Kumar return true; 10377fafaa07SVedant Kumar } 10387fafaa07SVedant Kumar return false; 10397fafaa07SVedant Kumar } 10407fafaa07SVedant Kumar 1041901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 1042901d04fcSVedant Kumar BinaryCoverageReader::create( 1043901d04fcSVedant Kumar MemoryBufferRef ObjectBuffer, StringRef Arch, 1044*8280ece0SPetr Hosek SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers, 1045*8280ece0SPetr Hosek StringRef CompilationDir) { 1046901d04fcSVedant Kumar std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; 1047dc707122SEaswaran Raman 1048901d04fcSVedant Kumar if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { 1049dc707122SEaswaran Raman // This is a special format used for testing. 1050*8280ece0SPetr Hosek auto ReaderOrErr = 1051*8280ece0SPetr Hosek loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir); 1052901d04fcSVedant Kumar if (!ReaderOrErr) 1053901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1054901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1055c55cf4afSBill Wendling return std::move(Readers); 1056901d04fcSVedant Kumar } 1057dc707122SEaswaran Raman 1058901d04fcSVedant Kumar auto BinOrErr = createBinary(ObjectBuffer); 1059901d04fcSVedant Kumar if (!BinOrErr) 1060901d04fcSVedant Kumar return BinOrErr.takeError(); 1061901d04fcSVedant Kumar std::unique_ptr<Binary> Bin = std::move(BinOrErr.get()); 1062901d04fcSVedant Kumar 10637fafaa07SVedant Kumar if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch)) 10647fafaa07SVedant Kumar return make_error<CoverageMapError>( 10657fafaa07SVedant Kumar coveragemap_error::invalid_or_missing_arch_specifier); 10667fafaa07SVedant Kumar 1067901d04fcSVedant Kumar // MachO universal binaries which contain archives need to be treated as 1068901d04fcSVedant Kumar // archives, not as regular binaries. 1069901d04fcSVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 1070901d04fcSVedant Kumar for (auto &ObjForArch : Universal->objects()) { 1071901d04fcSVedant Kumar // Skip slices within the universal binary which target the wrong arch. 1072901d04fcSVedant Kumar std::string ObjArch = ObjForArch.getArchFlagName(); 1073901d04fcSVedant Kumar if (Arch != ObjArch) 1074901d04fcSVedant Kumar continue; 1075901d04fcSVedant Kumar 1076901d04fcSVedant Kumar auto ArchiveOrErr = ObjForArch.getAsArchive(); 1077901d04fcSVedant Kumar if (!ArchiveOrErr) { 1078901d04fcSVedant Kumar // If this is not an archive, try treating it as a regular object. 1079901d04fcSVedant Kumar consumeError(ArchiveOrErr.takeError()); 1080901d04fcSVedant Kumar break; 1081901d04fcSVedant Kumar } 1082901d04fcSVedant Kumar 1083901d04fcSVedant Kumar return BinaryCoverageReader::create( 1084*8280ece0SPetr Hosek ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers, 1085*8280ece0SPetr Hosek CompilationDir); 1086901d04fcSVedant Kumar } 1087901d04fcSVedant Kumar } 1088901d04fcSVedant Kumar 1089901d04fcSVedant Kumar // Load coverage out of archive members. 1090901d04fcSVedant Kumar if (auto *Ar = dyn_cast<Archive>(Bin.get())) { 1091901d04fcSVedant Kumar Error Err = Error::success(); 1092901d04fcSVedant Kumar for (auto &Child : Ar->children(Err)) { 1093901d04fcSVedant Kumar Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef(); 1094901d04fcSVedant Kumar if (!ChildBufOrErr) 1095901d04fcSVedant Kumar return ChildBufOrErr.takeError(); 1096901d04fcSVedant Kumar 1097901d04fcSVedant Kumar auto ChildReadersOrErr = BinaryCoverageReader::create( 1098*8280ece0SPetr Hosek ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir); 1099901d04fcSVedant Kumar if (!ChildReadersOrErr) 1100901d04fcSVedant Kumar return ChildReadersOrErr.takeError(); 1101901d04fcSVedant Kumar for (auto &Reader : ChildReadersOrErr.get()) 1102901d04fcSVedant Kumar Readers.push_back(std::move(Reader)); 1103901d04fcSVedant Kumar } 1104901d04fcSVedant Kumar if (Err) 1105c55cf4afSBill Wendling return std::move(Err); 1106901d04fcSVedant Kumar 1107901d04fcSVedant Kumar // Thin archives reference object files outside of the archive file, i.e. 1108901d04fcSVedant Kumar // files which reside in memory not owned by the caller. Transfer ownership 1109901d04fcSVedant Kumar // to the caller. 1110901d04fcSVedant Kumar if (Ar->isThin()) 1111901d04fcSVedant Kumar for (auto &Buffer : Ar->takeThinBuffers()) 1112901d04fcSVedant Kumar ObjectFileBuffers.push_back(std::move(Buffer)); 1113901d04fcSVedant Kumar 1114c55cf4afSBill Wendling return std::move(Readers); 1115901d04fcSVedant Kumar } 1116901d04fcSVedant Kumar 1117*8280ece0SPetr Hosek auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir); 1118901d04fcSVedant Kumar if (!ReaderOrErr) 1119901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1120901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1121c55cf4afSBill Wendling return std::move(Readers); 1122dc707122SEaswaran Raman } 1123dc707122SEaswaran Raman 11249152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 1125dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 11269152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 1127dc707122SEaswaran Raman 1128dc707122SEaswaran Raman FunctionsFilenames.clear(); 1129dc707122SEaswaran Raman Expressions.clear(); 1130dc707122SEaswaran Raman MappingRegions.clear(); 1131dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 11325fbd1a33SPetr Hosek auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize); 11335fbd1a33SPetr Hosek RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames, 11345fbd1a33SPetr Hosek Expressions, MappingRegions); 1135dc707122SEaswaran Raman if (auto Err = Reader.read()) 1136dc707122SEaswaran Raman return Err; 1137dc707122SEaswaran Raman 1138dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 1139dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 1140dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 1141dc707122SEaswaran Raman Record.Expressions = Expressions; 1142dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 1143dc707122SEaswaran Raman 1144dc707122SEaswaran Raman ++CurrentRecord; 11459152fd17SVedant Kumar return Error::success(); 1146dc707122SEaswaran Raman } 1147