• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for reading coverage mapping data for
11 // instrumentation based coverage.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/Object/MachOUniversal.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/LEB128.h"
22 #include "llvm/Support/MathExtras.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 using namespace llvm;
26 using namespace coverage;
27 using namespace object;
28 
29 #define DEBUG_TYPE "coverage-mapping"
30 
increment()31 void CoverageMappingIterator::increment() {
32   // Check if all the records were read or if an error occurred while reading
33   // the next record.
34   if (auto E = Reader->readNextRecord(Record)) {
35     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
36       if (CME.get() == coveragemap_error::eof)
37         *this = CoverageMappingIterator();
38       else
39         llvm_unreachable("Unexpected error in coverage mapping iterator");
40     });
41   }
42 }
43 
readULEB128(uint64_t & Result)44 Error RawCoverageReader::readULEB128(uint64_t &Result) {
45   if (Data.size() < 1)
46     return make_error<CoverageMapError>(coveragemap_error::truncated);
47   unsigned N = 0;
48   Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
49   if (N > Data.size())
50     return make_error<CoverageMapError>(coveragemap_error::malformed);
51   Data = Data.substr(N);
52   return Error::success();
53 }
54 
readIntMax(uint64_t & Result,uint64_t MaxPlus1)55 Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
56   if (auto Err = readULEB128(Result))
57     return Err;
58   if (Result >= MaxPlus1)
59     return make_error<CoverageMapError>(coveragemap_error::malformed);
60   return Error::success();
61 }
62 
readSize(uint64_t & Result)63 Error RawCoverageReader::readSize(uint64_t &Result) {
64   if (auto Err = readULEB128(Result))
65     return Err;
66   // Sanity check the number.
67   if (Result > Data.size())
68     return make_error<CoverageMapError>(coveragemap_error::malformed);
69   return Error::success();
70 }
71 
readString(StringRef & Result)72 Error RawCoverageReader::readString(StringRef &Result) {
73   uint64_t Length;
74   if (auto Err = readSize(Length))
75     return Err;
76   Result = Data.substr(0, Length);
77   Data = Data.substr(Length);
78   return Error::success();
79 }
80 
read()81 Error RawCoverageFilenamesReader::read() {
82   uint64_t NumFilenames;
83   if (auto Err = readSize(NumFilenames))
84     return Err;
85   for (size_t I = 0; I < NumFilenames; ++I) {
86     StringRef Filename;
87     if (auto Err = readString(Filename))
88       return Err;
89     Filenames.push_back(Filename);
90   }
91   return Error::success();
92 }
93 
decodeCounter(unsigned Value,Counter & C)94 Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
95   auto Tag = Value & Counter::EncodingTagMask;
96   switch (Tag) {
97   case Counter::Zero:
98     C = Counter::getZero();
99     return Error::success();
100   case Counter::CounterValueReference:
101     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
102     return Error::success();
103   default:
104     break;
105   }
106   Tag -= Counter::Expression;
107   switch (Tag) {
108   case CounterExpression::Subtract:
109   case CounterExpression::Add: {
110     auto ID = Value >> Counter::EncodingTagBits;
111     if (ID >= Expressions.size())
112       return make_error<CoverageMapError>(coveragemap_error::malformed);
113     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
114     C = Counter::getExpression(ID);
115     break;
116   }
117   default:
118     return make_error<CoverageMapError>(coveragemap_error::malformed);
119   }
120   return Error::success();
121 }
122 
readCounter(Counter & C)123 Error RawCoverageMappingReader::readCounter(Counter &C) {
124   uint64_t EncodedCounter;
125   if (auto Err =
126           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
127     return Err;
128   if (auto Err = decodeCounter(EncodedCounter, C))
129     return Err;
130   return Error::success();
131 }
132 
133 static const unsigned EncodingExpansionRegionBit = 1
134                                                    << Counter::EncodingTagBits;
135 
136 /// \brief Read the sub-array of regions for the given inferred file id.
137 /// \param NumFileIDs the number of file ids that are defined for this
138 /// function.
readMappingRegionsSubArray(std::vector<CounterMappingRegion> & MappingRegions,unsigned InferredFileID,size_t NumFileIDs)139 Error RawCoverageMappingReader::readMappingRegionsSubArray(
140     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
141     size_t NumFileIDs) {
142   uint64_t NumRegions;
143   if (auto Err = readSize(NumRegions))
144     return Err;
145   unsigned LineStart = 0;
146   for (size_t I = 0; I < NumRegions; ++I) {
147     Counter C;
148     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
149 
150     // Read the combined counter + region kind.
151     uint64_t EncodedCounterAndRegion;
152     if (auto Err = readIntMax(EncodedCounterAndRegion,
153                               std::numeric_limits<unsigned>::max()))
154       return Err;
155     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
156     uint64_t ExpandedFileID = 0;
157     if (Tag != Counter::Zero) {
158       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
159         return Err;
160     } else {
161       // Is it an expansion region?
162       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
163         Kind = CounterMappingRegion::ExpansionRegion;
164         ExpandedFileID = EncodedCounterAndRegion >>
165                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
166         if (ExpandedFileID >= NumFileIDs)
167           return make_error<CoverageMapError>(coveragemap_error::malformed);
168       } else {
169         switch (EncodedCounterAndRegion >>
170                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
171         case CounterMappingRegion::CodeRegion:
172           // Don't do anything when we have a code region with a zero counter.
173           break;
174         case CounterMappingRegion::SkippedRegion:
175           Kind = CounterMappingRegion::SkippedRegion;
176           break;
177         default:
178           return make_error<CoverageMapError>(coveragemap_error::malformed);
179         }
180       }
181     }
182 
183     // Read the source range.
184     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
185     if (auto Err =
186             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
187       return Err;
188     if (auto Err = readULEB128(ColumnStart))
189       return Err;
190     if (ColumnStart > std::numeric_limits<unsigned>::max())
191       return make_error<CoverageMapError>(coveragemap_error::malformed);
192     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
193       return Err;
194     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
195       return Err;
196     LineStart += LineStartDelta;
197     // Adjust the column locations for the empty regions that are supposed to
198     // cover whole lines. Those regions should be encoded with the
199     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
200     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
201     // we set the column range to (0 -> 0) to ensure that the column start and
202     // column end take up one byte each.
203     // The std::numeric_limits<unsigned>::max() is used to represent a column
204     // position at the end of the line without knowing the length of that line.
205     if (ColumnStart == 0 && ColumnEnd == 0) {
206       ColumnStart = 1;
207       ColumnEnd = std::numeric_limits<unsigned>::max();
208     }
209 
210     DEBUG({
211       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
212              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
213              << ColumnEnd << ", ";
214       if (Kind == CounterMappingRegion::ExpansionRegion)
215         dbgs() << "Expands to file " << ExpandedFileID;
216       else
217         CounterMappingContext(Expressions).dump(C, dbgs());
218       dbgs() << "\n";
219     });
220 
221     MappingRegions.push_back(CounterMappingRegion(
222         C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
223         LineStart + NumLines, ColumnEnd, Kind));
224   }
225   return Error::success();
226 }
227 
read()228 Error RawCoverageMappingReader::read() {
229 
230   // Read the virtual file mapping.
231   llvm::SmallVector<unsigned, 8> VirtualFileMapping;
232   uint64_t NumFileMappings;
233   if (auto Err = readSize(NumFileMappings))
234     return Err;
235   for (size_t I = 0; I < NumFileMappings; ++I) {
236     uint64_t FilenameIndex;
237     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
238       return Err;
239     VirtualFileMapping.push_back(FilenameIndex);
240   }
241 
242   // Construct the files using unique filenames and virtual file mapping.
243   for (auto I : VirtualFileMapping) {
244     Filenames.push_back(TranslationUnitFilenames[I]);
245   }
246 
247   // Read the expressions.
248   uint64_t NumExpressions;
249   if (auto Err = readSize(NumExpressions))
250     return Err;
251   // Create an array of dummy expressions that get the proper counters
252   // when the expressions are read, and the proper kinds when the counters
253   // are decoded.
254   Expressions.resize(
255       NumExpressions,
256       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
257   for (size_t I = 0; I < NumExpressions; ++I) {
258     if (auto Err = readCounter(Expressions[I].LHS))
259       return Err;
260     if (auto Err = readCounter(Expressions[I].RHS))
261       return Err;
262   }
263 
264   // Read the mapping regions sub-arrays.
265   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
266        InferredFileID < S; ++InferredFileID) {
267     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
268                                               VirtualFileMapping.size()))
269       return Err;
270   }
271 
272   // Set the counters for the expansion regions.
273   // i.e. Counter of expansion region = counter of the first region
274   // from the expanded file.
275   // Perform multiple passes to correctly propagate the counters through
276   // all the nested expansion regions.
277   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
278   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
279   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
280     for (auto &R : MappingRegions) {
281       if (R.Kind != CounterMappingRegion::ExpansionRegion)
282         continue;
283       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
284       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
285     }
286     for (auto &R : MappingRegions) {
287       if (FileIDExpansionRegionMapping[R.FileID]) {
288         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
289         FileIDExpansionRegionMapping[R.FileID] = nullptr;
290       }
291     }
292   }
293 
294   return Error::success();
295 }
296 
isDummy()297 Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
298   // A dummy coverage mapping data consists of just one region with zero count.
299   uint64_t NumFileMappings;
300   if (Error Err = readSize(NumFileMappings))
301     return std::move(Err);
302   if (NumFileMappings != 1)
303     return false;
304   // We don't expect any specific value for the filename index, just skip it.
305   uint64_t FilenameIndex;
306   if (Error Err =
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)
313     return false;
314   uint64_t NumRegions;
315   if (Error Err = readSize(NumRegions))
316     return std::move(Err);
317   if (NumRegions != 1)
318     return false;
319   uint64_t EncodedCounterAndRegion;
320   if (Error Err = readIntMax(EncodedCounterAndRegion,
321                              std::numeric_limits<unsigned>::max()))
322     return std::move(Err);
323   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
324   return Tag == Counter::Zero;
325 }
326 
create(SectionRef & Section)327 Error InstrProfSymtab::create(SectionRef &Section) {
328   if (auto EC = Section.getContents(Data))
329     return errorCodeToError(EC);
330   Address = Section.getAddress();
331   return Error::success();
332 }
333 
getFuncName(uint64_t Pointer,size_t Size)334 StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
335   if (Pointer < Address)
336     return StringRef();
337   auto Offset = Pointer - Address;
338   if (Offset + Size > Data.size())
339     return StringRef();
340   return Data.substr(Pointer - Address, Size);
341 }
342 
343 // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
isCoverageMappingDummy(uint64_t Hash,StringRef Mapping)344 static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
345   // The hash value of dummy mapping records is always zero.
346   if (Hash)
347     return false;
348   return RawCoverageMappingDummyChecker(Mapping).isDummy();
349 }
350 
351 namespace {
352 struct CovMapFuncRecordReader {
353   // The interface to read coverage mapping function records for a module.
354   //
355   // \p Buf points to the buffer containing the \c CovHeader of the coverage
356   // mapping data associated with the module.
357   //
358   // Returns a pointer to the next \c CovHeader if it exists, or a pointer
359   // greater than \p End if not.
360   virtual Expected<const char *> readFunctionRecords(const char *Buf,
361                                                      const char *End) = 0;
~CovMapFuncRecordReader__anoncb2b51910211::CovMapFuncRecordReader362   virtual ~CovMapFuncRecordReader() {}
363   template <class IntPtrT, support::endianness Endian>
364   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
365   get(coverage::CovMapVersion Version, InstrProfSymtab &P,
366       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
367       std::vector<StringRef> &F);
368 };
369 
370 // A class for reading coverage mapping function records for a module.
371 template <coverage::CovMapVersion Version, class IntPtrT,
372           support::endianness Endian>
373 class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
374   typedef typename coverage::CovMapTraits<
375       Version, IntPtrT>::CovMapFuncRecordType FuncRecordType;
376   typedef typename coverage::CovMapTraits<Version, IntPtrT>::NameRefType
377       NameRefType;
378 
379   // Maps function's name references to the indexes of their records
380   // in \c Records.
381   llvm::DenseMap<NameRefType, size_t> FunctionRecords;
382   InstrProfSymtab &ProfileNames;
383   std::vector<StringRef> &Filenames;
384   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
385 
386   // Add the record to the collection if we don't already have a record that
387   // points to the same function name. This is useful to ignore the redundant
388   // records for the functions with ODR linkage.
389   // In addition, prefer records with real coverage mapping data to dummy
390   // records, which were emitted for inline functions which were seen but
391   // not used in the corresponding translation unit.
insertFunctionRecordIfNeeded(const FuncRecordType * CFR,StringRef Mapping,size_t FilenamesBegin)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>();
396     auto InsertResult =
397         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
398     if (InsertResult.second) {
399       StringRef FuncName;
400       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
401         return Err;
402       Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin,
403                            Filenames.size() - FilenamesBegin);
404       return Error::success();
405     }
406     // Update the existing record if it's a dummy and the new record is real.
407     size_t OldRecordIndex = InsertResult.first->second;
408     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
409         Records[OldRecordIndex];
410     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
411         OldRecord.FunctionHash, OldRecord.CoverageMapping);
412     if (Error Err = OldIsDummyExpected.takeError())
413       return Err;
414     if (!*OldIsDummyExpected)
415       return Error::success();
416     Expected<bool> NewIsDummyExpected =
417         isCoverageMappingDummy(FuncHash, Mapping);
418     if (Error Err = NewIsDummyExpected.takeError())
419       return Err;
420     if (*NewIsDummyExpected)
421       return Error::success();
422     OldRecord.FunctionHash = FuncHash;
423     OldRecord.CoverageMapping = Mapping;
424     OldRecord.FilenamesBegin = FilenamesBegin;
425     OldRecord.FilenamesSize = Filenames.size() - FilenamesBegin;
426     return Error::success();
427   }
428 
429 public:
VersionedCovMapFuncRecordReader(InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,std::vector<StringRef> & F)430   VersionedCovMapFuncRecordReader(
431       InstrProfSymtab &P,
432       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
433       std::vector<StringRef> &F)
434       : ProfileNames(P), Filenames(F), Records(R) {}
~VersionedCovMapFuncRecordReader()435   ~VersionedCovMapFuncRecordReader() override {}
436 
readFunctionRecords(const char * Buf,const char * End)437   Expected<const char *> readFunctionRecords(const char *Buf,
438                                              const char *End) override {
439     using namespace support;
440     if (Buf + sizeof(CovMapHeader) > End)
441       return make_error<CoverageMapError>(coveragemap_error::malformed);
442     auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf);
443     uint32_t NRecords = CovHeader->getNRecords<Endian>();
444     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
445     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
446     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
447     Buf = reinterpret_cast<const char *>(CovHeader + 1);
448 
449     // Skip past the function records, saving the start and end for later.
450     const char *FunBuf = Buf;
451     Buf += NRecords * sizeof(FuncRecordType);
452     const char *FunEnd = Buf;
453 
454     // Get the filenames.
455     if (Buf + FilenamesSize > End)
456       return make_error<CoverageMapError>(coveragemap_error::malformed);
457     size_t FilenamesBegin = Filenames.size();
458     RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames);
459     if (auto Err = Reader.read())
460       return std::move(Err);
461     Buf += FilenamesSize;
462 
463     // We'll read the coverage mapping records in the loop below.
464     const char *CovBuf = Buf;
465     Buf += CoverageSize;
466     const char *CovEnd = Buf;
467 
468     if (Buf > End)
469       return make_error<CoverageMapError>(coveragemap_error::malformed);
470     // Each coverage map has an alignment of 8, so we need to adjust alignment
471     // before reading the next map.
472     Buf += alignmentAdjustment(Buf, 8);
473 
474     auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf);
475     while ((const char *)CFR < FunEnd) {
476       // Read the function information
477       uint32_t DataSize = CFR->template getDataSize<Endian>();
478 
479       // Now use that to read the coverage data.
480       if (CovBuf + DataSize > CovEnd)
481         return make_error<CoverageMapError>(coveragemap_error::malformed);
482       auto Mapping = StringRef(CovBuf, DataSize);
483       CovBuf += DataSize;
484 
485       if (Error Err =
486               insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin))
487         return std::move(Err);
488       CFR++;
489     }
490     return Buf;
491   }
492 };
493 } // end anonymous namespace
494 
495 template <class IntPtrT, support::endianness Endian>
get(coverage::CovMapVersion Version,InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,std::vector<StringRef> & F)496 Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
497     coverage::CovMapVersion Version, InstrProfSymtab &P,
498     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
499     std::vector<StringRef> &F) {
500   using namespace coverage;
501   switch (Version) {
502   case CovMapVersion::Version1:
503     return llvm::make_unique<VersionedCovMapFuncRecordReader<
504         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
505   case CovMapVersion::Version2:
506     // Decompress the name data.
507     if (Error E = P.create(P.getNameData()))
508       return std::move(E);
509     return llvm::make_unique<VersionedCovMapFuncRecordReader<
510         CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
511   }
512   llvm_unreachable("Unsupported version");
513 }
514 
515 template <typename T, support::endianness Endian>
readCoverageMappingData(InstrProfSymtab & ProfileNames,StringRef Data,std::vector<BinaryCoverageReader::ProfileMappingRecord> & Records,std::vector<StringRef> & Filenames)516 static Error readCoverageMappingData(
517     InstrProfSymtab &ProfileNames, StringRef Data,
518     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
519     std::vector<StringRef> &Filenames) {
520   using namespace coverage;
521   // Read the records in the coverage data section.
522   auto CovHeader =
523       reinterpret_cast<const coverage::CovMapHeader *>(Data.data());
524   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
525   if (Version > coverage::CovMapVersion::CurrentVersion)
526     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
527   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
528       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
529                                              Filenames);
530   if (Error E = ReaderExpected.takeError())
531     return E;
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())
536       return E;
537     Buf = NextHeaderOrErr.get();
538   }
539   return Error::success();
540 }
541 static const char *TestingFormatMagic = "llvmcovmtestdata";
542 
loadTestingFormat(StringRef Data,InstrProfSymtab & ProfileNames,StringRef & CoverageMapping,uint8_t & BytesInAddress,support::endianness & Endian)543 static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames,
544                                StringRef &CoverageMapping,
545                                uint8_t &BytesInAddress,
546                                support::endianness &Endian) {
547   BytesInAddress = 8;
548   Endian = support::endianness::little;
549 
550   Data = Data.substr(StringRef(TestingFormatMagic).size());
551   if (Data.size() < 1)
552     return make_error<CoverageMapError>(coveragemap_error::truncated);
553   unsigned N = 0;
554   auto ProfileNamesSize =
555       decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
556   if (N > Data.size())
557     return make_error<CoverageMapError>(coveragemap_error::malformed);
558   Data = Data.substr(N);
559   if (Data.size() < 1)
560     return make_error<CoverageMapError>(coveragemap_error::truncated);
561   N = 0;
562   uint64_t Address =
563       decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
564   if (N > Data.size())
565     return make_error<CoverageMapError>(coveragemap_error::malformed);
566   Data = Data.substr(N);
567   if (Data.size() < ProfileNamesSize)
568     return make_error<CoverageMapError>(coveragemap_error::malformed);
569   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
570     return E;
571   CoverageMapping = Data.substr(ProfileNamesSize);
572   // Skip the padding bytes because coverage map data has an alignment of 8.
573   if (CoverageMapping.size() < 1)
574     return make_error<CoverageMapError>(coveragemap_error::truncated);
575   size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8);
576   if (CoverageMapping.size() < Pad)
577     return make_error<CoverageMapError>(coveragemap_error::malformed);
578   CoverageMapping = CoverageMapping.substr(Pad);
579   return Error::success();
580 }
581 
lookupSection(ObjectFile & OF,StringRef Name)582 static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) {
583   StringRef FoundName;
584   for (const auto &Section : OF.sections()) {
585     if (auto EC = Section.getName(FoundName))
586       return errorCodeToError(EC);
587     if (FoundName == Name)
588       return Section;
589   }
590   return make_error<CoverageMapError>(coveragemap_error::no_data_found);
591 }
592 
loadBinaryFormat(MemoryBufferRef ObjectBuffer,InstrProfSymtab & ProfileNames,StringRef & CoverageMapping,uint8_t & BytesInAddress,support::endianness & Endian,StringRef Arch)593 static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
594                               InstrProfSymtab &ProfileNames,
595                               StringRef &CoverageMapping,
596                               uint8_t &BytesInAddress,
597                               support::endianness &Endian, StringRef Arch) {
598   auto BinOrErr = object::createBinary(ObjectBuffer);
599   if (!BinOrErr)
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())) {
604     // If we have a universal binary, try to look up the object for the
605     // appropriate architecture.
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())) {
611     // For any other object file, upcast and take ownership.
612     OF.reset(cast<object::ObjectFile>(Bin.release()));
613     // If we've asked for a particular arch, make sure they match.
614     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
615       return errorCodeToError(object_error::arch_not_found);
616   } else
617     // We can only handle object files.
618     return make_error<CoverageMapError>(coveragemap_error::malformed);
619 
620   // The coverage uses native pointer sizes for the object it's written in.
621   BytesInAddress = OF->getBytesInAddress();
622   Endian = OF->isLittleEndian() ? support::endianness::little
623                                 : support::endianness::big;
624 
625   // Look for the sections that we are interested in.
626   auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false));
627   if (auto E = NamesSection.takeError())
628     return E;
629   auto CoverageSection =
630       lookupSection(*OF, getInstrProfCoverageSectionName(false));
631   if (auto E = CoverageSection.takeError())
632     return E;
633 
634   // Get the contents of the given sections.
635   if (auto EC = CoverageSection->getContents(CoverageMapping))
636     return errorCodeToError(EC);
637   if (Error E = ProfileNames.create(*NamesSection))
638     return E;
639 
640   return Error::success();
641 }
642 
643 Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> & ObjectBuffer,StringRef Arch)644 BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
645                              StringRef Arch) {
646   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
647 
648   StringRef Coverage;
649   uint8_t BytesInAddress;
650   support::endianness Endian;
651   Error E;
652   consumeError(std::move(E));
653   if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
654     // This is a special format used for testing.
655     E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames,
656                           Coverage, BytesInAddress, Endian);
657   else
658     E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames,
659                          Coverage, BytesInAddress, Endian, Arch);
660   if (E)
661     return std::move(E);
662 
663   if (BytesInAddress == 4 && Endian == support::endianness::little)
664     E = readCoverageMappingData<uint32_t, support::endianness::little>(
665         Reader->ProfileNames, Coverage, Reader->MappingRecords,
666         Reader->Filenames);
667   else if (BytesInAddress == 4 && Endian == support::endianness::big)
668     E = readCoverageMappingData<uint32_t, support::endianness::big>(
669         Reader->ProfileNames, Coverage, Reader->MappingRecords,
670         Reader->Filenames);
671   else if (BytesInAddress == 8 && Endian == support::endianness::little)
672     E = readCoverageMappingData<uint64_t, support::endianness::little>(
673         Reader->ProfileNames, Coverage, Reader->MappingRecords,
674         Reader->Filenames);
675   else if (BytesInAddress == 8 && Endian == support::endianness::big)
676     E = readCoverageMappingData<uint64_t, support::endianness::big>(
677         Reader->ProfileNames, Coverage, Reader->MappingRecords,
678         Reader->Filenames);
679   else
680     return make_error<CoverageMapError>(coveragemap_error::malformed);
681   if (E)
682     return std::move(E);
683   return std::move(Reader);
684 }
685 
readNextRecord(CoverageMappingRecord & Record)686 Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
687   if (CurrentRecord >= MappingRecords.size())
688     return make_error<CoverageMapError>(coveragemap_error::eof);
689 
690   FunctionsFilenames.clear();
691   Expressions.clear();
692   MappingRegions.clear();
693   auto &R = MappingRecords[CurrentRecord];
694   RawCoverageMappingReader Reader(
695       R.CoverageMapping,
696       makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
697       FunctionsFilenames, Expressions, MappingRegions);
698   if (auto Err = Reader.read())
699     return Err;
700 
701   Record.FunctionName = R.FunctionName;
702   Record.FunctionHash = R.FunctionHash;
703   Record.Filenames = FunctionsFilenames;
704   Record.Expressions = Expressions;
705   Record.MappingRegions = MappingRegions;
706 
707   ++CurrentRecord;
708   return Error::success();
709 }
710