LLVM: lib/ProfileData/Coverage/CoverageMappingReader.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

39#include

40

41using namespace llvm;

43using namespace object;

44

45#define DEBUG_TYPE "coverage-mapping"

46

47STATISTIC(CovMapNumRecords, "The # of coverage function records");

48STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");

49

50void CoverageMappingIterator::increment() {

52 return;

53

54

55

60 else

61 ReadErr = CME.get();

62 });

63}

64

66 if (Data.empty())

68 unsigned N = 0;

70 if (N > Data.size())

72 "the size of ULEB128 is too big");

75}

76

79 return Err;

80 if (Result >= MaxPlus1)

83 "the value of ULEB128 is greater than or equal to MaxPlus1");

85}

86

89 return Err;

90 if (Result > Data.size())

92 "the value of ULEB128 is too big");

94}

95

104

107 if (auto Err = readSize(NumFilenames))

108 return Err;

109 if (!NumFilenames)

111 "number of filenames is zero");

112

114 return readUncompressed(Version, NumFilenames);

115

116

117

119 if (auto Err = readULEB128(UncompressedLen))

120 return Err;

121

123 if (auto Err = readSize(CompressedLen))

124 return Err;

125

126 if (CompressedLen > 0) {

130

131

133

134

135 StringRef CompressedFilenames = Data.substr(0, CompressedLen);

136 Data = Data.substr(CompressedLen);

139 UncompressedLen);

140 if (Err) {

144 }

145

147 CompilationDir);

148 return Delegate.readUncompressed(Version, NumFilenames);

149 }

150

151 return readUncompressed(Version, NumFilenames);

152}

153

156

158 for (size_t I = 0; I < NumFilenames; ++I) {

161 return Err;

162 Filenames.push_back(Filename.str());

163 }

164 } else {

167 return Err;

168 Filenames.push_back(CWD.str());

169

170 for (size_t I = 1; I < NumFilenames; ++I) {

173 return Err;

175 Filenames.push_back(Filename.str());

176 } else {

177 SmallString<256> P;

178 if (!CompilationDir.empty())

179 P.assign(CompilationDir);

180 else

181 P.assign(CWD);

184 Filenames.push_back(static_caststd::string\(P.str()));

185 }

186 }

187 }

189}

190

191Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {

193 switch (Tag) {

200 default:

201 break;

202 }

204 switch (Tag) {

208 if (ID >= Expressions.size())

210 "counter expression is invalid");

213 break;

214 }

215 default:

217 "counter expression kind is invalid");

218 }

220}

221

222Error RawCoverageMappingReader::readCounter(Counter &C) {

223 uint64_t EncodedCounter;

224 if (auto Err =

225 readIntMax(EncodedCounter, std::numeric_limits::max()))

226 return Err;

227 if (auto Err = decodeCounter(EncodedCounter, C))

228 return Err;

230}

231

234

235

236

237

238Error RawCoverageMappingReader::readMappingRegionsSubArray(

239 std::vector &MappingRegions, unsigned InferredFileID,

240 size_t NumFileIDs) {

242 if (auto Err = readSize(NumRegions))

243 return Err;

244 unsigned LineStart = 0;

245 for (size_t I = 0; I < NumRegions; ++I) {

248

252

253

254 uint64_t EncodedCounterAndRegion;

255 if (auto Err = readIntMax(EncodedCounterAndRegion,

256 std::numeric_limits::max()))

257 return Err;

260

261

262

263

264

265

266

267

268

269

270

271

273 if (auto Err = decodeCounter(EncodedCounterAndRegion, C))

274 return Err;

275 } else {

276

279 ExpandedFileID = EncodedCounterAndRegion >>

281 if (ExpandedFileID >= NumFileIDs)

283 "ExpandedFileID is invalid");

284 } else {

285 switch (EncodedCounterAndRegion >>

288

289 break;

292 break;

294

296 if (auto Err = readCounter(C))

297 return Err;

298 if (auto Err = readCounter(C2))

299 return Err;

300 break;

302

304 if (auto Err = readCounter(C))

305 return Err;

306 if (auto Err = readCounter(C2))

307 return Err;

308 if (auto Err = readIntMax(ID1, std::numeric_limits<int16_t>::max()))

309 return Err;

310 if (auto Err = readIntMax(TID1, std::numeric_limits<int16_t>::max()))

311 return Err;

312 if (auto Err = readIntMax(FID1, std::numeric_limits<int16_t>::max()))

313 return Err;

314 if (ID1 == 0)

317 "MCDCConditionID shouldn't be zero");

319 static_cast<int16_t>(static_cast<int16_t>(ID1) - 1),

320 {static_cast<int16_t>(static_cast<int16_t>(FID1) - 1),

321 static_cast<int16_t>(static_cast<int16_t>(TID1) - 1)}};

