26 using namespace coverage;
27 using namespace object;
29 #define DEBUG_TYPE "coverage-mapping"
31 void CoverageMappingIterator::increment() {
34 if (Reader->readNextRecord(
Record))
46 return std::error_code();
51 if (
auto Err = readULEB128(Result))
53 if (Result >= MaxPlus1)
55 return std::error_code();
59 if (
auto Err = readULEB128(Result))
62 if (Result >
Data.size())
64 return std::error_code();
69 if (
auto Err = readSize(Length))
71 Result =
Data.substr(0, Length);
73 return std::error_code();
77 uint64_t NumFilenames;
78 if (
auto Err = readSize(NumFilenames))
80 for (
size_t I = 0;
I < NumFilenames; ++
I) {
82 if (
auto Err = readString(Filename))
84 Filenames.push_back(Filename);
86 return std::error_code();
89 std::error_code RawCoverageMappingReader::decodeCounter(
unsigned Value,
95 return std::error_code();
98 return std::error_code();
107 if (
ID >= Expressions.size())
116 return std::error_code();
119 std::error_code RawCoverageMappingReader::readCounter(
Counter &C) {
120 uint64_t EncodedCounter;
122 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
124 if (
auto Err = decodeCounter(EncodedCounter, C))
126 return std::error_code();
135 std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
136 std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID,
139 if (
auto Err = readSize(NumRegions))
141 unsigned LineStart = 0;
142 for (
size_t I = 0;
I < NumRegions; ++
I) {
147 uint64_t EncodedCounterAndRegion;
148 if (
auto Err = readIntMax(EncodedCounterAndRegion,
149 std::numeric_limits<unsigned>::max()))
152 uint64_t ExpandedFileID = 0;
154 if (
auto Err = decodeCounter(EncodedCounterAndRegion, C))
160 ExpandedFileID = EncodedCounterAndRegion >>
162 if (ExpandedFileID >= NumFileIDs)
165 switch (EncodedCounterAndRegion >>
180 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
182 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
184 if (
auto Err = readULEB128(ColumnStart))
186 if (ColumnStart > std::numeric_limits<unsigned>::max())
188 if (
auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
190 if (
auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
192 LineStart += LineStartDelta;
201 if (ColumnStart == 0 && ColumnEnd == 0) {
203 ColumnEnd = std::numeric_limits<unsigned>::max();
207 dbgs() <<
"Counter in file " << InferredFileID <<
" " << LineStart <<
":"
208 << ColumnStart <<
" -> " << (LineStart + NumLines) <<
":"
209 << ColumnEnd <<
", ";
211 dbgs() <<
"Expands to file " << ExpandedFileID;
218 C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
219 LineStart + NumLines, ColumnEnd, Kind));
221 return std::error_code();
228 uint64_t NumFileMappings;
229 if (
auto Err = readSize(NumFileMappings))
231 for (
size_t I = 0;
I < NumFileMappings; ++
I) {
232 uint64_t FilenameIndex;
233 if (
auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
235 VirtualFileMapping.
push_back(FilenameIndex);
239 for (
auto I : VirtualFileMapping) {
240 Filenames.push_back(TranslationUnitFilenames[
I]);
244 uint64_t NumExpressions;
245 if (
auto Err = readSize(NumExpressions))
253 for (
size_t I = 0;
I < NumExpressions; ++
I) {
254 if (
auto Err = readCounter(Expressions[
I].LHS))
256 if (
auto Err = readCounter(Expressions[
I].RHS))
261 for (
unsigned InferredFileID = 0, S = VirtualFileMapping.size();
262 InferredFileID < S; ++InferredFileID) {
263 if (
auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
264 VirtualFileMapping.size()))
274 FileIDExpansionRegionMapping.
resize(VirtualFileMapping.size(),
nullptr);
275 for (
unsigned Pass = 1, S = VirtualFileMapping.size();
Pass < S; ++
Pass) {
276 for (
auto &R : MappingRegions) {
279 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
280 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
282 for (
auto &R : MappingRegions) {
283 if (FileIDExpansionRegionMapping[R.FileID]) {
284 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
285 FileIDExpansionRegionMapping[R.FileID] =
nullptr;
290 return std::error_code();
305 return std::error_code();
308 std::error_code
get(uint64_t Pointer,
size_t Size,
StringRef &Result) {
311 auto Offset = Pointer -
Address;
312 if (Offset + Size >
Data.size())
314 Result =
Data.substr(Pointer - Address, Size);
315 return std::error_code();
320 template <
typename T, support::endianness Endian>
322 SectionData &ProfileNames,
StringRef Data,
323 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
324 std::vector<StringRef> &Filenames) {
325 using namespace support;
329 for (
const char *Buf = Data.
data(), *End = Buf + Data.
size(); Buf < End;) {
330 if (Buf + 4 *
sizeof(uint32_t) > End)
332 uint32_t NRecords = endian::readNext<uint32_t, Endian, unaligned>(Buf);
333 uint32_t FilenamesSize = endian::readNext<uint32_t, Endian, unaligned>(Buf);
334 uint32_t CoverageSize = endian::readNext<uint32_t, Endian, unaligned>(Buf);
335 uint32_t
Version = endian::readNext<uint32_t, Endian, unaligned>(Buf);
345 const char *FunBuf = Buf;
346 Buf += NRecords * (
sizeof(
T) + 2 *
sizeof(uint32_t) +
sizeof(uint64_t));
347 const char *FunEnd = Buf;
350 if (Buf + FilenamesSize > End)
352 size_t FilenamesBegin = Filenames.size();
354 if (
auto Err = Reader.
read())
356 Buf += FilenamesSize;
359 const char *CovBuf = Buf;
361 const char *CovEnd = Buf;
369 while (FunBuf < FunEnd) {
371 T NamePtr = endian::readNext<T, Endian, unaligned>(FunBuf);
372 uint32_t
NameSize = endian::readNext<uint32_t, Endian, unaligned>(FunBuf);
373 uint32_t DataSize = endian::readNext<uint32_t, Endian, unaligned>(FunBuf);
374 uint64_t FuncHash = endian::readNext<uint64_t, Endian, unaligned>(FunBuf);
377 if (CovBuf + DataSize > CovEnd)
379 auto Mapping =
StringRef(CovBuf, DataSize);
385 if (!UniqueFunctionMappingData.insert(NamePtr).second)
390 if (std::error_code EC = ProfileNames.get(NamePtr, NameSize, FuncName))
394 FilenamesBegin, Filenames.
size() - FilenamesBegin));
398 return std::error_code();
404 SectionData &ProfileNames,
406 uint8_t &BytesInAddress,
415 auto ProfileNamesSize =
423 ProfileNames.Address =
428 if (Data.
size() < ProfileNamesSize)
430 ProfileNames.Data = Data.
substr(0, ProfileNamesSize);
431 CoverageMapping = Data.
substr(ProfileNamesSize);
432 return std::error_code();
437 for (
const auto &Section : OF.
sections()) {
438 if (
auto EC = Section.
getName(FoundName))
440 if (FoundName == Name)
447 SectionData &ProfileNames,
449 uint8_t &BytesInAddress,
453 if (std::error_code EC = BinOrErr.getError())
455 auto Bin = std::move(BinOrErr.get());
456 std::unique_ptr<ObjectFile> OF;
457 if (
auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) {
460 auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
461 if (std::error_code EC = ObjectFileOrErr.getError())
463 OF = std::move(ObjectFileOrErr.get());
464 }
else if (isa<object::ObjectFile>(Bin.get())) {
466 OF.reset(cast<object::ObjectFile>(Bin.release()));
469 return object_error::arch_not_found;
475 BytesInAddress = OF->getBytesInAddress();
481 if (
auto EC = NamesSection.getError())
484 if (
auto EC = CoverageSection.getError())
488 if (std::error_code EC = CoverageSection->getContents(CoverageMapping))
490 if (std::error_code EC = ProfileNames.load(*NamesSection))
493 return std::error_code();
503 uint8_t BytesInAddress;
506 if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
509 BytesInAddress, Endian);
512 BytesInAddress, Endian, Arch);
517 EC = readCoverageMappingData<uint32_t, support::endianness::little>(
518 Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
520 EC = readCoverageMappingData<uint32_t, support::endianness::big>(
521 Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
523 EC = readCoverageMappingData<uint64_t, support::endianness::little>(
524 Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
526 EC = readCoverageMappingData<uint64_t, support::endianness::big>(
527 Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
532 return std::move(Reader);
537 if (CurrentRecord >= MappingRecords.size())
540 FunctionsFilenames.clear();
542 MappingRegions.clear();
543 auto &R = MappingRecords[CurrentRecord];
546 makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
547 FunctionsFilenames, Expressions, MappingRegions);
548 if (
auto Err = Reader.
read())
558 return std::error_code();
Pass interface - Implemented by all 'passes'.
void push_back(const T &Elt)
Represents either an error or a value T.
std::error_code readNextRecord(CoverageMappingRecord &Record) override
static const unsigned EncodingTagMask
Reader for the raw coverage mapping data.
static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, SectionData &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian, StringRef Arch)
size_t size() const
size - Get the string size.
static Counter getZero()
Return the counter that represents the number zero.
static std::error_code loadTestingFormat(StringRef Data, SectionData &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian)
DenseSet - This implements a dense probed hash-table based set.
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
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.
ArrayRef< CounterMappingRegion > MappingRegions
std::error_code readULEB128(uint64_t &Result)
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
static ErrorOr< SectionRef > lookupSection(ObjectFile &OF, StringRef Name)
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static cl::opt< std::string > FuncName("cppfname", cl::desc("Specify the name of the generated function"), cl::value_desc("function name"))
std::error_code getName(StringRef &Result) const
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr)
Utility function to decode a ULEB128 value.
ArrayRef< StringRef > Filenames
ErrorOr< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
Coverage mapping information for a single function.
void dump(const Counter &C, llvm::raw_ostream &OS) const
size_t alignmentAdjustment(const void *Ptr, size_t Alignment)
Returns the necessary adjustment for aligning Ptr to Alignment bytes, rounding up.
Reader for the raw coverage filenames.
A CodeRegion associates some code with a counter.
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.
static ErrorOr< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
section_iterator_range sections() const
std::error_code readString(StringRef &Result)
uint64_t getAddress() const
Triple - Helper class for working with autoconf configuration names.
A file format agnostic iterator over coverage mapping data.
static const unsigned EncodingExpansionRegionBit
static const char * TestingFormatMagic
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...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
std::error_code getContents(StringRef &Result) const
std::error_code readCoverageMappingData(SectionData &ProfileNames, StringRef Data, std::vector< BinaryCoverageReader::ProfileMappingRecord > &Records, std::vector< StringRef > &Filenames)
The mapping of profile information to coverage data.
const ARM::ArchExtKind Kind
static const unsigned EncodingTagBits
LLVM Value Representation.
std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1)
std::error_code readSize(uint64_t &Result)
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.
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...
bool empty() const
empty - Check if the string is empty.