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" 22e72c195fSserge-sans-paille #include "llvm/Object/Archive.h" 23e78d131aSEugene Zelenko #include "llvm/Object/Binary.h" 24ba7a92c0SNico Weber #include "llvm/Object/COFF.h" 25e78d131aSEugene Zelenko #include "llvm/Object/Error.h" 26dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h" 27dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.h" 28e78d131aSEugene Zelenko #include "llvm/ProfileData/InstrProf.h" 29e78d131aSEugene Zelenko #include "llvm/Support/Casting.h" 30dd1ea9deSVedant Kumar #include "llvm/Support/Compression.h" 31dc707122SEaswaran Raman #include "llvm/Support/Debug.h" 324a5ddf80SXinliang David Li #include "llvm/Support/Endian.h" 33e78d131aSEugene Zelenko #include "llvm/Support/Error.h" 34e78d131aSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 35dc707122SEaswaran Raman #include "llvm/Support/LEB128.h" 36dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h" 37ba7a92c0SNico Weber #include "llvm/Support/Path.h" 38dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 39e78d131aSEugene Zelenko #include <vector> 40dc707122SEaswaran Raman 41dc707122SEaswaran Raman using namespace llvm; 42dc707122SEaswaran Raman using namespace coverage; 43dc707122SEaswaran Raman using namespace object; 44dc707122SEaswaran Raman 45dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 46dc707122SEaswaran Raman 47dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records"); 48dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records"); 49dd1ea9deSVedant Kumar 50dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 51bae83970SVedant Kumar if (ReadErr != coveragemap_error::success) 52bae83970SVedant Kumar return; 53bae83970SVedant Kumar 54dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 55dc707122SEaswaran Raman // the next record. 56bae83970SVedant Kumar if (auto E = Reader->readNextRecord(Record)) 579152fd17SVedant Kumar handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 589152fd17SVedant Kumar if (CME.get() == coveragemap_error::eof) 59dc707122SEaswaran Raman *this = CoverageMappingIterator(); 609152fd17SVedant Kumar else 61bae83970SVedant Kumar ReadErr = CME.get(); 629152fd17SVedant Kumar }); 639152fd17SVedant Kumar } 64dc707122SEaswaran Raman 659152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) { 6672208a82SEugene Zelenko if (Data.empty()) 679152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 68dc707122SEaswaran Raman unsigned N = 0; 696a0746a9SFangrui Song Result = decodeULEB128(Data.bytes_begin(), &N); 70dc707122SEaswaran Raman if (N > Data.size()) 719152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 72dc707122SEaswaran Raman Data = Data.substr(N); 739152fd17SVedant Kumar return Error::success(); 74dc707122SEaswaran Raman } 75dc707122SEaswaran Raman 769152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { 77dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 78dc707122SEaswaran Raman return Err; 79dc707122SEaswaran Raman if (Result >= MaxPlus1) 809152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 819152fd17SVedant Kumar return Error::success(); 82dc707122SEaswaran Raman } 83dc707122SEaswaran Raman 849152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) { 85dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 86dc707122SEaswaran Raman return Err; 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) { 122*ea61750cSCole Kissane if (!compression::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); 132*ea61750cSCole Kissane auto Err = compression::zlib::uncompress(CompressedFilenames, StorageBuf, 133*ea61750cSCole Kissane 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()); 1418280ece0SPetr Hosek RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames, 1428280ece0SPetr 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 { 1728280ece0SPetr Hosek SmallString<256> P; 1738280ece0SPetr Hosek if (!CompilationDir.empty()) 1748280ece0SPetr Hosek P.assign(CompilationDir); 1758280ece0SPetr Hosek else 1768280ece0SPetr Hosek P.assign(CWD); 1775fbd1a33SPetr Hosek llvm::sys::path::append(P, Filename); 1780204fd25SPetr Hosek sys::path::remove_dots(P, /*remove_dot_dot=*/true); 1790204fd25SPetr Hosek Filenames.push_back(static_cast<std::string>(P.str())); 1805fbd1a33SPetr Hosek } 1815fbd1a33SPetr Hosek } 182dc707122SEaswaran Raman } 1839152fd17SVedant Kumar return Error::success(); 184dc707122SEaswaran Raman } 185dc707122SEaswaran Raman 1869152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 187dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 188dc707122SEaswaran Raman switch (Tag) { 189dc707122SEaswaran Raman case Counter::Zero: 190dc707122SEaswaran Raman C = Counter::getZero(); 1919152fd17SVedant Kumar return Error::success(); 192dc707122SEaswaran Raman case Counter::CounterValueReference: 193dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 1949152fd17SVedant Kumar return Error::success(); 195dc707122SEaswaran Raman default: 196dc707122SEaswaran Raman break; 197dc707122SEaswaran Raman } 198dc707122SEaswaran Raman Tag -= Counter::Expression; 199dc707122SEaswaran Raman switch (Tag) { 200dc707122SEaswaran Raman case CounterExpression::Subtract: 201dc707122SEaswaran Raman case CounterExpression::Add: { 202dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 203dc707122SEaswaran Raman if (ID >= Expressions.size()) 2049152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 205dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 206dc707122SEaswaran Raman C = Counter::getExpression(ID); 207dc707122SEaswaran Raman break; 208dc707122SEaswaran Raman } 209dc707122SEaswaran Raman default: 2109152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 211dc707122SEaswaran Raman } 2129152fd17SVedant Kumar return Error::success(); 213dc707122SEaswaran Raman } 214dc707122SEaswaran Raman 2159152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 216dc707122SEaswaran Raman uint64_t EncodedCounter; 217dc707122SEaswaran Raman if (auto Err = 218dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 219dc707122SEaswaran Raman return Err; 220dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 221dc707122SEaswaran Raman return Err; 2229152fd17SVedant Kumar return Error::success(); 223dc707122SEaswaran Raman } 224dc707122SEaswaran Raman 225dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 226dc707122SEaswaran Raman << Counter::EncodingTagBits; 227dc707122SEaswaran Raman 2285f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id. 229dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 230dc707122SEaswaran Raman /// function. 2319152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 232dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 233dc707122SEaswaran Raman size_t NumFileIDs) { 234dc707122SEaswaran Raman uint64_t NumRegions; 235dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 236dc707122SEaswaran Raman return Err; 237dc707122SEaswaran Raman unsigned LineStart = 0; 238dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 2399f2967bcSAlan Phipps Counter C, C2; 240dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 241dc707122SEaswaran Raman 242dc707122SEaswaran Raman // Read the combined counter + region kind. 243dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 244dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 245dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 246dc707122SEaswaran Raman return Err; 247dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 248dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 2499f2967bcSAlan Phipps 2509f2967bcSAlan Phipps // If Tag does not represent a ZeroCounter, then it is understood to refer 2519f2967bcSAlan Phipps // to a counter or counter expression with region kind assumed to be 2529f2967bcSAlan Phipps // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the 2539f2967bcSAlan Phipps // referenced counter or counter expression (and nothing else). 2549f2967bcSAlan Phipps // 2559f2967bcSAlan Phipps // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set, 2569f2967bcSAlan Phipps // then EncodedCounterAndRegion is interpreted to represent an 2579f2967bcSAlan Phipps // ExpansionRegion. In all other cases, EncodedCounterAndRegion is 2589f2967bcSAlan Phipps // interpreted to refer to a specific region kind, after which additional 2599f2967bcSAlan Phipps // fields may be read (e.g. BranchRegions have two encoded counters that 2609f2967bcSAlan Phipps // follow an encoded region kind value). 261dc707122SEaswaran Raman if (Tag != Counter::Zero) { 262dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 263dc707122SEaswaran Raman return Err; 264dc707122SEaswaran Raman } else { 265dc707122SEaswaran Raman // Is it an expansion region? 266dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 267dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 268dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 269dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 270dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 2719152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 272dc707122SEaswaran Raman } else { 273dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 274dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 275dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 276dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 277dc707122SEaswaran Raman break; 278dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 279dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 280dc707122SEaswaran Raman break; 2819f2967bcSAlan Phipps case CounterMappingRegion::BranchRegion: 2829f2967bcSAlan Phipps // For a Branch Region, read two successive counters. 2839f2967bcSAlan Phipps Kind = CounterMappingRegion::BranchRegion; 2849f2967bcSAlan Phipps if (auto Err = readCounter(C)) 2859f2967bcSAlan Phipps return Err; 2869f2967bcSAlan Phipps if (auto Err = readCounter(C2)) 2879f2967bcSAlan Phipps return Err; 2889f2967bcSAlan Phipps break; 289dc707122SEaswaran Raman default: 2909152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 291dc707122SEaswaran Raman } 292dc707122SEaswaran Raman } 293dc707122SEaswaran Raman } 294dc707122SEaswaran Raman 295dc707122SEaswaran Raman // Read the source range. 296dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 297dc707122SEaswaran Raman if (auto Err = 298dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 299dc707122SEaswaran Raman return Err; 300dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 301dc707122SEaswaran Raman return Err; 302dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 3039152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 304dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 305dc707122SEaswaran Raman return Err; 306dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 307dc707122SEaswaran Raman return Err; 308dc707122SEaswaran Raman LineStart += LineStartDelta; 309ad8f637bSVedant Kumar 310ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 311ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 312ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 313ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 314ad8f637bSVedant Kumar } 315ad8f637bSVedant Kumar 316dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 317dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 318dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 319dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 320dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 321dc707122SEaswaran Raman // column end take up one byte each. 322dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 323dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 324dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 325dc707122SEaswaran Raman ColumnStart = 1; 326dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 327dc707122SEaswaran Raman } 328dc707122SEaswaran Raman 329d34e60caSNicola Zaghen LLVM_DEBUG({ 330dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 331dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 332dc707122SEaswaran Raman << ColumnEnd << ", "; 333dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 334dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 335dc707122SEaswaran Raman else 336dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 337dc707122SEaswaran Raman dbgs() << "\n"; 338dc707122SEaswaran Raman }); 339dc707122SEaswaran Raman 3409f2967bcSAlan Phipps auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID, 341bae83970SVedant Kumar LineStart, ColumnStart, 342bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 343bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 344bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 345bae83970SVedant Kumar MappingRegions.push_back(CMR); 346dc707122SEaswaran Raman } 3479152fd17SVedant Kumar return Error::success(); 348dc707122SEaswaran Raman } 349dc707122SEaswaran Raman 3509152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 351dc707122SEaswaran Raman // Read the virtual file mapping. 352e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 353dc707122SEaswaran Raman uint64_t NumFileMappings; 354dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 355dc707122SEaswaran Raman return Err; 356dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 357dc707122SEaswaran Raman uint64_t FilenameIndex; 358dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 359dc707122SEaswaran Raman return Err; 360dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 361dc707122SEaswaran Raman } 362dc707122SEaswaran Raman 363dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 364dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 365dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 366dc707122SEaswaran Raman } 367dc707122SEaswaran Raman 368dc707122SEaswaran Raman // Read the expressions. 369dc707122SEaswaran Raman uint64_t NumExpressions; 370dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 371dc707122SEaswaran Raman return Err; 372dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 373dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 374dc707122SEaswaran Raman // are decoded. 375dc707122SEaswaran Raman Expressions.resize( 376dc707122SEaswaran Raman NumExpressions, 377dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 378dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 379dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 380dc707122SEaswaran Raman return Err; 381dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 382dc707122SEaswaran Raman return Err; 383dc707122SEaswaran Raman } 384dc707122SEaswaran Raman 385dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 386dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 387dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 388dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 389dc707122SEaswaran Raman VirtualFileMapping.size())) 390dc707122SEaswaran Raman return Err; 391dc707122SEaswaran Raman } 392dc707122SEaswaran Raman 393dc707122SEaswaran Raman // Set the counters for the expansion regions. 394dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 395dc707122SEaswaran Raman // from the expanded file. 396dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 397dc707122SEaswaran Raman // all the nested expansion regions. 398dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 399dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 400dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 401dc707122SEaswaran Raman for (auto &R : MappingRegions) { 402dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 403dc707122SEaswaran Raman continue; 404dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 405dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 406dc707122SEaswaran Raman } 407dc707122SEaswaran Raman for (auto &R : MappingRegions) { 408dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 409dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 410dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 411dc707122SEaswaran Raman } 412dc707122SEaswaran Raman } 413dc707122SEaswaran Raman } 414dc707122SEaswaran Raman 4159152fd17SVedant Kumar return Error::success(); 416dc707122SEaswaran Raman } 417dc707122SEaswaran Raman 418ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 419ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 420ac40e819SIgor Kudrin uint64_t NumFileMappings; 421ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 422c55cf4afSBill Wendling return std::move(Err); 423ac40e819SIgor Kudrin if (NumFileMappings != 1) 424ac40e819SIgor Kudrin return false; 425ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 426ac40e819SIgor Kudrin uint64_t FilenameIndex; 427ac40e819SIgor Kudrin if (Error Err = 428ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 429c55cf4afSBill Wendling return std::move(Err); 430ac40e819SIgor Kudrin uint64_t NumExpressions; 431ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 432c55cf4afSBill Wendling return std::move(Err); 433ac40e819SIgor Kudrin if (NumExpressions != 0) 434ac40e819SIgor Kudrin return false; 435ac40e819SIgor Kudrin uint64_t NumRegions; 436ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 437c55cf4afSBill Wendling return std::move(Err); 438ac40e819SIgor Kudrin if (NumRegions != 1) 439ac40e819SIgor Kudrin return false; 440ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 441ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 442ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 443c55cf4afSBill Wendling return std::move(Err); 444ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 445ac40e819SIgor Kudrin return Tag == Counter::Zero; 446ac40e819SIgor Kudrin } 447ac40e819SIgor Kudrin 4489152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 449e183340cSFangrui Song Expected<StringRef> DataOrErr = Section.getContents(); 450e183340cSFangrui Song if (!DataOrErr) 451e183340cSFangrui Song return DataOrErr.takeError(); 452e183340cSFangrui Song Data = *DataOrErr; 453dc707122SEaswaran Raman Address = Section.getAddress(); 4548b6af001SReid Kleckner 4558b6af001SReid Kleckner // If this is a linked PE/COFF file, then we have to skip over the null byte 4568b6af001SReid Kleckner // that is allocated in the .lprfn$A section in the LLVM profiling runtime. 4578b6af001SReid Kleckner const ObjectFile *Obj = Section.getObject(); 4588b6af001SReid Kleckner if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) 4598b6af001SReid Kleckner Data = Data.drop_front(1); 4608b6af001SReid Kleckner 4619152fd17SVedant Kumar return Error::success(); 462dc707122SEaswaran Raman } 463dc707122SEaswaran Raman 464dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 465dc707122SEaswaran Raman if (Pointer < Address) 466dc707122SEaswaran Raman return StringRef(); 467dc707122SEaswaran Raman auto Offset = Pointer - Address; 468dc707122SEaswaran Raman if (Offset + Size > Data.size()) 469dc707122SEaswaran Raman return StringRef(); 470dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 471dc707122SEaswaran Raman } 472dc707122SEaswaran Raman 473ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 474ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 475ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 476ac40e819SIgor Kudrin if (Hash) 477ac40e819SIgor Kudrin return false; 478ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 479ac40e819SIgor Kudrin } 480ac40e819SIgor Kudrin 481dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of 482dd1ea9deSVedant Kumar /// filenames in a vector-like container. 483dd1ea9deSVedant Kumar struct FilenameRange { 484dd1ea9deSVedant Kumar unsigned StartingIndex; 485dd1ea9deSVedant Kumar unsigned Length; 486dd1ea9deSVedant Kumar 487dd1ea9deSVedant Kumar FilenameRange(unsigned StartingIndex, unsigned Length) 488dd1ea9deSVedant Kumar : StartingIndex(StartingIndex), Length(Length) {} 489dd1ea9deSVedant Kumar 490dd1ea9deSVedant Kumar void markInvalid() { Length = 0; } 491dd1ea9deSVedant Kumar bool isInvalid() const { return Length == 0; } 492dd1ea9deSVedant Kumar }; 493dd1ea9deSVedant Kumar 494dc707122SEaswaran Raman namespace { 495e78d131aSEugene Zelenko 496dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module. 497dc707122SEaswaran Raman struct CovMapFuncRecordReader { 498e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 499e78d131aSEugene Zelenko 500dd1ea9deSVedant Kumar // Read a coverage header. 5013739b95dSVedant Kumar // 502dd1ea9deSVedant Kumar // \p CovBuf points to the buffer containing the \c CovHeader of the coverage 5033739b95dSVedant Kumar // mapping data associated with the module. 5043739b95dSVedant Kumar // 505dd1ea9deSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or to an address 506dd1ea9deSVedant Kumar // greater than \p CovEnd if not. 5075fbd1a33SPetr Hosek virtual Expected<const char *> readCoverageHeader(const char *CovBuf, 5085fbd1a33SPetr Hosek const char *CovBufEnd) = 0; 509dd1ea9deSVedant Kumar 510dd1ea9deSVedant Kumar // Read function records. 511dd1ea9deSVedant Kumar // 512dd1ea9deSVedant Kumar // \p FuncRecBuf points to the buffer containing a batch of function records. 513dd1ea9deSVedant Kumar // \p FuncRecBufEnd points past the end of the batch of records. 514dd1ea9deSVedant Kumar // 515dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 516dd1ea9deSVedant Kumar // associated with the function records. It is unused in Version4. 517dd1ea9deSVedant Kumar // 518dd1ea9deSVedant Kumar // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 519dd1ea9deSVedant Kumar // mappings associated with the function records. It is unused in Version4. 520dd1ea9deSVedant Kumar virtual Error readFunctionRecords(const char *FuncRecBuf, 521dd1ea9deSVedant Kumar const char *FuncRecBufEnd, 522dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 523dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 524dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) = 0; 525e78d131aSEugene Zelenko 526dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 5279152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 528e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 5298280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 5305fbd1a33SPetr Hosek std::vector<std::string> &F); 531dc707122SEaswaran Raman }; 532dc707122SEaswaran Raman 533dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 534e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 535dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 53672208a82SEugene Zelenko using FuncRecordType = 53772208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 53872208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 539dc707122SEaswaran Raman 540ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 541ac40e819SIgor Kudrin // in \c Records. 542e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 543dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 5448280ece0SPetr Hosek StringRef CompilationDir; 5455fbd1a33SPetr Hosek std::vector<std::string> &Filenames; 546dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 547dc707122SEaswaran Raman 548dd1ea9deSVedant Kumar // Maps a hash of the filenames in a TU to a \c FileRange. The range 549dd1ea9deSVedant Kumar // specifies the location of the hashed filenames in \c Filenames. 550dd1ea9deSVedant Kumar DenseMap<uint64_t, FilenameRange> FileRangeMap; 551dd1ea9deSVedant Kumar 552ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 553ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 554ac40e819SIgor Kudrin // records for the functions with ODR linkage. 555ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 556ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 557ac40e819SIgor Kudrin // not used in the corresponding translation unit. 558ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 559dd1ea9deSVedant Kumar StringRef Mapping, 560dd1ea9deSVedant Kumar FilenameRange FileRange) { 561dd1ea9deSVedant Kumar ++CovMapNumRecords; 562ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 563ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 564ac40e819SIgor Kudrin auto InsertResult = 565ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 566ac40e819SIgor Kudrin if (InsertResult.second) { 567ac40e819SIgor Kudrin StringRef FuncName; 568ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 569ac40e819SIgor Kudrin return Err; 570b5794ca9SVedant Kumar if (FuncName.empty()) 571ee88b8d6SGulfem Savrun Yeniceri return make_error<InstrProfError>(instrprof_error::malformed, 572ee88b8d6SGulfem Savrun Yeniceri "function name is empty"); 573dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 574dd1ea9deSVedant Kumar Records.emplace_back(Version, FuncName, FuncHash, Mapping, 575dd1ea9deSVedant Kumar FileRange.StartingIndex, FileRange.Length); 576ac40e819SIgor Kudrin return Error::success(); 577ac40e819SIgor Kudrin } 578ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 579ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 580ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 581ac40e819SIgor Kudrin Records[OldRecordIndex]; 582ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 583ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 584ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 585ac40e819SIgor Kudrin return Err; 586ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 587ac40e819SIgor Kudrin return Error::success(); 588ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 589ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 590ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 591ac40e819SIgor Kudrin return Err; 592ac40e819SIgor Kudrin if (*NewIsDummyExpected) 593ac40e819SIgor Kudrin return Error::success(); 594dd1ea9deSVedant Kumar ++CovMapNumUsedRecords; 595ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 596ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 597dd1ea9deSVedant Kumar OldRecord.FilenamesBegin = FileRange.StartingIndex; 598dd1ea9deSVedant Kumar OldRecord.FilenamesSize = FileRange.Length; 599ac40e819SIgor Kudrin return Error::success(); 600ac40e819SIgor Kudrin } 601ac40e819SIgor Kudrin 602dc707122SEaswaran Raman public: 603dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 604dc707122SEaswaran Raman InstrProfSymtab &P, 6058280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 6065fbd1a33SPetr Hosek std::vector<std::string> &F) 6078280ece0SPetr Hosek : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {} 608e78d131aSEugene Zelenko 609e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 610dc707122SEaswaran Raman 6115fbd1a33SPetr Hosek Expected<const char *> readCoverageHeader(const char *CovBuf, 6125fbd1a33SPetr Hosek const char *CovBufEnd) override { 613dc707122SEaswaran Raman using namespace support; 614e78d131aSEugene Zelenko 615dd1ea9deSVedant Kumar if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) 6169152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 617dd1ea9deSVedant Kumar auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); 618dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 619dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 620dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 621dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 622dd1ea9deSVedant Kumar CovBuf = reinterpret_cast<const char *>(CovHeader + 1); 623dc707122SEaswaran Raman 624dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 625dd1ea9deSVedant Kumar // This is a no-op in Version4 (function records are read after all headers 626dd1ea9deSVedant Kumar // are read). 627dd1ea9deSVedant Kumar const char *FuncRecBuf = nullptr; 628dd1ea9deSVedant Kumar const char *FuncRecBufEnd = nullptr; 629dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 630dd1ea9deSVedant Kumar FuncRecBuf = CovBuf; 631dd1ea9deSVedant Kumar CovBuf += NRecords * sizeof(FuncRecordType); 632dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 633dd1ea9deSVedant Kumar FuncRecBufEnd = CovBuf; 634dc707122SEaswaran Raman 635dc707122SEaswaran Raman // Get the filenames. 636dd1ea9deSVedant Kumar if (CovBuf + FilenamesSize > CovBufEnd) 6379152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 638dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 639dd1ea9deSVedant Kumar StringRef FilenameRegion(CovBuf, FilenamesSize); 6408280ece0SPetr Hosek RawCoverageFilenamesReader Reader(FilenameRegion, Filenames, 6418280ece0SPetr Hosek CompilationDir); 6425fbd1a33SPetr Hosek if (auto Err = Reader.read(Version)) 643c55cf4afSBill Wendling return std::move(Err); 644dd1ea9deSVedant Kumar CovBuf += FilenamesSize; 645dd1ea9deSVedant Kumar FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin); 646dd1ea9deSVedant Kumar 6479f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) { 648dd1ea9deSVedant Kumar // Map a hash of the filenames region to the filename range associated 649dd1ea9deSVedant Kumar // with this coverage header. 650dd1ea9deSVedant Kumar int64_t FilenamesRef = 651dd1ea9deSVedant Kumar llvm::IndexedInstrProf::ComputeHash(FilenameRegion); 652dd1ea9deSVedant Kumar auto Insert = 653dd1ea9deSVedant Kumar FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange)); 654dd1ea9deSVedant Kumar if (!Insert.second) { 655dd1ea9deSVedant Kumar // The same filenames ref was encountered twice. It's possible that 656dd1ea9deSVedant Kumar // the associated filenames are the same. 657dd1ea9deSVedant Kumar auto It = Filenames.begin(); 658dd1ea9deSVedant Kumar FilenameRange &OrigRange = Insert.first->getSecond(); 659dd1ea9deSVedant Kumar if (std::equal(It + OrigRange.StartingIndex, 660dd1ea9deSVedant Kumar It + OrigRange.StartingIndex + OrigRange.Length, 661dd1ea9deSVedant Kumar It + FileRange.StartingIndex, 662dd1ea9deSVedant Kumar It + FileRange.StartingIndex + FileRange.Length)) 663dd1ea9deSVedant Kumar // Map the new range to the original one. 664dd1ea9deSVedant Kumar FileRange = OrigRange; 665dd1ea9deSVedant Kumar else 666dd1ea9deSVedant Kumar // This is a hash collision. Mark the filenames ref invalid. 667dd1ea9deSVedant Kumar OrigRange.markInvalid(); 668dd1ea9deSVedant Kumar } 669dd1ea9deSVedant Kumar } 670dc707122SEaswaran Raman 671dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 672dd1ea9deSVedant Kumar // This is a no-op in Version4 (coverage mappings are not affixed to the 673dd1ea9deSVedant Kumar // coverage header). 674dd1ea9deSVedant Kumar const char *MappingBuf = CovBuf; 6759f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && CoverageSize != 0) 6769152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 677dd1ea9deSVedant Kumar CovBuf += CoverageSize; 678dd1ea9deSVedant Kumar const char *MappingEnd = CovBuf; 679dd1ea9deSVedant Kumar 680dd1ea9deSVedant Kumar if (CovBuf > CovBufEnd) 681dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 682dd1ea9deSVedant Kumar 683dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 684dd1ea9deSVedant Kumar // Read each function record. 685dd1ea9deSVedant Kumar if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange, 686dd1ea9deSVedant Kumar MappingBuf, MappingEnd)) 687dd1ea9deSVedant Kumar return std::move(E); 688dd1ea9deSVedant Kumar } 689dd1ea9deSVedant Kumar 690dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 691dc707122SEaswaran Raman // before reading the next map. 692dd1ea9deSVedant Kumar CovBuf += offsetToAlignedAddr(CovBuf, Align(8)); 693dc707122SEaswaran Raman 694dd1ea9deSVedant Kumar return CovBuf; 69599317124SVedant Kumar } 696dd1ea9deSVedant Kumar 697dd1ea9deSVedant Kumar Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd, 698dd1ea9deSVedant Kumar Optional<FilenameRange> OutOfLineFileRange, 699dd1ea9deSVedant Kumar const char *OutOfLineMappingBuf, 700dd1ea9deSVedant Kumar const char *OutOfLineMappingBufEnd) override { 701dd1ea9deSVedant Kumar auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf); 702dd1ea9deSVedant Kumar while ((const char *)CFR < FuncRecBufEnd) { 703dd1ea9deSVedant Kumar // Validate the length of the coverage mapping for this function. 704dd1ea9deSVedant Kumar const char *NextMappingBuf; 705dd1ea9deSVedant Kumar const FuncRecordType *NextCFR; 706dd1ea9deSVedant Kumar std::tie(NextMappingBuf, NextCFR) = 707dd1ea9deSVedant Kumar CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); 708dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) 709dd1ea9deSVedant Kumar if (NextMappingBuf > OutOfLineMappingBufEnd) 710dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 711dd1ea9deSVedant Kumar 712dd1ea9deSVedant Kumar // Look up the set of filenames associated with this function record. 713dd1ea9deSVedant Kumar Optional<FilenameRange> FileRange; 714dd1ea9deSVedant Kumar if (Version < CovMapVersion::Version4) { 715dd1ea9deSVedant Kumar FileRange = OutOfLineFileRange; 716dd1ea9deSVedant Kumar } else { 717dd1ea9deSVedant Kumar uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); 718dd1ea9deSVedant Kumar auto It = FileRangeMap.find(FilenamesRef); 719dd1ea9deSVedant Kumar if (It == FileRangeMap.end()) 720dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 721dd1ea9deSVedant Kumar else 722dd1ea9deSVedant Kumar FileRange = It->getSecond(); 723dd1ea9deSVedant Kumar } 724dd1ea9deSVedant Kumar 725dd1ea9deSVedant Kumar // Now, read the coverage data. 726dd1ea9deSVedant Kumar if (FileRange && !FileRange->isInvalid()) { 727dd1ea9deSVedant Kumar StringRef Mapping = 728dd1ea9deSVedant Kumar CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); 7299f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4 && 730dd1ea9deSVedant Kumar Mapping.data() + Mapping.size() > FuncRecBufEnd) 731dd1ea9deSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 732dd1ea9deSVedant Kumar if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) 733dd1ea9deSVedant Kumar return Err; 734dd1ea9deSVedant Kumar } 735dd1ea9deSVedant Kumar 736dd1ea9deSVedant Kumar std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR); 737dd1ea9deSVedant Kumar } 738dd1ea9deSVedant Kumar return Error::success(); 739dc707122SEaswaran Raman } 740dc707122SEaswaran Raman }; 741e78d131aSEugene Zelenko 742dc707122SEaswaran Raman } // end anonymous namespace 743dc707122SEaswaran Raman 744dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 7459152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 746e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 7478280ece0SPetr Hosek std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, 7485fbd1a33SPetr Hosek std::vector<std::string> &F) { 749dc707122SEaswaran Raman using namespace coverage; 750e78d131aSEugene Zelenko 751dc707122SEaswaran Raman switch (Version) { 752dc707122SEaswaran Raman case CovMapVersion::Version1: 7530eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 7548280ece0SPetr Hosek CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F); 755dc707122SEaswaran Raman case CovMapVersion::Version2: 756ad8f637bSVedant Kumar case CovMapVersion::Version3: 757dd1ea9deSVedant Kumar case CovMapVersion::Version4: 7589f2967bcSAlan Phipps case CovMapVersion::Version5: 7595fbd1a33SPetr Hosek case CovMapVersion::Version6: 760dc707122SEaswaran Raman // Decompress the name data. 7619152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 762c55cf4afSBill Wendling return std::move(E); 763ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 7640eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 7658280ece0SPetr Hosek CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F); 766dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version3) 7670eaee545SJonas Devlieghere return std::make_unique<VersionedCovMapFuncRecordReader< 7688280ece0SPetr Hosek CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F); 769dd1ea9deSVedant Kumar else if (Version == CovMapVersion::Version4) 770dd1ea9deSVedant Kumar return std::make_unique<VersionedCovMapFuncRecordReader< 7718280ece0SPetr Hosek CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F); 7729f2967bcSAlan Phipps else if (Version == CovMapVersion::Version5) 7739f2967bcSAlan Phipps return std::make_unique<VersionedCovMapFuncRecordReader< 7748280ece0SPetr Hosek CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F); 7755fbd1a33SPetr Hosek else if (Version == CovMapVersion::Version6) 7765fbd1a33SPetr Hosek return std::make_unique<VersionedCovMapFuncRecordReader< 7778280ece0SPetr Hosek CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F); 778dc707122SEaswaran Raman } 779dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 780dc707122SEaswaran Raman } 781dc707122SEaswaran Raman 782dc707122SEaswaran Raman template <typename T, support::endianness Endian> 7839152fd17SVedant Kumar static Error readCoverageMappingData( 784dd1ea9deSVedant Kumar InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, 785dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 7868280ece0SPetr Hosek StringRef CompilationDir, std::vector<std::string> &Filenames) { 787dc707122SEaswaran Raman using namespace coverage; 788e78d131aSEugene Zelenko 789dc707122SEaswaran Raman // Read the records in the coverage data section. 790dc707122SEaswaran Raman auto CovHeader = 791dd1ea9deSVedant Kumar reinterpret_cast<const CovMapHeader *>(CovMap.data()); 792dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 793e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 7949152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 7959152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 796dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 7978280ece0SPetr Hosek CompilationDir, Filenames); 7989152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 7999152fd17SVedant Kumar return E; 8009152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 801dd1ea9deSVedant Kumar const char *CovBuf = CovMap.data(); 802dd1ea9deSVedant Kumar const char *CovBufEnd = CovBuf + CovMap.size(); 803dd1ea9deSVedant Kumar const char *FuncRecBuf = FuncRecords.data(); 804dd1ea9deSVedant Kumar const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size(); 805dd1ea9deSVedant Kumar while (CovBuf < CovBufEnd) { 806dd1ea9deSVedant Kumar // Read the current coverage header & filename data. 807dd1ea9deSVedant Kumar // 808dd1ea9deSVedant Kumar // Prior to Version4, this also reads all function records affixed to the 809dd1ea9deSVedant Kumar // header. 810dd1ea9deSVedant Kumar // 811dd1ea9deSVedant Kumar // Return a pointer to the next coverage header. 8125fbd1a33SPetr Hosek auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd); 813dd1ea9deSVedant Kumar if (auto E = NextOrErr.takeError()) 8149152fd17SVedant Kumar return E; 815dd1ea9deSVedant Kumar CovBuf = NextOrErr.get(); 816dc707122SEaswaran Raman } 817dd1ea9deSVedant Kumar // In Version4, function records are not affixed to coverage headers. Read 818dd1ea9deSVedant Kumar // the records from their dedicated section. 8199f2967bcSAlan Phipps if (Version >= CovMapVersion::Version4) 820dd1ea9deSVedant Kumar return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr, 821dd1ea9deSVedant Kumar nullptr); 8229152fd17SVedant Kumar return Error::success(); 823dc707122SEaswaran Raman } 824e78d131aSEugene Zelenko 825dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 826dc707122SEaswaran Raman 827901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 828901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer( 829effc3339Sserge-sans-paille StringRef Coverage, FuncRecordsStorage &&FuncRecords, 8308280ece0SPetr Hosek InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, 8318280ece0SPetr Hosek support::endianness Endian, StringRef CompilationDir) { 83280cd518bSVedant Kumar std::unique_ptr<BinaryCoverageReader> Reader( 83380cd518bSVedant Kumar new BinaryCoverageReader(std::move(FuncRecords))); 834901d04fcSVedant Kumar Reader->ProfileNames = std::move(ProfileNames); 835effc3339Sserge-sans-paille StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer(); 836901d04fcSVedant Kumar if (BytesInAddress == 4 && Endian == support::endianness::little) { 837901d04fcSVedant Kumar if (Error E = 838901d04fcSVedant Kumar readCoverageMappingData<uint32_t, support::endianness::little>( 83980cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8408280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 841c55cf4afSBill Wendling return std::move(E); 842901d04fcSVedant Kumar } else if (BytesInAddress == 4 && Endian == support::endianness::big) { 843901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( 84480cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8458280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 846c55cf4afSBill Wendling return std::move(E); 847901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::little) { 848901d04fcSVedant Kumar if (Error E = 849901d04fcSVedant Kumar readCoverageMappingData<uint64_t, support::endianness::little>( 85080cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8518280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 852c55cf4afSBill Wendling return std::move(E); 853901d04fcSVedant Kumar } else if (BytesInAddress == 8 && Endian == support::endianness::big) { 854901d04fcSVedant Kumar if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( 85580cd518bSVedant Kumar Reader->ProfileNames, Coverage, FuncRecordsRef, 8568280ece0SPetr Hosek Reader->MappingRecords, CompilationDir, Reader->Filenames)) 857c55cf4afSBill Wendling return std::move(E); 858901d04fcSVedant Kumar } else 859901d04fcSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 860c55cf4afSBill Wendling return std::move(Reader); 861901d04fcSVedant Kumar } 862901d04fcSVedant Kumar 863901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 8648280ece0SPetr Hosek loadTestingFormat(StringRef Data, StringRef CompilationDir) { 865901d04fcSVedant Kumar uint8_t BytesInAddress = 8; 866901d04fcSVedant Kumar support::endianness Endian = support::endianness::little; 867dc707122SEaswaran Raman 868dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 86972208a82SEugene Zelenko if (Data.empty()) 8709152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 871dc707122SEaswaran Raman unsigned N = 0; 8726a0746a9SFangrui Song uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); 873dc707122SEaswaran Raman if (N > Data.size()) 8749152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 875dc707122SEaswaran Raman Data = Data.substr(N); 87672208a82SEugene Zelenko if (Data.empty()) 8779152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 878dc707122SEaswaran Raman N = 0; 8796a0746a9SFangrui Song uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); 880dc707122SEaswaran Raman if (N > Data.size()) 8819152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 882dc707122SEaswaran Raman Data = Data.substr(N); 883dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 8849152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 885901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 8869152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 887c55cf4afSBill Wendling return std::move(E); 888489a3531SPetr Hosek Data = Data.substr(ProfileNamesSize); 889eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 890489a3531SPetr Hosek size_t Pad = offsetToAlignedAddr(Data.data(), Align(8)); 891489a3531SPetr Hosek if (Data.size() < Pad) 892489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 893489a3531SPetr Hosek Data = Data.substr(Pad); 894489a3531SPetr Hosek if (Data.size() < sizeof(CovMapHeader)) 895489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::malformed); 896489a3531SPetr Hosek auto const *CovHeader = reinterpret_cast<const CovMapHeader *>( 897489a3531SPetr Hosek Data.substr(0, sizeof(CovMapHeader)).data()); 898489a3531SPetr Hosek CovMapVersion Version = 899489a3531SPetr Hosek (CovMapVersion)CovHeader->getVersion<support::endianness::little>(); 900effc3339Sserge-sans-paille StringRef CoverageMapping; 901effc3339Sserge-sans-paille BinaryCoverageReader::FuncRecordsStorage CoverageRecords; 902489a3531SPetr Hosek if (Version < CovMapVersion::Version4) { 903489a3531SPetr Hosek CoverageMapping = Data; 90472208a82SEugene Zelenko if (CoverageMapping.empty()) 9059152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 906effc3339Sserge-sans-paille CoverageRecords = MemoryBuffer::getMemBuffer(""); 907489a3531SPetr Hosek } else { 908489a3531SPetr Hosek uint32_t FilenamesSize = 909489a3531SPetr Hosek CovHeader->getFilenamesSize<support::endianness::little>(); 910489a3531SPetr Hosek uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; 911489a3531SPetr Hosek CoverageMapping = Data.substr(0, CoverageMappingSize); 912489a3531SPetr Hosek if (CoverageMapping.empty()) 913489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 914489a3531SPetr Hosek Data = Data.substr(CoverageMappingSize); 915489a3531SPetr Hosek // Skip the padding bytes because coverage records data has an alignment 916489a3531SPetr Hosek // of 8. 917489a3531SPetr Hosek Pad = offsetToAlignedAddr(Data.data(), Align(8)); 918489a3531SPetr Hosek if (Data.size() < Pad) 9199152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 920effc3339Sserge-sans-paille CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad)); 921effc3339Sserge-sans-paille if (CoverageRecords->getBufferSize() == 0) 922489a3531SPetr Hosek return make_error<CoverageMapError>(coveragemap_error::truncated); 923489a3531SPetr Hosek } 924901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 925effc3339Sserge-sans-paille CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames), 9268280ece0SPetr Hosek BytesInAddress, Endian, CompilationDir); 927dc707122SEaswaran Raman } 928dc707122SEaswaran Raman 92980cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats 93080cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF. 93180cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, 93280cd518bSVedant Kumar StringRef Name) { 9338b6af001SReid Kleckner // On COFF, the object file section name may end in "$M". This tells the 9348b6af001SReid Kleckner // linker to sort these sections between "$A" and "$Z". The linker removes the 9358b6af001SReid Kleckner // dollar and everything after it in the final binary. Do the same to match. 9368b6af001SReid Kleckner bool IsCOFF = isa<COFFObjectFile>(OF); 9378b6af001SReid Kleckner auto stripSuffix = [IsCOFF](StringRef N) { 9388b6af001SReid Kleckner return IsCOFF ? N.split('$').first : N; 9398b6af001SReid Kleckner }; 9408b6af001SReid Kleckner Name = stripSuffix(Name); 9418b6af001SReid Kleckner 94280cd518bSVedant Kumar std::vector<SectionRef> Sections; 943dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 944bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 945bcc00e1aSGeorge Rimar if (!NameOrErr) 946bcc00e1aSGeorge Rimar return NameOrErr.takeError(); 947bcc00e1aSGeorge Rimar if (stripSuffix(*NameOrErr) == Name) 94880cd518bSVedant Kumar Sections.push_back(Section); 949dc707122SEaswaran Raman } 95080cd518bSVedant Kumar if (Sections.empty()) 9519152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 95280cd518bSVedant Kumar return Sections; 953dc707122SEaswaran Raman } 954dc707122SEaswaran Raman 955901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>> 9568280ece0SPetr Hosek loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, 9578280ece0SPetr Hosek StringRef CompilationDir = "") { 958dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 959e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 960dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 961dc707122SEaswaran Raman // appropriate architecture. 9624fd11c1eSAlexander Shaposhnikov auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); 9639acb1099SKevin Enderby if (!ObjectFileOrErr) 9649acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 965dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 966e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 967dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 968e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 969dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 970dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 9719152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 972dc707122SEaswaran Raman } else 973dc707122SEaswaran Raman // We can only handle object files. 9749152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 975dc707122SEaswaran Raman 976dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 977901d04fcSVedant Kumar uint8_t BytesInAddress = OF->getBytesInAddress(); 978901d04fcSVedant Kumar support::endianness Endian = OF->isLittleEndian() 979901d04fcSVedant Kumar ? support::endianness::little 980dc707122SEaswaran Raman : support::endianness::big; 981dc707122SEaswaran Raman 982dc707122SEaswaran Raman // Look for the sections that we are interested in. 9831a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 9844a5ddf80SXinliang David Li auto NamesSection = 98580cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 9861a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9879152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 988c55cf4afSBill Wendling return std::move(E); 9894a5ddf80SXinliang David Li auto CoverageSection = 99080cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 9911a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 9929152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 993c55cf4afSBill Wendling return std::move(E); 99480cd518bSVedant Kumar std::vector<SectionRef> CoverageSectionRefs = *CoverageSection; 99580cd518bSVedant Kumar if (CoverageSectionRefs.size() != 1) 99680cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 99780cd518bSVedant Kumar auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); 998901d04fcSVedant Kumar if (!CoverageMappingOrErr) 999901d04fcSVedant Kumar return CoverageMappingOrErr.takeError(); 1000dd1ea9deSVedant Kumar StringRef CoverageMapping = CoverageMappingOrErr.get(); 1001e183340cSFangrui Song 1002901d04fcSVedant Kumar InstrProfSymtab ProfileNames; 100380cd518bSVedant Kumar std::vector<SectionRef> NamesSectionRefs = *NamesSection; 100480cd518bSVedant Kumar if (NamesSectionRefs.size() != 1) 100580cd518bSVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 100680cd518bSVedant Kumar if (Error E = ProfileNames.create(NamesSectionRefs.back())) 1007c55cf4afSBill Wendling return std::move(E); 1008dc707122SEaswaran Raman 1009dd1ea9deSVedant Kumar // Look for the coverage records section (Version4 only). 101080cd518bSVedant Kumar auto CoverageRecordsSections = 101180cd518bSVedant Kumar lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, 1012dd1ea9deSVedant Kumar /*AddSegmentInfo=*/false)); 1013effc3339Sserge-sans-paille 1014effc3339Sserge-sans-paille BinaryCoverageReader::FuncRecordsStorage FuncRecords; 1015effc3339Sserge-sans-paille if (auto E = CoverageRecordsSections.takeError()) { 1016dd1ea9deSVedant Kumar consumeError(std::move(E)); 1017effc3339Sserge-sans-paille FuncRecords = MemoryBuffer::getMemBuffer(""); 1018effc3339Sserge-sans-paille } else { 1019effc3339Sserge-sans-paille // Compute the FuncRecordsBuffer of the buffer, taking into account the 1020effc3339Sserge-sans-paille // padding between each record, and making sure the first block is aligned 1021effc3339Sserge-sans-paille // in memory to maintain consistency between buffer address and size 1022effc3339Sserge-sans-paille // alignment. 1023effc3339Sserge-sans-paille const Align RecordAlignment(8); 1024effc3339Sserge-sans-paille uint64_t FuncRecordsSize = 0; 102580cd518bSVedant Kumar for (SectionRef Section : *CoverageRecordsSections) { 102680cd518bSVedant Kumar auto CoverageRecordsOrErr = Section.getContents(); 1027dd1ea9deSVedant Kumar if (!CoverageRecordsOrErr) 1028dd1ea9deSVedant Kumar return CoverageRecordsOrErr.takeError(); 1029effc3339Sserge-sans-paille FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment); 103080cd518bSVedant Kumar } 1031effc3339Sserge-sans-paille auto WritableBuffer = 1032effc3339Sserge-sans-paille WritableMemoryBuffer::getNewUninitMemBuffer(FuncRecordsSize); 1033effc3339Sserge-sans-paille char *FuncRecordsBuffer = WritableBuffer->getBufferStart(); 1034effc3339Sserge-sans-paille assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) && 1035effc3339Sserge-sans-paille "Allocated memory is correctly aligned"); 1036effc3339Sserge-sans-paille 1037effc3339Sserge-sans-paille for (SectionRef Section : *CoverageRecordsSections) { 1038effc3339Sserge-sans-paille auto CoverageRecordsOrErr = Section.getContents(); 1039effc3339Sserge-sans-paille if (!CoverageRecordsOrErr) 1040effc3339Sserge-sans-paille return CoverageRecordsOrErr.takeError(); 1041effc3339Sserge-sans-paille const auto &CoverageRecords = CoverageRecordsOrErr.get(); 1042effc3339Sserge-sans-paille FuncRecordsBuffer = std::copy(CoverageRecords.begin(), 1043effc3339Sserge-sans-paille CoverageRecords.end(), FuncRecordsBuffer); 1044effc3339Sserge-sans-paille FuncRecordsBuffer = 1045effc3339Sserge-sans-paille std::fill_n(FuncRecordsBuffer, 1046effc3339Sserge-sans-paille alignAddr(FuncRecordsBuffer, RecordAlignment) - 1047effc3339Sserge-sans-paille (uintptr_t)FuncRecordsBuffer, 1048effc3339Sserge-sans-paille '\0'); 1049effc3339Sserge-sans-paille } 1050effc3339Sserge-sans-paille assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() && 1051effc3339Sserge-sans-paille "consistent init"); 1052effc3339Sserge-sans-paille FuncRecords = std::move(WritableBuffer); 1053dd1ea9deSVedant Kumar } 1054dd1ea9deSVedant Kumar 1055901d04fcSVedant Kumar return BinaryCoverageReader::createCoverageReaderFromBuffer( 105680cd518bSVedant Kumar CoverageMapping, std::move(FuncRecords), std::move(ProfileNames), 10578280ece0SPetr Hosek BytesInAddress, Endian, CompilationDir); 1058dc707122SEaswaran Raman } 1059dc707122SEaswaran Raman 10607fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin. 10617fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) { 10627fafaa07SVedant Kumar // If we have a universal binary and Arch doesn't identify any of its slices, 10637fafaa07SVedant Kumar // it's user error. 10647fafaa07SVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) { 10657fafaa07SVedant Kumar for (auto &ObjForArch : Universal->objects()) 10667fafaa07SVedant Kumar if (Arch == ObjForArch.getArchFlagName()) 10677fafaa07SVedant Kumar return false; 10687fafaa07SVedant Kumar return true; 10697fafaa07SVedant Kumar } 10707fafaa07SVedant Kumar return false; 10717fafaa07SVedant Kumar } 10727fafaa07SVedant Kumar 1073901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 1074901d04fcSVedant Kumar BinaryCoverageReader::create( 1075901d04fcSVedant Kumar MemoryBufferRef ObjectBuffer, StringRef Arch, 10768280ece0SPetr Hosek SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers, 10778280ece0SPetr Hosek StringRef CompilationDir) { 1078901d04fcSVedant Kumar std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; 1079dc707122SEaswaran Raman 1080901d04fcSVedant Kumar if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { 1081dc707122SEaswaran Raman // This is a special format used for testing. 10828280ece0SPetr Hosek auto ReaderOrErr = 10838280ece0SPetr Hosek loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir); 1084901d04fcSVedant Kumar if (!ReaderOrErr) 1085901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1086901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1087c55cf4afSBill Wendling return std::move(Readers); 1088901d04fcSVedant Kumar } 1089dc707122SEaswaran Raman 1090901d04fcSVedant Kumar auto BinOrErr = createBinary(ObjectBuffer); 1091901d04fcSVedant Kumar if (!BinOrErr) 1092901d04fcSVedant Kumar return BinOrErr.takeError(); 1093901d04fcSVedant Kumar std::unique_ptr<Binary> Bin = std::move(BinOrErr.get()); 1094901d04fcSVedant Kumar 10957fafaa07SVedant Kumar if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch)) 10967fafaa07SVedant Kumar return make_error<CoverageMapError>( 10977fafaa07SVedant Kumar coveragemap_error::invalid_or_missing_arch_specifier); 10987fafaa07SVedant Kumar 1099901d04fcSVedant Kumar // MachO universal binaries which contain archives need to be treated as 1100901d04fcSVedant Kumar // archives, not as regular binaries. 1101901d04fcSVedant Kumar if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 1102901d04fcSVedant Kumar for (auto &ObjForArch : Universal->objects()) { 1103901d04fcSVedant Kumar // Skip slices within the universal binary which target the wrong arch. 1104901d04fcSVedant Kumar std::string ObjArch = ObjForArch.getArchFlagName(); 1105901d04fcSVedant Kumar if (Arch != ObjArch) 1106901d04fcSVedant Kumar continue; 1107901d04fcSVedant Kumar 1108901d04fcSVedant Kumar auto ArchiveOrErr = ObjForArch.getAsArchive(); 1109901d04fcSVedant Kumar if (!ArchiveOrErr) { 1110901d04fcSVedant Kumar // If this is not an archive, try treating it as a regular object. 1111901d04fcSVedant Kumar consumeError(ArchiveOrErr.takeError()); 1112901d04fcSVedant Kumar break; 1113901d04fcSVedant Kumar } 1114901d04fcSVedant Kumar 1115901d04fcSVedant Kumar return BinaryCoverageReader::create( 11168280ece0SPetr Hosek ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers, 11178280ece0SPetr Hosek CompilationDir); 1118901d04fcSVedant Kumar } 1119901d04fcSVedant Kumar } 1120901d04fcSVedant Kumar 1121901d04fcSVedant Kumar // Load coverage out of archive members. 1122901d04fcSVedant Kumar if (auto *Ar = dyn_cast<Archive>(Bin.get())) { 1123901d04fcSVedant Kumar Error Err = Error::success(); 1124901d04fcSVedant Kumar for (auto &Child : Ar->children(Err)) { 1125901d04fcSVedant Kumar Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef(); 1126901d04fcSVedant Kumar if (!ChildBufOrErr) 1127901d04fcSVedant Kumar return ChildBufOrErr.takeError(); 1128901d04fcSVedant Kumar 1129901d04fcSVedant Kumar auto ChildReadersOrErr = BinaryCoverageReader::create( 11308280ece0SPetr Hosek ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir); 1131901d04fcSVedant Kumar if (!ChildReadersOrErr) 1132901d04fcSVedant Kumar return ChildReadersOrErr.takeError(); 1133901d04fcSVedant Kumar for (auto &Reader : ChildReadersOrErr.get()) 1134901d04fcSVedant Kumar Readers.push_back(std::move(Reader)); 1135901d04fcSVedant Kumar } 1136901d04fcSVedant Kumar if (Err) 1137c55cf4afSBill Wendling return std::move(Err); 1138901d04fcSVedant Kumar 1139901d04fcSVedant Kumar // Thin archives reference object files outside of the archive file, i.e. 1140901d04fcSVedant Kumar // files which reside in memory not owned by the caller. Transfer ownership 1141901d04fcSVedant Kumar // to the caller. 1142901d04fcSVedant Kumar if (Ar->isThin()) 1143901d04fcSVedant Kumar for (auto &Buffer : Ar->takeThinBuffers()) 1144901d04fcSVedant Kumar ObjectFileBuffers.push_back(std::move(Buffer)); 1145901d04fcSVedant Kumar 1146c55cf4afSBill Wendling return std::move(Readers); 1147901d04fcSVedant Kumar } 1148901d04fcSVedant Kumar 11498280ece0SPetr Hosek auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir); 1150901d04fcSVedant Kumar if (!ReaderOrErr) 1151901d04fcSVedant Kumar return ReaderOrErr.takeError(); 1152901d04fcSVedant Kumar Readers.push_back(std::move(ReaderOrErr.get())); 1153c55cf4afSBill Wendling return std::move(Readers); 1154dc707122SEaswaran Raman } 1155dc707122SEaswaran Raman 11569152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 1157dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 11589152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 1159dc707122SEaswaran Raman 1160dc707122SEaswaran Raman FunctionsFilenames.clear(); 1161dc707122SEaswaran Raman Expressions.clear(); 1162dc707122SEaswaran Raman MappingRegions.clear(); 1163dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 11645fbd1a33SPetr Hosek auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize); 11655fbd1a33SPetr Hosek RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames, 11665fbd1a33SPetr Hosek Expressions, MappingRegions); 1167dc707122SEaswaran Raman if (auto Err = Reader.read()) 1168dc707122SEaswaran Raman return Err; 1169dc707122SEaswaran Raman 1170dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 1171dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 1172dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 1173dc707122SEaswaran Raman Record.Expressions = Expressions; 1174dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 1175dc707122SEaswaran Raman 1176dc707122SEaswaran Raman ++CurrentRecord; 11779152fd17SVedant Kumar return Error::success(); 1178dc707122SEaswaran Raman } 1179