322 break;

325 if (auto Err = readIntMax(BIDX, std::numeric_limits::max()))

326 return Err;

327 if (auto Err = readIntMax(NC, std::numeric_limits<int16_t>::max()))

328 return Err;

331 break;

332 default:

334 "region kind is incorrect");

335 }

336 }

337 }

338

339

340 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;

341 if (auto Err =

342 readIntMax(LineStartDelta, std::numeric_limits::max()))

343 return Err;

345 return Err;

346 if (ColumnStart > std::numeric_limits::max())

348 "start column is too big");

349 if (auto Err = readIntMax(NumLines, std::numeric_limits::max()))

350 return Err;

351 if (auto Err = readIntMax(ColumnEnd, std::numeric_limits::max()))

352 return Err;

353 LineStart += LineStartDelta;

354

355

356 if (ColumnEnd & (1U << 31)) {

358 ColumnEnd &= ~(1U << 31);

359 }

360

361

362

363

364

365

366

367

368

369 if (ColumnStart == 0 && ColumnEnd == 0) {

370 ColumnStart = 1;

371 ColumnEnd = std::numeric_limits::max();

372 }

373

375 dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"

376 << ColumnStart << " -> " << (LineStart + NumLines) << ":"

377 << ColumnEnd << ", ";

379 dbgs() << "Expands to file " << ExpandedFileID;

380 else

382 dbgs() << "\n";

383 });

384

386 C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,

387 LineStart + NumLines, ColumnEnd, Kind, Params);

388 if (CMR.startLoc() > CMR.endLoc())

391 "counter mapping region locations are incorrect");

392 MappingRegions.push_back(CMR);

393 }

395}

396

398

401 if (auto Err = readSize(NumFileMappings))

402 return Err;

403 for (size_t I = 0; I < NumFileMappings; ++I) {

405 if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))

406 return Err;

407 VirtualFileMapping.push_back(FilenameIndex);

408 }

409

410

411 for (auto I : VirtualFileMapping) {

412 Filenames.push_back(TranslationUnitFilenames[I]);

413 }

414

415

417 if (auto Err = readSize(NumExpressions))

418 return Err;

419

420

421

422 Expressions.resize(

423 NumExpressions,

425 for (size_t I = 0; I < NumExpressions; ++I) {

426 if (auto Err = readCounter(Expressions[I].LHS))

427 return Err;

428 if (auto Err = readCounter(Expressions[I].RHS))

429 return Err;

430 }

431

432

433 for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();

434 InferredFileID < S; ++InferredFileID) {

435 if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,

436 VirtualFileMapping.size()))

437 return Err;

438 }

439

440

441

442

443

444

446 FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);

447 for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {

448 for (auto &R : MappingRegions) {

450 continue;

451 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);

452 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;

453 }

454 for (auto &R : MappingRegions) {

455 if (FileIDExpansionRegionMapping[R.FileID]) {

456 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;

457 FileIDExpansionRegionMapping[R.FileID] = nullptr;

458 }

459 }

460 }

461

463}

464

466

469 return std::move(Err);

470 if (NumFileMappings != 1)

471 return false;

472

475 readIntMax(FilenameIndex, std::numeric_limits::max()))

476 return std::move(Err);

479 return std::move(Err);

480 if (NumExpressions != 0)

481 return false;

484 return std::move(Err);

485 if (NumRegions != 1)

486 return false;

487 uint64_t EncodedCounterAndRegion;

489 std::numeric_limits::max()))

490 return std::move(Err);

493}

494

495

497 const ObjectFile *Obj = Section.getObject();

498

499

500

501

505 return true;

506 return false;

507}

508

511 if (!DataOrErr)

513 Data = *DataOrErr;

514 Address = Section.getAddress();

515

517 Data = Data.substr(1);

518

520}

521

523 if (Pointer < Address)

525 auto Offset = Pointer - Address;

528 return Data.substr(Pointer - Address, Size);

529}

530

531

533

534 if (Hash)

535 return false;

537}

538

539

540

551

