1dc707122SEaswaran Raman //=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// 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 15dc707122SEaswaran Raman #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 16dc707122SEaswaran Raman #include "llvm/ADT/DenseSet.h" 17dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h" 18dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.h" 19dc707122SEaswaran Raman #include "llvm/Support/Debug.h" 20dc707122SEaswaran Raman #include "llvm/Support/Endian.h" 21dc707122SEaswaran Raman #include "llvm/Support/LEB128.h" 22dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h" 23dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h" 24dc707122SEaswaran Raman 25dc707122SEaswaran Raman using namespace llvm; 26dc707122SEaswaran Raman using namespace coverage; 27dc707122SEaswaran Raman using namespace object; 28dc707122SEaswaran Raman 29dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping" 30dc707122SEaswaran Raman 31dc707122SEaswaran Raman void CoverageMappingIterator::increment() { 32dc707122SEaswaran Raman // Check if all the records were read or if an error occurred while reading 33dc707122SEaswaran Raman // the next record. 34*9152fd17SVedant Kumar if (auto E = Reader->readNextRecord(Record)) { 35*9152fd17SVedant Kumar handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 36*9152fd17SVedant Kumar if (CME.get() == coveragemap_error::eof) 37dc707122SEaswaran Raman *this = CoverageMappingIterator(); 38*9152fd17SVedant Kumar else 39*9152fd17SVedant Kumar llvm_unreachable("Unexpected error in coverage mapping iterator"); 40*9152fd17SVedant Kumar }); 41*9152fd17SVedant Kumar } 42dc707122SEaswaran Raman } 43dc707122SEaswaran Raman 44*9152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) { 45dc707122SEaswaran Raman if (Data.size() < 1) 46*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 47dc707122SEaswaran Raman unsigned N = 0; 48dc707122SEaswaran Raman Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 49dc707122SEaswaran Raman if (N > Data.size()) 50*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 51dc707122SEaswaran Raman Data = Data.substr(N); 52*9152fd17SVedant Kumar return Error::success(); 53dc707122SEaswaran Raman } 54dc707122SEaswaran Raman 55*9152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { 56dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 57dc707122SEaswaran Raman return Err; 58dc707122SEaswaran Raman if (Result >= MaxPlus1) 59*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 60*9152fd17SVedant Kumar return Error::success(); 61dc707122SEaswaran Raman } 62dc707122SEaswaran Raman 63*9152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) { 64dc707122SEaswaran Raman if (auto Err = readULEB128(Result)) 65dc707122SEaswaran Raman return Err; 66dc707122SEaswaran Raman // Sanity check the number. 67dc707122SEaswaran Raman if (Result > Data.size()) 68*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 69*9152fd17SVedant Kumar return Error::success(); 70dc707122SEaswaran Raman } 71dc707122SEaswaran Raman 72*9152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) { 73dc707122SEaswaran Raman uint64_t Length; 74dc707122SEaswaran Raman if (auto Err = readSize(Length)) 75dc707122SEaswaran Raman return Err; 76dc707122SEaswaran Raman Result = Data.substr(0, Length); 77dc707122SEaswaran Raman Data = Data.substr(Length); 78*9152fd17SVedant Kumar return Error::success(); 79dc707122SEaswaran Raman } 80dc707122SEaswaran Raman 81*9152fd17SVedant Kumar Error RawCoverageFilenamesReader::read() { 82dc707122SEaswaran Raman uint64_t NumFilenames; 83dc707122SEaswaran Raman if (auto Err = readSize(NumFilenames)) 84dc707122SEaswaran Raman return Err; 85dc707122SEaswaran Raman for (size_t I = 0; I < NumFilenames; ++I) { 86dc707122SEaswaran Raman StringRef Filename; 87dc707122SEaswaran Raman if (auto Err = readString(Filename)) 88dc707122SEaswaran Raman return Err; 89dc707122SEaswaran Raman Filenames.push_back(Filename); 90dc707122SEaswaran Raman } 91*9152fd17SVedant Kumar return Error::success(); 92dc707122SEaswaran Raman } 93dc707122SEaswaran Raman 94*9152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { 95dc707122SEaswaran Raman auto Tag = Value & Counter::EncodingTagMask; 96dc707122SEaswaran Raman switch (Tag) { 97dc707122SEaswaran Raman case Counter::Zero: 98dc707122SEaswaran Raman C = Counter::getZero(); 99*9152fd17SVedant Kumar return Error::success(); 100dc707122SEaswaran Raman case Counter::CounterValueReference: 101dc707122SEaswaran Raman C = Counter::getCounter(Value >> Counter::EncodingTagBits); 102*9152fd17SVedant Kumar return Error::success(); 103dc707122SEaswaran Raman default: 104dc707122SEaswaran Raman break; 105dc707122SEaswaran Raman } 106dc707122SEaswaran Raman Tag -= Counter::Expression; 107dc707122SEaswaran Raman switch (Tag) { 108dc707122SEaswaran Raman case CounterExpression::Subtract: 109dc707122SEaswaran Raman case CounterExpression::Add: { 110dc707122SEaswaran Raman auto ID = Value >> Counter::EncodingTagBits; 111dc707122SEaswaran Raman if (ID >= Expressions.size()) 112*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 113dc707122SEaswaran Raman Expressions[ID].Kind = CounterExpression::ExprKind(Tag); 114dc707122SEaswaran Raman C = Counter::getExpression(ID); 115dc707122SEaswaran Raman break; 116dc707122SEaswaran Raman } 117dc707122SEaswaran Raman default: 118*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 119dc707122SEaswaran Raman } 120*9152fd17SVedant Kumar return Error::success(); 121dc707122SEaswaran Raman } 122dc707122SEaswaran Raman 123*9152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) { 124dc707122SEaswaran Raman uint64_t EncodedCounter; 125dc707122SEaswaran Raman if (auto Err = 126dc707122SEaswaran Raman readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) 127dc707122SEaswaran Raman return Err; 128dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounter, C)) 129dc707122SEaswaran Raman return Err; 130*9152fd17SVedant Kumar return Error::success(); 131dc707122SEaswaran Raman } 132dc707122SEaswaran Raman 133dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1 134dc707122SEaswaran Raman << Counter::EncodingTagBits; 135dc707122SEaswaran Raman 136dc707122SEaswaran Raman /// \brief Read the sub-array of regions for the given inferred file id. 137dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this 138dc707122SEaswaran Raman /// function. 139*9152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray( 140dc707122SEaswaran Raman std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, 141dc707122SEaswaran Raman size_t NumFileIDs) { 142dc707122SEaswaran Raman uint64_t NumRegions; 143dc707122SEaswaran Raman if (auto Err = readSize(NumRegions)) 144dc707122SEaswaran Raman return Err; 145dc707122SEaswaran Raman unsigned LineStart = 0; 146dc707122SEaswaran Raman for (size_t I = 0; I < NumRegions; ++I) { 147dc707122SEaswaran Raman Counter C; 148dc707122SEaswaran Raman CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; 149dc707122SEaswaran Raman 150dc707122SEaswaran Raman // Read the combined counter + region kind. 151dc707122SEaswaran Raman uint64_t EncodedCounterAndRegion; 152dc707122SEaswaran Raman if (auto Err = readIntMax(EncodedCounterAndRegion, 153dc707122SEaswaran Raman std::numeric_limits<unsigned>::max())) 154dc707122SEaswaran Raman return Err; 155dc707122SEaswaran Raman unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; 156dc707122SEaswaran Raman uint64_t ExpandedFileID = 0; 157dc707122SEaswaran Raman if (Tag != Counter::Zero) { 158dc707122SEaswaran Raman if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) 159dc707122SEaswaran Raman return Err; 160dc707122SEaswaran Raman } else { 161dc707122SEaswaran Raman // Is it an expansion region? 162dc707122SEaswaran Raman if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { 163dc707122SEaswaran Raman Kind = CounterMappingRegion::ExpansionRegion; 164dc707122SEaswaran Raman ExpandedFileID = EncodedCounterAndRegion >> 165dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits; 166dc707122SEaswaran Raman if (ExpandedFileID >= NumFileIDs) 167*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 168dc707122SEaswaran Raman } else { 169dc707122SEaswaran Raman switch (EncodedCounterAndRegion >> 170dc707122SEaswaran Raman Counter::EncodingCounterTagAndExpansionRegionTagBits) { 171dc707122SEaswaran Raman case CounterMappingRegion::CodeRegion: 172dc707122SEaswaran Raman // Don't do anything when we have a code region with a zero counter. 173dc707122SEaswaran Raman break; 174dc707122SEaswaran Raman case CounterMappingRegion::SkippedRegion: 175dc707122SEaswaran Raman Kind = CounterMappingRegion::SkippedRegion; 176dc707122SEaswaran Raman break; 177dc707122SEaswaran Raman default: 178*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 179dc707122SEaswaran Raman } 180dc707122SEaswaran Raman } 181dc707122SEaswaran Raman } 182dc707122SEaswaran Raman 183dc707122SEaswaran Raman // Read the source range. 184dc707122SEaswaran Raman uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; 185dc707122SEaswaran Raman if (auto Err = 186dc707122SEaswaran Raman readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) 187dc707122SEaswaran Raman return Err; 188dc707122SEaswaran Raman if (auto Err = readULEB128(ColumnStart)) 189dc707122SEaswaran Raman return Err; 190dc707122SEaswaran Raman if (ColumnStart > std::numeric_limits<unsigned>::max()) 191*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 192dc707122SEaswaran Raman if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) 193dc707122SEaswaran Raman return Err; 194dc707122SEaswaran Raman if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) 195dc707122SEaswaran Raman return Err; 196dc707122SEaswaran Raman LineStart += LineStartDelta; 197dc707122SEaswaran Raman // Adjust the column locations for the empty regions that are supposed to 198dc707122SEaswaran Raman // cover whole lines. Those regions should be encoded with the 199dc707122SEaswaran Raman // column range (1 -> std::numeric_limits<unsigned>::max()), but because 200dc707122SEaswaran Raman // the encoded std::numeric_limits<unsigned>::max() is several bytes long, 201dc707122SEaswaran Raman // we set the column range to (0 -> 0) to ensure that the column start and 202dc707122SEaswaran Raman // column end take up one byte each. 203dc707122SEaswaran Raman // The std::numeric_limits<unsigned>::max() is used to represent a column 204dc707122SEaswaran Raman // position at the end of the line without knowing the length of that line. 205dc707122SEaswaran Raman if (ColumnStart == 0 && ColumnEnd == 0) { 206dc707122SEaswaran Raman ColumnStart = 1; 207dc707122SEaswaran Raman ColumnEnd = std::numeric_limits<unsigned>::max(); 208dc707122SEaswaran Raman } 209dc707122SEaswaran Raman 210dc707122SEaswaran Raman DEBUG({ 211dc707122SEaswaran Raman dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" 212dc707122SEaswaran Raman << ColumnStart << " -> " << (LineStart + NumLines) << ":" 213dc707122SEaswaran Raman << ColumnEnd << ", "; 214dc707122SEaswaran Raman if (Kind == CounterMappingRegion::ExpansionRegion) 215dc707122SEaswaran Raman dbgs() << "Expands to file " << ExpandedFileID; 216dc707122SEaswaran Raman else 217dc707122SEaswaran Raman CounterMappingContext(Expressions).dump(C, dbgs()); 218dc707122SEaswaran Raman dbgs() << "\n"; 219dc707122SEaswaran Raman }); 220dc707122SEaswaran Raman 221dc707122SEaswaran Raman MappingRegions.push_back(CounterMappingRegion( 222dc707122SEaswaran Raman C, InferredFileID, ExpandedFileID, LineStart, ColumnStart, 223dc707122SEaswaran Raman LineStart + NumLines, ColumnEnd, Kind)); 224dc707122SEaswaran Raman } 225*9152fd17SVedant Kumar return Error::success(); 226dc707122SEaswaran Raman } 227dc707122SEaswaran Raman 228*9152fd17SVedant Kumar Error RawCoverageMappingReader::read() { 229dc707122SEaswaran Raman 230dc707122SEaswaran Raman // Read the virtual file mapping. 231dc707122SEaswaran Raman llvm::SmallVector<unsigned, 8> VirtualFileMapping; 232dc707122SEaswaran Raman uint64_t NumFileMappings; 233dc707122SEaswaran Raman if (auto Err = readSize(NumFileMappings)) 234dc707122SEaswaran Raman return Err; 235dc707122SEaswaran Raman for (size_t I = 0; I < NumFileMappings; ++I) { 236dc707122SEaswaran Raman uint64_t FilenameIndex; 237dc707122SEaswaran Raman if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) 238dc707122SEaswaran Raman return Err; 239dc707122SEaswaran Raman VirtualFileMapping.push_back(FilenameIndex); 240dc707122SEaswaran Raman } 241dc707122SEaswaran Raman 242dc707122SEaswaran Raman // Construct the files using unique filenames and virtual file mapping. 243dc707122SEaswaran Raman for (auto I : VirtualFileMapping) { 244dc707122SEaswaran Raman Filenames.push_back(TranslationUnitFilenames[I]); 245dc707122SEaswaran Raman } 246dc707122SEaswaran Raman 247dc707122SEaswaran Raman // Read the expressions. 248dc707122SEaswaran Raman uint64_t NumExpressions; 249dc707122SEaswaran Raman if (auto Err = readSize(NumExpressions)) 250dc707122SEaswaran Raman return Err; 251dc707122SEaswaran Raman // Create an array of dummy expressions that get the proper counters 252dc707122SEaswaran Raman // when the expressions are read, and the proper kinds when the counters 253dc707122SEaswaran Raman // are decoded. 254dc707122SEaswaran Raman Expressions.resize( 255dc707122SEaswaran Raman NumExpressions, 256dc707122SEaswaran Raman CounterExpression(CounterExpression::Subtract, Counter(), Counter())); 257dc707122SEaswaran Raman for (size_t I = 0; I < NumExpressions; ++I) { 258dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].LHS)) 259dc707122SEaswaran Raman return Err; 260dc707122SEaswaran Raman if (auto Err = readCounter(Expressions[I].RHS)) 261dc707122SEaswaran Raman return Err; 262dc707122SEaswaran Raman } 263dc707122SEaswaran Raman 264dc707122SEaswaran Raman // Read the mapping regions sub-arrays. 265dc707122SEaswaran Raman for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); 266dc707122SEaswaran Raman InferredFileID < S; ++InferredFileID) { 267dc707122SEaswaran Raman if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, 268dc707122SEaswaran Raman VirtualFileMapping.size())) 269dc707122SEaswaran Raman return Err; 270dc707122SEaswaran Raman } 271dc707122SEaswaran Raman 272dc707122SEaswaran Raman // Set the counters for the expansion regions. 273dc707122SEaswaran Raman // i.e. Counter of expansion region = counter of the first region 274dc707122SEaswaran Raman // from the expanded file. 275dc707122SEaswaran Raman // Perform multiple passes to correctly propagate the counters through 276dc707122SEaswaran Raman // all the nested expansion regions. 277dc707122SEaswaran Raman SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; 278dc707122SEaswaran Raman FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); 279dc707122SEaswaran Raman for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { 280dc707122SEaswaran Raman for (auto &R : MappingRegions) { 281dc707122SEaswaran Raman if (R.Kind != CounterMappingRegion::ExpansionRegion) 282dc707122SEaswaran Raman continue; 283dc707122SEaswaran Raman assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); 284dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; 285dc707122SEaswaran Raman } 286dc707122SEaswaran Raman for (auto &R : MappingRegions) { 287dc707122SEaswaran Raman if (FileIDExpansionRegionMapping[R.FileID]) { 288dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; 289dc707122SEaswaran Raman FileIDExpansionRegionMapping[R.FileID] = nullptr; 290dc707122SEaswaran Raman } 291dc707122SEaswaran Raman } 292dc707122SEaswaran Raman } 293dc707122SEaswaran Raman 294*9152fd17SVedant Kumar return Error::success(); 295dc707122SEaswaran Raman } 296dc707122SEaswaran Raman 297*9152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) { 298*9152fd17SVedant Kumar if (auto EC = Section.getContents(Data)) 299*9152fd17SVedant Kumar return errorCodeToError(EC); 300dc707122SEaswaran Raman Address = Section.getAddress(); 301*9152fd17SVedant Kumar return Error::success(); 302dc707122SEaswaran Raman } 303dc707122SEaswaran Raman 304dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { 305dc707122SEaswaran Raman if (Pointer < Address) 306dc707122SEaswaran Raman return StringRef(); 307dc707122SEaswaran Raman auto Offset = Pointer - Address; 308dc707122SEaswaran Raman if (Offset + Size > Data.size()) 309dc707122SEaswaran Raman return StringRef(); 310dc707122SEaswaran Raman return Data.substr(Pointer - Address, Size); 311dc707122SEaswaran Raman } 312dc707122SEaswaran Raman 313dc707122SEaswaran Raman namespace { 314dc707122SEaswaran Raman struct CovMapFuncRecordReader { 315dc707122SEaswaran Raman // The interface to read coverage mapping function records for 316dc707122SEaswaran Raman // a module. \p Buf is a reference to the buffer pointer pointing 317dc707122SEaswaran Raman // to the \c CovHeader of coverage mapping data associated with 318dc707122SEaswaran Raman // the module. 319*9152fd17SVedant Kumar virtual Error readFunctionRecords(const char *&Buf, const char *End) = 0; 320dc707122SEaswaran Raman virtual ~CovMapFuncRecordReader() {} 321dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 322*9152fd17SVedant Kumar static Expected<std::unique_ptr<CovMapFuncRecordReader>> 323dc707122SEaswaran Raman get(coverage::CovMapVersion Version, InstrProfSymtab &P, 324dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 325dc707122SEaswaran Raman std::vector<StringRef> &F); 326dc707122SEaswaran Raman }; 327dc707122SEaswaran Raman 328dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module. 329dc707122SEaswaran Raman template <coverage::CovMapVersion Version, class IntPtrT, 330dc707122SEaswaran Raman support::endianness Endian> 331dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { 332dc707122SEaswaran Raman typedef typename coverage::CovMapTraits< 333dc707122SEaswaran Raman Version, IntPtrT>::CovMapFuncRecordType FuncRecordType; 334dc707122SEaswaran Raman typedef typename coverage::CovMapTraits<Version, IntPtrT>::NameRefType 335dc707122SEaswaran Raman NameRefType; 336dc707122SEaswaran Raman 337dc707122SEaswaran Raman llvm::DenseSet<NameRefType> UniqueFunctionMappingData; 338dc707122SEaswaran Raman InstrProfSymtab &ProfileNames; 339dc707122SEaswaran Raman std::vector<StringRef> &Filenames; 340dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; 341dc707122SEaswaran Raman 342dc707122SEaswaran Raman public: 343dc707122SEaswaran Raman VersionedCovMapFuncRecordReader( 344dc707122SEaswaran Raman InstrProfSymtab &P, 345dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 346dc707122SEaswaran Raman std::vector<StringRef> &F) 347dc707122SEaswaran Raman : ProfileNames(P), Filenames(F), Records(R) {} 348dc707122SEaswaran Raman ~VersionedCovMapFuncRecordReader() override {} 349dc707122SEaswaran Raman 350*9152fd17SVedant Kumar Error readFunctionRecords(const char *&Buf, const char *End) override { 351dc707122SEaswaran Raman using namespace support; 352dc707122SEaswaran Raman if (Buf + sizeof(CovMapHeader) > End) 353*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 354dc707122SEaswaran Raman auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf); 355dc707122SEaswaran Raman uint32_t NRecords = CovHeader->getNRecords<Endian>(); 356dc707122SEaswaran Raman uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); 357dc707122SEaswaran Raman uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); 358dc707122SEaswaran Raman assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version); 359dc707122SEaswaran Raman Buf = reinterpret_cast<const char *>(CovHeader + 1); 360dc707122SEaswaran Raman 361dc707122SEaswaran Raman // Skip past the function records, saving the start and end for later. 362dc707122SEaswaran Raman const char *FunBuf = Buf; 363dc707122SEaswaran Raman Buf += NRecords * sizeof(FuncRecordType); 364dc707122SEaswaran Raman const char *FunEnd = Buf; 365dc707122SEaswaran Raman 366dc707122SEaswaran Raman // Get the filenames. 367dc707122SEaswaran Raman if (Buf + FilenamesSize > End) 368*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 369dc707122SEaswaran Raman size_t FilenamesBegin = Filenames.size(); 370dc707122SEaswaran Raman RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); 371dc707122SEaswaran Raman if (auto Err = Reader.read()) 372dc707122SEaswaran Raman return Err; 373dc707122SEaswaran Raman Buf += FilenamesSize; 374dc707122SEaswaran Raman 375dc707122SEaswaran Raman // We'll read the coverage mapping records in the loop below. 376dc707122SEaswaran Raman const char *CovBuf = Buf; 377dc707122SEaswaran Raman Buf += CoverageSize; 378dc707122SEaswaran Raman const char *CovEnd = Buf; 379dc707122SEaswaran Raman 380dc707122SEaswaran Raman if (Buf > End) 381*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 382dc707122SEaswaran Raman // Each coverage map has an alignment of 8, so we need to adjust alignment 383dc707122SEaswaran Raman // before reading the next map. 384dc707122SEaswaran Raman Buf += alignmentAdjustment(Buf, 8); 385dc707122SEaswaran Raman 386dc707122SEaswaran Raman auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf); 387dc707122SEaswaran Raman while ((const char *)CFR < FunEnd) { 388dc707122SEaswaran Raman // Read the function information 389dc707122SEaswaran Raman uint32_t DataSize = CFR->template getDataSize<Endian>(); 390dc707122SEaswaran Raman uint64_t FuncHash = CFR->template getFuncHash<Endian>(); 391dc707122SEaswaran Raman 392dc707122SEaswaran Raman // Now use that to read the coverage data. 393dc707122SEaswaran Raman if (CovBuf + DataSize > CovEnd) 394*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 395dc707122SEaswaran Raman auto Mapping = StringRef(CovBuf, DataSize); 396dc707122SEaswaran Raman CovBuf += DataSize; 397dc707122SEaswaran Raman 398dc707122SEaswaran Raman // Ignore this record if we already have a record that points to the same 399dc707122SEaswaran Raman // function name. This is useful to ignore the redundant records for the 400dc707122SEaswaran Raman // functions with ODR linkage. 401dc707122SEaswaran Raman NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); 402dc707122SEaswaran Raman if (!UniqueFunctionMappingData.insert(NameRef).second) { 403dc707122SEaswaran Raman CFR++; 404dc707122SEaswaran Raman continue; 405dc707122SEaswaran Raman } 406dc707122SEaswaran Raman 407dc707122SEaswaran Raman StringRef FuncName; 408*9152fd17SVedant Kumar if (Error E = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) 409*9152fd17SVedant Kumar return E; 410dc707122SEaswaran Raman Records.push_back(BinaryCoverageReader::ProfileMappingRecord( 411dc707122SEaswaran Raman Version, FuncName, FuncHash, Mapping, FilenamesBegin, 412dc707122SEaswaran Raman Filenames.size() - FilenamesBegin)); 413dc707122SEaswaran Raman CFR++; 414dc707122SEaswaran Raman } 415*9152fd17SVedant Kumar return Error::success(); 416dc707122SEaswaran Raman } 417dc707122SEaswaran Raman }; 418dc707122SEaswaran Raman } // end anonymous namespace 419dc707122SEaswaran Raman 420dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian> 421*9152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( 422dc707122SEaswaran Raman coverage::CovMapVersion Version, InstrProfSymtab &P, 423dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, 424dc707122SEaswaran Raman std::vector<StringRef> &F) { 425dc707122SEaswaran Raman using namespace coverage; 426dc707122SEaswaran Raman switch (Version) { 427dc707122SEaswaran Raman case CovMapVersion::Version1: 428dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 429dc707122SEaswaran Raman CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); 430dc707122SEaswaran Raman case CovMapVersion::Version2: 431dc707122SEaswaran Raman // Decompress the name data. 432*9152fd17SVedant Kumar if (Error E = P.create(P.getNameData())) 433*9152fd17SVedant Kumar return std::move(E); 434dc707122SEaswaran Raman return llvm::make_unique<VersionedCovMapFuncRecordReader< 435dc707122SEaswaran Raman CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); 436dc707122SEaswaran Raman } 437dc707122SEaswaran Raman llvm_unreachable("Unsupported version"); 438dc707122SEaswaran Raman } 439dc707122SEaswaran Raman 440dc707122SEaswaran Raman template <typename T, support::endianness Endian> 441*9152fd17SVedant Kumar static Error readCoverageMappingData( 442dc707122SEaswaran Raman InstrProfSymtab &ProfileNames, StringRef Data, 443dc707122SEaswaran Raman std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, 444dc707122SEaswaran Raman std::vector<StringRef> &Filenames) { 445dc707122SEaswaran Raman using namespace coverage; 446dc707122SEaswaran Raman // Read the records in the coverage data section. 447dc707122SEaswaran Raman auto CovHeader = 448dc707122SEaswaran Raman reinterpret_cast<const coverage::CovMapHeader *>(Data.data()); 449dc707122SEaswaran Raman CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); 450dc707122SEaswaran Raman if (Version > coverage::CovMapVersion::CurrentVersion) 451*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::unsupported_version); 452*9152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = 453dc707122SEaswaran Raman CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, 454dc707122SEaswaran Raman Filenames); 455*9152fd17SVedant Kumar if (Error E = ReaderExpected.takeError()) 456*9152fd17SVedant Kumar return E; 457*9152fd17SVedant Kumar auto Reader = std::move(ReaderExpected.get()); 458dc707122SEaswaran Raman for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { 459*9152fd17SVedant Kumar if (Error E = Reader->readFunctionRecords(Buf, End)) 460*9152fd17SVedant Kumar return E; 461dc707122SEaswaran Raman } 462*9152fd17SVedant Kumar return Error::success(); 463dc707122SEaswaran Raman } 464dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata"; 465dc707122SEaswaran Raman 466*9152fd17SVedant Kumar static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, 467dc707122SEaswaran Raman StringRef &CoverageMapping, 468dc707122SEaswaran Raman uint8_t &BytesInAddress, 469dc707122SEaswaran Raman support::endianness &Endian) { 470dc707122SEaswaran Raman BytesInAddress = 8; 471dc707122SEaswaran Raman Endian = support::endianness::little; 472dc707122SEaswaran Raman 473dc707122SEaswaran Raman Data = Data.substr(StringRef(TestingFormatMagic).size()); 474dc707122SEaswaran Raman if (Data.size() < 1) 475*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 476dc707122SEaswaran Raman unsigned N = 0; 477dc707122SEaswaran Raman auto ProfileNamesSize = 478dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 479dc707122SEaswaran Raman if (N > Data.size()) 480*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 481dc707122SEaswaran Raman Data = Data.substr(N); 482dc707122SEaswaran Raman if (Data.size() < 1) 483*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 484dc707122SEaswaran Raman N = 0; 485dc707122SEaswaran Raman uint64_t Address = 486dc707122SEaswaran Raman decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); 487dc707122SEaswaran Raman if (N > Data.size()) 488*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 489dc707122SEaswaran Raman Data = Data.substr(N); 490dc707122SEaswaran Raman if (Data.size() < ProfileNamesSize) 491*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 492*9152fd17SVedant Kumar if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) 493*9152fd17SVedant Kumar return E; 494dc707122SEaswaran Raman CoverageMapping = Data.substr(ProfileNamesSize); 495eb103073SIgor Kudrin // Skip the padding bytes because coverage map data has an alignment of 8. 496eb103073SIgor Kudrin if (CoverageMapping.size() < 1) 497*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::truncated); 498eb103073SIgor Kudrin size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8); 499eb103073SIgor Kudrin if (CoverageMapping.size() < Pad) 500*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 501eb103073SIgor Kudrin CoverageMapping = CoverageMapping.substr(Pad); 502*9152fd17SVedant Kumar return Error::success(); 503dc707122SEaswaran Raman } 504dc707122SEaswaran Raman 505*9152fd17SVedant Kumar static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { 506dc707122SEaswaran Raman StringRef FoundName; 507dc707122SEaswaran Raman for (const auto &Section : OF.sections()) { 508dc707122SEaswaran Raman if (auto EC = Section.getName(FoundName)) 509*9152fd17SVedant Kumar return errorCodeToError(EC); 510dc707122SEaswaran Raman if (FoundName == Name) 511dc707122SEaswaran Raman return Section; 512dc707122SEaswaran Raman } 513*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::no_data_found); 514dc707122SEaswaran Raman } 515dc707122SEaswaran Raman 516*9152fd17SVedant Kumar static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, 517*9152fd17SVedant Kumar InstrProfSymtab &ProfileNames, 518*9152fd17SVedant Kumar StringRef &CoverageMapping, 519*9152fd17SVedant Kumar uint8_t &BytesInAddress, 520dc707122SEaswaran Raman support::endianness &Endian, StringRef Arch) { 521dc707122SEaswaran Raman auto BinOrErr = object::createBinary(ObjectBuffer); 522dc707122SEaswaran Raman if (!BinOrErr) 523*9152fd17SVedant Kumar return BinOrErr.takeError(); 524dc707122SEaswaran Raman auto Bin = std::move(BinOrErr.get()); 525dc707122SEaswaran Raman std::unique_ptr<ObjectFile> OF; 526dc707122SEaswaran Raman if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) { 527dc707122SEaswaran Raman // If we have a universal binary, try to look up the object for the 528dc707122SEaswaran Raman // appropriate architecture. 529dc707122SEaswaran Raman auto ObjectFileOrErr = Universal->getObjectForArch(Arch); 530*9152fd17SVedant Kumar if (auto EC = ObjectFileOrErr.getError()) 531*9152fd17SVedant Kumar return errorCodeToError(EC); 532dc707122SEaswaran Raman OF = std::move(ObjectFileOrErr.get()); 533dc707122SEaswaran Raman } else if (isa<object::ObjectFile>(Bin.get())) { 534dc707122SEaswaran Raman // For any other object file, upcast and take ownership. 535dc707122SEaswaran Raman OF.reset(cast<object::ObjectFile>(Bin.release())); 536dc707122SEaswaran Raman // If we've asked for a particular arch, make sure they match. 537dc707122SEaswaran Raman if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) 538*9152fd17SVedant Kumar return errorCodeToError(object_error::arch_not_found); 539dc707122SEaswaran Raman } else 540dc707122SEaswaran Raman // We can only handle object files. 541*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 542dc707122SEaswaran Raman 543dc707122SEaswaran Raman // The coverage uses native pointer sizes for the object it's written in. 544dc707122SEaswaran Raman BytesInAddress = OF->getBytesInAddress(); 545dc707122SEaswaran Raman Endian = OF->isLittleEndian() ? support::endianness::little 546dc707122SEaswaran Raman : support::endianness::big; 547dc707122SEaswaran Raman 548dc707122SEaswaran Raman // Look for the sections that we are interested in. 549dc707122SEaswaran Raman auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false)); 550*9152fd17SVedant Kumar if (auto E = NamesSection.takeError()) 551*9152fd17SVedant Kumar return E; 552dc707122SEaswaran Raman auto CoverageSection = 553dc707122SEaswaran Raman lookupSection(*OF, getInstrProfCoverageSectionName(false)); 554*9152fd17SVedant Kumar if (auto E = CoverageSection.takeError()) 555*9152fd17SVedant Kumar return E; 556dc707122SEaswaran Raman 557dc707122SEaswaran Raman // Get the contents of the given sections. 558*9152fd17SVedant Kumar if (auto EC = CoverageSection->getContents(CoverageMapping)) 559*9152fd17SVedant Kumar return errorCodeToError(EC); 560*9152fd17SVedant Kumar if (Error E = ProfileNames.create(*NamesSection)) 561*9152fd17SVedant Kumar return E; 562dc707122SEaswaran Raman 563*9152fd17SVedant Kumar return Error::success(); 564dc707122SEaswaran Raman } 565dc707122SEaswaran Raman 566*9152fd17SVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>> 567dc707122SEaswaran Raman BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, 568dc707122SEaswaran Raman StringRef Arch) { 569dc707122SEaswaran Raman std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); 570dc707122SEaswaran Raman 571dc707122SEaswaran Raman StringRef Coverage; 572dc707122SEaswaran Raman uint8_t BytesInAddress; 573dc707122SEaswaran Raman support::endianness Endian; 574*9152fd17SVedant Kumar Error E; 575*9152fd17SVedant Kumar consumeError(std::move(E)); 576dc707122SEaswaran Raman if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) 577dc707122SEaswaran Raman // This is a special format used for testing. 578*9152fd17SVedant Kumar E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames, 579dc707122SEaswaran Raman Coverage, BytesInAddress, Endian); 580dc707122SEaswaran Raman else 581*9152fd17SVedant Kumar E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames, 582dc707122SEaswaran Raman Coverage, BytesInAddress, Endian, Arch); 583*9152fd17SVedant Kumar if (E) 584*9152fd17SVedant Kumar return std::move(E); 585dc707122SEaswaran Raman 586dc707122SEaswaran Raman if (BytesInAddress == 4 && Endian == support::endianness::little) 587*9152fd17SVedant Kumar E = readCoverageMappingData<uint32_t, support::endianness::little>( 588dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 589dc707122SEaswaran Raman Reader->Filenames); 590dc707122SEaswaran Raman else if (BytesInAddress == 4 && Endian == support::endianness::big) 591*9152fd17SVedant Kumar E = readCoverageMappingData<uint32_t, support::endianness::big>( 592dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 593dc707122SEaswaran Raman Reader->Filenames); 594dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::little) 595*9152fd17SVedant Kumar E = readCoverageMappingData<uint64_t, support::endianness::little>( 596dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 597dc707122SEaswaran Raman Reader->Filenames); 598dc707122SEaswaran Raman else if (BytesInAddress == 8 && Endian == support::endianness::big) 599*9152fd17SVedant Kumar E = readCoverageMappingData<uint64_t, support::endianness::big>( 600dc707122SEaswaran Raman Reader->ProfileNames, Coverage, Reader->MappingRecords, 601dc707122SEaswaran Raman Reader->Filenames); 602dc707122SEaswaran Raman else 603*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::malformed); 604*9152fd17SVedant Kumar if (E) 605*9152fd17SVedant Kumar return std::move(E); 606dc707122SEaswaran Raman return std::move(Reader); 607dc707122SEaswaran Raman } 608dc707122SEaswaran Raman 609*9152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 610dc707122SEaswaran Raman if (CurrentRecord >= MappingRecords.size()) 611*9152fd17SVedant Kumar return make_error<CoverageMapError>(coveragemap_error::eof); 612dc707122SEaswaran Raman 613dc707122SEaswaran Raman FunctionsFilenames.clear(); 614dc707122SEaswaran Raman Expressions.clear(); 615dc707122SEaswaran Raman MappingRegions.clear(); 616dc707122SEaswaran Raman auto &R = MappingRecords[CurrentRecord]; 617dc707122SEaswaran Raman RawCoverageMappingReader Reader( 618dc707122SEaswaran Raman R.CoverageMapping, 619dc707122SEaswaran Raman makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), 620dc707122SEaswaran Raman FunctionsFilenames, Expressions, MappingRegions); 621dc707122SEaswaran Raman if (auto Err = Reader.read()) 622dc707122SEaswaran Raman return Err; 623dc707122SEaswaran Raman 624dc707122SEaswaran Raman Record.FunctionName = R.FunctionName; 625dc707122SEaswaran Raman Record.FunctionHash = R.FunctionHash; 626dc707122SEaswaran Raman Record.Filenames = FunctionsFilenames; 627dc707122SEaswaran Raman Record.Expressions = Expressions; 628dc707122SEaswaran Raman Record.MappingRegions = MappingRegions; 629dc707122SEaswaran Raman 630dc707122SEaswaran Raman ++CurrentRecord; 631*9152fd17SVedant Kumar return Error::success(); 632dc707122SEaswaran Raman } 633