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