552namespace {

553

554

555struct CovMapFuncRecordReader {

556 virtual ~CovMapFuncRecordReader() = default;

557

558

559

560

561

562

563

564

565 virtual Expected<const char *> readCoverageHeader(const char *CovBuf,

566 const char *CovBufEnd) = 0;

567

568

569

570

571

572

573

574

575

576

577

579 readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,

580 std::optional OutOfLineFileRange,

581 const char *OutOfLineMappingBuf,

582 const char *OutOfLineMappingBufEnd) = 0;

583

584 template <class IntPtrT, llvm::endianness Endian>

585 static Expected<std::unique_ptr>

587 std::vectorBinaryCoverageReader::ProfileMappingRecord &R, StringRef D,

588 std::vectorstd::string &F);

589};

590

591

592template <CovMapVersion Version, class IntPtrT, llvm::endianness Endian>

593class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {

594 using FuncRecordType =

597

598

599

600 DenseMap<NameRefType, size_t> FunctionRecords;

601 InstrProfSymtab &ProfileNames;

602 StringRef CompilationDir;

603 std::vectorstd::string &Filenames;

604 std::vectorBinaryCoverageReader::ProfileMappingRecord &Records;

605

606

607

608 DenseMap<uint64_t, FilenameRange> FileRangeMap;

609

610

611

612

613

614

615

616 Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,

617 StringRef Mapping,

618 FilenameRange FileRange) {

619 ++CovMapNumRecords;

620 uint64_t FuncHash = CFR->template getFuncHash();

621 NameRefType NameRef = CFR->template getFuncNameRef();

622 auto InsertResult =

624 if (InsertResult.second) {

625 StringRef FuncName;

626 if (Error Err = CFR->template getFuncName(ProfileNames, FuncName))

627 return Err;

628 if (FuncName.empty())

630 "function name is empty");

631 ++CovMapNumUsedRecords;

635 }

636

637 size_t OldRecordIndex = InsertResult.first->second;

638 BinaryCoverageReader::ProfileMappingRecord &OldRecord =

643 return Err;

644 if (!*OldIsDummyExpected)

646 Expected NewIsDummyExpected =

649 return Err;

650 if (*NewIsDummyExpected)

652 ++CovMapNumUsedRecords;

658 }

659

660public:

661 VersionedCovMapFuncRecordReader(

662 InstrProfSymtab &P,

663 std::vectorBinaryCoverageReader::ProfileMappingRecord &R, StringRef D,

664 std::vectorstd::string &F)

665 : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}

666

667 ~VersionedCovMapFuncRecordReader() override = default;

668

669 Expected<const char *> readCoverageHeader(const char *CovBuf,

670 const char *CovBufEnd) override {

671 using namespace support;

672

673 if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)

675 coveragemap_error::malformed,

676 "coverage mapping header section is larger than buffer size");

677 auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);

678 uint32_t NRecords = CovHeader->getNRecords();

679 uint32_t FilenamesSize = CovHeader->getFilenamesSize();

680 uint32_t CoverageSize = CovHeader->getCoverageSize();

682 CovBuf = reinterpret_cast<const char *>(CovHeader + 1);

683

684

685

686

687 const char *FuncRecBuf = nullptr;

688 const char *FuncRecBufEnd = nullptr;

689 if (Version < CovMapVersion::Version4)

690 FuncRecBuf = CovBuf;

691 CovBuf += NRecords * sizeof(FuncRecordType);

692 if (Version < CovMapVersion::Version4)

693 FuncRecBufEnd = CovBuf;

694

695

698 coveragemap_error::malformed,

699 "filenames section is larger than buffer size");

700 size_t FilenamesBegin = Filenames.size();

702 RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,

703 CompilationDir);

704 if (auto Err = Reader.read(Version))

705 return std::move(Err);

707 FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);

708

709 if (Version >= CovMapVersion::Version4) {

710

711

712 int64_t FilenamesRef =

715 FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));

716 if (Insert.second) {

717

718

719 auto It = Filenames.begin();

720 FilenameRange &OrigRange = Insert.first->getSecond();

725

726 FileRange = OrigRange;

727 else

728

730 }

731 }

732

733

734

735

736 const char *MappingBuf = CovBuf;

739 "coverage mapping size is not zero");

741 const char *MappingEnd = CovBuf;

742

743 if (CovBuf > CovBufEnd)

745 coveragemap_error::malformed,

746 "function records section is larger than buffer size");

747

748 if (Version < CovMapVersion::Version4) {

749

750 if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,

751 MappingBuf, MappingEnd))

752 return std::move(E);

753 }

754

755

756

758

