172208a82SEugene Zelenko //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===// 2dc707122SEaswaran Raman // 3dc707122SEaswaran Raman // The LLVM Compiler Infrastructure 4dc707122SEaswaran Raman // 5dc707122SEaswaran Raman // This file is distributed under the University of Illinois Open Source 6dc707122SEaswaran Raman // License. See LICENSE.TXT for details. 7dc707122SEaswaran Raman // 8dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 9dc707122SEaswaran Raman // 10dc707122SEaswaran Raman // This file contains support for reading coverage mapping data for 11dc707122SEaswaran Raman // instrumentation based coverage. 12dc707122SEaswaran Raman // 13dc707122SEaswaran Raman //===----------------------------------------------------------------------===// 14dc707122SEaswaran Raman 154a5ddf80SXinliang David Li #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 16e78d131aSEugene Zelenko #include "llvm/ADT/ArrayRef.h" 17ac40e819SIgor Kudrin #include "llvm/ADT/DenseMap.h" 18e78d131aSEugene Zelenko #include "llvm/ADT/STLExtras.h" 194a5ddf80SXinliang David Li #include "llvm/ADT/SmallVector.h" 20e78d131aSEugene Zelenko #include "llvm/ADT/StringRef.h" 21e78d131aSEugene Zelenko #include "llvm/ADT/Triple.h" 22e78d131aSEugene Zelenko #include "llvm/Object/Binary.h" 234a5ddf80SXinliang David Li #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" 29dc707122SEaswaran Raman #include "llvm/Support/Debug.h" 304a5ddf80SXinliang David Li #include "llvm/Support/Endian.h" 31e78d131aSEugene Zelenko #include "llvm/Support/Error.h" 32e78d131aSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 33dc707122SEaswaran Raman #include "llvm/Support/LEB128.h" 34dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h" 35dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 36e78d131aSEugene Zelenko #include <algorithm> 37e78d131aSEugene Zelenko #include <cassert> 38e78d131aSEugene Zelenko #include <cstddef> 39e78d131aSEugene Zelenko #include <cstdint> 40e78d131aSEugene Zelenko #include <limits> 41e78d131aSEugene Zelenko #include <memory> 42e78d131aSEugene Zelenko #include <utility> 43e78d131aSEugene Zelenko #include <vector> 44dc707122SEaswaran Raman 45dc707122SEaswaran Raman using namespace llvm; 46dc707122SEaswaran Raman using namespace coverage; 47dc707122SEaswaran Raman using namespace object; 48dc707122SEaswaran Raman 49dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 50dc707122SEaswaran Raman 51dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 52bae83970SVedant Kumar if (ReadErr != coveragemap_error::success) 53bae83970SVedant Kumar return; 54bae83970SVedant Kumar 55dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 56dc707122SEaswaran Raman // the next record. 57bae83970SVedant Kumar if (auto E = Reader->readNextRecord(Record)) 589152fd17SVedant Kumar handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 599152fd17SVedant Kumar if (CME.get() == coveragemap_error::eof) 60dc707122SEaswaran Raman *this = CoverageMappingIterator(); 619152fd17SVedant Kumar else 62bae83970SVedant Kumar ReadErr = CME.get(); 639152fd17SVedant Kumar }); 649152fd17SVedant Kumar } 65dc707122SEaswaran Raman 669152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) { 6772208a82SEugene Zelenko if (Data.empty()) 689152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 69dc707122SEaswaran Raman unsigned N = 0; 70dc707122SEaswaran Raman Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 71dc707122SEaswaran Raman if (N > Data.size()) 729152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 73dc707122SEaswaran Raman Data = Data.substr(N); 749152fd17SVedant Kumar return Error::success(); 75dc707122SEaswaran Raman } 76dc707122SEaswaran Raman 779152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { 78dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 79dc707122SEaswaran Raman return Err; 80dc707122SEaswaran Raman if (Result >= MaxPlus1) 819152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 829152fd17SVedant Kumar return Error::success(); 83dc707122SEaswaran Raman } 84dc707122SEaswaran Raman 859152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) { 86dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 87dc707122SEaswaran Raman return Err; 88dc707122SEaswaran Raman // Sanity check the number. 89dc707122SEaswaran Raman if (Result > Data.size()) 909152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 919152fd17SVedant Kumar return Error::success(); 92dc707122SEaswaran Raman } 93dc707122SEaswaran Raman 949152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) { 95dc707122SEaswaran Raman uint64_t Length; 96dc707122SEaswaran Raman if (auto Err = readSize(Length)) 97dc707122SEaswaran Raman return Err; 98dc707122SEaswaran Raman Result = Data.substr(0, Length); 99dc707122SEaswaran Raman Data = Data.substr(Length); 1009152fd17SVedant Kumar return Error::success(); 101dc707122SEaswaran Raman } 102dc707122SEaswaran Raman 1039152fd17SVedant Kumar Error RawCoverageFilenamesReader::read() { 104dc707122SEaswaran Raman uint64_t NumFilenames; 105dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 106dc707122SEaswaran Raman return Err; 107dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 108dc707122SEaswaran Raman StringRef Filename; 109dc707122SEaswaran Raman if (auto Err = readString(Filename)) 110dc707122SEaswaran Raman return Err; 111dc707122SEaswaran Raman Filenames.push_back(Filename); 112dc707122SEaswaran Raman } 1139152fd17SVedant Kumar return Error::success(); 114dc707122SEaswaran Raman } 115dc707122SEaswaran Raman 1169152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 117dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 118dc707122SEaswaran Raman switch (Tag) { 119dc707122SEaswaran Raman case Counter::Zero: 120dc707122SEaswaran Raman C = Counter::getZero(); 1219152fd17SVedant Kumar return Error::success(); 122dc707122SEaswaran Raman case Counter::CounterValueReference: 123dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 1249152fd17SVedant Kumar return Error::success(); 125dc707122SEaswaran Raman default: 126dc707122SEaswaran Raman break; 127dc707122SEaswaran Raman } 128dc707122SEaswaran Raman Tag -= Counter::Expression; 129dc707122SEaswaran Raman switch (Tag) { 130dc707122SEaswaran Raman case CounterExpression::Subtract: 131dc707122SEaswaran Raman case CounterExpression::Add: { 132dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 133dc707122SEaswaran Raman if (ID >= Expressions.size()) 1349152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 135dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 136dc707122SEaswaran Raman C = Counter::getExpression(ID); 137dc707122SEaswaran Raman break; 138dc707122SEaswaran Raman } 139dc707122SEaswaran Raman default: 1409152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 141dc707122SEaswaran Raman } 1429152fd17SVedant Kumar return Error::success(); 143dc707122SEaswaran Raman } 144dc707122SEaswaran Raman 1459152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 146dc707122SEaswaran Raman uint64_t EncodedCounter; 147dc707122SEaswaran Raman if (auto Err = 148dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 149dc707122SEaswaran Raman return Err; 150dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 151dc707122SEaswaran Raman return Err; 1529152fd17SVedant Kumar return Error::success(); 153dc707122SEaswaran Raman } 154dc707122SEaswaran Raman 155dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 156dc707122SEaswaran Raman << Counter::EncodingTagBits; 157dc707122SEaswaran Raman 158dc707122SEaswaran Raman /// \brief Read the sub-array of regions for the given inferred file id. 159dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 160dc707122SEaswaran Raman /// function. 1619152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 162dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 163dc707122SEaswaran Raman size_t NumFileIDs) { 164dc707122SEaswaran Raman uint64_t NumRegions; 165dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 166dc707122SEaswaran Raman return Err; 167dc707122SEaswaran Raman unsigned LineStart = 0; 168dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 169dc707122SEaswaran Raman Counter C; 170dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 171dc707122SEaswaran Raman 172dc707122SEaswaran Raman // Read the combined counter + region kind. 173dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 174dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 175dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 176dc707122SEaswaran Raman return Err; 177dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 178dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 179dc707122SEaswaran Raman if (Tag != Counter::Zero) { 180dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 181dc707122SEaswaran Raman return Err; 182dc707122SEaswaran Raman } else { 183dc707122SEaswaran Raman // Is it an expansion region? 184dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 185dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 186dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 187dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 188dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 1899152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 190dc707122SEaswaran Raman } else { 191dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 192dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 193dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 194dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 195dc707122SEaswaran Raman break; 196dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 197dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 198dc707122SEaswaran Raman break; 199dc707122SEaswaran Raman default: 2009152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 201dc707122SEaswaran Raman } 202dc707122SEaswaran Raman } 203dc707122SEaswaran Raman } 204dc707122SEaswaran Raman 205dc707122SEaswaran Raman // Read the source range. 206dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 207dc707122SEaswaran Raman if (auto Err = 208dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 209dc707122SEaswaran Raman return Err; 210dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 211dc707122SEaswaran Raman return Err; 212dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 2139152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 214dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 215dc707122SEaswaran Raman return Err; 216dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 217dc707122SEaswaran Raman return Err; 218dc707122SEaswaran Raman LineStart += LineStartDelta; 219*ad8f637bSVedant Kumar 220*ad8f637bSVedant Kumar // If the high bit of ColumnEnd is set, this is a gap region. 221*ad8f637bSVedant Kumar if (ColumnEnd & (1U << 31)) { 222*ad8f637bSVedant Kumar Kind = CounterMappingRegion::GapRegion; 223*ad8f637bSVedant Kumar ColumnEnd &= ~(1U << 31); 224*ad8f637bSVedant Kumar } 225*ad8f637bSVedant Kumar 226dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 227dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 228dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 229dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 230dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 231dc707122SEaswaran Raman // column end take up one byte each. 232dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 233dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 234dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 235dc707122SEaswaran Raman ColumnStart = 1; 236dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 237dc707122SEaswaran Raman } 238dc707122SEaswaran Raman 239dc707122SEaswaran Raman DEBUG({ 240dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 241dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 242dc707122SEaswaran Raman << ColumnEnd << ", "; 243dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 244dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 245dc707122SEaswaran Raman else 246dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 247dc707122SEaswaran Raman dbgs() << "\n"; 248dc707122SEaswaran Raman }); 249dc707122SEaswaran Raman 250bae83970SVedant Kumar auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID, 251bae83970SVedant Kumar LineStart, ColumnStart, 252bae83970SVedant Kumar LineStart + NumLines, ColumnEnd, Kind); 253bae83970SVedant Kumar if (CMR.startLoc() > CMR.endLoc()) 254bae83970SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 255bae83970SVedant Kumar MappingRegions.push_back(CMR); 256dc707122SEaswaran Raman } 2579152fd17SVedant Kumar return Error::success(); 258dc707122SEaswaran Raman } 259dc707122SEaswaran Raman 2609152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 261dc707122SEaswaran Raman // Read the virtual file mapping. 262e78d131aSEugene Zelenko SmallVector<unsigned, 8> VirtualFileMapping; 263dc707122SEaswaran Raman uint64_t NumFileMappings; 264dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 265dc707122SEaswaran Raman return Err; 266dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 267dc707122SEaswaran Raman uint64_t FilenameIndex; 268dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 269dc707122SEaswaran Raman return Err; 270dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 271dc707122SEaswaran Raman } 272dc707122SEaswaran Raman 273dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 274dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 275dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 276dc707122SEaswaran Raman } 277dc707122SEaswaran Raman 278dc707122SEaswaran Raman // Read the expressions. 279dc707122SEaswaran Raman uint64_t NumExpressions; 280dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 281dc707122SEaswaran Raman return Err; 282dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 283dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 284dc707122SEaswaran Raman // are decoded. 285dc707122SEaswaran Raman Expressions.resize( 286dc707122SEaswaran Raman NumExpressions, 287dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 288dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 289dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 290dc707122SEaswaran Raman return Err; 291dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 292dc707122SEaswaran Raman return Err; 293dc707122SEaswaran Raman } 294dc707122SEaswaran Raman 295dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 296dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 297dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 298dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 299dc707122SEaswaran Raman VirtualFileMapping.size())) 300dc707122SEaswaran Raman return Err; 301dc707122SEaswaran Raman } 302dc707122SEaswaran Raman 303dc707122SEaswaran Raman // Set the counters for the expansion regions. 304dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 305dc707122SEaswaran Raman // from the expanded file. 306dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 307dc707122SEaswaran Raman // all the nested expansion regions. 308dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 309dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 310dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 311dc707122SEaswaran Raman for (auto &R : MappingRegions) { 312dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 313dc707122SEaswaran Raman continue; 314dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 315dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 316dc707122SEaswaran Raman } 317dc707122SEaswaran Raman for (auto &R : MappingRegions) { 318dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 319dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 320dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 321dc707122SEaswaran Raman } 322dc707122SEaswaran Raman } 323dc707122SEaswaran Raman } 324dc707122SEaswaran Raman 3259152fd17SVedant Kumar return Error::success(); 326dc707122SEaswaran Raman } 327dc707122SEaswaran Raman 328ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() { 329ac40e819SIgor Kudrin // A dummy coverage mapping data consists of just one region with zero count. 330ac40e819SIgor Kudrin uint64_t NumFileMappings; 331ac40e819SIgor Kudrin if (Error Err = readSize(NumFileMappings)) 332ac40e819SIgor Kudrin return std::move(Err); 333ac40e819SIgor Kudrin if (NumFileMappings != 1) 334ac40e819SIgor Kudrin return false; 335ac40e819SIgor Kudrin // We don't expect any specific value for the filename index, just skip it. 336ac40e819SIgor Kudrin uint64_t FilenameIndex; 337ac40e819SIgor Kudrin if (Error Err = 338ac40e819SIgor Kudrin readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) 339ac40e819SIgor Kudrin return std::move(Err); 340ac40e819SIgor Kudrin uint64_t NumExpressions; 341ac40e819SIgor Kudrin if (Error Err = readSize(NumExpressions)) 342ac40e819SIgor Kudrin return std::move(Err); 343ac40e819SIgor Kudrin if (NumExpressions != 0) 344ac40e819SIgor Kudrin return false; 345ac40e819SIgor Kudrin uint64_t NumRegions; 346ac40e819SIgor Kudrin if (Error Err = readSize(NumRegions)) 347ac40e819SIgor Kudrin return std::move(Err); 348ac40e819SIgor Kudrin if (NumRegions != 1) 349ac40e819SIgor Kudrin return false; 350ac40e819SIgor Kudrin uint64_t EncodedCounterAndRegion; 351ac40e819SIgor Kudrin if (Error Err = readIntMax(EncodedCounterAndRegion, 352ac40e819SIgor Kudrin std::numeric_limits<unsigned>::max())) 353ac40e819SIgor Kudrin return std::move(Err); 354ac40e819SIgor Kudrin unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 355ac40e819SIgor Kudrin return Tag == Counter::Zero; 356ac40e819SIgor Kudrin } 357ac40e819SIgor Kudrin 3589152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 3599152fd17SVedant Kumar if (auto EC = Section.getContents(Data)) 3609152fd17SVedant Kumar return errorCodeToError(EC); 361dc707122SEaswaran Raman Address = Section.getAddress(); 3629152fd17SVedant Kumar return Error::success(); 363dc707122SEaswaran Raman } 364dc707122SEaswaran Raman 365dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 366dc707122SEaswaran Raman if (Pointer < Address) 367dc707122SEaswaran Raman return StringRef(); 368dc707122SEaswaran Raman auto Offset = Pointer - Address; 369dc707122SEaswaran Raman if (Offset + Size > Data.size()) 370dc707122SEaswaran Raman return StringRef(); 371dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 372dc707122SEaswaran Raman } 373dc707122SEaswaran Raman 374ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function. 375ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { 376ac40e819SIgor Kudrin // The hash value of dummy mapping records is always zero. 377ac40e819SIgor Kudrin if (Hash) 378ac40e819SIgor Kudrin return false; 379ac40e819SIgor Kudrin return RawCoverageMappingDummyChecker(Mapping).isDummy(); 380ac40e819SIgor Kudrin } 381ac40e819SIgor Kudrin 382dc707122SEaswaran Raman namespace { 383e78d131aSEugene Zelenko 384dc707122SEaswaran Raman struct CovMapFuncRecordReader { 385e78d131aSEugene Zelenko virtual ~CovMapFuncRecordReader() = default; 386e78d131aSEugene Zelenko 3873739b95dSVedant Kumar // The interface to read coverage mapping function records for a module. 3883739b95dSVedant Kumar // 3893739b95dSVedant Kumar // \p Buf points to the buffer containing the \c CovHeader of the coverage 3903739b95dSVedant Kumar // mapping data associated with the module. 3913739b95dSVedant Kumar // 3923739b95dSVedant Kumar // Returns a pointer to the next \c CovHeader if it exists, or a pointer 3933739b95dSVedant Kumar // greater than \p End if not. 3943739b95dSVedant Kumar virtual Expected<const char *> readFunctionRecords(const char *Buf, 3953739b95dSVedant Kumar const char *End) = 0; 396e78d131aSEugene Zelenko 397dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 3989152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 399e78d131aSEugene Zelenko get(CovMapVersion Version, InstrProfSymtab &P, 400dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 401dc707122SEaswaran Raman std::vector<StringRef> &F); 402dc707122SEaswaran Raman }; 403dc707122SEaswaran Raman 404dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 405e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian> 406dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 40772208a82SEugene Zelenko using FuncRecordType = 40872208a82SEugene Zelenko typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; 40972208a82SEugene Zelenko using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; 410dc707122SEaswaran Raman 411ac40e819SIgor Kudrin // Maps function's name references to the indexes of their records 412ac40e819SIgor Kudrin // in \c Records. 413e78d131aSEugene Zelenko DenseMap<NameRefType, size_t> FunctionRecords; 414dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 415dc707122SEaswaran Raman std::vector<StringRef> &Filenames; 416dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 417dc707122SEaswaran Raman 418ac40e819SIgor Kudrin // Add the record to the collection if we don't already have a record that 419ac40e819SIgor Kudrin // points to the same function name. This is useful to ignore the redundant 420ac40e819SIgor Kudrin // records for the functions with ODR linkage. 421ac40e819SIgor Kudrin // In addition, prefer records with real coverage mapping data to dummy 422ac40e819SIgor Kudrin // records, which were emitted for inline functions which were seen but 423ac40e819SIgor Kudrin // not used in the corresponding translation unit. 424ac40e819SIgor Kudrin Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, 425ac40e819SIgor Kudrin StringRef Mapping, size_t FilenamesBegin) { 426ac40e819SIgor Kudrin uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 427ac40e819SIgor Kudrin NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 428ac40e819SIgor Kudrin auto InsertResult = 429ac40e819SIgor Kudrin FunctionRecords.insert(std::make_pair(NameRef, Records.size())); 430ac40e819SIgor Kudrin if (InsertResult.second) { 431ac40e819SIgor Kudrin StringRef FuncName; 432ac40e819SIgor Kudrin if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 433ac40e819SIgor Kudrin return Err; 434b5794ca9SVedant Kumar if (FuncName.empty()) 435b5794ca9SVedant Kumar return make_error<InstrProfError>(instrprof_error::malformed); 436ac40e819SIgor Kudrin Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin, 437ac40e819SIgor Kudrin Filenames.size() - FilenamesBegin); 438ac40e819SIgor Kudrin return Error::success(); 439ac40e819SIgor Kudrin } 440ac40e819SIgor Kudrin // Update the existing record if it's a dummy and the new record is real. 441ac40e819SIgor Kudrin size_t OldRecordIndex = InsertResult.first->second; 442ac40e819SIgor Kudrin BinaryCoverageReader::ProfileMappingRecord &OldRecord = 443ac40e819SIgor Kudrin Records[OldRecordIndex]; 444ac40e819SIgor Kudrin Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( 445ac40e819SIgor Kudrin OldRecord.FunctionHash, OldRecord.CoverageMapping); 446ac40e819SIgor Kudrin if (Error Err = OldIsDummyExpected.takeError()) 447ac40e819SIgor Kudrin return Err; 448ac40e819SIgor Kudrin if (!*OldIsDummyExpected) 449ac40e819SIgor Kudrin return Error::success(); 450ac40e819SIgor Kudrin Expected<bool> NewIsDummyExpected = 451ac40e819SIgor Kudrin isCoverageMappingDummy(FuncHash, Mapping); 452ac40e819SIgor Kudrin if (Error Err = NewIsDummyExpected.takeError()) 453ac40e819SIgor Kudrin return Err; 454ac40e819SIgor Kudrin if (*NewIsDummyExpected) 455ac40e819SIgor Kudrin return Error::success(); 456ac40e819SIgor Kudrin OldRecord.FunctionHash = FuncHash; 457ac40e819SIgor Kudrin OldRecord.CoverageMapping = Mapping; 458ac40e819SIgor Kudrin OldRecord.FilenamesBegin = FilenamesBegin; 459ac40e819SIgor Kudrin OldRecord.FilenamesSize = Filenames.size() - FilenamesBegin; 460ac40e819SIgor Kudrin return Error::success(); 461ac40e819SIgor Kudrin } 462ac40e819SIgor Kudrin 463dc707122SEaswaran Raman public: 464dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 465dc707122SEaswaran Raman InstrProfSymtab &P, 466dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 467dc707122SEaswaran Raman std::vector<StringRef> &F) 468dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 469e78d131aSEugene Zelenko 470e78d131aSEugene Zelenko ~VersionedCovMapFuncRecordReader() override = default; 471dc707122SEaswaran Raman 4723739b95dSVedant Kumar Expected<const char *> readFunctionRecords(const char *Buf, 4733739b95dSVedant Kumar const char *End) override { 474dc707122SEaswaran Raman using namespace support; 475e78d131aSEugene Zelenko 476dc707122SEaswaran Raman if (Buf + sizeof(CovMapHeader) > End) 4779152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 478e78d131aSEugene Zelenko auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf); 479dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 480dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 481dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 482dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 483dc707122SEaswaran Raman Buf = reinterpret_cast<const char *>(CovHeader + 1); 484dc707122SEaswaran Raman 485dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 486dc707122SEaswaran Raman const char *FunBuf = Buf; 487dc707122SEaswaran Raman Buf += NRecords * sizeof(FuncRecordType); 488dc707122SEaswaran Raman const char *FunEnd = Buf; 489dc707122SEaswaran Raman 490dc707122SEaswaran Raman // Get the filenames. 491dc707122SEaswaran Raman if (Buf + FilenamesSize > End) 4929152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 493dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 494dc707122SEaswaran Raman RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); 495dc707122SEaswaran Raman if (auto Err = Reader.read()) 4963739b95dSVedant Kumar return std::move(Err); 497dc707122SEaswaran Raman Buf += FilenamesSize; 498dc707122SEaswaran Raman 499dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 500dc707122SEaswaran Raman const char *CovBuf = Buf; 501dc707122SEaswaran Raman Buf += CoverageSize; 502dc707122SEaswaran Raman const char *CovEnd = Buf; 503dc707122SEaswaran Raman 504dc707122SEaswaran Raman if (Buf > End) 5059152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 506dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 507dc707122SEaswaran Raman // before reading the next map. 508dc707122SEaswaran Raman Buf += alignmentAdjustment(Buf, 8); 509dc707122SEaswaran Raman 510dc707122SEaswaran Raman auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf); 511dc707122SEaswaran Raman while ((const char *)CFR < FunEnd) { 512dc707122SEaswaran Raman // Read the function information 513dc707122SEaswaran Raman uint32_t DataSize = CFR->template getDataSize<Endian>(); 514dc707122SEaswaran Raman 515dc707122SEaswaran Raman // Now use that to read the coverage data. 516dc707122SEaswaran Raman if (CovBuf + DataSize > CovEnd) 5179152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 518dc707122SEaswaran Raman auto Mapping = StringRef(CovBuf, DataSize); 519dc707122SEaswaran Raman CovBuf += DataSize; 520dc707122SEaswaran Raman 521ac40e819SIgor Kudrin if (Error Err = 522ac40e819SIgor Kudrin insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin)) 5233739b95dSVedant Kumar return std::move(Err); 524dc707122SEaswaran Raman CFR++; 525dc707122SEaswaran Raman } 5263739b95dSVedant Kumar return Buf; 527dc707122SEaswaran Raman } 528dc707122SEaswaran Raman }; 529e78d131aSEugene Zelenko 530dc707122SEaswaran Raman } // end anonymous namespace 531dc707122SEaswaran Raman 532dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 5339152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 534e78d131aSEugene Zelenko CovMapVersion Version, InstrProfSymtab &P, 535dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 536dc707122SEaswaran Raman std::vector<StringRef> &F) { 537dc707122SEaswaran Raman using namespace coverage; 538e78d131aSEugene Zelenko 539dc707122SEaswaran Raman switch (Version) { 540dc707122SEaswaran Raman case CovMapVersion::Version1: 541dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 542dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 543dc707122SEaswaran Raman case CovMapVersion::Version2: 544*ad8f637bSVedant Kumar case CovMapVersion::Version3: 545dc707122SEaswaran Raman // Decompress the name data. 5469152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 5479152fd17SVedant Kumar return std::move(E); 548*ad8f637bSVedant Kumar if (Version == CovMapVersion::Version2) 549dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 550dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 551*ad8f637bSVedant Kumar else 552*ad8f637bSVedant Kumar return llvm::make_unique<VersionedCovMapFuncRecordReader< 553*ad8f637bSVedant Kumar CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); 554dc707122SEaswaran Raman } 555dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 556dc707122SEaswaran Raman } 557dc707122SEaswaran Raman 558dc707122SEaswaran Raman template <typename T, support::endianness Endian> 5599152fd17SVedant Kumar static Error readCoverageMappingData( 560dc707122SEaswaran Raman InstrProfSymtab &ProfileNames, StringRef Data, 561dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 562dc707122SEaswaran Raman std::vector<StringRef> &Filenames) { 563dc707122SEaswaran Raman using namespace coverage; 564e78d131aSEugene Zelenko 565dc707122SEaswaran Raman // Read the records in the coverage data section. 566dc707122SEaswaran Raman auto CovHeader = 567e78d131aSEugene Zelenko reinterpret_cast<const CovMapHeader *>(Data.data()); 568dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 569e78d131aSEugene Zelenko if (Version > CovMapVersion::CurrentVersion) 5709152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 5719152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 572dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 573dc707122SEaswaran Raman Filenames); 5749152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 5759152fd17SVedant Kumar return E; 5769152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 577dc707122SEaswaran Raman for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { 5783739b95dSVedant Kumar auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End); 5793739b95dSVedant Kumar if (auto E = NextHeaderOrErr.takeError()) 5809152fd17SVedant Kumar return E; 5813739b95dSVedant Kumar Buf = NextHeaderOrErr.get(); 582dc707122SEaswaran Raman } 5839152fd17SVedant Kumar return Error::success(); 584dc707122SEaswaran Raman } 585e78d131aSEugene Zelenko 586dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 587dc707122SEaswaran Raman 5889152fd17SVedant Kumar static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, 589dc707122SEaswaran Raman StringRef &CoverageMapping, 590dc707122SEaswaran Raman uint8_t &BytesInAddress, 591dc707122SEaswaran Raman support::endianness &Endian) { 592dc707122SEaswaran Raman BytesInAddress = 8; 593dc707122SEaswaran Raman Endian = support::endianness::little; 594dc707122SEaswaran Raman 595dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 59672208a82SEugene Zelenko if (Data.empty()) 5979152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 598dc707122SEaswaran Raman unsigned N = 0; 599dc707122SEaswaran Raman auto ProfileNamesSize = 600dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 601dc707122SEaswaran Raman if (N > Data.size()) 6029152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 603dc707122SEaswaran Raman Data = Data.substr(N); 60472208a82SEugene Zelenko if (Data.empty()) 6059152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 606dc707122SEaswaran Raman N = 0; 607dc707122SEaswaran Raman uint64_t Address = 608dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 609dc707122SEaswaran Raman if (N > Data.size()) 6109152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 611dc707122SEaswaran Raman Data = Data.substr(N); 612dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 6139152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 6149152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 6159152fd17SVedant Kumar return E; 616dc707122SEaswaran Raman CoverageMapping = Data.substr(ProfileNamesSize); 617eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 61872208a82SEugene Zelenko if (CoverageMapping.empty()) 6199152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 620eb103073SIgor Kudrin size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8); 621eb103073SIgor Kudrin if (CoverageMapping.size() < Pad) 6229152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 623eb103073SIgor Kudrin CoverageMapping = CoverageMapping.substr(Pad); 6249152fd17SVedant Kumar return Error::success(); 625dc707122SEaswaran Raman } 626dc707122SEaswaran Raman 6279152fd17SVedant Kumar static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { 628dc707122SEaswaran Raman StringRef FoundName; 629dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 630dc707122SEaswaran Raman if (auto EC = Section.getName(FoundName)) 6319152fd17SVedant Kumar return errorCodeToError(EC); 632dc707122SEaswaran Raman if (FoundName == Name) 633dc707122SEaswaran Raman return Section; 634dc707122SEaswaran Raman } 6359152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 636dc707122SEaswaran Raman } 637dc707122SEaswaran Raman 6389152fd17SVedant Kumar static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, 6399152fd17SVedant Kumar InstrProfSymtab &ProfileNames, 6409152fd17SVedant Kumar StringRef &CoverageMapping, 6419152fd17SVedant Kumar uint8_t &BytesInAddress, 642dc707122SEaswaran Raman support::endianness &Endian, StringRef Arch) { 643e78d131aSEugene Zelenko auto BinOrErr = createBinary(ObjectBuffer); 644dc707122SEaswaran Raman if (!BinOrErr) 6459152fd17SVedant Kumar return BinOrErr.takeError(); 646dc707122SEaswaran Raman auto Bin = std::move(BinOrErr.get()); 647dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 648e78d131aSEugene Zelenko if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { 649dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 650dc707122SEaswaran Raman // appropriate architecture. 651dc707122SEaswaran Raman auto ObjectFileOrErr = Universal->getObjectForArch(Arch); 6529acb1099SKevin Enderby if (!ObjectFileOrErr) 6539acb1099SKevin Enderby return ObjectFileOrErr.takeError(); 654dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 655e78d131aSEugene Zelenko } else if (isa<ObjectFile>(Bin.get())) { 656dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 657e78d131aSEugene Zelenko OF.reset(cast<ObjectFile>(Bin.release())); 658dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 659dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 6609152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 661dc707122SEaswaran Raman } else 662dc707122SEaswaran Raman // We can only handle object files. 6639152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 664dc707122SEaswaran Raman 665dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 666dc707122SEaswaran Raman BytesInAddress = OF->getBytesInAddress(); 667dc707122SEaswaran Raman Endian = OF->isLittleEndian() ? support::endianness::little 668dc707122SEaswaran Raman : support::endianness::big; 669dc707122SEaswaran Raman 670dc707122SEaswaran Raman // Look for the sections that we are interested in. 6711a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 6724a5ddf80SXinliang David Li auto NamesSection = 6731a6a2b64SVedant Kumar lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, 6741a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 6759152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 6769152fd17SVedant Kumar return E; 6774a5ddf80SXinliang David Li auto CoverageSection = 6781a6a2b64SVedant Kumar lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, 6791a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)); 6809152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 6819152fd17SVedant Kumar return E; 682dc707122SEaswaran Raman 683dc707122SEaswaran Raman // Get the contents of the given sections. 6849152fd17SVedant Kumar if (auto EC = CoverageSection->getContents(CoverageMapping)) 6859152fd17SVedant Kumar return errorCodeToError(EC); 6869152fd17SVedant Kumar if (Error E = ProfileNames.create(*NamesSection)) 6879152fd17SVedant Kumar return E; 688dc707122SEaswaran Raman 6899152fd17SVedant Kumar return Error::success(); 690dc707122SEaswaran Raman } 691dc707122SEaswaran Raman 6929152fd17SVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 693a30139d5SVedant Kumar BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, 694a30139d5SVedant Kumar StringRef Arch) { 695dc707122SEaswaran Raman std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); 696dc707122SEaswaran Raman 697dc707122SEaswaran Raman StringRef Coverage; 698dc707122SEaswaran Raman uint8_t BytesInAddress; 699dc707122SEaswaran Raman support::endianness Endian; 70041af4309SMehdi Amini Error E = Error::success(); 7019152fd17SVedant Kumar consumeError(std::move(E)); 702a30139d5SVedant Kumar if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) 703dc707122SEaswaran Raman // This is a special format used for testing. 704a30139d5SVedant Kumar E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames, 705dc707122SEaswaran Raman Coverage, BytesInAddress, Endian); 706dc707122SEaswaran Raman else 707a30139d5SVedant Kumar E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames, 708dc707122SEaswaran Raman Coverage, BytesInAddress, Endian, Arch); 7099152fd17SVedant Kumar if (E) 7109152fd17SVedant Kumar return std::move(E); 711dc707122SEaswaran Raman 712dc707122SEaswaran Raman if (BytesInAddress == 4 && Endian == support::endianness::little) 7139152fd17SVedant Kumar E = readCoverageMappingData<uint32_t, support::endianness::little>( 714dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 715dc707122SEaswaran Raman Reader->Filenames); 716dc707122SEaswaran Raman else if (BytesInAddress == 4 && Endian == support::endianness::big) 7179152fd17SVedant Kumar E = readCoverageMappingData<uint32_t, support::endianness::big>( 718dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 719dc707122SEaswaran Raman Reader->Filenames); 720dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::little) 7219152fd17SVedant Kumar E = readCoverageMappingData<uint64_t, support::endianness::little>( 722dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 723dc707122SEaswaran Raman Reader->Filenames); 724dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::big) 7259152fd17SVedant Kumar E = readCoverageMappingData<uint64_t, support::endianness::big>( 726dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 727dc707122SEaswaran Raman Reader->Filenames); 728dc707122SEaswaran Raman else 7299152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 7309152fd17SVedant Kumar if (E) 7319152fd17SVedant Kumar return std::move(E); 732dc707122SEaswaran Raman return std::move(Reader); 733dc707122SEaswaran Raman } 734dc707122SEaswaran Raman 7359152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 736dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 7379152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 738dc707122SEaswaran Raman 739dc707122SEaswaran Raman FunctionsFilenames.clear(); 740dc707122SEaswaran Raman Expressions.clear(); 741dc707122SEaswaran Raman MappingRegions.clear(); 742dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 743dc707122SEaswaran Raman RawCoverageMappingReader Reader( 744dc707122SEaswaran Raman R.CoverageMapping, 745dc707122SEaswaran Raman makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), 746dc707122SEaswaran Raman FunctionsFilenames, Expressions, MappingRegions); 747dc707122SEaswaran Raman if (auto Err = Reader.read()) 748dc707122SEaswaran Raman return Err; 749dc707122SEaswaran Raman 750dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 751dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 752dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 753dc707122SEaswaran Raman Record.Expressions = Expressions; 754dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 755dc707122SEaswaran Raman 756dc707122SEaswaran Raman ++CurrentRecord; 7579152fd17SVedant Kumar return Error::success(); 758dc707122SEaswaran Raman } 759