blob: c8108d4ce9945e9759c38c71e0559261cff5d3ff [file] [log] [blame]
Alex Lorenza20a5d52014-07-24 23:57:54 +00001//=-- 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/CoverageMappingReader.h"
16#include "llvm/ADT/DenseSet.h"
17#include "llvm/Object/ObjectFile.h"
18#include "llvm/Support/LEB128.h"
19
20using namespace llvm;
21using namespace coverage;
22using namespace object;
23
24void CoverageMappingIterator::increment() {
25 // Check if all the records were read or if an error occurred while reading
26 // the next record.
27 if (Reader->readNextRecord(Record))
28 *this = CoverageMappingIterator();
29}
30
31std::error_code RawCoverageReader::readULEB128(uint64_t &Result) {
32 if (Data.size() < 1)
33 return error(instrprof_error::truncated);
34 unsigned N = 0;
35 Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
36 if (N > Data.size())
37 return error(instrprof_error::malformed);
38 Data = Data.substr(N);
39 return success();
40}
41
42std::error_code RawCoverageReader::readIntMax(uint64_t &Result,
43 uint64_t MaxPlus1) {
44 if (auto Err = readULEB128(Result))
45 return Err;
46 if (Result >= MaxPlus1)
47 return error(instrprof_error::malformed);
48 return success();
49}
50
51std::error_code RawCoverageReader::readSize(uint64_t &Result) {
52 if (auto Err = readULEB128(Result))
53 return Err;
54 // Sanity check the number.
55 if (Result > Data.size())
56 return error(instrprof_error::malformed);
57 return success();
58}
59
60std::error_code RawCoverageReader::readString(StringRef &Result) {
61 uint64_t Length;
62 if (auto Err = readSize(Length))
63 return Err;
64 Result = Data.substr(0, Length);
65 Data = Data.substr(Length);
66 return success();
67}
68
69std::error_code RawCoverageFilenamesReader::read() {
70 uint64_t NumFilenames;
71 if (auto Err = readSize(NumFilenames))
72 return Err;
73 for (size_t I = 0; I < NumFilenames; ++I) {
74 StringRef Filename;
75 if (auto Err = readString(Filename))
76 return Err;
77 Filenames.push_back(Filename);
78 }
79 return success();
80}
81
82std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value,
83 Counter &C) {
84 auto Tag = Value & Counter::EncodingTagMask;
85 switch (Tag) {
86 case Counter::Zero:
87 C = Counter::getZero();
88 return success();
89 case Counter::CounterValueReference:
90 C = Counter::getCounter(Value >> Counter::EncodingTagBits);
91 return success();
92 default:
93 break;
94 }
95 Tag -= Counter::Expression;
96 switch (Tag) {
97 case CounterExpression::Subtract:
98 case CounterExpression::Add: {
99 auto ID = Value >> Counter::EncodingTagBits;
100 if (ID >= Expressions.size())
101 return error(instrprof_error::malformed);
102 Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
103 C = Counter::getExpression(ID);
104 break;
105 }
106 default:
107 return error(instrprof_error::malformed);
108 }
109 return success();
110}
111
112std::error_code RawCoverageMappingReader::readCounter(Counter &C) {
113 uint64_t EncodedCounter;
114 if (auto Err =
115 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
116 return Err;
117 if (auto Err = decodeCounter(EncodedCounter, C))
118 return Err;
119 return success();
120}
121
122static const unsigned EncodingExpansionRegionBit = 1
123 << Counter::EncodingTagBits;
124
125/// \brief Read the sub-array of regions for the given inferred file id.
Ehsan Akhgari29b61ce2014-07-25 02:51:57 +0000126/// \param NumFileIDs the number of file ids that are defined for this
Alex Lorenza20a5d52014-07-24 23:57:54 +0000127/// function.
128std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
129 std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
130 size_t NumFileIDs) {
131 uint64_t NumRegions;
132 if (auto Err = readSize(NumRegions))
133 return Err;
134 unsigned LineStart = 0;
135 for (size_t I = 0; I < NumRegions; ++I) {
136 Counter C;
137 CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
138
139 // Read the combined counter + region kind.
140 uint64_t EncodedCounterAndRegion;
141 if (auto Err = readIntMax(EncodedCounterAndRegion,
142 std::numeric_limits<unsigned>::max()))
143 return Err;
144 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
145 uint64_t ExpandedFileID = 0;
146 if (Tag != Counter::Zero) {
147 if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
148 return Err;
149 } else {
150 // Is it an expansion region?
151 if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
152 Kind = CounterMappingRegion::ExpansionRegion;
153 ExpandedFileID = EncodedCounterAndRegion >>
154 Counter::EncodingCounterTagAndExpansionRegionTagBits;
155 if (ExpandedFileID >= NumFileIDs)
156 return error(instrprof_error::malformed);
157 } else {
158 switch (EncodedCounterAndRegion >>
159 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
160 case CounterMappingRegion::CodeRegion:
161 // Don't do anything when we have a code region with a zero counter.
162 break;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000163 case CounterMappingRegion::SkippedRegion:
164 Kind = CounterMappingRegion::SkippedRegion;
165 break;
166 default:
167 return error(instrprof_error::malformed);
168 }
169 }
170 }
171
172 // Read the source range.
Alex Lorenz1193b5e2014-08-04 18:00:51 +0000173 uint64_t LineStartDelta, CodeBeforeColumnStart, NumLines, ColumnEnd;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000174 if (auto Err =
175 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
176 return Err;
Alex Lorenz1193b5e2014-08-04 18:00:51 +0000177 if (auto Err = readULEB128(CodeBeforeColumnStart))
Alex Lorenza20a5d52014-07-24 23:57:54 +0000178 return Err;
Alex Lorenz1193b5e2014-08-04 18:00:51 +0000179 bool HasCodeBefore = CodeBeforeColumnStart & 1;
180 uint64_t ColumnStart = CodeBeforeColumnStart >>
181 CounterMappingRegion::EncodingHasCodeBeforeBits;
182 if (ColumnStart > std::numeric_limits<unsigned>::max())
183 return error(instrprof_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000184 if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
185 return Err;
186 if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
187 return Err;
188 LineStart += LineStartDelta;
189 // Adjust the column locations for the empty regions that are supposed to
190 // cover whole lines. Those regions should be encoded with the
191 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
192 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
193 // we set the column range to (0 -> 0) to ensure that the column start and
194 // column end take up one byte each.
195 // The std::numeric_limits<unsigned>::max() is used to represent a column
196 // position at the end of the line without knowing the length of that line.
197 if (ColumnStart == 0 && ColumnEnd == 0) {
198 ColumnStart = 1;
199 ColumnEnd = std::numeric_limits<unsigned>::max();
200 }
Alex Lorenz1193b5e2014-08-04 18:00:51 +0000201 MappingRegions.push_back(CounterMappingRegion(
202 C, InferredFileID, LineStart, ColumnStart, LineStart + NumLines,
203 ColumnEnd, HasCodeBefore, Kind));
Alex Lorenza20a5d52014-07-24 23:57:54 +0000204 MappingRegions.back().ExpandedFileID = ExpandedFileID;
205 }
206 return success();
207}
208
209std::error_code RawCoverageMappingReader::read(CoverageMappingRecord &Record) {
210
211 // Read the virtual file mapping.
212 llvm::SmallVector<unsigned, 8> VirtualFileMapping;
213 uint64_t NumFileMappings;
214 if (auto Err = readSize(NumFileMappings))
215 return Err;
216 for (size_t I = 0; I < NumFileMappings; ++I) {
217 uint64_t FilenameIndex;
218 if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
219 return Err;
220 VirtualFileMapping.push_back(FilenameIndex);
221 }
222
223 // Construct the files using unique filenames and virtual file mapping.
224 for (auto I : VirtualFileMapping) {
225 Filenames.push_back(TranslationUnitFilenames[I]);
226 }
227
228 // Read the expressions.
229 uint64_t NumExpressions;
230 if (auto Err = readSize(NumExpressions))
231 return Err;
232 // Create an array of dummy expressions that get the proper counters
233 // when the expressions are read, and the proper kinds when the counters
234 // are decoded.
235 Expressions.resize(
236 NumExpressions,
237 CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
238 for (size_t I = 0; I < NumExpressions; ++I) {
239 if (auto Err = readCounter(Expressions[I].LHS))
240 return Err;
241 if (auto Err = readCounter(Expressions[I].RHS))
242 return Err;
243 }
244
245 // Read the mapping regions sub-arrays.
246 for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
247 InferredFileID < S; ++InferredFileID) {
248 if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
249 VirtualFileMapping.size()))
250 return Err;
251 }
252
253 // Set the counters for the expansion regions.
254 // i.e. Counter of expansion region = counter of the first region
255 // from the expanded file.
256 // Perform multiple passes to correctly propagate the counters through
257 // all the nested expansion regions.
Alex Lorenz251b3e32014-07-29 21:42:24 +0000258 SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
259 FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000260 for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
Alex Lorenz251b3e32014-07-29 21:42:24 +0000261 for (auto &R : MappingRegions) {
262 if (R.Kind != CounterMappingRegion::ExpansionRegion)
263 continue;
264 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
265 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
266 }
267 for (auto &R : MappingRegions) {
268 if (FileIDExpansionRegionMapping[R.FileID]) {
269 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
270 FileIDExpansionRegionMapping[R.FileID] = nullptr;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000271 }
272 }
273 }
274
275 Record.FunctionName = FunctionName;
276 Record.Filenames = Filenames;
277 Record.Expressions = Expressions;
278 Record.MappingRegions = MappingRegions;
279 return success();
280}
281
282ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader(
283 StringRef FileName)
284 : CurrentRecord(0) {
285 auto File = llvm::object::ObjectFile::createObjectFile(FileName);
286 if (!File)
287 error(File.getError());
288 else
Rafael Espindola437b0d52014-07-31 03:12:45 +0000289 Object = std::move(File.get());
Alex Lorenza20a5d52014-07-24 23:57:54 +0000290}
291
292ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader(
293 std::unique_ptr<MemoryBuffer> &ObjectBuffer, sys::fs::file_magic Type)
294 : CurrentRecord(0) {
295 auto File = llvm::object::ObjectFile::createObjectFile(ObjectBuffer, Type);
296 if (!File)
297 error(File.getError());
298 else
Rafael Espindola437b0d52014-07-31 03:12:45 +0000299 Object = std::move(File.get());
Alex Lorenza20a5d52014-07-24 23:57:54 +0000300}
301
302namespace {
303/// \brief The coverage mapping data for a single function.
304/// It points to the function's name.
305template <typename IntPtrT> struct CoverageMappingFunctionRecord {
306 IntPtrT FunctionNamePtr;
307 uint32_t FunctionNameSize;
308 uint32_t CoverageMappingSize;
309};
310
311/// \brief The coverage mapping data for a single translation unit.
312/// It points to the array of function coverage mapping records and the encoded
313/// filenames array.
314template <typename IntPtrT> struct CoverageMappingTURecord {
315 uint32_t FunctionRecordsSize;
316 uint32_t FilenamesSize;
317 uint32_t CoverageMappingsSize;
318 uint32_t Version;
319};
320
321/// \brief A helper structure to access the data from a section
322/// in an object file.
323struct SectionData {
324 StringRef Data;
325 uint64_t Address;
326
327 std::error_code load(SectionRef &Section) {
328 if (auto Err = Section.getContents(Data))
329 return Err;
330 return Section.getAddress(Address);
331 }
332
333 std::error_code get(uint64_t Pointer, size_t Size, StringRef &Result) {
334 if (Pointer < Address)
335 return instrprof_error::malformed;
336 auto Offset = Pointer - Address;
337 if (Offset + Size > Data.size())
338 return instrprof_error::malformed;
339 Result = Data.substr(Pointer - Address, Size);
340 return instrprof_error::success;
341 }
342};
343}
344
345template <typename T>
346std::error_code readCoverageMappingData(
347 SectionRef &ProfileNames, SectionRef &CoverageMapping,
348 std::vector<ObjectFileCoverageMappingReader::ProfileMappingRecord> &Records,
349 std::vector<StringRef> &Filenames) {
350 llvm::DenseSet<T> UniqueFunctionMappingData;
351
352 // Get the contents of the given sections.
353 StringRef Data;
354 if (auto Err = CoverageMapping.getContents(Data))
355 return Err;
356 SectionData ProfileNamesData;
357 if (auto Err = ProfileNamesData.load(ProfileNames))
358 return Err;
359
360 // Read the records in the coverage data section.
361 while (!Data.empty()) {
362 if (Data.size() < sizeof(CoverageMappingTURecord<T>))
363 return instrprof_error::malformed;
364 auto TU = reinterpret_cast<const CoverageMappingTURecord<T> *>(Data.data());
365 Data = Data.substr(sizeof(CoverageMappingTURecord<T>));
366 switch (TU->Version) {
367 case CoverageMappingVersion1:
368 break;
369 default:
370 return instrprof_error::unsupported_version;
371 }
372 auto Version = CoverageMappingVersion(TU->Version);
373
374 // Get the function records.
375 auto FunctionRecords =
376 reinterpret_cast<const CoverageMappingFunctionRecord<T> *>(Data.data());
377 if (Data.size() <
378 sizeof(CoverageMappingFunctionRecord<T>) * TU->FunctionRecordsSize)
379 return instrprof_error::malformed;
380 Data = Data.substr(sizeof(CoverageMappingFunctionRecord<T>) *
381 TU->FunctionRecordsSize);
382
383 // Get the filenames.
384 if (Data.size() < TU->FilenamesSize)
385 return instrprof_error::malformed;
386 auto RawFilenames = Data.substr(0, TU->FilenamesSize);
387 Data = Data.substr(TU->FilenamesSize);
388 size_t FilenamesBegin = Filenames.size();
389 RawCoverageFilenamesReader Reader(RawFilenames, Filenames);
390 if (auto Err = Reader.read())
391 return Err;
392
393 // Get the coverage mappings.
394 if (Data.size() < TU->CoverageMappingsSize)
395 return instrprof_error::malformed;
396 auto CoverageMappings = Data.substr(0, TU->CoverageMappingsSize);
397 Data = Data.substr(TU->CoverageMappingsSize);
398
399 for (unsigned I = 0; I < TU->FunctionRecordsSize; ++I) {
400 auto &MappingRecord = FunctionRecords[I];
401
402 // Get the coverage mapping.
403 if (CoverageMappings.size() < MappingRecord.CoverageMappingSize)
404 return instrprof_error::malformed;
405 auto Mapping =
406 CoverageMappings.substr(0, MappingRecord.CoverageMappingSize);
407 CoverageMappings =
408 CoverageMappings.substr(MappingRecord.CoverageMappingSize);
409
410 // Ignore this record if we already have a record that points to the same
411 // function name.
412 // This is useful to ignore the redundant records for the functions
413 // with ODR linkage.
414 if (UniqueFunctionMappingData.count(MappingRecord.FunctionNamePtr))
415 continue;
416 UniqueFunctionMappingData.insert(MappingRecord.FunctionNamePtr);
417 StringRef FunctionName;
418 if (auto Err = ProfileNamesData.get(MappingRecord.FunctionNamePtr,
419 MappingRecord.FunctionNameSize,
420 FunctionName))
421 return Err;
422 Records.push_back(ObjectFileCoverageMappingReader::ProfileMappingRecord(
423 Version, FunctionName, Mapping, FilenamesBegin,
424 Filenames.size() - FilenamesBegin));
425 }
426 }
427
428 return instrprof_error::success;
429}
430
431std::error_code ObjectFileCoverageMappingReader::readHeader() {
432 if (!Object)
433 return getError();
434 auto BytesInAddress = Object->getBytesInAddress();
435 if (BytesInAddress != 4 && BytesInAddress != 8)
436 return error(instrprof_error::malformed);
437
438 // Look for the sections that we are interested in.
439 int FoundSectionCount = 0;
440 SectionRef ProfileNames, CoverageMapping;
441 for (const auto &Section : Object->sections()) {
442 StringRef Name;
443 if (auto Err = Section.getName(Name))
444 return Err;
445 if (Name == "__llvm_prf_names") {
446 ProfileNames = Section;
447 } else if (Name == "__llvm_covmap") {
448 CoverageMapping = Section;
449 } else
450 continue;
451 ++FoundSectionCount;
452 }
453 if (FoundSectionCount != 2)
454 return error(instrprof_error::bad_header);
455
456 // Load the data from the found sections.
457 std::error_code Err;
458 if (BytesInAddress == 4)
459 Err = readCoverageMappingData<uint32_t>(ProfileNames, CoverageMapping,
460 MappingRecords, Filenames);
461 else
462 Err = readCoverageMappingData<uint64_t>(ProfileNames, CoverageMapping,
463 MappingRecords, Filenames);
464 if (Err)
465 return error(Err);
466
467 return success();
468}
469
470std::error_code
471ObjectFileCoverageMappingReader::readNextRecord(CoverageMappingRecord &Record) {
472 if (CurrentRecord >= MappingRecords.size())
473 return error(instrprof_error::eof);
474
475 FunctionsFilenames.clear();
476 Expressions.clear();
477 MappingRegions.clear();
478 auto &R = MappingRecords[CurrentRecord];
479 RawCoverageMappingReader Reader(
480 R.FunctionName, R.CoverageMapping,
481 makeArrayRef(Filenames.data() + R.FilenamesBegin, R.FilenamesSize),
482 FunctionsFilenames, Expressions, MappingRegions);
483 if (auto Err = Reader.read(Record))
484 return Err;
485 ++CurrentRecord;
486 return success();
487}