759 return CovBuf;

760 }

761

762 Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,

763 std::optional OutOfLineFileRange,

764 const char *OutOfLineMappingBuf,

765 const char *OutOfLineMappingBufEnd) override {

766 auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);

767 while ((const char *)CFR < FuncRecBufEnd) {

768

769 const char *NextMappingBuf;

770 const FuncRecordType *NextCFR;

771 std::tie(NextMappingBuf, NextCFR) =

772 CFR->template advanceByOne(OutOfLineMappingBuf);

773 if (Version < CovMapVersion::Version4)

774 if (NextMappingBuf > OutOfLineMappingBufEnd)

776 coveragemap_error::malformed,

777 "next mapping buffer is larger than buffer size");

778

779

780 std::optional FileRange;

781 if (Version < CovMapVersion::Version4) {

782 FileRange = OutOfLineFileRange;

783 } else {

784 uint64_t FilenamesRef = CFR->template getFilenamesRef();

785 auto It = FileRangeMap.find(FilenamesRef);

786 if (It == FileRangeMap.end())

788 coveragemap_error::malformed,

789 "no filename found for function with hash=0x" +

791 else

792 FileRange = It->getSecond();

793 }

794

795

796 if (FileRange && !FileRange->isInvalid()) {

797 StringRef Mapping =

798 CFR->template getCoverageMapping(OutOfLineMappingBuf);

799 if (Version >= CovMapVersion::Version4 &&

800 Mapping.data() + Mapping.size() > FuncRecBufEnd)

802 coveragemap_error::malformed,

803 "coverage mapping data is larger than buffer size");

804 if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))

805 return Err;

806 }

807

808 std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);

809 }

811 }

812};

813

814}

815

816template <class IntPtrT, llvm::endianness Endian>

817Expected<std::unique_ptr> CovMapFuncRecordReader::get(

819 std::vectorBinaryCoverageReader::ProfileMappingRecord &R, StringRef D,

820 std::vectorstd::string &F) {

821 using namespace coverage;

822

825 return std::make_unique<VersionedCovMapFuncRecordReader<

833

834 if (Error E = P.create(P.getNameData()))

835 return std::move(E);

837 return std::make_unique<VersionedCovMapFuncRecordReader<

840 return std::make_unique<VersionedCovMapFuncRecordReader<

843 return std::make_unique<VersionedCovMapFuncRecordReader<

846 return std::make_unique<VersionedCovMapFuncRecordReader<

849 return std::make_unique<VersionedCovMapFuncRecordReader<

852 return std::make_unique<VersionedCovMapFuncRecordReader<

854 }

856}

857

858template <typename T, llvm::endianness Endian>

861 std::vectorBinaryCoverageReader::ProfileMappingRecord &Records,

862 StringRef CompilationDir, std::vectorstd::string &Filenames) {

864

865

866 auto CovHeader =

872 CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,

873 CompilationDir, Filenames);

875 return E;

876 auto Reader = std::move(ReaderExpected.get());

877 const char *CovBuf = CovMap.data();

878 const char *CovBufEnd = CovBuf + CovMap.size();

879 const char *FuncRecBuf = FuncRecords.data();

880 const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();

881 while (CovBuf < CovBufEnd) {

882

883

884

885

886

887

888 auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);

889 if (auto E = NextOrErr.takeError())

890 return E;

891 CovBuf = NextOrErr.get();

892 }

893

894

896 return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,

897 nullptr, nullptr);

899}

900

901Expected<std::unique_ptr>

905 std::unique_ptr ProfileNamesPtr, uint8_t BytesInAddress,

907 if (ProfileNamesPtr == nullptr)

909 "Caller must provide ProfileNames");

910 std::unique_ptr Reader(

911 new BinaryCoverageReader(std::move(ProfileNamesPtr),

912 std::move(FuncRecords), std::move(CoverageMap)));

914 StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();

917 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,

918 CompilationDir, Reader->Filenames))

919 return std::move(E);

922 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,

923 CompilationDir, Reader->Filenames))

924 return std::move(E);

927 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,

928 CompilationDir, Reader->Filenames))

929 return std::move(E);

932 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,

933 CompilationDir, Reader->Filenames))

934 return std::move(E);

935 } else

938 "not supported endianness or bytes in address");

939 return std::move(Reader);

940}

941

944 uint8_t BytesInAddress = 8;

946

947

951 "the size of data is too small");

953 *reinterpret_cast<const uint64_t *>(Data.data()),

956

957

