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