LLVM 20.0.0git
CoverageMappingReader.cpp
Go to the documentation of this file.
1//===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains support for reading coverage mapping data for
10// instrumentation based coverage.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Object/Archive.h"
22#include "llvm/Object/Binary.h"
23#include "llvm/Object/COFF.h"
24#include "llvm/Object/Error.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/Endian.h"
32#include "llvm/Support/Error.h"
34#include "llvm/Support/LEB128.h"
36#include "llvm/Support/Path.h"
39#include <vector>
40
41using namespace llvm;
42using namespace coverage;
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() {
51 if (ReadErr != coveragemap_error::success)
52 return;
53
54 // Check if all the records were read or if an error occurred while reading
55 // the next record.
56 if (auto E = Reader->readNextRecord(Record))
57 handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
58 if (CME.get() == coveragemap_error::eof)
60 else
61 ReadErr = CME.get();
62 });
63}
64
66 if (Data.empty())
67 return make_error<CoverageMapError>(coveragemap_error::truncated);
68 unsigned N = 0;
69 Result = decodeULEB128(Data.bytes_begin(), &N);
70 if (N > Data.size())
71 return make_error<CoverageMapError>(coveragemap_error::malformed,
72 "the size of ULEB128 is too big");
73 Data = Data.substr(N);
74 return Error::success();
75}
76
78 if (auto Err = readULEB128(Result))
79 return Err;
80 if (Result >= MaxPlus1)
81 return make_error<CoverageMapError>(
83 "the value of ULEB128 is greater than or equal to MaxPlus1");
84 return Error::success();
85}
86
88 if (auto Err = readULEB128(Result))
89 return Err;
90 if (Result > Data.size())
91 return make_error<CoverageMapError>(coveragemap_error::malformed,
92 "the value of ULEB128 is too big");
93 return Error::success();
94}
95
98 if (auto Err = readSize(Length))
99 return Err;
100 Result = Data.substr(0, Length);
102 return Error::success();
103}
104
106 uint64_t NumFilenames;
107 if (auto Err = readSize(NumFilenames))
108 return Err;
109 if (!NumFilenames)
110 return make_error<CoverageMapError>(coveragemap_error::malformed,
111 "number of filenames is zero");
112
114 return readUncompressed(Version, NumFilenames);
115
116 // The uncompressed length may exceed the size of the encoded filenames.
117 // Skip size validation.
118 uint64_t UncompressedLen;
119 if (auto Err = readULEB128(UncompressedLen))
120 return Err;
121
122 uint64_t CompressedLen;
123 if (auto Err = readSize(CompressedLen))
124 return Err;
125
126 if (CompressedLen > 0) {
128 return make_error<CoverageMapError>(
130
131 // Allocate memory for the decompressed filenames.
132 SmallVector<uint8_t, 0> StorageBuf;
133
134 // Read compressed filenames.
135 StringRef CompressedFilenames = Data.substr(0, CompressedLen);
136 Data = Data.substr(CompressedLen);
138 arrayRefFromStringRef(CompressedFilenames), StorageBuf,
139 UncompressedLen);
140 if (Err) {
141 consumeError(std::move(Err));
142 return make_error<CoverageMapError>(
144 }
145
146 RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,
147 CompilationDir);
148 return Delegate.readUncompressed(Version, NumFilenames);
149 }
150
151 return readUncompressed(Version, NumFilenames);
152}
153
154Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
155 uint64_t NumFilenames) {
156 // Read uncompressed filenames.
158 for (size_t I = 0; I < NumFilenames; ++I) {
159 StringRef Filename;
160 if (auto Err = readString(Filename))
161 return Err;
162 Filenames.push_back(Filename.str());
163 }
164 } else {
165 StringRef CWD;
166 if (auto Err = readString(CWD))
167 return Err;
168 Filenames.push_back(CWD.str());
169
170 for (size_t I = 1; I < NumFilenames; ++I) {
171 StringRef Filename;
172 if (auto Err = readString(Filename))
173 return Err;
174 if (sys::path::is_absolute(Filename)) {
175 Filenames.push_back(Filename.str());
176 } else {
178 if (!CompilationDir.empty())
179 P.assign(CompilationDir);
180 else
181 P.assign(CWD);
182 llvm::sys::path::append(P, Filename);
183 sys::path::remove_dots(P, /*remove_dot_dot=*/true);
184 Filenames.push_back(static_cast<std::string>(P.str()));
185 }
186 }
187 }
188 return Error::success();
189}
190
191Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
193 switch (Tag) {
194 case Counter::Zero:
196 return Error::success();
199 return Error::success();
200 default:
201 break;
202 }
204 switch (Tag) {
208 if (ID >= Expressions.size())
209 return make_error<CoverageMapError>(coveragemap_error::malformed,
210 "counter expression is invalid");
211 Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
213 break;
214 }
215 default:
216 return make_error<CoverageMapError>(coveragemap_error::malformed,
217 "counter expression kind is invalid");
218 }
219 return Error::success();
220}
221
222Error RawCoverageMappingReader::readCounter(Counter &C) {
223 uint64_t EncodedCounter;
224 if (auto Err =
225 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
226 return Err;
227 if (auto Err = decodeCounter(EncodedCounter, C))
228 return Err;
229 return Error::success();
230}
231
232static const unsigned EncodingExpansionRegionBit = 1
234
235/// Read the sub-array of regions for the given inferred file id.
236/// \param NumFileIDs the number of file ids that are defined for this
237/// function.
238Error RawCoverageMappingReader::readMappingRegionsSubArray(
239 std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
240 size_t NumFileIDs) {
241 uint64_t NumRegions;
242 if (auto Err = readSize(NumRegions))
243 return Err;
244 unsigned LineStart = 0;
245 for (size_t I = 0; I < NumRegions; ++I) {
246 Counter C, C2;
247 uint64_t BIDX, NC;
248 // They are stored as internal values plus 1 (min is -1)
249 uint64_t ID1, TID1, FID1;
250 mcdc::Parameters Params;
252
253 // Read the combined counter + region kind.
254 uint64_t EncodedCounterAndRegion;
255 if (auto Err = readIntMax(EncodedCounterAndRegion,
256 std::numeric_limits<unsigned>::max()))
257 return Err;
258 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
259 uint64_t ExpandedFileID = 0;
260
261 // If Tag does not represent a ZeroCounter, then it is understood to refer
262 // to a counter or counter expression with region kind assumed to be
263 // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
264 // referenced counter or counter expression (and nothing else).
265 //
266 // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
267 // then EncodedCounterAndRegion is interpreted to represent an
268 // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
269 // interpreted to refer to a specific region kind, after which additional
270 // fields may be read (e.g. BranchRegions have two encoded counters that
271 // follow an encoded region kind value).
272 if (Tag != Counter::Zero) {
273 if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
274 return Err;
275 } else {
276 // Is it an expansion region?
277 if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
279 ExpandedFileID = EncodedCounterAndRegion >>
281 if (ExpandedFileID >= NumFileIDs)
282 return make_error<CoverageMapError>(coveragemap_error::malformed,
283 "ExpandedFileID is invalid");
284 } else {
285 switch (EncodedCounterAndRegion >>
288 // Don't do anything when we have a code region with a zero counter.
289 break;
292 break;
294 // For a Branch Region, read two successive counters.
296 if (auto Err = readCounter(C))
297 return Err;
298 if (auto Err = readCounter(C2))
299 return Err;
300 break;
302 // For a MCDC Branch Region, read two successive counters and 3 IDs.
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)
315 return make_error<CoverageMapError>(
317 "MCDCConditionID shouldn't be zero");
318 Params = mcdc::BranchParameters{
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<unsigned>::max()))
326 return Err;
327 if (auto Err = readIntMax(NC, std::numeric_limits<int16_t>::max()))
328 return Err;
329 Params = mcdc::DecisionParameters{static_cast<unsigned>(BIDX),
330 static_cast<uint16_t>(NC)};
331 break;
332 default:
333 return make_error<CoverageMapError>(coveragemap_error::malformed,
334 "region kind is incorrect");
335 }
336 }
337 }
338
339 // Read the source range.
340 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
341 if (auto Err =
342 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
343 return Err;
344 if (auto Err = readULEB128(ColumnStart))
345 return Err;
346 if (ColumnStart > std::numeric_limits<unsigned>::max())
347 return make_error<CoverageMapError>(coveragemap_error::malformed,
348 "start column is too big");
349 if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
350 return Err;
351 if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
352 return Err;
353 LineStart += LineStartDelta;
354
355 // If the high bit of ColumnEnd is set, this is a gap region.
356 if (ColumnEnd & (1U << 31)) {
358 ColumnEnd &= ~(1U << 31);
359 }
360
361 // Adjust the column locations for the empty regions that are supposed to
362 // cover whole lines. Those regions should be encoded with the
363 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
364 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
365 // we set the column range to (0 -> 0) to ensure that the column start and
366 // column end take up one byte each.
367 // The std::numeric_limits<unsigned>::max() is used to represent a column
368 // position at the end of the line without knowing the length of that line.
369 if (ColumnStart == 0 && ColumnEnd == 0) {
370 ColumnStart = 1;
371 ColumnEnd = std::numeric_limits<unsigned>::max();
372 }
373
374 LLVM_DEBUG({
375 dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
376 << ColumnStart << " -> " << (LineStart + NumLines) << ":"
377 << ColumnEnd << ", ";
379 dbgs() << "Expands to file " << ExpandedFileID;
380 else
381 CounterMappingContext(Expressions).dump(C, dbgs());
382 dbgs() << "\n";
383 });
384
385 auto CMR = CounterMappingRegion(
386 C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
387 LineStart + NumLines, ColumnEnd, Kind, Params);
388 if (CMR.startLoc() > CMR.endLoc())
389 return make_error<CoverageMapError>(
391 "counter mapping region locations are incorrect");
392 MappingRegions.push_back(CMR);
393 }
394 return Error::success();
395}
396
398 // Read the virtual file mapping.
399 SmallVector<unsigned, 8> VirtualFileMapping;
400 uint64_t NumFileMappings;
401 if (auto Err = readSize(NumFileMappings))
402 return Err;
403 for (size_t I = 0; I < NumFileMappings; ++I) {
404 uint64_t FilenameIndex;
405 if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
406 return Err;
407 VirtualFileMapping.push_back(FilenameIndex);
408 }
409
410 // Construct the files using unique filenames and virtual file mapping.
411 for (auto I : VirtualFileMapping) {
412 Filenames.push_back(TranslationUnitFilenames[I]);
413 }
414
415 // Read the expressions.
416 uint64_t NumExpressions;
417 if (auto Err = readSize(NumExpressions))
418 return Err;
419 // Create an array of dummy expressions that get the proper counters
420 // when the expressions are read, and the proper kinds when the counters
421 // are decoded.
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 // Read the mapping regions sub-arrays.
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 // Set the counters for the expansion regions.
441 // i.e. Counter of expansion region = counter of the first region
442 // from the expanded file.
443 // Perform multiple passes to correctly propagate the counters through
444 // all the nested expansion regions.
445 SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
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
462 return Error::success();
463}
464
466 // A dummy coverage mapping data consists of just one region with zero count.
467 uint64_t NumFileMappings;
468 if (Error Err = readSize(NumFileMappings))
469 return std::move(Err);
470 if (NumFileMappings != 1)
471 return false;
472 // We don't expect any specific value for the filename index, just skip it.
473 uint64_t FilenameIndex;
474 if (Error Err =
475 readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
476 return std::move(Err);
477 uint64_t NumExpressions;
478 if (Error Err = readSize(NumExpressions))
479 return std::move(Err);
480 if (NumExpressions != 0)
481 return false;
482 uint64_t NumRegions;
483 if (Error Err = readSize(NumRegions))
484 return std::move(Err);
485 if (NumRegions != 1)
486 return false;
487 uint64_t EncodedCounterAndRegion;
488 if (Error Err = readIntMax(EncodedCounterAndRegion,
489 std::numeric_limits<unsigned>::max()))
490 return std::move(Err);
491 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
492 return Tag == Counter::Zero;
493}
494
496 Expected<StringRef> DataOrErr = Section.getContents();
497 if (!DataOrErr)
498 return DataOrErr.takeError();
499 Data = *DataOrErr;
500 Address = Section.getAddress();
501
502 // If this is a linked PE/COFF file, then we have to skip over the null byte
503 // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
504 // If the name section is .lprfcovnames, it doesn't have the null byte at the
505 // beginning.
506 const ObjectFile *Obj = Section.getObject();
507 if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
508 if (Expected<StringRef> NameOrErr = Section.getName())
509 if (*NameOrErr != getInstrProfSectionName(IPSK_covname, Triple::COFF))
510 Data = Data.drop_front(1);
511
512 return Error::success();
513}
514
516 if (Pointer < Address)
517 return StringRef();
518 auto Offset = Pointer - Address;
519 if (Offset + Size > Data.size())
520 return StringRef();
521 return Data.substr(Pointer - Address, Size);
522}
523
524// Check if the mapping data is a dummy, i.e. is emitted for an unused function.
526 // The hash value of dummy mapping records is always zero.
527 if (Hash)
528 return false;
529 return RawCoverageMappingDummyChecker(Mapping).isDummy();
530}
531
532/// A range of filename indices. Used to specify the location of a batch of
533/// filenames in a vector-like container.
536 unsigned Length;
537
538 FilenameRange(unsigned StartingIndex, unsigned Length)
539 : StartingIndex(StartingIndex), Length(Length) {}
540
541 void markInvalid() { Length = 0; }
542 bool isInvalid() const { return Length == 0; }
543};
544
545namespace {
546
547/// The interface to read coverage mapping function records for a module.
548struct CovMapFuncRecordReader {
549 virtual ~CovMapFuncRecordReader() = default;
550
551 // Read a coverage header.
552 //
553 // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
554 // mapping data associated with the module.
555 //
556 // Returns a pointer to the next \c CovHeader if it exists, or to an address
557 // greater than \p CovEnd if not.
558 virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
559 const char *CovBufEnd) = 0;
560
561 // Read function records.
562 //
563 // \p FuncRecBuf points to the buffer containing a batch of function records.
564 // \p FuncRecBufEnd points past the end of the batch of records.
565 //
566 // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
567 // associated with the function records. It is unused in Version4.
568 //
569 // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
570 // mappings associated with the function records. It is unused in Version4.
571 virtual Error
572 readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
573 std::optional<FilenameRange> OutOfLineFileRange,
574 const char *OutOfLineMappingBuf,
575 const char *OutOfLineMappingBufEnd) = 0;
576
577 template <class IntPtrT, llvm::endianness Endian>
580 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
581 std::vector<std::string> &F);
582};
583
584// A class for reading coverage mapping function records for a module.
585template <CovMapVersion Version, class IntPtrT, llvm::endianness Endian>
586class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
587 using FuncRecordType =
589 using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
590
591 // Maps function's name references to the indexes of their records
592 // in \c Records.
593 DenseMap<NameRefType, size_t> FunctionRecords;
594 InstrProfSymtab &ProfileNames;
595 StringRef CompilationDir;
596 std::vector<std::string> &Filenames;
597 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
598
599 // Maps a hash of the filenames in a TU to a \c FileRange. The range
600 // specifies the location of the hashed filenames in \c Filenames.
602
603 // Add the record to the collection if we don't already have a record that
604 // points to the same function name. This is useful to ignore the redundant
605 // records for the functions with ODR linkage.
606 // In addition, prefer records with real coverage mapping data to dummy
607 // records, which were emitted for inline functions which were seen but
608 // not used in the corresponding translation unit.
609 Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
610 StringRef Mapping,
611 FilenameRange FileRange) {
612 ++CovMapNumRecords;
613 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
614 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
615 auto InsertResult =
616 FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
617 if (InsertResult.second) {
618 StringRef FuncName;
619 if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
620 return Err;
621 if (FuncName.empty())
622 return make_error<InstrProfError>(instrprof_error::malformed,
623 "function name is empty");
624 ++CovMapNumUsedRecords;
625 Records.emplace_back(Version, FuncName, FuncHash, Mapping,
626 FileRange.StartingIndex, FileRange.Length);
627 return Error::success();
628 }
629 // Update the existing record if it's a dummy and the new record is real.
630 size_t OldRecordIndex = InsertResult.first->second;
632 Records[OldRecordIndex];
633 Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
634 OldRecord.FunctionHash, OldRecord.CoverageMapping);
635 if (Error Err = OldIsDummyExpected.takeError())
636 return Err;
637 if (!*OldIsDummyExpected)
638 return Error::success();
639 Expected<bool> NewIsDummyExpected =
640 isCoverageMappingDummy(FuncHash, Mapping);
641 if (Error Err = NewIsDummyExpected.takeError())
642 return Err;
643 if (*NewIsDummyExpected)
644 return Error::success();
645 ++CovMapNumUsedRecords;
646 OldRecord.FunctionHash = FuncHash;
647 OldRecord.CoverageMapping = Mapping;
648 OldRecord.FilenamesBegin = FileRange.StartingIndex;
649 OldRecord.FilenamesSize = FileRange.Length;
650 return Error::success();
651 }
652
653public:
654 VersionedCovMapFuncRecordReader(
656 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
657 std::vector<std::string> &F)
658 : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
659
660 ~VersionedCovMapFuncRecordReader() override = default;
661
662 Expected<const char *> readCoverageHeader(const char *CovBuf,
663 const char *CovBufEnd) override {
664 using namespace support;
665
666 if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
667 return make_error<CoverageMapError>(
668 coveragemap_error::malformed,
669 "coverage mapping header section is larger than buffer size");
670 auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
671 uint32_t NRecords = CovHeader->getNRecords<Endian>();
672 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
673 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
674 assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
675 CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
676
677 // Skip past the function records, saving the start and end for later.
678 // This is a no-op in Version4 (function records are read after all headers
679 // are read).
680 const char *FuncRecBuf = nullptr;
681 const char *FuncRecBufEnd = nullptr;
682 if (Version < CovMapVersion::Version4)
683 FuncRecBuf = CovBuf;
684 CovBuf += NRecords * sizeof(FuncRecordType);
685 if (Version < CovMapVersion::Version4)
686 FuncRecBufEnd = CovBuf;
687
688 // Get the filenames.
689 if (CovBuf + FilenamesSize > CovBufEnd)
690 return make_error<CoverageMapError>(
691 coveragemap_error::malformed,
692 "filenames section is larger than buffer size");
693 size_t FilenamesBegin = Filenames.size();
694 StringRef FilenameRegion(CovBuf, FilenamesSize);
695 RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
696 CompilationDir);
697 if (auto Err = Reader.read(Version))
698 return std::move(Err);
699 CovBuf += FilenamesSize;
700 FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
701
702 if (Version >= CovMapVersion::Version4) {
703 // Map a hash of the filenames region to the filename range associated
704 // with this coverage header.
705 int64_t FilenamesRef =
707 auto Insert =
708 FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
709 if (!Insert.second) {
710 // The same filenames ref was encountered twice. It's possible that
711 // the associated filenames are the same.
712 auto It = Filenames.begin();
713 FilenameRange &OrigRange = Insert.first->getSecond();
714 if (std::equal(It + OrigRange.StartingIndex,
715 It + OrigRange.StartingIndex + OrigRange.Length,
716 It + FileRange.StartingIndex,
717 It + FileRange.StartingIndex + FileRange.Length))
718 // Map the new range to the original one.
719 FileRange = OrigRange;
720 else
721 // This is a hash collision. Mark the filenames ref invalid.
722 OrigRange.markInvalid();
723 }
724 }
725
726 // We'll read the coverage mapping records in the loop below.
727 // This is a no-op in Version4 (coverage mappings are not affixed to the
728 // coverage header).
729 const char *MappingBuf = CovBuf;
730 if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
731 return make_error<CoverageMapError>(coveragemap_error::malformed,
732 "coverage mapping size is not zero");
733 CovBuf += CoverageSize;
734 const char *MappingEnd = CovBuf;
735
736 if (CovBuf > CovBufEnd)
737 return make_error<CoverageMapError>(
738 coveragemap_error::malformed,
739 "function records section is larger than buffer size");
740
741 if (Version < CovMapVersion::Version4) {
742 // Read each function record.
743 if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
744 MappingBuf, MappingEnd))
745 return std::move(E);
746 }
747
748 // Each coverage map has an alignment of 8, so we need to adjust alignment
749 // before reading the next map.
750 CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
751
752 return CovBuf;
753 }
754
755 Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
756 std::optional<FilenameRange> OutOfLineFileRange,
757 const char *OutOfLineMappingBuf,
758 const char *OutOfLineMappingBufEnd) override {
759 auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
760 while ((const char *)CFR < FuncRecBufEnd) {
761 // Validate the length of the coverage mapping for this function.
762 const char *NextMappingBuf;
763 const FuncRecordType *NextCFR;
764 std::tie(NextMappingBuf, NextCFR) =
765 CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
766 if (Version < CovMapVersion::Version4)
767 if (NextMappingBuf > OutOfLineMappingBufEnd)
768 return make_error<CoverageMapError>(
769 coveragemap_error::malformed,
770 "next mapping buffer is larger than buffer size");
771
772 // Look up the set of filenames associated with this function record.
773 std::optional<FilenameRange> FileRange;
774 if (Version < CovMapVersion::Version4) {
775 FileRange = OutOfLineFileRange;
776 } else {
777 uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
778 auto It = FileRangeMap.find(FilenamesRef);
779 if (It == FileRangeMap.end())
780 return make_error<CoverageMapError>(
781 coveragemap_error::malformed,
782 "no filename found for function with hash=0x" +
783 Twine::utohexstr(FilenamesRef));
784 else
785 FileRange = It->getSecond();
786 }
787
788 // Now, read the coverage data.
789 if (FileRange && !FileRange->isInvalid()) {
790 StringRef Mapping =
791 CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
792 if (Version >= CovMapVersion::Version4 &&
793 Mapping.data() + Mapping.size() > FuncRecBufEnd)
794 return make_error<CoverageMapError>(
795 coveragemap_error::malformed,
796 "coverage mapping data is larger than buffer size");
797 if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
798 return Err;
799 }
800
801 std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
802 }
803 return Error::success();
804 }
805};
806
807} // end anonymous namespace
808
809template <class IntPtrT, llvm::endianness Endian>
810Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
812 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
813 std::vector<std::string> &F) {
814 using namespace coverage;
815
816 switch (Version) {
818 return std::make_unique<VersionedCovMapFuncRecordReader<
826 // Decompress the name data.
827 if (Error E = P.create(P.getNameData()))
828 return std::move(E);
830 return std::make_unique<VersionedCovMapFuncRecordReader<
833 return std::make_unique<VersionedCovMapFuncRecordReader<
836 return std::make_unique<VersionedCovMapFuncRecordReader<
839 return std::make_unique<VersionedCovMapFuncRecordReader<
842 return std::make_unique<VersionedCovMapFuncRecordReader<
845 return std::make_unique<VersionedCovMapFuncRecordReader<
847 }
848 llvm_unreachable("Unsupported version");
849}
850
851template <typename T, llvm::endianness Endian>
853 InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
854 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
855 StringRef CompilationDir, std::vector<std::string> &Filenames) {
856 using namespace coverage;
857
858 // Read the records in the coverage data section.
859 auto CovHeader =
860 reinterpret_cast<const CovMapHeader *>(CovMap.data());
861 CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
863 return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
865 CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
866 CompilationDir, Filenames);
867 if (Error E = ReaderExpected.takeError())
868 return E;
869 auto Reader = std::move(ReaderExpected.get());
870 const char *CovBuf = CovMap.data();
871 const char *CovBufEnd = CovBuf + CovMap.size();
872 const char *FuncRecBuf = FuncRecords.data();
873 const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
874 while (CovBuf < CovBufEnd) {
875 // Read the current coverage header & filename data.
876 //
877 // Prior to Version4, this also reads all function records affixed to the
878 // header.
879 //
880 // Return a pointer to the next coverage header.
881 auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
882 if (auto E = NextOrErr.takeError())
883 return E;
884 CovBuf = NextOrErr.get();
885 }
886 // In Version4, function records are not affixed to coverage headers. Read
887 // the records from their dedicated section.
889 return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
890 nullptr, nullptr);
891 return Error::success();
892}
893
896 StringRef Coverage, FuncRecordsStorage &&FuncRecords,
897 std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
898 llvm::endianness Endian, StringRef CompilationDir) {
899 if (ProfileNamesPtr == nullptr)
900 return make_error<CoverageMapError>(coveragemap_error::malformed,
901 "Caller must provide ProfileNames");
902 std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader(
903 std::move(ProfileNamesPtr), std::move(FuncRecords)));
904 InstrProfSymtab &ProfileNames = *Reader->ProfileNames;
905 StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
906 if (BytesInAddress == 4 && Endian == llvm::endianness::little) {
907 if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(
908 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
909 CompilationDir, Reader->Filenames))
910 return std::move(E);
911 } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) {
912 if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(
913 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
914 CompilationDir, Reader->Filenames))
915 return std::move(E);
916 } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) {
917 if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(
918 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
919 CompilationDir, Reader->Filenames))
920 return std::move(E);
921 } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) {
922 if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(
923 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
924 CompilationDir, Reader->Filenames))
925 return std::move(E);
926 } else
927 return make_error<CoverageMapError>(
929 "not supported endianness or bytes in address");
930 return std::move(Reader);
931}
932
935 uint8_t BytesInAddress = 8;
937
938 // Read the magic and version.
939 Data = Data.substr(sizeof(TestingFormatMagic));
940 if (Data.size() < sizeof(uint64_t))
941 return make_error<CoverageMapError>(coveragemap_error::malformed,
942 "the size of data is too small");
943 auto TestingVersion =
944 support::endian::byte_swap<uint64_t, llvm::endianness::little>(
945 *reinterpret_cast<const uint64_t *>(Data.data()));
946 Data = Data.substr(sizeof(uint64_t));
947
948 // Read the ProfileNames data.
949 if (Data.empty())
950 return make_error<CoverageMapError>(coveragemap_error::truncated);
951 unsigned N = 0;
952 uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
953 if (N > Data.size())
954 return make_error<CoverageMapError>(
956 "the size of TestingFormatMagic is too big");
957 Data = Data.substr(N);
958 if (Data.empty())
959 return make_error<CoverageMapError>(coveragemap_error::truncated);
960 N = 0;
961 uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
962 if (N > Data.size())
963 return make_error<CoverageMapError>(coveragemap_error::malformed,
964 "the size of ULEB128 is too big");
965 Data = Data.substr(N);
966 if (Data.size() < ProfileNamesSize)
967 return make_error<CoverageMapError>(coveragemap_error::malformed,
968 "the size of ProfileNames is too big");
969 auto ProfileNames = std::make_unique<InstrProfSymtab>();
970 if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address))
971 return std::move(E);
972 Data = Data.substr(ProfileNamesSize);
973
974 // In Version2, the size of CoverageMapping is stored directly.
975 uint64_t CoverageMappingSize;
976 if (TestingVersion == uint64_t(TestingFormatVersion::Version2)) {
977 N = 0;
978 CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N);
979 if (N > Data.size())
980 return make_error<CoverageMapError>(coveragemap_error::malformed,
981 "the size of ULEB128 is too big");
982 Data = Data.substr(N);
983 if (CoverageMappingSize < sizeof(CovMapHeader))
984 return make_error<CoverageMapError>(
986 "the size of CoverageMapping is teoo small");
987 } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) {
988 return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
989 }
990
991 // Skip the padding bytes because coverage map data has an alignment of 8.
992 auto Pad = offsetToAlignedAddr(Data.data(), Align(8));
993 if (Data.size() < Pad)
994 return make_error<CoverageMapError>(coveragemap_error::malformed,
995 "insufficient padding");
996 Data = Data.substr(Pad);
997 if (Data.size() < sizeof(CovMapHeader))
998 return make_error<CoverageMapError>(
1000 "coverage mapping header section is larger than data size");
1001 auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
1002 Data.substr(0, sizeof(CovMapHeader)).data());
1003 auto Version =
1004 CovMapVersion(CovHeader->getVersion<llvm::endianness::little>());
1005
1006 // In Version1, the size of CoverageMapping is calculated.
1007 if (TestingVersion == uint64_t(TestingFormatVersion::Version1)) {
1009 CoverageMappingSize = Data.size();
1010 } else {
1011 auto FilenamesSize =
1012 CovHeader->getFilenamesSize<llvm::endianness::little>();
1013 CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
1014 }
1015 }
1016
1017 auto CoverageMapping = Data.substr(0, CoverageMappingSize);
1018 Data = Data.substr(CoverageMappingSize);
1019
1020 // Read the CoverageRecords data.
1022 if (!Data.empty())
1023 return make_error<CoverageMapError>(coveragemap_error::malformed,
1024 "data is not empty");
1025 } else {
1026 // Skip the padding bytes because coverage records data has an alignment
1027 // of 8.
1028 Pad = offsetToAlignedAddr(Data.data(), Align(8));
1029 if (Data.size() < Pad)
1030 return make_error<CoverageMapError>(coveragemap_error::malformed,
1031 "insufficient padding");
1032 Data = Data.substr(Pad);
1033 }
1036
1038 CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
1039 BytesInAddress, Endian, CompilationDir);
1040}
1041
1042/// Find all sections that match \p IPSK name. There may be more than one if
1043/// comdats are in use, e.g. for the __llvm_covfun section on ELF.
1046 auto ObjFormat = OF.getTripleObjectFormat();
1047 auto Name =
1048 getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false);
1049 // On COFF, the object file section name may end in "$M". This tells the
1050 // linker to sort these sections between "$A" and "$Z". The linker removes the
1051 // dollar and everything after it in the final binary. Do the same to match.
1052 bool IsCOFF = isa<COFFObjectFile>(OF);
1053 auto stripSuffix = [IsCOFF](StringRef N) {
1054 return IsCOFF ? N.split('$').first : N;
1055 };
1056 Name = stripSuffix(Name);
1057
1058 std::vector<SectionRef> Sections;
1059 for (const auto &Section : OF.sections()) {
1060 Expected<StringRef> NameOrErr = Section.getName();
1061 if (!NameOrErr)
1062 return NameOrErr.takeError();
1063 if (stripSuffix(*NameOrErr) == Name) {
1064 // COFF profile name section contains two null bytes indicating the
1065 // start/end of the section. If its size is 2 bytes, it's empty.
1066 if (IsCOFF && IPSK == IPSK_name && Section.getSize() == 2)
1067 continue;
1068 Sections.push_back(Section);
1069 }
1070 }
1071 if (Sections.empty())
1072 return make_error<CoverageMapError>(coveragemap_error::no_data_found);
1073 return Sections;
1074}
1075
1077loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
1078 StringRef CompilationDir = "",
1079 object::BuildIDRef *BinaryID = nullptr) {
1080 std::unique_ptr<ObjectFile> OF;
1081 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1082 // If we have a universal binary, try to look up the object for the
1083 // appropriate architecture.
1084 auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
1085 if (!ObjectFileOrErr)
1086 return ObjectFileOrErr.takeError();
1087 OF = std::move(ObjectFileOrErr.get());
1088 } else if (isa<ObjectFile>(Bin.get())) {
1089 // For any other object file, upcast and take ownership.
1090 OF.reset(cast<ObjectFile>(Bin.release()));
1091 // If we've asked for a particular arch, make sure they match.
1092 if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
1093 return errorCodeToError(object_error::arch_not_found);
1094 } else
1095 // We can only handle object files.
1096 return make_error<CoverageMapError>(coveragemap_error::malformed,
1097 "binary is not an object file");
1098
1099 // The coverage uses native pointer sizes for the object it's written in.
1100 uint8_t BytesInAddress = OF->getBytesInAddress();
1102 OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;
1103
1104 // Look for the sections that we are interested in.
1105 auto ProfileNames = std::make_unique<InstrProfSymtab>();
1106 std::vector<SectionRef> NamesSectionRefs;
1107 // If IPSK_name is not found, fallback to search for IPK_covname, which is
1108 // used when binary correlation is enabled.
1109 auto NamesSection = lookupSections(*OF, IPSK_name);
1110 if (auto E = NamesSection.takeError()) {
1111 consumeError(std::move(E));
1112 NamesSection = lookupSections(*OF, IPSK_covname);
1113 if (auto E = NamesSection.takeError())
1114 return std::move(E);
1115 }
1116 NamesSectionRefs = *NamesSection;
1117
1118 if (NamesSectionRefs.size() != 1)
1119 return make_error<CoverageMapError>(
1121 "the size of coverage mapping section is not one");
1122 if (Error E = ProfileNames->create(NamesSectionRefs.back()))
1123 return std::move(E);
1124
1125 auto CoverageSection = lookupSections(*OF, IPSK_covmap);
1126 if (auto E = CoverageSection.takeError())
1127 return std::move(E);
1128 std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
1129 if (CoverageSectionRefs.size() != 1)
1130 return make_error<CoverageMapError>(coveragemap_error::malformed,
1131 "the size of name section is not one");
1132 auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
1133 if (!CoverageMappingOrErr)
1134 return CoverageMappingOrErr.takeError();
1135 StringRef CoverageMapping = CoverageMappingOrErr.get();
1136
1137 // Look for the coverage records section (Version4 only).
1138 auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun);
1139
1141 if (auto E = CoverageRecordsSections.takeError()) {
1142 consumeError(std::move(E));
1143 FuncRecords = MemoryBuffer::getMemBuffer("");
1144 } else {
1145 // Compute the FuncRecordsBuffer of the buffer, taking into account the
1146 // padding between each record, and making sure the first block is aligned
1147 // in memory to maintain consistency between buffer address and size
1148 // alignment.
1149 const Align RecordAlignment(8);
1150 uint64_t FuncRecordsSize = 0;
1151 for (SectionRef Section : *CoverageRecordsSections) {
1152 auto CoverageRecordsOrErr = Section.getContents();
1153 if (!CoverageRecordsOrErr)
1154 return CoverageRecordsOrErr.takeError();
1155 FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1156 }
1157 auto WritableBuffer =
1159 char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
1160 assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&
1161 "Allocated memory is correctly aligned");
1162
1163 for (SectionRef Section : *CoverageRecordsSections) {
1164 auto CoverageRecordsOrErr = Section.getContents();
1165 if (!CoverageRecordsOrErr)
1166 return CoverageRecordsOrErr.takeError();
1167 const auto &CoverageRecords = CoverageRecordsOrErr.get();
1168 FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
1169 CoverageRecords.end(), FuncRecordsBuffer);
1170 FuncRecordsBuffer =
1171 std::fill_n(FuncRecordsBuffer,
1172 alignAddr(FuncRecordsBuffer, RecordAlignment) -
1173 (uintptr_t)FuncRecordsBuffer,
1174 '\0');
1175 }
1176 assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
1177 "consistent init");
1178 FuncRecords = std::move(WritableBuffer);
1179 }
1180
1181 if (BinaryID)
1182 *BinaryID = getBuildID(OF.get());
1183
1185 CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
1186 BytesInAddress, Endian, CompilationDir);
1187}
1188
1189/// Determine whether \p Arch is invalid or empty, given \p Bin.
1191 // If we have a universal binary and Arch doesn't identify any of its slices,
1192 // it's user error.
1193 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
1194 for (auto &ObjForArch : Universal->objects())
1195 if (Arch == ObjForArch.getArchFlagName())
1196 return false;
1197 return true;
1198 }
1199 return false;
1200}
1201
1204 MemoryBufferRef ObjectBuffer, StringRef Arch,
1205 SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
1206 StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
1207 std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
1208
1209 if (ObjectBuffer.getBuffer().size() > sizeof(TestingFormatMagic)) {
1210 uint64_t Magic =
1211 support::endian::byte_swap<uint64_t, llvm::endianness::little>(
1212 *reinterpret_cast<const uint64_t *>(ObjectBuffer.getBufferStart()));
1213 if (Magic == TestingFormatMagic) {
1214 // This is a special format used for testing.
1215 auto ReaderOrErr =
1216 loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
1217 if (!ReaderOrErr)
1218 return ReaderOrErr.takeError();
1219 Readers.push_back(std::move(ReaderOrErr.get()));
1220 return std::move(Readers);
1221 }
1222 }
1223
1224 auto BinOrErr = createBinary(ObjectBuffer);
1225 if (!BinOrErr)
1226 return BinOrErr.takeError();
1227 std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
1228
1229 if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
1230 return make_error<CoverageMapError>(
1232
1233 // MachO universal binaries which contain archives need to be treated as
1234 // archives, not as regular binaries.
1235 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1236 for (auto &ObjForArch : Universal->objects()) {
1237 // Skip slices within the universal binary which target the wrong arch.
1238 std::string ObjArch = ObjForArch.getArchFlagName();
1239 if (Arch != ObjArch)
1240 continue;
1241
1242 auto ArchiveOrErr = ObjForArch.getAsArchive();
1243 if (!ArchiveOrErr) {
1244 // If this is not an archive, try treating it as a regular object.
1245 consumeError(ArchiveOrErr.takeError());
1246 break;
1247 }
1248
1250 ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1251 CompilationDir, BinaryIDs);
1252 }
1253 }
1254
1255 // Load coverage out of archive members.
1256 if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1257 Error Err = Error::success();
1258 for (auto &Child : Ar->children(Err)) {
1259 Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1260 if (!ChildBufOrErr)
1261 return ChildBufOrErr.takeError();
1262
1263 auto ChildReadersOrErr = BinaryCoverageReader::create(
1264 ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,
1265 BinaryIDs);
1266 if (!ChildReadersOrErr)
1267 return ChildReadersOrErr.takeError();
1268 for (auto &Reader : ChildReadersOrErr.get())
1269 Readers.push_back(std::move(Reader));
1270 }
1271 if (Err)
1272 return std::move(Err);
1273
1274 // Thin archives reference object files outside of the archive file, i.e.
1275 // files which reside in memory not owned by the caller. Transfer ownership
1276 // to the caller.
1277 if (Ar->isThin())
1278 for (auto &Buffer : Ar->takeThinBuffers())
1279 ObjectFileBuffers.push_back(std::move(Buffer));
1280
1281 return std::move(Readers);
1282 }
1283
1284 object::BuildIDRef BinaryID;
1285 auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
1286 BinaryIDs ? &BinaryID : nullptr);
1287 if (!ReaderOrErr)
1288 return ReaderOrErr.takeError();
1289 Readers.push_back(std::move(ReaderOrErr.get()));
1290 if (!BinaryID.empty())
1291 BinaryIDs->push_back(BinaryID);
1292 return std::move(Readers);
1293}
1294
1296 if (CurrentRecord >= MappingRecords.size())
1297 return make_error<CoverageMapError>(coveragemap_error::eof);
1298
1299 FunctionsFilenames.clear();
1300 Expressions.clear();
1301 MappingRegions.clear();
1302 auto &R = MappingRecords[CurrentRecord];
1303 auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
1304 RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
1305 Expressions, MappingRegions);
1306 if (auto Err = Reader.read())
1307 return Err;
1308
1309 Record.FunctionName = R.FunctionName;
1310 Record.FunctionHash = R.FunctionHash;
1311 Record.Filenames = FunctionsFilenames;
1312 Record.Expressions = Expressions;
1313 Record.MappingRegions = MappingRegions;
1314
1315 ++CurrentRecord;
1316 return Error::success();
1317}
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)
static Expected< std::unique_ptr< BinaryCoverageReader > > loadBinaryFormat(std::unique_ptr< Binary > Bin, StringRef Arch, StringRef CompilationDir="", object::BuildIDRef *BinaryID=nullptr)
static Expected< std::unique_ptr< BinaryCoverageReader > > loadTestingFormat(StringRef Data, StringRef CompilationDir)
static Expected< std::vector< SectionRef > > lookupSections(ObjectFile &OF, InstrProfSectKind IPSK)
Find all sections that match IPSK name.
static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch)
Determine whether Arch is invalid or empty, given Bin.
static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)
static const unsigned EncodingExpansionRegionBit
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseMap class.
std::string Name
uint64_t Size
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
endianness Endian
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)
Definition: Statistic.h:166
Value * RHS
Value * LHS
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition: ArrayRef.h:195
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:211
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
reference get()
Returns a reference to the stored T value.
Definition: Error.h:578
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Definition: InstrProf.h:458
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
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.
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:94
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void resize(size_type N)
Definition: SmallVector.h:651
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:215
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:556
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:416
LLVM Value Representation.
Definition: Value.h:74
static 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.
Reader for the coverage mapping data that is emitted by the frontend and stored in an object file.
static Expected< std::unique_ptr< BinaryCoverageReader > > createCoverageReaderFromBuffer(StringRef Coverage, FuncRecordsStorage &&FuncRecords, std::unique_ptr< InstrProfSymtab > ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir="")
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)
std::unique_ptr< MemoryBuffer > FuncRecordsStorage
Error readNextRecord(CoverageMappingRecord &Record) override
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
void dump(const Counter &C, raw_ostream &OS) const
coveragemap_error get() const
A file format agnostic iterator over coverage mapping data.
virtual Error readNextRecord(CoverageMappingRecord &Record)=0
The mapping of profile information to coverage data.
Reader for the raw coverage filenames.
Checks if the given coverage mapping data is exported for an unused function.
Reader for the raw coverage mapping data.
Error readIntMax(uint64_t &Result, uint64_t MaxPlus1)
Triple::ObjectFormatType getTripleObjectFormat() const
Definition: Binary.h:163
This class is the base class for all object file types.
Definition: ObjectFile.h:229
section_iterator_range sections() const
Definition: ObjectFile.h:329
virtual bool isRelocatableObject() const =0
True if this is a relocatable object (.o/.obj).
Represents a GOFF physical record.
Definition: GOFF.h:31
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:1119
llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records
Definition: RecordsSlice.h:197
Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition: MCDCTypes.h:56
constexpr uint64_t TestingFormatMagic
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
BuildIDRef getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
Definition: BuildID.cpp:56
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:45
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition: Path.cpp:716
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:672
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
@ Length
Definition: DWP.cpp:480
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:977
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.
Definition: LEB128.h:131
uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment)
Returns the necessary adjustment for aligning Addr to Alignment bytes, rounding up.
Definition: Alignment.h:203
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
Definition: InstrProf.cpp:236
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
InstrProfSectKind
Definition: InstrProf.h:60
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:111
endianness
Definition: bit.h:70
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1069
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition: Alignment.h:150
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
Definition: Alignment.h:187
#define N
#define NC
Definition: regutils.h:42
A range of filename indices.
FilenameRange(unsigned StartingIndex, unsigned Length)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
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.
Coverage mapping information for a single function.