958 if (Data.empty())

960 unsigned N = 0;

962 if (N > Data.size())

965 "the size of TestingFormatMagic is too big");

967 if (Data.empty())

969 N = 0;

971 if (N > Data.size())

973 "the size of ULEB128 is too big");

975 if (Data.size() < ProfileNamesSize)

977 "the size of ProfileNames is too big");

978 auto ProfileNames = std::make_unique();

979 if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address))

980 return std::move(E);

981 Data = Data.substr(ProfileNamesSize);

982

983

984 uint64_t CoverageMappingSize;

986 N = 0;

988 if (N > Data.size())

990 "the size of ULEB128 is too big");

992 if (CoverageMappingSize < sizeof(CovMapHeader))

995 "the size of CoverageMapping is teoo small");

998 }

999

1000

1002 if (Data.size() < Pad)

1004 "insufficient padding");

1009 "coverage mapping header section is larger than data size");

1010 auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(

1012 auto Version =

1014

1015

1018 CoverageMappingSize = Data.size();

1019 } else {

1023 }

1024 }

1025

1027 Data = Data.substr(CoverageMappingSize);

1028

1029

1031 if (Data.empty())

1033 "data is not empty");

1034 } else {

1035

1036

1038 if (Data.size() < Pad)

1040 "insufficient padding");

1042 }

1045

1048 std::move(ProfileNames), BytesInAddress, Endian, CompilationDir);

1049}

1050

1051

1052

1053static Expected<std::vector>

1055 auto ObjFormat = OF.getTripleObjectFormat();

1056 auto Name =

1058

1059

1060

1062 auto stripSuffix = [IsCOFF](StringRef N) {

1063 return IsCOFF ? N.split('$').first : N;

1064 };

1065 Name = stripSuffix(Name);

1066

1067 std::vector Sections;

1068 for (const auto &Section : OF.sections()) {

1070 if (!NameOrErr)

1072 if (stripSuffix(*NameOrErr) == Name) {

1073

1074

1075

1076 if (IPSK == IPSK_name &&

1077 (Section.getSize() == 0 || (IsCOFF && Section.getSize() == 2)))

1078 continue;

1079 Sections.push_back(Section);

1080 }

1081 }

1082 if (Sections.empty())

1084 return Sections;

1085}

1086

1087

1088

1089

1090static Expected<std::pair<StringRef, uint64_t>>

1092

1094 std::vector<const WasmSegment *> Segments;

1095 auto ObjFormat = OF.getTripleObjectFormat();

1096 auto Name =

1098 for (const auto &DebugName : WOF->debugNames()) {

1100 DebugName.Name != Name)

1101 continue;

1102 if (DebugName.Index >= WOF->dataSegments().size())

1104 auto &Segment = WOF->dataSegments()[DebugName.Index];

1105 Segments.push_back(&Segment);

1106 }

1107 if (Segments.empty())

1109 if (Segments.size() != 1)

1111

1112 const auto &Segment = *Segments.front();

1113 auto &Data = Segment.Data;

1114 StringRef Content(reinterpret_cast<const char *>(Data.Content.data()),

1115 Data.Content.size());

1116 return std::make_pair(Content, Segment.SectionOffset);

1117 }

1118

1119

1121 if (!Sections)

1122 return Sections.takeError();

1123 if (Sections->size() != 1)

1126 "the size of coverage mapping section is not one");

1127 auto &Section = Sections->front();

1128 auto ContentsOrErr = Section.getContents();

1129 if (!ContentsOrErr)

1130 return ContentsOrErr.takeError();

1131 auto Content = *ContentsOrErr;

1133 Content = Content.drop_front(1);

1134 return std::make_pair(Content, Section.getAddress());

1135}

1136

1137static Expected<std::unique_ptr>

1141 std::unique_ptr OF;

1143

1144

1145 auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);

1146 if (!ObjectFileOrErr)

1147 return ObjectFileOrErr.takeError();

1148 OF = std::move(ObjectFileOrErr.get());

1150

1152

1153 if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())

1155 } else

1156

1158 "binary is not an object file");

1159

1160

1161 uint8_t BytesInAddress = OF->getBytesInAddress();

1164

1165

1166 auto ProfileNames = std::make_unique();

1167

1168

1170 if (auto E = NamesSection.takeError()) {

1173 if (auto E = NamesSection.takeError())

1174 return std::move(E);

1175 }

1176

1179 std::tie(NamesContent, NamesAddress) = *NamesSection;

