LLVM  3.7.0
CoverageMappingReader.cpp
Go to the documentation of this file.
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 
16 #include "llvm/ADT/DenseSet.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"
24 
25 using namespace llvm;
26 using namespace coverage;
27 using namespace object;
28 
29 #define DEBUG_TYPE "coverage-mapping"
30 
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 (Reader->readNextRecord(Record))
35  *this = CoverageMappingIterator();
36 }
37 
38 std::error_code RawCoverageReader::readULEB128(uint64_t &Result) {
39  if (Data.size() < 1)
41  unsigned N = 0;
42  Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
43  if (N > Data.size())
45  Data = Data.substr(N);
46  return std::error_code();
47 }
48 
49 std::error_code RawCoverageReader::readIntMax(uint64_t &Result,
50  uint64_t MaxPlus1) {
51  if (auto Err = readULEB128(Result))
52  return Err;
53  if (Result >= MaxPlus1)
55  return std::error_code();
56 }
57 
58 std::error_code RawCoverageReader::readSize(uint64_t &Result) {
59  if (auto Err = readULEB128(Result))
60  return Err;
61  // Sanity check the number.
62  if (Result > Data.size())
64  return std::error_code();
65 }
66 
67 std::error_code RawCoverageReader::readString(StringRef &Result) {
68  uint64_t Length;
69  if (auto Err = readSize(Length))
70  return Err;
71  Result = Data.substr(0, Length);
72  Data = Data.substr(Length);
73  return std::error_code();
74 }
75 
77  uint64_t NumFilenames;
78  if (auto Err = readSize(NumFilenames))
79  return Err;
80  for (size_t I = 0; I < NumFilenames; ++I) {
81  StringRef Filename;
82  if (auto Err = readString(Filename))
83  return Err;
84  Filenames.push_back(Filename);
85  }
86  return std::error_code();
87 }
88 
89 std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value,
90  Counter &C) {
91  auto Tag = Value & Counter::EncodingTagMask;
92  switch (Tag) {
93  case Counter::Zero:
94  C = Counter::getZero();
95  return std::error_code();
98  return std::error_code();
99  default:
100  break;
101  }
103  switch (Tag) {
105  case CounterExpression::Add: {
106  auto ID = Value >> Counter::EncodingTagBits;
107  if (ID >= Expressions.size())
109  Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
111  break;
112  }
113  default:
115  }
116  return std::error_code();
117 }
118 
119 std::error_code RawCoverageMappingReader::readCounter(Counter &C) {
120  uint64_t EncodedCounter;
121  if (auto Err =
122  readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
123  return Err;
124  if (auto Err = decodeCounter(EncodedCounter, C))
125  return Err;
126  return std::error_code();
127 }
128 
129 static const unsigned EncodingExpansionRegionBit = 1
131 
132 /// \brief Read the sub-array of regions for the given inferred file id.
133 /// \param NumFileIDs the number of file ids that are defined for this
134 /// function.
135 std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
136  std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
137  size_t NumFileIDs) {
138  uint64_t NumRegions;
139  if (auto Err = readSize(NumRegions))
140  return Err;
141  unsigned LineStart = 0;
142  for (size_t I = 0; I < NumRegions; ++I) {
143  Counter C;
145 
146  // Read the combined counter + region kind.
147  uint64_t EncodedCounterAndRegion;
148  if (auto Err = readIntMax(EncodedCounterAndRegion,
149  std::numeric_limits<unsigned>::max()))
150  return Err;
151  unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
152  uint64_t ExpandedFileID = 0;
153  if (Tag != Counter::Zero) {
154  if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
155  return Err;
156  } else {
157  // Is it an expansion region?
158  if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
160  ExpandedFileID = EncodedCounterAndRegion >>
162  if (ExpandedFileID >= NumFileIDs)
164  } else {
165  switch (EncodedCounterAndRegion >>
168  // Don't do anything when we have a code region with a zero counter.
169  break;
172  break;
173  default:
175  }
176  }
177  }
178 
179  // Read the source range.
180  uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
181  if (auto Err =
182  readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
183  return Err;
184  if (auto Err = readULEB128(ColumnStart))
185  return Err;
186  if (ColumnStart > std::numeric_limits<unsigned>::max())
188  if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
189  return Err;
190  if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
191  return Err;
192  LineStart += LineStartDelta;
193  // Adjust the column locations for the empty regions that are supposed to
194  // cover whole lines. Those regions should be encoded with the
195  // column range (1 -> std::numeric_limits<unsigned>::max()), but because
196  // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
197  // we set the column range to (0 -> 0) to ensure that the column start and
198  // column end take up one byte each.
199  // The std::numeric_limits<unsigned>::max() is used to represent a column
200  // position at the end of the line without knowing the length of that line.
201  if (ColumnStart == 0 && ColumnEnd == 0) {
202  ColumnStart = 1;
203  ColumnEnd = std::numeric_limits<unsigned>::max();
204  }
205 
206  DEBUG({
207  dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
208  << ColumnStart << " -> " << (LineStart + NumLines) << ":"
209  << ColumnEnd << ", ";
211  dbgs() << "Expands to file " << ExpandedFileID;
212  else
213  CounterMappingContext(Expressions).dump(C, dbgs());
214  dbgs() << "\n";
215  });
216 
217  MappingRegions.push_back(CounterMappingRegion(
218  C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
219  LineStart + NumLines, ColumnEnd, Kind));
220  }
221  return std::error_code();
222 }
223 
225 
226  // Read the virtual file mapping.
227  llvm::SmallVector<unsigned, 8> VirtualFileMapping;
228  uint64_t NumFileMappings;
229  if (auto Err = readSize(NumFileMappings))
230  return Err;
231  for (size_t I = 0; I < NumFileMappings; ++I) {
232  uint64_t FilenameIndex;
233  if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
234  return Err;
235  VirtualFileMapping.push_back(FilenameIndex);
236  }
237 
238  // Construct the files using unique filenames and virtual file mapping.
239  for (auto I : VirtualFileMapping) {
240  Filenames.push_back(TranslationUnitFilenames[I]);
241  }
242 
243  // Read the expressions.
244  uint64_t NumExpressions;
245  if (auto Err = readSize(NumExpressions))
246  return Err;
247  // Create an array of dummy expressions that get the proper counters
248  // when the expressions are read, and the proper kinds when the counters
249  // are decoded.
250  Expressions.resize(
251  NumExpressions,
253  for (size_t I = 0; I < NumExpressions; ++I) {
254  if (auto Err = readCounter(Expressions[I].LHS))
255  return Err;
256  if (auto Err = readCounter(Expressions[I].RHS))
257  return Err;
258  }
259 
260  // Read the mapping regions sub-arrays.
261  for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
262  InferredFileID < S; ++InferredFileID) {
263  if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
264  VirtualFileMapping.size()))
265  return Err;
266  }
267 
268  // Set the counters for the expansion regions.
269  // i.e. Counter of expansion region = counter of the first region
270  // from the expanded file.
271  // Perform multiple passes to correctly propagate the counters through
272  // all the nested expansion regions.
273  SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
274  FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
275  for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
276  for (auto &R : MappingRegions) {
278  continue;
279  assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
280  FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
281  }
282  for (auto &R : MappingRegions) {
283  if (FileIDExpansionRegionMapping[R.FileID]) {
284  FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
285  FileIDExpansionRegionMapping[R.FileID] = nullptr;
286  }
287  }
288  }
289 
290  return std::error_code();
291 }
292 
293 namespace {
294 
295 /// \brief A helper structure to access the data from a section
296 /// in an object file.
297 struct SectionData {
298  StringRef Data;
299  uint64_t Address;
300 
301  std::error_code load(SectionRef &Section) {
302  if (auto Err = Section.getContents(Data))
303  return Err;
304  Address = Section.getAddress();
305  return std::error_code();
306  }
307 
308  std::error_code get(uint64_t Pointer, size_t Size, StringRef &Result) {
309  if (Pointer < Address)
311  auto Offset = Pointer - Address;
312  if (Offset + Size > Data.size())
314  Result = Data.substr(Pointer - Address, Size);
315  return std::error_code();
316  }
317 };
318 }
319 
320 template <typename T, support::endianness Endian>
321 std::error_code readCoverageMappingData(
322  SectionData &ProfileNames, StringRef Data,
323  std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
324  std::vector<StringRef> &Filenames) {
325  using namespace support;
326  llvm::DenseSet<T> UniqueFunctionMappingData;
327 
328  // Read the records in the coverage data section.
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);
336 
337  switch (Version) {
339  break;
340  default:
342  }
343 
344  // Skip past the function records, saving the start and end for later.
345  const char *FunBuf = Buf;
346  Buf += NRecords * (sizeof(T) + 2 * sizeof(uint32_t) + sizeof(uint64_t));
347  const char *FunEnd = Buf;
348 
349  // Get the filenames.
350  if (Buf + FilenamesSize > End)
352  size_t FilenamesBegin = Filenames.size();
353  RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames);
354  if (auto Err = Reader.read())
355  return Err;
356  Buf += FilenamesSize;
357 
358  // We'll read the coverage mapping records in the loop below.
359  const char *CovBuf = Buf;
360  Buf += CoverageSize;
361  const char *CovEnd = Buf;
362 
363  if (Buf > End)
365  // Each coverage map has an alignment of 8, so we need to adjust alignment
366  // before reading the next map.
367  Buf += alignmentAdjustment(Buf, 8);
368 
369  while (FunBuf < FunEnd) {
370  // Read the function information
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);
375 
376  // Now use that to read the coverage data.
377  if (CovBuf + DataSize > CovEnd)
379  auto Mapping = StringRef(CovBuf, DataSize);
380  CovBuf += DataSize;
381 
382  // Ignore this record if we already have a record that points to the same
383  // function name. This is useful to ignore the redundant records for the
384  // functions with ODR linkage.
385  if (!UniqueFunctionMappingData.insert(NamePtr).second)
386  continue;
387 
388  // Finally, grab the name and create a record.
390  if (std::error_code EC = ProfileNames.get(NamePtr, NameSize, FuncName))
391  return EC;
393  CoverageMappingVersion(Version), FuncName, FuncHash, Mapping,
394  FilenamesBegin, Filenames.size() - FilenamesBegin));
395  }
396  }
397 
398  return std::error_code();
399 }
400 
401 static const char *TestingFormatMagic = "llvmcovmtestdata";
402 
403 static std::error_code loadTestingFormat(StringRef Data,
404  SectionData &ProfileNames,
406  uint8_t &BytesInAddress,
407  support::endianness &Endian) {
408  BytesInAddress = 8;
410 
411  Data = Data.substr(StringRef(TestingFormatMagic).size());
412  if (Data.size() < 1)
414  unsigned N = 0;
415  auto ProfileNamesSize =
416  decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
417  if (N > Data.size())
419  Data = Data.substr(N);
420  if (Data.size() < 1)
422  N = 0;
423  ProfileNames.Address =
424  decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
425  if (N > Data.size())
427  Data = Data.substr(N);
428  if (Data.size() < ProfileNamesSize)
430  ProfileNames.Data = Data.substr(0, ProfileNamesSize);
431  CoverageMapping = Data.substr(ProfileNamesSize);
432  return std::error_code();
433 }
434 
436  StringRef FoundName;
437  for (const auto &Section : OF.sections()) {
438  if (auto EC = Section.getName(FoundName))
439  return EC;
440  if (FoundName == Name)
441  return Section;
442  }
444 }
445 
446 static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer,
447  SectionData &ProfileNames,
449  uint8_t &BytesInAddress,
450  support::endianness &Endian,
451  StringRef Arch) {
452  auto BinOrErr = object::createBinary(ObjectBuffer);
453  if (std::error_code EC = BinOrErr.getError())
454  return EC;
455  auto Bin = std::move(BinOrErr.get());
456  std::unique_ptr<ObjectFile> OF;
457  if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) {
458  // If we have a universal binary, try to look up the object for the
459  // appropriate architecture.
460  auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
461  if (std::error_code EC = ObjectFileOrErr.getError())
462  return EC;
463  OF = std::move(ObjectFileOrErr.get());
464  } else if (isa<object::ObjectFile>(Bin.get())) {
465  // For any other object file, upcast and take ownership.
466  OF.reset(cast<object::ObjectFile>(Bin.release()));
467  // If we've asked for a particular arch, make sure they match.
468  if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
469  return object_error::arch_not_found;
470  } else
471  // We can only handle object files.
473 
474  // The coverage uses native pointer sizes for the object it's written in.
475  BytesInAddress = OF->getBytesInAddress();
476  Endian = OF->isLittleEndian() ? support::endianness::little
478 
479  // Look for the sections that we are interested in.
480  auto NamesSection = lookupSection(*OF, "__llvm_prf_names");
481  if (auto EC = NamesSection.getError())
482  return EC;
483  auto CoverageSection = lookupSection(*OF, "__llvm_covmap");
484  if (auto EC = CoverageSection.getError())
485  return EC;
486 
487  // Get the contents of the given sections.
488  if (std::error_code EC = CoverageSection->getContents(CoverageMapping))
489  return EC;
490  if (std::error_code EC = ProfileNames.load(*NamesSection))
491  return EC;
492 
493  return std::error_code();
494 }
495 
497 BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
498  StringRef Arch) {
499  std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
500 
501  SectionData Profile;
502  StringRef Coverage;
503  uint8_t BytesInAddress;
504  support::endianness Endian;
505  std::error_code EC;
506  if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
507  // This is a special format used for testing.
508  EC = loadTestingFormat(ObjectBuffer->getBuffer(), Profile, Coverage,
509  BytesInAddress, Endian);
510  else
511  EC = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Profile, Coverage,
512  BytesInAddress, Endian, Arch);
513  if (EC)
514  return EC;
515 
516  if (BytesInAddress == 4 && Endian == support::endianness::little)
517  EC = readCoverageMappingData<uint32_t, support::endianness::little>(
518  Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
519  else if (BytesInAddress == 4 && Endian == support::endianness::big)
520  EC = readCoverageMappingData<uint32_t, support::endianness::big>(
521  Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
522  else if (BytesInAddress == 8 && Endian == support::endianness::little)
523  EC = readCoverageMappingData<uint64_t, support::endianness::little>(
524  Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
525  else if (BytesInAddress == 8 && Endian == support::endianness::big)
526  EC = readCoverageMappingData<uint64_t, support::endianness::big>(
527  Profile, Coverage, Reader->MappingRecords, Reader->Filenames);
528  else
530  if (EC)
531  return EC;
532  return std::move(Reader);
533 }
534 
535 std::error_code
537  if (CurrentRecord >= MappingRecords.size())
538  return coveragemap_error::eof;
539 
540  FunctionsFilenames.clear();
541  Expressions.clear();
542  MappingRegions.clear();
543  auto &R = MappingRecords[CurrentRecord];
545  R.CoverageMapping,
546  makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
547  FunctionsFilenames, Expressions, MappingRegions);
548  if (auto Err = Reader.read())
549  return Err;
550 
551  Record.FunctionName = R.FunctionName;
552  Record.FunctionHash = R.FunctionHash;
553  Record.Filenames = FunctionsFilenames;
554  Record.Expressions = Expressions;
555  Record.MappingRegions = MappingRegions;
556 
557  ++CurrentRecord;
558  return std::error_code();
559 }
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:82
void push_back(const T &Elt)
Definition: SmallVector.h:222
Represents either an error or a value T.
Definition: ErrorOr.h:82
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.
Definition: StringRef.h:113
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.
Definition: DenseSet.h:39
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:405
This class is the base class for all object file types.
Definition: ObjectFile.h:176
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.
Definition: ArrayRef.h:308
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).
Definition: StringRef.h:107
#define T
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
Definition: ObjectFile.h:362
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:242
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:80
ErrorOr< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:39
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.
Definition: MathExtras.h:576
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
Definition: ObjectFile.h:253
std::error_code readString(StringRef &Result)
uint64_t getAddress() const
Definition: ObjectFile.h:366
aarch64 type AArch64 Type Promotion Pass
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
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.
Definition: Debug.cpp:123
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
std::error_code getContents(StringRef &Result) const
Definition: ObjectFile.h:374
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.
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
void size_t size
const ARM::ArchExtKind Kind
static const unsigned EncodingTagBits
LLVM Value Representation.
Definition: Value.h:69
std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1)
#define DEBUG(X)
Definition: Debug.h:92
std::error_code readSize(uint64_t &Result)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
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...
Definition: ObjectFile.h:69
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
void resize(size_type N)
Definition: SmallVector.h:376