26 using namespace coverage;
27 using namespace object;
29 #define DEBUG_TYPE "coverage-mapping"
31 void CoverageMappingIterator::increment() {
34 if (
auto E = Reader->readNextRecord(
Record)) {
48 Result =
decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
51 Data = Data.substr(N);
56 if (
auto Err = readULEB128(Result))
58 if (Result >= MaxPlus1)
64 if (
auto Err = readULEB128(Result))
67 if (Result > Data.size())
74 if (
auto Err = readSize(Length))
76 Result = Data.substr(0, Length);
77 Data = Data.substr(Length);
82 uint64_t NumFilenames;
83 if (
auto Err = readSize(NumFilenames))
85 for (
size_t I = 0;
I < NumFilenames; ++
I) {
87 if (
auto Err = readString(Filename))
89 Filenames.push_back(Filename);
123 Error RawCoverageMappingReader::readCounter(
Counter &C) {
124 uint64_t EncodedCounter;
126 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
128 if (
auto Err = decodeCounter(EncodedCounter, C))
139 Error RawCoverageMappingReader::readMappingRegionsSubArray(
140 std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID,
143 if (
auto Err = readSize(NumRegions))
145 unsigned LineStart = 0;
146 for (
size_t I = 0;
I < NumRegions; ++
I) {
151 uint64_t EncodedCounterAndRegion;
152 if (
auto Err = readIntMax(EncodedCounterAndRegion,
153 std::numeric_limits<unsigned>::max()))
156 uint64_t ExpandedFileID = 0;
158 if (
auto Err = decodeCounter(EncodedCounterAndRegion, C))
164 ExpandedFileID = EncodedCounterAndRegion >>
166 if (ExpandedFileID >= NumFileIDs)
169 switch (EncodedCounterAndRegion >>
184 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
186 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
188 if (
auto Err = readULEB128(ColumnStart))
190 if (ColumnStart > std::numeric_limits<unsigned>::max())
192 if (
auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
194 if (
auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
196 LineStart += LineStartDelta;
205 if (ColumnStart == 0 && ColumnEnd == 0) {
207 ColumnEnd = std::numeric_limits<unsigned>::max();
211 dbgs() <<
"Counter in file " << InferredFileID <<
" " << LineStart <<
":"
212 << ColumnStart <<
" -> " << (LineStart + NumLines) <<
":"
213 << ColumnEnd <<
", ";
215 dbgs() <<
"Expands to file " << ExpandedFileID;
222 C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
223 LineStart + NumLines, ColumnEnd, Kind));
232 uint64_t NumFileMappings;
233 if (
auto Err = readSize(NumFileMappings))
235 for (
size_t I = 0;
I < NumFileMappings; ++
I) {
236 uint64_t FilenameIndex;
237 if (
auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
239 VirtualFileMapping.
push_back(FilenameIndex);
243 for (
auto I : VirtualFileMapping) {
244 Filenames.push_back(TranslationUnitFilenames[
I]);
248 uint64_t NumExpressions;
249 if (
auto Err = readSize(NumExpressions))
257 for (
size_t I = 0;
I < NumExpressions; ++
I) {
265 for (
unsigned InferredFileID = 0, S = VirtualFileMapping.size();
266 InferredFileID < S; ++InferredFileID) {
267 if (
auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
268 VirtualFileMapping.size()))
278 FileIDExpansionRegionMapping.
resize(VirtualFileMapping.size(),
nullptr);
279 for (
unsigned Pass = 1, S = VirtualFileMapping.size();
Pass < S; ++
Pass) {
280 for (
auto &R : MappingRegions) {
283 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
284 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
286 for (
auto &R : MappingRegions) {
287 if (FileIDExpansionRegionMapping[R.FileID]) {
288 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
289 FileIDExpansionRegionMapping[R.FileID] =
nullptr;
299 uint64_t NumFileMappings;
300 if (
Error Err = readSize(NumFileMappings))
301 return std::move(Err);
302 if (NumFileMappings != 1)
305 uint64_t FilenameIndex;
307 readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
308 return std::move(Err);
309 uint64_t NumExpressions;
310 if (
Error Err = readSize(NumExpressions))
311 return std::move(Err);
312 if (NumExpressions != 0)
315 if (
Error Err = readSize(NumRegions))
316 return std::move(Err);
319 uint64_t EncodedCounterAndRegion;
320 if (
Error Err = readIntMax(EncodedCounterAndRegion,
321 std::numeric_limits<unsigned>::max()))
322 return std::move(Err);
338 if (
Offset + Size > Data.size())
340 return Data.substr(Pointer - Address, Size);
352 struct CovMapFuncRecordReader {
361 const char *
End) = 0;
362 virtual ~CovMapFuncRecordReader() {}
363 template <
class IntPtrT, support::endianness Endian>
366 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
367 std::vector<StringRef> &
F);
373 class VersionedCovMapFuncRecordReader :
public CovMapFuncRecordReader {
375 Version, IntPtrT>::CovMapFuncRecordType FuncRecordType;
383 std::vector<StringRef> &Filenames;
384 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
392 Error insertFunctionRecordIfNeeded(
const FuncRecordType *CFR,
393 StringRef Mapping,
size_t FilenamesBegin) {
394 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
395 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
397 FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
398 if (InsertResult.second) {
400 if (
Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
402 Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin,
403 Filenames.
size() - FilenamesBegin);
407 size_t OldRecordIndex = InsertResult.first->second;
409 Records[OldRecordIndex];
414 if (!*OldIsDummyExpected)
420 if (*NewIsDummyExpected)
430 VersionedCovMapFuncRecordReader(
432 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
433 std::vector<StringRef> &
F)
434 : ProfileNames(P), Filenames(F), Records(R) {}
435 ~VersionedCovMapFuncRecordReader()
override {}
438 const char *
End)
override {
439 using namespace support;
443 uint32_t NRecords = CovHeader->getNRecords<Endian>();
444 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
445 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
447 Buf =
reinterpret_cast<const char *
>(CovHeader + 1);
450 const char *FunBuf = Buf;
451 Buf += NRecords *
sizeof(FuncRecordType);
452 const char *FunEnd = Buf;
455 if (Buf + FilenamesSize > End)
457 size_t FilenamesBegin = Filenames.size();
459 if (
auto Err = Reader.read())
460 return std::move(Err);
461 Buf += FilenamesSize;
464 const char *CovBuf = Buf;
466 const char *CovEnd = Buf;
474 auto CFR =
reinterpret_cast<const FuncRecordType *
>(FunBuf);
475 while ((
const char *)CFR < FunEnd) {
477 uint32_t DataSize = CFR->template getDataSize<Endian>();
480 if (CovBuf + DataSize > CovEnd)
482 auto Mapping =
StringRef(CovBuf, DataSize);
486 insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin))
487 return std::move(Err);
495 template <
class IntPtrT, support::endianness Endian>
498 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
499 std::vector<StringRef> &
F) {
500 using namespace coverage;
507 if (
Error E = P.create(P.getNameData()))
515 template <
typename T, support::endianness Endian>
518 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
519 std::vector<StringRef> &Filenames) {
520 using namespace coverage;
528 CovMapFuncRecordReader::get<T, Endian>(
Version, ProfileNames, Records,
530 if (
Error E = ReaderExpected.takeError())
532 auto Reader = std::move(ReaderExpected.get());
533 for (
const char *Buf = Data.
data(), *End = Buf + Data.
size(); Buf <
End;) {
534 auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End);
535 if (
auto E = NextHeaderOrErr.takeError())
537 Buf = NextHeaderOrErr.get();
545 uint8_t &BytesInAddress,
554 auto ProfileNamesSize =
567 if (Data.
size() < ProfileNamesSize)
571 CoverageMapping = Data.
substr(ProfileNamesSize);
573 if (CoverageMapping.
size() < 1)
576 if (CoverageMapping.
size() < Pad)
578 CoverageMapping = CoverageMapping.
substr(Pad);
585 if (
auto EC =
Section.getName(FoundName))
587 if (FoundName == Name)
596 uint8_t &BytesInAddress,
600 return BinOrErr.takeError();
601 auto Bin = std::move(BinOrErr.get());
602 std::unique_ptr<ObjectFile> OF;
603 if (
auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) {
606 auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
607 if (!ObjectFileOrErr)
608 return ObjectFileOrErr.takeError();
609 OF = std::move(ObjectFileOrErr.get());
610 }
else if (isa<object::ObjectFile>(Bin.get())) {
612 OF.reset(cast<object::ObjectFile>(Bin.release()));
621 BytesInAddress = OF->getBytesInAddress();
627 if (
auto E = NamesSection.takeError())
629 auto CoverageSection =
631 if (
auto E = CoverageSection.takeError())
635 if (
auto EC = CoverageSection->getContents(CoverageMapping))
649 uint8_t BytesInAddress;
653 if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
656 Coverage, BytesInAddress, Endian);
659 Coverage, BytesInAddress, Endian, Arch);
664 E = readCoverageMappingData<uint32_t, support::endianness::little>(
665 Reader->ProfileNames, Coverage, Reader->MappingRecords,
668 E = readCoverageMappingData<uint32_t, support::endianness::big>(
669 Reader->ProfileNames, Coverage, Reader->MappingRecords,
672 E = readCoverageMappingData<uint64_t, support::endianness::little>(
673 Reader->ProfileNames, Coverage, Reader->MappingRecords,
676 E = readCoverageMappingData<uint64_t, support::endianness::big>(
677 Reader->ProfileNames, Coverage, Reader->MappingRecords,
683 return std::move(Reader);
687 if (CurrentRecord >= MappingRecords.size())
690 FunctionsFilenames.clear();
692 MappingRegions.clear();
693 auto &R = MappingRecords[CurrentRecord];
696 makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
698 if (
auto Err = Reader.
read())
Pass interface - Implemented by all 'passes'.
void push_back(const T &Elt)
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
static const unsigned EncodingTagMask
Reader for the raw coverage mapping data.
static Counter getZero()
Return the counter that represents the number zero.
aarch64 AArch64 CCMP Pass
coveragemap_error get() const
Checks if the given coverage mapping data is exported for an unused function.
This class is the base class for all object file types.
A Counter expression is a value that represents an arithmetic operation with two counters.
Error takeError()
Take ownership of the stored error.
ArrayRef< CounterMappingRegion > MappingRegions
gvn Early GVN Hoisting of Expressions
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
Error readSize(uint64_t &Result)
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
Reader for the coverage mapping data that is emitted by the frontend and stored in an object file...
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
ArrayRef< CounterExpression > Expressions
StringRef getInstrProfCoverageSectionName(bool AddSegment)
Return the name of the section containing function coverage mapping data.
Tagged union holding either a T or a Error.
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
StringRef CoverageMapping
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Error readIntMax(uint64_t &Result, uint64_t MaxPlus1)
Error readNextRecord(CoverageMappingRecord &Record) override
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr)
Utility function to decode a ULEB128 value.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
ArrayRef< StringRef > Filenames
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Coverage mapping information for a single function.
void dump(const Counter &C, llvm::raw_ostream &OS) const
static Error readCoverageMappingData(InstrProfSymtab &ProfileNames, StringRef Data, std::vector< BinaryCoverageReader::ProfileMappingRecord > &Records, std::vector< StringRef > &Filenames)
size_t alignmentAdjustment(const void *Ptr, size_t Alignment)
Returns the necessary adjustment for aligning Ptr to Alignment bytes, rounding up.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Reader for the raw coverage filenames.
Error readULEB128(uint64_t &Result)
A CodeRegion associates some code with a counter.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
A Counter mapping region associates a source range with a specific counter.
Expected< bool > isDummy()
Error readString(StringRef &Result)
static const unsigned End
void handleAllErrors(Error E, HandlerTs &&...Handlers)
Behaves the same as handleErrors, except that it requires that all errors be handled by the given han...
section_iterator_range sections() const
uint64_t getAddress() const
void consumeError(Error Err)
Consume a Error without doing anything.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
A file format agnostic iterator over coverage mapping data.
static ErrorSuccess success()
Create a success value.
static Expected< SectionRef > lookupSection(ObjectFile &OF, StringRef Name)
static const unsigned EncodingExpansionRegionBit
static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, InstrProfSymtab &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian, StringRef Arch)
static const char * TestingFormatMagic
static Expected< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
std::error_code getContents(StringRef &Result) const
The mapping of profile information to coverage data.
static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const unsigned EncodingTagBits
static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)
LLVM Value Representation.
Lightweight error class with error context and mandatory checking.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
std::string Hash(const Unit &U)
StringRef - Represent a constant reference to a string, i.e.
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
StringRef getInstrProfNameSectionName(bool AddSegment)
Return the name of data section containing names of instrumented functions.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
This is a value type class that represents a single section in the list of sections in the object fil...