1180 if (Error E = ProfileNames->create(NamesContent, NamesAddress))

1181 return std::move(E);

1182

1183 auto CoverageSection = lookupSections(*OF, IPSK_covmap);

1184 if (auto E = CoverageSection.takeError())

1185 return std::move(E);

1186 std::vector CoverageSectionRefs = *CoverageSection;

1187 if (CoverageSectionRefs.size() != 1)

1189 "the size of name section is not one");

1190 auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();

1191 if (!CoverageMappingOrErr)

1192 return CoverageMappingOrErr.takeError();

1194

1195

1196

1197

1198 std::unique_ptr CoverageMapCopy;

1202 }

1203

1204

1205 auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun);

1206

1208 if (auto E = CoverageRecordsSections.takeError()) {

1211 } else {

1212

1213

1214

1215

1216 const Align RecordAlignment(8);

1217 uint64_t FuncRecordsSize = 0;

1218 for (SectionRef Section : *CoverageRecordsSections) {

1219 auto CoverageRecordsOrErr = Section.getContents();

1220 if (!CoverageRecordsOrErr)

1221 return CoverageRecordsOrErr.takeError();

1222 FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);

1223 }

1224 auto WritableBuffer =

1226 char *FuncRecordsBuffer = WritableBuffer->getBufferStart();

1228 "Allocated memory is correctly aligned");

1229

1230 for (SectionRef Section : *CoverageRecordsSections) {

1231 auto CoverageRecordsOrErr = Section.getContents();

1232 if (!CoverageRecordsOrErr)

1233 return CoverageRecordsOrErr.takeError();

1234 const auto &CoverageRecords = CoverageRecordsOrErr.get();

1235 FuncRecordsBuffer = llvm::copy(CoverageRecords, FuncRecordsBuffer);

1236 FuncRecordsBuffer =

1237 std::fill_n(FuncRecordsBuffer,

1238 alignAddr(FuncRecordsBuffer, RecordAlignment) -

1239 (uintptr_t)FuncRecordsBuffer,

1240 '\0');

1241 }

1242 assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&

1243 "consistent init");

1244 FuncRecords = std::move(WritableBuffer);

1245 }

1246

1247 if (BinaryID)

1249

1251 CoverageMapping, std::move(FuncRecords), std::move(CoverageMapCopy),

1252 std::move(ProfileNames), BytesInAddress, Endian, CompilationDir);

1253}

1254

1255

1257

1258

1260 for (auto &ObjForArch : Universal->objects())

1261 if (Arch == ObjForArch.getArchFlagName())

1262 return false;

1263 return true;

1264 }

1265 return false;

1266}

1267

1268Expected<std::vector<std::unique_ptr>>

1271 SmallVectorImpl<std::unique_ptr> &ObjectFileBuffers,

1273 std::vector<std::unique_ptr> Readers;

1274

1280

1281 auto ReaderOrErr =

1283 if (!ReaderOrErr)

1284 return ReaderOrErr.takeError();

1285 Readers.push_back(std::move(ReaderOrErr.get()));

1286 return std::move(Readers);

1287 }

1288 }

1289

1291 if (!BinOrErr)

1292 return BinOrErr.takeError();

1293 std::unique_ptr Bin = std::move(BinOrErr.get());

1294

1298

1299

1300

1302 for (auto &ObjForArch : Universal->objects()) {

1303

1304 std::string ObjArch = ObjForArch.getArchFlagName();

1305 if (Arch != ObjArch)

1306 continue;

1307

1308 auto ArchiveOrErr = ObjForArch.getAsArchive();

1309 if (!ArchiveOrErr) {

1310

1312 break;

1313 }

1314

1316 ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,

1317 CompilationDir, BinaryIDs);

1318 }

1319 }

1320

1321

1324 for (auto &Child : Ar->children(Err)) {

1326 if (!ChildBufOrErr)

1327 return ChildBufOrErr.takeError();

1328

1330 ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,

1331 BinaryIDs);

1332 if (!ChildReadersOrErr)

1333 return ChildReadersOrErr.takeError();

1334 for (auto &Reader : ChildReadersOrErr.get())

1335 Readers.push_back(std::move(Reader));

1336 }

1337 if (Err)

1338 return std::move(Err);

1339

1340

1341

1342

1343 if (Ar->isThin())

1344 for (auto &Buffer : Ar->takeThinBuffers())

1345 ObjectFileBuffers.push_back(std::move(Buffer));

1346

1347 return std::move(Readers);

1348 }

1349

