LLVM 17.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 Data = Data.substr(N);
73 return Error::success();
74}
75
77 if (auto Err = readULEB128(Result))
78 return Err;
79 if (Result >= MaxPlus1)
80 return make_error<CoverageMapError>(coveragemap_error::malformed);
81 return Error::success();
82}
83
85 if (auto Err = readULEB128(Result))
86 return Err;
87 if (Result > Data.size())
88 return make_error<CoverageMapError>(coveragemap_error::malformed);
89 return Error::success();
90}
91
94 if (auto Err = readSize(Length))
95 return Err;
96 Result = Data.substr(0, Length);
98 return Error::success();
99}
100
102 uint64_t NumFilenames;
103 if (auto Err = readSize(NumFilenames))
104 return Err;
105 if (!NumFilenames)
106 return make_error<CoverageMapError>(coveragemap_error::malformed);
107
108 if (Version < CovMapVersion::Version4)
109 return readUncompressed(Version, NumFilenames);
110
111 // The uncompressed length may exceed the size of the encoded filenames.
112 // Skip size validation.
113 uint64_t UncompressedLen;
114 if (auto Err = readULEB128(UncompressedLen))
115 return Err;
116
117 uint64_t CompressedLen;
118 if (auto Err = readSize(CompressedLen))
119 return Err;
120
121 if (CompressedLen > 0) {
123 return make_error<CoverageMapError>(
125
126 // Allocate memory for the decompressed filenames.
127 SmallVector<uint8_t, 0> StorageBuf;
128
129 // Read compressed filenames.
130 StringRef CompressedFilenames = Data.substr(0, CompressedLen);
131 Data = Data.substr(CompressedLen);
133 arrayRefFromStringRef(CompressedFilenames), StorageBuf,
134 UncompressedLen);
135 if (Err) {
136 consumeError(std::move(Err));
137 return make_error<CoverageMapError>(
139 }
140
141 RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,
142 CompilationDir);
143 return Delegate.readUncompressed(Version, NumFilenames);
144 }
145
146 return readUncompressed(Version, NumFilenames);
147}
148
149Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
150 uint64_t NumFilenames) {
151 // Read uncompressed filenames.
152 if (Version < CovMapVersion::Version6) {
153 for (size_t I = 0; I < NumFilenames; ++I) {
154 StringRef Filename;
155 if (auto Err = readString(Filename))
156 return Err;
157 Filenames.push_back(Filename.str());
158 }
159 } else {
160 StringRef CWD;
161 if (auto Err = readString(CWD))
162 return Err;
163 Filenames.push_back(CWD.str());
164
165 for (size_t I = 1; I < NumFilenames; ++I) {
166 StringRef Filename;
167 if (auto Err = readString(Filename))
168 return Err;
169 if (sys::path::is_absolute(Filename)) {
170 Filenames.push_back(Filename.str());
171 } else {
173 if (!CompilationDir.empty())
174 P.assign(CompilationDir);
175 else
176 P.assign(CWD);
177 llvm::sys::path::append(P, Filename);
178 sys::path::remove_dots(P, /*remove_dot_dot=*/true);
179 Filenames.push_back(static_cast<std::string>(P.str()));
180 }
181 }
182 }
183 return Error::success();
184}
185
186Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
188 switch (Tag) {
189 case Counter::Zero:
191 return Error::success();
194 return Error::success();
195 default:
196 break;
197 }
199 switch (Tag) {
203 if (ID >= Expressions.size())
204 return make_error<CoverageMapError>(coveragemap_error::malformed);
205 Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
207 break;
208 }
209 default:
210 return make_error<CoverageMapError>(coveragemap_error::malformed);
211 }
212 return Error::success();
213}
214
215Error RawCoverageMappingReader::readCounter(Counter &C) {
216 uint64_t EncodedCounter;
217 if (auto Err =
218 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
219 return Err;
220 if (auto Err = decodeCounter(EncodedCounter, C))
221 return Err;
222 return Error::success();
223}
224
225static const unsigned EncodingExpansionRegionBit = 1
227
228/// Read the sub-array of regions for the given inferred file id.
229/// \param NumFileIDs the number of file ids that are defined for this
230/// function.
231Error RawCoverageMappingReader::readMappingRegionsSubArray(
232 std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
233 size_t NumFileIDs) {
234 uint64_t NumRegions;
235 if (auto Err = readSize(NumRegions))
236 return Err;
237 unsigned LineStart = 0;
238 for (size_t I = 0; I < NumRegions; ++I) {
239 Counter C, C2;
241
242 // Read the combined counter + region kind.
243 uint64_t EncodedCounterAndRegion;
244 if (auto Err = readIntMax(EncodedCounterAndRegion,
245 std::numeric_limits<unsigned>::max()))
246 return Err;
247 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
248 uint64_t ExpandedFileID = 0;
249
250 // If Tag does not represent a ZeroCounter, then it is understood to refer
251 // to a counter or counter expression with region kind assumed to be
252 // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
253 // referenced counter or counter expression (and nothing else).
254 //
255 // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
256 // then EncodedCounterAndRegion is interpreted to represent an
257 // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
258 // interpreted to refer to a specific region kind, after which additional
259 // fields may be read (e.g. BranchRegions have two encoded counters that
260 // follow an encoded region kind value).
261 if (Tag != Counter::Zero) {
262 if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
263 return Err;
264 } else {
265 // Is it an expansion region?
266 if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
268 ExpandedFileID = EncodedCounterAndRegion >>
270 if (ExpandedFileID >= NumFileIDs)
271 return make_error<CoverageMapError>(coveragemap_error::malformed);
272 } else {
273 switch (EncodedCounterAndRegion >>
276 // Don't do anything when we have a code region with a zero counter.
277 break;
280 break;
282 // For a Branch Region, read two successive counters.
284 if (auto Err = readCounter(C))
285 return Err;
286 if (auto Err = readCounter(C2))
287 return Err;
288 break;
289 default:
290 return make_error<CoverageMapError>(coveragemap_error::malformed);
291 }
292 }
293 }
294
295 // Read the source range.
296 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
297 if (auto Err =
298 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
299 return Err;
300 if (auto Err = readULEB128(ColumnStart))
301 return Err;
302 if (ColumnStart > std::numeric_limits<unsigned>::max())
303 return make_error<CoverageMapError>(coveragemap_error::malformed);
304 if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
305 return Err;
306 if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
307 return Err;
308 LineStart += LineStartDelta;
309
310 // If the high bit of ColumnEnd is set, this is a gap region.
311 if (ColumnEnd & (1U << 31)) {
313 ColumnEnd &= ~(1U << 31);
314 }
315
316 // Adjust the column locations for the empty regions that are supposed to
317 // cover whole lines. Those regions should be encoded with the
318 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
319 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
320 // we set the column range to (0 -> 0) to ensure that the column start and
321 // column end take up one byte each.
322 // The std::numeric_limits<unsigned>::max() is used to represent a column
323 // position at the end of the line without knowing the length of that line.
324 if (ColumnStart == 0 && ColumnEnd == 0) {
325 ColumnStart = 1;
326 ColumnEnd = std::numeric_limits<unsigned>::max();
327 }
328
329 LLVM_DEBUG({
330 dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
331 << ColumnStart << " -> " << (LineStart + NumLines) << ":"
332 << ColumnEnd << ", ";
334 dbgs() << "Expands to file " << ExpandedFileID;
335 else
336 CounterMappingContext(Expressions).dump(C, dbgs());
337 dbgs() << "\n";
338 });
339
340 auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
341 LineStart, ColumnStart,
342 LineStart + NumLines, ColumnEnd, Kind);
343 if (CMR.startLoc() > CMR.endLoc())
344 return make_error<CoverageMapError>(coveragemap_error::malformed);
345 MappingRegions.push_back(CMR);
346 }
347 return Error::success();
348}
349
351 // Read the virtual file mapping.
352 SmallVector<unsigned, 8> VirtualFileMapping;
353 uint64_t NumFileMappings;
354 if (auto Err = readSize(NumFileMappings))
355 return Err;
356 for (size_t I = 0; I < NumFileMappings; ++I) {
357 uint64_t FilenameIndex;
358 if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
359 return Err;
360 VirtualFileMapping.push_back(FilenameIndex);
361 }
362
363 // Construct the files using unique filenames and virtual file mapping.
364 for (auto I : VirtualFileMapping) {
365 Filenames.push_back(TranslationUnitFilenames[I]);
366 }
367
368 // Read the expressions.
369 uint64_t NumExpressions;
370 if (auto Err = readSize(NumExpressions))
371 return Err;
372 // Create an array of dummy expressions that get the proper counters
373 // when the expressions are read, and the proper kinds when the counters
374 // are decoded.
375 Expressions.resize(
376 NumExpressions,
378 for (size_t I = 0; I < NumExpressions; ++I) {
379 if (auto Err = readCounter(Expressions[I].LHS))
380 return Err;
381 if (auto Err = readCounter(Expressions[I].RHS))
382 return Err;
383 }
384
385 // Read the mapping regions sub-arrays.
386 for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
387 InferredFileID < S; ++InferredFileID) {
388 if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
389 VirtualFileMapping.size()))
390 return Err;
391 }
392
393 // Set the counters for the expansion regions.
394 // i.e. Counter of expansion region = counter of the first region
395 // from the expanded file.
396 // Perform multiple passes to correctly propagate the counters through
397 // all the nested expansion regions.
398 SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
399 FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
400 for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
401 for (auto &R : MappingRegions) {
403 continue;
404 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
405 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
406 }
407 for (auto &R : MappingRegions) {
408 if (FileIDExpansionRegionMapping[R.FileID]) {
409 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
410 FileIDExpansionRegionMapping[R.FileID] = nullptr;
411 }
412 }
413 }
414
415 return Error::success();
416}
417
419 // A dummy coverage mapping data consists of just one region with zero count.
420 uint64_t NumFileMappings;
421 if (Error Err = readSize(NumFileMappings))
422 return std::move(Err);
423 if (NumFileMappings != 1)
424 return false;
425 // We don't expect any specific value for the filename index, just skip it.
426 uint64_t FilenameIndex;
427 if (Error Err =
428 readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
429 return std::move(Err);
430 uint64_t NumExpressions;
431 if (Error Err = readSize(NumExpressions))
432 return std::move(Err);
433 if (NumExpressions != 0)
434 return false;
435 uint64_t NumRegions;
436 if (Error Err = readSize(NumRegions))
437 return std::move(Err);
438 if (NumRegions != 1)
439 return false;
440 uint64_t EncodedCounterAndRegion;
441 if (Error Err = readIntMax(EncodedCounterAndRegion,
442 std::numeric_limits<unsigned>::max()))
443 return std::move(Err);
444 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
445 return Tag == Counter::Zero;
446}
447
449 Expected<StringRef> DataOrErr = Section.getContents();
450 if (!DataOrErr)
451 return DataOrErr.takeError();
452 Data = *DataOrErr;
453 Address = Section.getAddress();
454
455 // If this is a linked PE/COFF file, then we have to skip over the null byte
456 // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
457 const ObjectFile *Obj = Section.getObject();
458 if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
459 Data = Data.drop_front(1);
460
461 return Error::success();
462}
463
465 if (Pointer < Address)
466 return StringRef();
467 auto Offset = Pointer - Address;
468 if (Offset + Size > Data.size())
469 return StringRef();
470 return Data.substr(Pointer - Address, Size);
471}
472
473// Check if the mapping data is a dummy, i.e. is emitted for an unused function.
475 // The hash value of dummy mapping records is always zero.
476 if (Hash)
477 return false;
478 return RawCoverageMappingDummyChecker(Mapping).isDummy();
479}
480
481/// A range of filename indices. Used to specify the location of a batch of
482/// filenames in a vector-like container.
485 unsigned Length;
486
487 FilenameRange(unsigned StartingIndex, unsigned Length)
488 : StartingIndex(StartingIndex), Length(Length) {}
489
490 void markInvalid() { Length = 0; }
491 bool isInvalid() const { return Length == 0; }
492};
493
494namespace {
495
496/// The interface to read coverage mapping function records for a module.
497struct CovMapFuncRecordReader {
498 virtual ~CovMapFuncRecordReader() = default;
499
500 // Read a coverage header.
501 //
502 // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
503 // mapping data associated with the module.
504 //
505 // Returns a pointer to the next \c CovHeader if it exists, or to an address
506 // greater than \p CovEnd if not.
507 virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
508 const char *CovBufEnd) = 0;
509
510 // Read function records.
511 //
512 // \p FuncRecBuf points to the buffer containing a batch of function records.
513 // \p FuncRecBufEnd points past the end of the batch of records.
514 //
515 // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
516 // associated with the function records. It is unused in Version4.
517 //
518 // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
519 // mappings associated with the function records. It is unused in Version4.
520 virtual Error
521 readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
522 std::optional<FilenameRange> OutOfLineFileRange,
523 const char *OutOfLineMappingBuf,
524 const char *OutOfLineMappingBufEnd) = 0;
525
526 template <class IntPtrT, support::endianness Endian>
529 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
530 std::vector<std::string> &F);
531};
532
533// A class for reading coverage mapping function records for a module.
534template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
535class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
536 using FuncRecordType =
538 using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
539
540 // Maps function's name references to the indexes of their records
541 // in \c Records.
542 DenseMap<NameRefType, size_t> FunctionRecords;
543 InstrProfSymtab &ProfileNames;
544 StringRef CompilationDir;
545 std::vector<std::string> &Filenames;
546 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
547
548 // Maps a hash of the filenames in a TU to a \c FileRange. The range
549 // specifies the location of the hashed filenames in \c Filenames.
551
552 // Add the record to the collection if we don't already have a record that
553 // points to the same function name. This is useful to ignore the redundant
554 // records for the functions with ODR linkage.
555 // In addition, prefer records with real coverage mapping data to dummy
556 // records, which were emitted for inline functions which were seen but
557 // not used in the corresponding translation unit.
558 Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
559 StringRef Mapping,
560 FilenameRange FileRange) {
561 ++CovMapNumRecords;
562 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
563 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
564 auto InsertResult =
565 FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
566 if (InsertResult.second) {
567 StringRef FuncName;
568 if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
569 return Err;
570 if (FuncName.empty())
571 return make_error<InstrProfError>(instrprof_error::malformed,
572 "function name is empty");
573 ++CovMapNumUsedRecords;
574 Records.emplace_back(Version, FuncName, FuncHash, Mapping,
575 FileRange.StartingIndex, FileRange.Length);
576 return Error::success();
577 }
578 // Update the existing record if it's a dummy and the new record is real.
579 size_t OldRecordIndex = InsertResult.first->second;
581 Records[OldRecordIndex];
582 Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
583 OldRecord.FunctionHash, OldRecord.CoverageMapping);
584 if (Error Err = OldIsDummyExpected.takeError())
585 return Err;
586 if (!*OldIsDummyExpected)
587 return Error::success();
588 Expected<bool> NewIsDummyExpected =
589 isCoverageMappingDummy(FuncHash, Mapping);
590 if (Error Err = NewIsDummyExpected.takeError())
591 return Err;
592 if (*NewIsDummyExpected)
593 return Error::success();
594 ++CovMapNumUsedRecords;
595 OldRecord.FunctionHash = FuncHash;
596 OldRecord.CoverageMapping = Mapping;
597 OldRecord.FilenamesBegin = FileRange.StartingIndex;
598 OldRecord.FilenamesSize = FileRange.Length;
599 return Error::success();
600 }
601
602public:
603 VersionedCovMapFuncRecordReader(
605 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
606 std::vector<std::string> &F)
607 : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
608
609 ~VersionedCovMapFuncRecordReader() override = default;
610
611 Expected<const char *> readCoverageHeader(const char *CovBuf,
612 const char *CovBufEnd) override {
613 using namespace support;
614
615 if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
616 return make_error<CoverageMapError>(coveragemap_error::malformed);
617 auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
618 uint32_t NRecords = CovHeader->getNRecords<Endian>();
619 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
620 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
621 assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
622 CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
623
624 // Skip past the function records, saving the start and end for later.
625 // This is a no-op in Version4 (function records are read after all headers
626 // are read).
627 const char *FuncRecBuf = nullptr;
628 const char *FuncRecBufEnd = nullptr;
629 if (Version < CovMapVersion::Version4)
630 FuncRecBuf = CovBuf;
631 CovBuf += NRecords * sizeof(FuncRecordType);
632 if (Version < CovMapVersion::Version4)
633 FuncRecBufEnd = CovBuf;
634
635 // Get the filenames.
636 if (CovBuf + FilenamesSize > CovBufEnd)
637 return make_error<CoverageMapError>(coveragemap_error::malformed);
638 size_t FilenamesBegin = Filenames.size();
639 StringRef FilenameRegion(CovBuf, FilenamesSize);
640 RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
641 CompilationDir);
642 if (auto Err = Reader.read(Version))
643 return std::move(Err);
644 CovBuf += FilenamesSize;
645 FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
646
647 if (Version >= CovMapVersion::Version4) {
648 // Map a hash of the filenames region to the filename range associated
649 // with this coverage header.
650 int64_t FilenamesRef =
652 auto Insert =
653 FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
654 if (!Insert.second) {
655 // The same filenames ref was encountered twice. It's possible that
656 // the associated filenames are the same.
657 auto It = Filenames.begin();
658 FilenameRange &OrigRange = Insert.first->getSecond();
659 if (std::equal(It + OrigRange.StartingIndex,
660 It + OrigRange.StartingIndex + OrigRange.Length,
661 It + FileRange.StartingIndex,
662 It + FileRange.StartingIndex + FileRange.Length))
663 // Map the new range to the original one.
664 FileRange = OrigRange;
665 else
666 // This is a hash collision. Mark the filenames ref invalid.
667 OrigRange.markInvalid();
668 }
669 }
670
671 // We'll read the coverage mapping records in the loop below.
672 // This is a no-op in Version4 (coverage mappings are not affixed to the
673 // coverage header).
674 const char *MappingBuf = CovBuf;
675 if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
676 return make_error<CoverageMapError>(coveragemap_error::malformed);
677 CovBuf += CoverageSize;
678 const char *MappingEnd = CovBuf;
679
680 if (CovBuf > CovBufEnd)
681 return make_error<CoverageMapError>(coveragemap_error::malformed);
682
683 if (Version < CovMapVersion::Version4) {
684 // Read each function record.
685 if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
686 MappingBuf, MappingEnd))
687 return std::move(E);
688 }
689
690 // Each coverage map has an alignment of 8, so we need to adjust alignment
691 // before reading the next map.
692 CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
693
694 return CovBuf;
695 }
696
697 Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
698 std::optional<FilenameRange> OutOfLineFileRange,
699 const char *OutOfLineMappingBuf,
700 const char *OutOfLineMappingBufEnd) override {
701 auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
702 while ((const char *)CFR < FuncRecBufEnd) {
703 // Validate the length of the coverage mapping for this function.
704 const char *NextMappingBuf;
705 const FuncRecordType *NextCFR;
706 std::tie(NextMappingBuf, NextCFR) =
707 CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
708 if (Version < CovMapVersion::Version4)
709 if (NextMappingBuf > OutOfLineMappingBufEnd)
710 return make_error<CoverageMapError>(coveragemap_error::malformed);
711
712 // Look up the set of filenames associated with this function record.
713 std::optional<FilenameRange> FileRange;
714 if (Version < CovMapVersion::Version4) {
715 FileRange = OutOfLineFileRange;
716 } else {
717 uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
718 auto It = FileRangeMap.find(FilenamesRef);
719 if (It == FileRangeMap.end())
720 return make_error<CoverageMapError>(coveragemap_error::malformed);
721 else
722 FileRange = It->getSecond();
723 }
724
725 // Now, read the coverage data.
726 if (FileRange && !FileRange->isInvalid()) {
727 StringRef Mapping =
728 CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
729 if (Version >= CovMapVersion::Version4 &&
730 Mapping.data() + Mapping.size() > FuncRecBufEnd)
731 return make_error<CoverageMapError>(coveragemap_error::malformed);
732 if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
733 return Err;
734 }
735
736 std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
737 }
738 return Error::success();
739 }
740};
741
742} // end anonymous namespace
743
744template <class IntPtrT, support::endianness Endian>
745Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
747 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
748 std::vector<std::string> &F) {
749 using namespace coverage;
750
751 switch (Version) {
753 return std::make_unique<VersionedCovMapFuncRecordReader<
754 CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
760 // Decompress the name data.
761 if (Error E = P.create(P.getNameData()))
762 return std::move(E);
763 if (Version == CovMapVersion::Version2)
764 return std::make_unique<VersionedCovMapFuncRecordReader<
765 CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
766 else if (Version == CovMapVersion::Version3)
767 return std::make_unique<VersionedCovMapFuncRecordReader<
768 CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
769 else if (Version == CovMapVersion::Version4)
770 return std::make_unique<VersionedCovMapFuncRecordReader<
771 CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
772 else if (Version == CovMapVersion::Version5)
773 return std::make_unique<VersionedCovMapFuncRecordReader<
774 CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
775 else if (Version == CovMapVersion::Version6)
776 return std::make_unique<VersionedCovMapFuncRecordReader<
777 CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
778 }
779 llvm_unreachable("Unsupported version");
780}
781
782template <typename T, support::endianness Endian>
784 InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
785 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
786 StringRef CompilationDir, std::vector<std::string> &Filenames) {
787 using namespace coverage;
788
789 // Read the records in the coverage data section.
790 auto CovHeader =
791 reinterpret_cast<const CovMapHeader *>(CovMap.data());
792 CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
793 if (Version > CovMapVersion::CurrentVersion)
794 return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
796 CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
797 CompilationDir, Filenames);
798 if (Error E = ReaderExpected.takeError())
799 return E;
800 auto Reader = std::move(ReaderExpected.get());
801 const char *CovBuf = CovMap.data();
802 const char *CovBufEnd = CovBuf + CovMap.size();
803 const char *FuncRecBuf = FuncRecords.data();
804 const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
805 while (CovBuf < CovBufEnd) {
806 // Read the current coverage header & filename data.
807 //
808 // Prior to Version4, this also reads all function records affixed to the
809 // header.
810 //
811 // Return a pointer to the next coverage header.
812 auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
813 if (auto E = NextOrErr.takeError())
814 return E;
815 CovBuf = NextOrErr.get();
816 }
817 // In Version4, function records are not affixed to coverage headers. Read
818 // the records from their dedicated section.
819 if (Version >= CovMapVersion::Version4)
820 return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
821 nullptr, nullptr);
822 return Error::success();
823}
824
825static const char *TestingFormatMagic = "llvmcovmtestdata";
826
829 StringRef Coverage, FuncRecordsStorage &&FuncRecords,
830 InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
831 support::endianness Endian, StringRef CompilationDir) {
832 std::unique_ptr<BinaryCoverageReader> Reader(
833 new BinaryCoverageReader(std::move(FuncRecords)));
834 Reader->ProfileNames = std::move(ProfileNames);
835 StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
836 if (BytesInAddress == 4 && Endian == support::endianness::little) {
837 if (Error E =
838 readCoverageMappingData<uint32_t, support::endianness::little>(
839 Reader->ProfileNames, Coverage, FuncRecordsRef,
840 Reader->MappingRecords, CompilationDir, Reader->Filenames))
841 return std::move(E);
842 } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
843 if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
844 Reader->ProfileNames, Coverage, FuncRecordsRef,
845 Reader->MappingRecords, CompilationDir, Reader->Filenames))
846 return std::move(E);
847 } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
848 if (Error E =
849 readCoverageMappingData<uint64_t, support::endianness::little>(
850 Reader->ProfileNames, Coverage, FuncRecordsRef,
851 Reader->MappingRecords, CompilationDir, Reader->Filenames))
852 return std::move(E);
853 } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
854 if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
855 Reader->ProfileNames, Coverage, FuncRecordsRef,
856 Reader->MappingRecords, CompilationDir, Reader->Filenames))
857 return std::move(E);
858 } else
859 return make_error<CoverageMapError>(coveragemap_error::malformed);
860 return std::move(Reader);
861}
862
865 uint8_t BytesInAddress = 8;
866 support::endianness Endian = support::endianness::little;
867
869 if (Data.empty())
870 return make_error<CoverageMapError>(coveragemap_error::truncated);
871 unsigned N = 0;
872 uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
873 if (N > Data.size())
874 return make_error<CoverageMapError>(coveragemap_error::malformed);
875 Data = Data.substr(N);
876 if (Data.empty())
877 return make_error<CoverageMapError>(coveragemap_error::truncated);
878 N = 0;
879 uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
880 if (N > Data.size())
881 return make_error<CoverageMapError>(coveragemap_error::malformed);
882 Data = Data.substr(N);
883 if (Data.size() < ProfileNamesSize)
884 return make_error<CoverageMapError>(coveragemap_error::malformed);
885 InstrProfSymtab ProfileNames;
886 if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
887 return std::move(E);
888 Data = Data.substr(ProfileNamesSize);
889 // Skip the padding bytes because coverage map data has an alignment of 8.
890 size_t Pad = offsetToAlignedAddr(Data.data(), Align(8));
891 if (Data.size() < Pad)
892 return make_error<CoverageMapError>(coveragemap_error::malformed);
893 Data = Data.substr(Pad);
894 if (Data.size() < sizeof(CovMapHeader))
895 return make_error<CoverageMapError>(coveragemap_error::malformed);
896 auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
897 Data.substr(0, sizeof(CovMapHeader)).data());
898 CovMapVersion Version =
899 (CovMapVersion)CovHeader->getVersion<support::endianness::little>();
902 if (Version < CovMapVersion::Version4) {
904 if (CoverageMapping.empty())
905 return make_error<CoverageMapError>(coveragemap_error::truncated);
906 CoverageRecords = MemoryBuffer::getMemBuffer("");
907 } else {
908 uint32_t FilenamesSize =
909 CovHeader->getFilenamesSize<support::endianness::little>();
910 uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
911 CoverageMapping = Data.substr(0, CoverageMappingSize);
912 if (CoverageMapping.empty())
913 return make_error<CoverageMapError>(coveragemap_error::truncated);
914 Data = Data.substr(CoverageMappingSize);
915 // Skip the padding bytes because coverage records data has an alignment
916 // of 8.
917 Pad = offsetToAlignedAddr(Data.data(), Align(8));
918 if (Data.size() < Pad)
919 return make_error<CoverageMapError>(coveragemap_error::malformed);
920 CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad));
921 if (CoverageRecords->getBufferSize() == 0)
922 return make_error<CoverageMapError>(coveragemap_error::truncated);
923 }
925 CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
926 BytesInAddress, Endian, CompilationDir);
927}
928
929/// Find all sections that match \p Name. There may be more than one if comdats
930/// are in use, e.g. for the __llvm_covfun section on ELF.
932 StringRef Name) {
933 // On COFF, the object file section name may end in "$M". This tells the
934 // linker to sort these sections between "$A" and "$Z". The linker removes the
935 // dollar and everything after it in the final binary. Do the same to match.
936 bool IsCOFF = isa<COFFObjectFile>(OF);
937 auto stripSuffix = [IsCOFF](StringRef N) {
938 return IsCOFF ? N.split('$').first : N;
939 };
940 Name = stripSuffix(Name);
941
942 std::vector<SectionRef> Sections;
943 for (const auto &Section : OF.sections()) {
944 Expected<StringRef> NameOrErr = Section.getName();
945 if (!NameOrErr)
946 return NameOrErr.takeError();
947 if (stripSuffix(*NameOrErr) == Name)
948 Sections.push_back(Section);
949 }
950 if (Sections.empty())
951 return make_error<CoverageMapError>(coveragemap_error::no_data_found);
952 return Sections;
953}
954
956loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
957 StringRef CompilationDir = "",
958 std::optional<object::BuildIDRef> *BinaryID = nullptr) {
959 std::unique_ptr<ObjectFile> OF;
960 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
961 // If we have a universal binary, try to look up the object for the
962 // appropriate architecture.
963 auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
964 if (!ObjectFileOrErr)
965 return ObjectFileOrErr.takeError();
966 OF = std::move(ObjectFileOrErr.get());
967 } else if (isa<ObjectFile>(Bin.get())) {
968 // For any other object file, upcast and take ownership.
969 OF.reset(cast<ObjectFile>(Bin.release()));
970 // If we've asked for a particular arch, make sure they match.
971 if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
972 return errorCodeToError(object_error::arch_not_found);
973 } else
974 // We can only handle object files.
975 return make_error<CoverageMapError>(coveragemap_error::malformed);
976
977 // The coverage uses native pointer sizes for the object it's written in.
978 uint8_t BytesInAddress = OF->getBytesInAddress();
979 support::endianness Endian = OF->isLittleEndian()
980 ? support::endianness::little
981 : support::endianness::big;
982
983 // Look for the sections that we are interested in.
984 auto ObjFormat = OF->getTripleObjectFormat();
985 auto NamesSection =
986 lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
987 /*AddSegmentInfo=*/false));
988 if (auto E = NamesSection.takeError())
989 return std::move(E);
990 auto CoverageSection =
991 lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
992 /*AddSegmentInfo=*/false));
993 if (auto E = CoverageSection.takeError())
994 return std::move(E);
995 std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
996 if (CoverageSectionRefs.size() != 1)
997 return make_error<CoverageMapError>(coveragemap_error::malformed);
998 auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
999 if (!CoverageMappingOrErr)
1000 return CoverageMappingOrErr.takeError();
1001 StringRef CoverageMapping = CoverageMappingOrErr.get();
1002
1003 InstrProfSymtab ProfileNames;
1004 std::vector<SectionRef> NamesSectionRefs = *NamesSection;
1005 if (NamesSectionRefs.size() != 1)
1006 return make_error<CoverageMapError>(coveragemap_error::malformed);
1007 if (Error E = ProfileNames.create(NamesSectionRefs.back()))
1008 return std::move(E);
1009
1010 // Look for the coverage records section (Version4 only).
1011 auto CoverageRecordsSections =
1012 lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
1013 /*AddSegmentInfo=*/false));
1014
1016 if (auto E = CoverageRecordsSections.takeError()) {
1017 consumeError(std::move(E));
1018 FuncRecords = MemoryBuffer::getMemBuffer("");
1019 } else {
1020 // Compute the FuncRecordsBuffer of the buffer, taking into account the
1021 // padding between each record, and making sure the first block is aligned
1022 // in memory to maintain consistency between buffer address and size
1023 // alignment.
1024 const Align RecordAlignment(8);
1025 uint64_t FuncRecordsSize = 0;
1026 for (SectionRef Section : *CoverageRecordsSections) {
1027 auto CoverageRecordsOrErr = Section.getContents();
1028 if (!CoverageRecordsOrErr)
1029 return CoverageRecordsOrErr.takeError();
1030 FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1031 }
1032 auto WritableBuffer =
1034 char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
1035 assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&
1036 "Allocated memory is correctly aligned");
1037
1038 for (SectionRef Section : *CoverageRecordsSections) {
1039 auto CoverageRecordsOrErr = Section.getContents();
1040 if (!CoverageRecordsOrErr)
1041 return CoverageRecordsOrErr.takeError();
1042 const auto &CoverageRecords = CoverageRecordsOrErr.get();
1043 FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
1044 CoverageRecords.end(), FuncRecordsBuffer);
1045 FuncRecordsBuffer =
1046 std::fill_n(FuncRecordsBuffer,
1047 alignAddr(FuncRecordsBuffer, RecordAlignment) -
1048 (uintptr_t)FuncRecordsBuffer,
1049 '\0');
1050 }
1051 assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
1052 "consistent init");
1053 FuncRecords = std::move(WritableBuffer);
1054 }
1055
1056 if (BinaryID)
1057 *BinaryID = getBuildID(OF.get());
1058
1060 CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
1061 BytesInAddress, Endian, CompilationDir);
1062}
1063
1064/// Determine whether \p Arch is invalid or empty, given \p Bin.
1066 // If we have a universal binary and Arch doesn't identify any of its slices,
1067 // it's user error.
1068 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
1069 for (auto &ObjForArch : Universal->objects())
1070 if (Arch == ObjForArch.getArchFlagName())
1071 return false;
1072 return true;
1073 }
1074 return false;
1075}
1076
1079 MemoryBufferRef ObjectBuffer, StringRef Arch,
1080 SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
1081 StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
1082 std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
1083
1084 if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
1085 // This is a special format used for testing.
1086 auto ReaderOrErr =
1087 loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
1088 if (!ReaderOrErr)
1089 return ReaderOrErr.takeError();
1090 Readers.push_back(std::move(ReaderOrErr.get()));
1091 return std::move(Readers);
1092 }
1093
1094 auto BinOrErr = createBinary(ObjectBuffer);
1095 if (!BinOrErr)
1096 return BinOrErr.takeError();
1097 std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
1098
1099 if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
1100 return make_error<CoverageMapError>(
1102
1103 // MachO universal binaries which contain archives need to be treated as
1104 // archives, not as regular binaries.
1105 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1106 for (auto &ObjForArch : Universal->objects()) {
1107 // Skip slices within the universal binary which target the wrong arch.
1108 std::string ObjArch = ObjForArch.getArchFlagName();
1109 if (Arch != ObjArch)
1110 continue;
1111
1112 auto ArchiveOrErr = ObjForArch.getAsArchive();
1113 if (!ArchiveOrErr) {
1114 // If this is not an archive, try treating it as a regular object.
1115 consumeError(ArchiveOrErr.takeError());
1116 break;
1117 }
1118
1120 ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1121 CompilationDir, BinaryIDs);
1122 }
1123 }
1124
1125 // Load coverage out of archive members.
1126 if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1127 Error Err = Error::success();
1128 for (auto &Child : Ar->children(Err)) {
1129 Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1130 if (!ChildBufOrErr)
1131 return ChildBufOrErr.takeError();
1132
1133 auto ChildReadersOrErr = BinaryCoverageReader::create(
1134 ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,
1135 BinaryIDs);
1136 if (!ChildReadersOrErr)
1137 return ChildReadersOrErr.takeError();
1138 for (auto &Reader : ChildReadersOrErr.get())
1139 Readers.push_back(std::move(Reader));
1140 }
1141 if (Err)
1142 return std::move(Err);
1143
1144 // Thin archives reference object files outside of the archive file, i.e.
1145 // files which reside in memory not owned by the caller. Transfer ownership
1146 // to the caller.
1147 if (Ar->isThin())
1148 for (auto &Buffer : Ar->takeThinBuffers())
1149 ObjectFileBuffers.push_back(std::move(Buffer));
1150
1151 return std::move(Readers);
1152 }
1153
1154 std::optional<object::BuildIDRef> BinaryID;
1155 auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
1156 BinaryIDs ? &BinaryID : nullptr);
1157 if (!ReaderOrErr)
1158 return ReaderOrErr.takeError();
1159 Readers.push_back(std::move(ReaderOrErr.get()));
1160 if (BinaryID)
1161 BinaryIDs->push_back(*BinaryID);
1162 return std::move(Readers);
1163}
1164
1166 if (CurrentRecord >= MappingRecords.size())
1167 return make_error<CoverageMapError>(coveragemap_error::eof);
1168
1169 FunctionsFilenames.clear();
1170 Expressions.clear();
1171 MappingRegions.clear();
1172 auto &R = MappingRecords[CurrentRecord];
1173 auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
1174 RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
1175 Expressions, MappingRegions);
1176 if (auto Err = Reader.read())
1177 return Err;
1178
1179 Record.FunctionName = R.FunctionName;
1180 Record.FunctionHash = R.FunctionHash;
1181 Record.Filenames = FunctionsFilenames;
1182 Record.Expressions = Expressions;
1183 Record.MappingRegions = MappingRegions;
1184
1185 ++CurrentRecord;
1186 return Error::success();
1187}
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="", std::optional< object::BuildIDRef > *BinaryID=nullptr)
static Expected< std::unique_ptr< BinaryCoverageReader > > loadTestingFormat(StringRef Data, StringRef CompilationDir)
static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch)
Determine whether Arch is invalid or empty, given Bin.
static const char * TestingFormatMagic
static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)
static const unsigned EncodingExpansionRegionBit
static Expected< std::vector< SectionRef > > lookupSections(ObjectFile &OF, StringRef Name)
Find all sections that match Name.
#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
return ToRemove size() > 0
#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.
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:167
Value * RHS
Value * LHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
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:193
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
Definition: InstrProf.h:446
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.
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:91
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:577
void resize(size_type N)
Definition: SmallVector.h:642
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:559
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
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
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::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)
static Expected< std::unique_ptr< BinaryCoverageReader > > createCoverageReaderFromBuffer(StringRef Coverage, FuncRecordsStorage &&FuncRecords, InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, support::endianness Endian, StringRef CompilationDir="")
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)
This class is the base class for all object file types.
Definition: ObjectFile.h:228
section_iterator_range sections() const
Definition: ObjectFile.h:327
virtual bool isRelocatableObject() const =0
True if this is a relocatable object (.o/.obj).
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
#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:1062
Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< BuildIDRef > getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
Definition: BuildID.cpp:48
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:715
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:671
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
@ Length
Definition: DWP.cpp:406
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:966
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:128
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:213
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
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:92
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
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
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...
@ 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.