1351 auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,

1352 BinaryIDs ? &BinaryID : nullptr);

1353 if (!ReaderOrErr)

1354 return ReaderOrErr.takeError();

1355 Readers.push_back(std::move(ReaderOrErr.get()));

1356 if (!BinaryID.empty())

1358 return std::move(Readers);

1359}

1360

1362 if (CurrentRecord >= MappingRecords.size())

1364

1365 FunctionsFilenames.clear();

1366 Expressions.clear();

1367 MappingRegions.clear();

1368 auto &R = MappingRecords[CurrentRecord];

1369 auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);

1371 Expressions, MappingRegions);

1372 if (auto Err = Reader.read())

1373 return Err;

1374

1375 Record.FunctionName = R.FunctionName;

1376 Record.FunctionHash = R.FunctionHash;

1377 Record.Filenames = FunctionsFilenames;

1378 Record.Expressions = Expressions;

1379 Record.MappingRegions = MappingRegions;

1380

1381 ++CurrentRecord;

1383}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static Error readCoverageMappingData(InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, std::vector< BinaryCoverageReader::ProfileMappingRecord > &Records, StringRef CompilationDir, std::vector< std::string > &Filenames)

Definition CoverageMappingReader.cpp:859

static Expected< std::pair< StringRef, uint64_t > > lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK)

Find a section that matches Name and is allocatable at runtime.

Definition CoverageMappingReader.cpp:1091

static Expected< std::unique_ptr< BinaryCoverageReader > > loadBinaryFormat(std::unique_ptr< Binary > Bin, StringRef Arch, StringRef CompilationDir="", object::BuildIDRef *BinaryID=nullptr)

Definition CoverageMappingReader.cpp:1138

static Expected< std::unique_ptr< BinaryCoverageReader > > loadTestingFormat(StringRef Data, StringRef CompilationDir)

Definition CoverageMappingReader.cpp:943

static Expected< std::vector< SectionRef > > lookupSections(ObjectFile &OF, InstrProfSectKind IPSK)

Find all sections that match IPSK name.

Definition CoverageMappingReader.cpp:1054

static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch)

Determine whether Arch is invalid or empty, given Bin.

Definition CoverageMappingReader.cpp:1256

static bool shouldSkipSectionFirstByte(SectionRef &Section)

Determine if we should skip the first byte of the section content.

Definition CoverageMappingReader.cpp:496

static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)

Definition CoverageMappingReader.cpp:532

static const unsigned EncodingExpansionRegionBit

Definition CoverageMappingReader.cpp:232

This file defines the DenseMap class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

bool empty() const

empty - Check if the array is empty.

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...

LLVM_ABI StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize) const

Return function's PGO name from the function name's symbol address in the object file.

Definition CoverageMappingReader.cpp:522

LLVM_ABI Error create(object::SectionRef &Section)

Create InstrProfSymtab from an object file section which contains function PGO names.

Definition CoverageMappingReader.cpp:509

const char * getBufferStart() const

StringRef getBuffer() const

static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)

Open the specified memory range as a MemoryBuffer.

static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")

Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.

Pass interface - Implemented by all 'passes'.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

constexpr bool empty() const

empty - Check if the string is empty.

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

Triple - Helper class for working with autoconf configuration names.

static Twine utohexstr(uint64_t Val)

static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)

Allocate a new MemoryBuffer of the specified size that is not initialized.

static Expected< std::unique_ptr< BinaryCoverageReader > > createCoverageReaderFromBuffer(StringRef Coverage, FuncRecordsStorage &&FuncRecords, CoverageMapCopyStorage &&CoverageMap, std::unique_ptr< InstrProfSymtab > ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir="")

Definition CoverageMappingReader.cpp:902

std::unique_ptr< MemoryBuffer > CoverageMapCopyStorage

static Expected< std::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)

Definition CoverageMappingReader.cpp:1269

std::unique_ptr< MemoryBuffer > FuncRecordsStorage

Error readNextRecord(CoverageMappingRecord &Record) override

Definition CoverageMappingReader.cpp:1361

A Counter mapping context is used to connect the counters, expressions and the obtained counter value...

LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const

coveragemap_error get() const

CoverageMappingIterator()

virtual Error readNextRecord(CoverageMappingRecord &Record)=0

The mapping of profile information to coverage data.

RawCoverageFilenamesReader(StringRef Data, std::vector< std::string > &Filenames, StringRef CompilationDir="")

LLVM_ABI Error read(CovMapVersion Version)

Definition CoverageMappingReader.cpp:105

Checks if the given coverage mapping data is exported for an unused function.

LLVM_ABI Expected< bool > isDummy()

Definition CoverageMappingReader.cpp:465

Reader for the raw coverage mapping data.

LLVM_ABI Error read()

Definition CoverageMappingReader.cpp:397

LLVM_ABI Error readSize(uint64_t &Result)

Definition CoverageMappingReader.cpp:87

LLVM_ABI Error readIntMax(uint64_t &Result, uint64_t MaxPlus1)

Definition CoverageMappingReader.cpp:77

LLVM_ABI Error readULEB128(uint64_t &Result)

Definition CoverageMappingReader.cpp:65

LLVM_ABI Error readString(StringRef &Result)

Definition CoverageMappingReader.cpp:96

This class is the base class for all object file types.

Represents a GOFF physical record.

This is a value type class that represents a single section in the list of sections in the object fil...

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

uint64_t ComputeHash(StringRef K)

llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records

LLVM_ABI Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)

LLVM_ABI bool isAvailable()

std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters

The type of MC/DC-specific parameters.

@ invalid_or_missing_arch_specifier

constexpr uint64_t TestingFormatMagic

LLVM_ABI BuildIDRef getBuildID(const ObjectFile *Obj)

Returns the build ID, if any, contained in the given object file.

ArrayRef< uint8_t > BuildIDRef

A reference to a BuildID in binary form.

LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)

Create a Binary from Source, autodetecting the file type.

value_type byte_swap(value_type value, endianness endian)

LLVM_ABI bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)

In-place remove any '.

LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)

Is path absolute?

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)

Construct a string ref from an array ref of unsigned chars.

FunctionAddr VTableAddr uintptr_t uintptr_t FilenamesSize

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

FunctionAddr VTableAddr uintptr_t uintptr_t CoverageSize

uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)

Utility function to decode a ULEB128 value.

uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment)

Returns the necessary adjustment for aligning Addr to Alignment bytes, rounding up.

LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)

Return the name of the profile section corresponding to IPSK.

FunctionAddr VTableAddr uintptr_t uintptr_t Version

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

ArrayRef(const T &OneElt) -> ArrayRef< T >

OutputIt copy(R &&Range, OutputIt Out)

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

FunctionAddr VTableAddr uintptr_t uintptr_t NRecords

void consumeError(Error Err)

Consume a Error without doing anything.

StringRef toStringRef(bool B)

Construct a string ref from a boolean.

bool isAddrAligned(Align Lhs, const void *Addr)

Checks that Addr is a multiple of the alignment.

uintptr_t alignAddr(const void *Addr, Align Alignment)

Aligns Addr to Alignment bytes, rounding up.

unsigned StartingIndex

Definition CoverageMappingReader.cpp:542

unsigned Length

Definition CoverageMappingReader.cpp:543

FilenameRange(unsigned StartingIndex, unsigned Length)

Definition CoverageMappingReader.cpp:545

void markInvalid()

Definition CoverageMappingReader.cpp:548

bool isInvalid() const

Definition CoverageMappingReader.cpp:549

This struct is a compact representation of a valid (non-zero power of two) alignment.

StringRef CoverageMapping

A Counter expression is a value that represents an arithmetic operation with two counters.

A Counter mapping region associates a source range with a specific counter.

@ ExpansionRegion

An ExpansionRegion represents a file expansion region that associates a source range with the expansi...

@ MCDCDecisionRegion

A DecisionRegion represents a top-level boolean expression and is associated with a variable length b...

@ MCDCBranchRegion

A Branch Region can be extended to include IDs to facilitate MC/DC.

@ SkippedRegion

A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...

@ GapRegion

A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...

@ BranchRegion

A BranchRegion represents leaf-level boolean expressions and is associated with two counters,...

@ CodeRegion

A CodeRegion associates some code with a counter.

A Counter is an abstract value that describes how to compute the execution count for a region of code...

static const unsigned EncodingTagBits

static Counter getZero()

Return the counter that represents the number zero.

static Counter getCounter(unsigned CounterId)

Return the counter that corresponds to a specific profile counter.

static const unsigned EncodingCounterTagAndExpansionRegionTagBits

static const unsigned EncodingTagMask

static Counter getExpression(unsigned ExpressionId)

Return the counter that corresponds to a specific addition counter expression.

CovMapFunctionRecordV3 CovMapFuncRecordType

Coverage mapping information for a single function.