LLVM  14.0.0git
DWARFVerifier.cpp
Go to the documentation of this file.
1 //===- DWARFVerifier.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/Support/DJB.h"
21 #include "llvm/Support/WithColor.h"
23 #include <map>
24 #include <set>
25 #include <vector>
26 
27 using namespace llvm;
28 using namespace dwarf;
29 using namespace object;
30 
33  auto Begin = Ranges.begin();
34  auto End = Ranges.end();
35  auto Pos = std::lower_bound(Begin, End, R);
36 
37  if (Pos != End) {
38  DWARFAddressRange Range(*Pos);
39  if (Pos->merge(R))
40  return Range;
41  }
42  if (Pos != Begin) {
43  auto Iter = Pos - 1;
44  DWARFAddressRange Range(*Iter);
45  if (Iter->merge(R))
46  return Range;
47  }
48 
49  Ranges.insert(Pos, R);
50  return None;
51 }
52 
55  if (RI.Ranges.empty())
56  return Children.end();
57 
58  auto End = Children.end();
59  auto Iter = Children.begin();
60  while (Iter != End) {
61  if (Iter->intersects(RI))
62  return Iter;
63  ++Iter;
64  }
65  Children.insert(RI);
66  return Children.end();
67 }
68 
70  auto I1 = Ranges.begin(), E1 = Ranges.end();
71  auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end();
72  if (I2 == E2)
73  return true;
74 
75  DWARFAddressRange R = *I2;
76  while (I1 != E1) {
77  bool Covered = I1->LowPC <= R.LowPC;
78  if (R.LowPC == R.HighPC || (Covered && R.HighPC <= I1->HighPC)) {
79  if (++I2 == E2)
80  return true;
81  R = *I2;
82  continue;
83  }
84  if (!Covered)
85  return false;
86  if (R.LowPC < I1->HighPC)
87  R.LowPC = I1->HighPC;
88  ++I1;
89  }
90  return false;
91 }
92 
94  auto I1 = Ranges.begin(), E1 = Ranges.end();
95  auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end();
96  while (I1 != E1 && I2 != E2) {
97  if (I1->intersects(*I2))
98  return true;
99  if (I1->LowPC < I2->LowPC)
100  ++I1;
101  else
102  ++I2;
103  }
104  return false;
105 }
106 
107 bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
108  uint64_t *Offset, unsigned UnitIndex,
109  uint8_t &UnitType, bool &isUnitDWARF64) {
110  uint64_t AbbrOffset, Length;
111  uint8_t AddrSize = 0;
113  bool Success = true;
114 
115  bool ValidLength = false;
116  bool ValidVersion = false;
117  bool ValidAddrSize = false;
118  bool ValidType = true;
119  bool ValidAbbrevOffset = true;
120 
121  uint64_t OffsetStart = *Offset;
122  DwarfFormat Format;
123  std::tie(Length, Format) = DebugInfoData.getInitialLength(Offset);
124  isUnitDWARF64 = Format == DWARF64;
125  Version = DebugInfoData.getU16(Offset);
126 
127  if (Version >= 5) {
128  UnitType = DebugInfoData.getU8(Offset);
129  AddrSize = DebugInfoData.getU8(Offset);
130  AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset);
131  ValidType = dwarf::isUnitType(UnitType);
132  } else {
133  UnitType = 0;
134  AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset);
135  AddrSize = DebugInfoData.getU8(Offset);
136  }
137 
138  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
139  ValidAbbrevOffset = false;
140 
141  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
143  ValidAddrSize = DWARFContext::isAddressSizeSupported(AddrSize);
144  if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
145  !ValidType) {
146  Success = false;
147  error() << format("Units[%d] - start offset: 0x%08" PRIx64 " \n", UnitIndex,
148  OffsetStart);
149  if (!ValidLength)
150  note() << "The length for this unit is too "
151  "large for the .debug_info provided.\n";
152  if (!ValidVersion)
153  note() << "The 16 bit unit header version is not valid.\n";
154  if (!ValidType)
155  note() << "The unit type encoding is not valid.\n";
156  if (!ValidAbbrevOffset)
157  note() << "The offset into the .debug_abbrev section is "
158  "not valid.\n";
159  if (!ValidAddrSize)
160  note() << "The address size is unsupported.\n";
161  }
162  *Offset = OffsetStart + Length + (isUnitDWARF64 ? 12 : 4);
163  return Success;
164 }
165 
166 bool DWARFVerifier::verifyName(const DWARFDie &Die) {
167  // FIXME Add some kind of record of which DIE names have already failed and
168  // don't bother checking a DIE that uses an already failed DIE.
169 
170  std::string ReconstructedName;
171  raw_string_ostream OS(ReconstructedName);
172  std::string OriginalFullName;
173  Die.getFullName(OS, &OriginalFullName);
174  OS.flush();
175  if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
176  return 0;
177 
178  error() << "Simplified template DW_AT_name could not be reconstituted:\n"
179  << formatv(" original: {0}\n"
180  " reconstituted: {1}\n",
181  OriginalFullName, ReconstructedName);
182  dump(Die) << '\n';
183  dump(Die.getDwarfUnit()->getUnitDIE()) << '\n';
184  return 1;
185 }
186 
187 unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
188  ReferenceMap &UnitLocalReferences,
189  ReferenceMap &CrossUnitReferences) {
190  unsigned NumUnitErrors = 0;
191  unsigned NumDies = Unit.getNumDIEs();
192  for (unsigned I = 0; I < NumDies; ++I) {
193  auto Die = Unit.getDIEAtIndex(I);
194 
195  if (Die.getTag() == DW_TAG_null)
196  continue;
197 
198  for (auto AttrValue : Die.attributes()) {
199  NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
200  NumUnitErrors += verifyDebugInfoForm(Die, AttrValue, UnitLocalReferences,
201  CrossUnitReferences);
202  }
203 
204  NumUnitErrors += verifyName(Die);
205 
206  if (Die.hasChildren()) {
207  if (Die.getFirstChild().isValid() &&
208  Die.getFirstChild().getTag() == DW_TAG_null) {
209  warn() << dwarf::TagString(Die.getTag())
210  << " has DW_CHILDREN_yes but DIE has no children: ";
211  Die.dump(OS);
212  }
213  }
214 
215  NumUnitErrors += verifyDebugInfoCallSite(Die);
216  }
217 
218  DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
219  if (!Die) {
220  error() << "Compilation unit without DIE.\n";
221  NumUnitErrors++;
222  return NumUnitErrors;
223  }
224 
225  if (!dwarf::isUnitType(Die.getTag())) {
226  error() << "Compilation unit root DIE is not a unit DIE: "
227  << dwarf::TagString(Die.getTag()) << ".\n";
228  NumUnitErrors++;
229  }
230 
231  uint8_t UnitType = Unit.getUnitType();
233  error() << "Compilation unit type (" << dwarf::UnitTypeString(UnitType)
234  << ") and root DIE (" << dwarf::TagString(Die.getTag())
235  << ") do not match.\n";
236  NumUnitErrors++;
237  }
238 
239  // According to DWARF Debugging Information Format Version 5,
240  // 3.1.2 Skeleton Compilation Unit Entries:
241  // "A skeleton compilation unit has no children."
242  if (Die.getTag() == dwarf::DW_TAG_skeleton_unit && Die.hasChildren()) {
243  error() << "Skeleton compilation unit has children.\n";
244  NumUnitErrors++;
245  }
246 
247  DieRangeInfo RI;
248  NumUnitErrors += verifyDieRanges(Die, RI);
249 
250  return NumUnitErrors;
251 }
252 
253 unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
254  if (Die.getTag() != DW_TAG_call_site && Die.getTag() != DW_TAG_GNU_call_site)
255  return 0;
256 
257  DWARFDie Curr = Die.getParent();
258  for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) {
259  if (Curr.getTag() == DW_TAG_inlined_subroutine) {
260  error() << "Call site entry nested within inlined subroutine:";
261  Curr.dump(OS);
262  return 1;
263  }
264  }
265 
266  if (!Curr.isValid()) {
267  error() << "Call site entry not nested within a valid subprogram:";
268  Die.dump(OS);
269  return 1;
270  }
271 
272  Optional<DWARFFormValue> CallAttr =
273  Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
274  DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
275  DW_AT_GNU_all_source_call_sites,
276  DW_AT_GNU_all_tail_call_sites});
277  if (!CallAttr) {
278  error() << "Subprogram with call site entry has no DW_AT_call attribute:";
279  Curr.dump(OS);
280  Die.dump(OS, /*indent*/ 1);
281  return 1;
282  }
283 
284  return 0;
285 }
286 
287 unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
288  unsigned NumErrors = 0;
289  if (Abbrev) {
290  const DWARFAbbreviationDeclarationSet *AbbrDecls =
292  for (auto AbbrDecl : *AbbrDecls) {
294  for (auto Attribute : AbbrDecl.attributes()) {
295  auto Result = AttributeSet.insert(Attribute.Attr);
296  if (!Result.second) {
297  error() << "Abbreviation declaration contains multiple "
298  << AttributeString(Attribute.Attr) << " attributes.\n";
299  AbbrDecl.dump(OS);
300  ++NumErrors;
301  }
302  }
303  }
304  }
305  return NumErrors;
306 }
307 
309  OS << "Verifying .debug_abbrev...\n";
310 
311  const DWARFObject &DObj = DCtx.getDWARFObj();
312  unsigned NumErrors = 0;
313  if (!DObj.getAbbrevSection().empty())
314  NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
315  if (!DObj.getAbbrevDWOSection().empty())
316  NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
317 
318  return NumErrors == 0;
319 }
320 
321 unsigned DWARFVerifier::verifyUnits(const DWARFUnitVector &Units) {
322  unsigned NumDebugInfoErrors = 0;
323  ReferenceMap CrossUnitReferences;
324 
325  for (const auto &Unit : Units) {
326  ReferenceMap UnitLocalReferences;
327  NumDebugInfoErrors +=
328  verifyUnitContents(*Unit, UnitLocalReferences, CrossUnitReferences);
329  NumDebugInfoErrors += verifyDebugInfoReferences(
330  UnitLocalReferences, [&](uint64_t Offset) { return Unit.get(); });
331  }
332 
333  NumDebugInfoErrors += verifyDebugInfoReferences(
334  CrossUnitReferences, [&](uint64_t Offset) -> DWARFUnit * {
335  if (DWARFUnit *U = Units.getUnitForOffset(Offset))
336  return U;
337  return nullptr;
338  });
339 
340  return NumDebugInfoErrors;
341 }
342 
343 unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S) {
344  const DWARFObject &DObj = DCtx.getDWARFObj();
345  DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
346  unsigned NumDebugInfoErrors = 0;
347  uint64_t Offset = 0, UnitIdx = 0;
348  uint8_t UnitType = 0;
349  bool isUnitDWARF64 = false;
350  bool isHeaderChainValid = true;
351  bool hasDIE = DebugInfoData.isValidOffset(Offset);
352  DWARFUnitVector TypeUnitVector;
353  DWARFUnitVector CompileUnitVector;
354  /// A map that tracks all references (converted absolute references) so we
355  /// can verify each reference points to a valid DIE and not an offset that
356  /// lies between to valid DIEs.
357  ReferenceMap CrossUnitReferences;
358  while (hasDIE) {
359  if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
360  isUnitDWARF64)) {
361  isHeaderChainValid = false;
362  if (isUnitDWARF64)
363  break;
364  }
365  hasDIE = DebugInfoData.isValidOffset(Offset);
366  ++UnitIdx;
367  }
368  if (UnitIdx == 0 && !hasDIE) {
369  warn() << "Section is empty.\n";
370  isHeaderChainValid = true;
371  }
372  if (!isHeaderChainValid)
373  ++NumDebugInfoErrors;
374  return NumDebugInfoErrors;
375 }
376 
378  const DWARFObject &DObj = DCtx.getDWARFObj();
379  unsigned NumErrors = 0;
380 
381  OS << "Verifying .debug_info Unit Header Chain...\n";
382  DObj.forEachInfoSections([&](const DWARFSection &S) {
383  NumErrors += verifyUnitSection(S);
384  });
385 
386  OS << "Verifying .debug_types Unit Header Chain...\n";
387  DObj.forEachTypesSections([&](const DWARFSection &S) {
388  NumErrors += verifyUnitSection(S);
389  });
390 
391  OS << "Verifying non-dwo Units...\n";
392  NumErrors += verifyUnits(DCtx.getNormalUnitsVector());
393  return NumErrors == 0;
394 }
395 
396 unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
397  DieRangeInfo &ParentRI) {
398  unsigned NumErrors = 0;
399 
400  if (!Die.isValid())
401  return NumErrors;
402 
403  auto RangesOrError = Die.getAddressRanges();
404  if (!RangesOrError) {
405  // FIXME: Report the error.
406  ++NumErrors;
407  llvm::consumeError(RangesOrError.takeError());
408  return NumErrors;
409  }
410 
411  const DWARFAddressRangesVector &Ranges = RangesOrError.get();
412  // Build RI for this DIE and check that ranges within this DIE do not
413  // overlap.
414  DieRangeInfo RI(Die);
415 
416  // TODO support object files better
417  //
418  // Some object file formats (i.e. non-MachO) support COMDAT. ELF in
419  // particular does so by placing each function into a section. The DWARF data
420  // for the function at that point uses a section relative DW_FORM_addrp for
421  // the DW_AT_low_pc and a DW_FORM_data4 for the offset as the DW_AT_high_pc.
422  // In such a case, when the Die is the CU, the ranges will overlap, and we
423  // will flag valid conflicting ranges as invalid.
424  //
425  // For such targets, we should read the ranges from the CU and partition them
426  // by the section id. The ranges within a particular section should be
427  // disjoint, although the ranges across sections may overlap. We would map
428  // the child die to the entity that it references and the section with which
429  // it is associated. The child would then be checked against the range
430  // information for the associated section.
431  //
432  // For now, simply elide the range verification for the CU DIEs if we are
433  // processing an object file.
434 
435  if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) {
436  bool DumpDieAfterError = false;
437  for (const auto &Range : Ranges) {
438  if (!Range.valid()) {
439  ++NumErrors;
440  error() << "Invalid address range " << Range << "\n";
441  DumpDieAfterError = true;
442  continue;
443  }
444 
445  // Verify that ranges don't intersect and also build up the DieRangeInfo
446  // address ranges. Don't break out of the loop below early, or we will
447  // think this DIE doesn't have all of the address ranges it is supposed
448  // to have. Compile units often have DW_AT_ranges that can contain one or
449  // more dead stripped address ranges which tend to all be at the same
450  // address: 0 or -1.
451  if (auto PrevRange = RI.insert(Range)) {
452  ++NumErrors;
453  error() << "DIE has overlapping ranges in DW_AT_ranges attribute: "
454  << *PrevRange << " and " << Range << '\n';
455  DumpDieAfterError = true;
456  }
457  }
458  if (DumpDieAfterError)
459  dump(Die, 2) << '\n';
460  }
461 
462  // Verify that children don't intersect.
463  const auto IntersectingChild = ParentRI.insert(RI);
464  if (IntersectingChild != ParentRI.Children.end()) {
465  ++NumErrors;
466  error() << "DIEs have overlapping address ranges:";
467  dump(Die);
468  dump(IntersectingChild->Die) << '\n';
469  }
470 
471  // Verify that ranges are contained within their parent.
472  bool ShouldBeContained = !RI.Ranges.empty() && !ParentRI.Ranges.empty() &&
473  !(Die.getTag() == DW_TAG_subprogram &&
474  ParentRI.Die.getTag() == DW_TAG_subprogram);
475  if (ShouldBeContained && !ParentRI.contains(RI)) {
476  ++NumErrors;
477  error() << "DIE address ranges are not contained in its parent's ranges:";
478  dump(ParentRI.Die);
479  dump(Die, 2) << '\n';
480  }
481 
482  // Recursively check children.
483  for (DWARFDie Child : Die)
484  NumErrors += verifyDieRanges(Child, RI);
485 
486  return NumErrors;
487 }
488 
489 unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
490  DWARFAttribute &AttrValue) {
491  unsigned NumErrors = 0;
492  auto ReportError = [&](const Twine &TitleMsg) {
493  ++NumErrors;
494  error() << TitleMsg << '\n';
495  dump(Die) << '\n';
496  };
497 
498  const DWARFObject &DObj = DCtx.getDWARFObj();
499  const auto Attr = AttrValue.Attr;
500  switch (Attr) {
501  case DW_AT_ranges:
502  // Make sure the offset in the DW_AT_ranges attribute is valid.
503  if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
504  unsigned DwarfVersion = Die.getDwarfUnit()->getVersion();
505  const DWARFSection &RangeSection = DwarfVersion < 5
506  ? DObj.getRangesSection()
507  : DObj.getRnglistsSection();
508  if (*SectionOffset >= RangeSection.Data.size())
509  ReportError(
510  "DW_AT_ranges offset is beyond " +
511  StringRef(DwarfVersion < 5 ? ".debug_ranges" : ".debug_rnglists") +
512  " bounds: " + llvm::formatv("{0:x8}", *SectionOffset));
513  break;
514  }
515  ReportError("DIE has invalid DW_AT_ranges encoding:");
516  break;
517  case DW_AT_stmt_list:
518  // Make sure the offset in the DW_AT_stmt_list attribute is valid.
519  if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
520  if (*SectionOffset >= DObj.getLineSection().Data.size())
521  ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
522  llvm::formatv("{0:x8}", *SectionOffset));
523  break;
524  }
525  ReportError("DIE has invalid DW_AT_stmt_list encoding:");
526  break;
527  case DW_AT_location: {
528  if (Expected<std::vector<DWARFLocationExpression>> Loc =
529  Die.getLocations(DW_AT_location)) {
530  DWARFUnit *U = Die.getDwarfUnit();
531  for (const auto &Entry : *Loc) {
532  DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), 0);
534  U->getFormParams().Format);
535  bool Error =
537  return Op.isError();
538  });
539  if (Error || !Expression.verify(U))
540  ReportError("DIE contains invalid DWARF expression:");
541  }
542  } else
543  ReportError(toString(Loc.takeError()));
544  break;
545  }
546  case DW_AT_specification:
547  case DW_AT_abstract_origin: {
548  if (auto ReferencedDie = Die.getAttributeValueAsReferencedDie(Attr)) {
549  auto DieTag = Die.getTag();
550  auto RefTag = ReferencedDie.getTag();
551  if (DieTag == RefTag)
552  break;
553  if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
554  break;
555  if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
556  break;
557  // This might be reference to a function declaration.
558  if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram)
559  break;
560  ReportError("DIE with tag " + TagString(DieTag) + " has " +
561  AttributeString(Attr) +
562  " that points to DIE with "
563  "incompatible tag " +
564  TagString(RefTag));
565  }
566  break;
567  }
568  case DW_AT_type: {
569  DWARFDie TypeDie = Die.getAttributeValueAsReferencedDie(DW_AT_type);
570  if (TypeDie && !isType(TypeDie.getTag())) {
571  ReportError("DIE has " + AttributeString(Attr) +
572  " with incompatible tag " + TagString(TypeDie.getTag()));
573  }
574  break;
575  }
576  case DW_AT_call_file:
577  case DW_AT_decl_file: {
578  if (auto FileIdx = AttrValue.Value.getAsUnsignedConstant()) {
579  DWARFUnit *U = Die.getDwarfUnit();
580  const auto *LT = U->getContext().getLineTableForUnit(U);
581  if (LT) {
582  if (!LT->hasFileAtIndex(*FileIdx)) {
583  bool IsZeroIndexed = LT->Prologue.getVersion() >= 5;
584  if (Optional<uint64_t> LastFileIdx = LT->getLastValidFileIndex()) {
585  ReportError("DIE has " + AttributeString(Attr) +
586  " with an invalid file index " +
587  llvm::formatv("{0}", *FileIdx) +
588  " (valid values are [" + (IsZeroIndexed ? "0-" : "1-") +
589  llvm::formatv("{0}", *LastFileIdx) + "])");
590  } else {
591  ReportError("DIE has " + AttributeString(Attr) +
592  " with an invalid file index " +
593  llvm::formatv("{0}", *FileIdx) +
594  " (the file table in the prologue is empty)");
595  }
596  }
597  } else {
598  ReportError("DIE has " + AttributeString(Attr) +
599  " that references a file with index " +
600  llvm::formatv("{0}", *FileIdx) +
601  " and the compile unit has no line table");
602  }
603  } else {
604  ReportError("DIE has " + AttributeString(Attr) +
605  " with invalid encoding");
606  }
607  break;
608  }
609  default:
610  break;
611  }
612  return NumErrors;
613 }
614 
615 unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
616  DWARFAttribute &AttrValue,
617  ReferenceMap &LocalReferences,
618  ReferenceMap &CrossUnitReferences) {
619  const DWARFObject &DObj = DCtx.getDWARFObj();
620  auto DieCU = Die.getDwarfUnit();
621  unsigned NumErrors = 0;
622  const auto Form = AttrValue.Value.getForm();
623  switch (Form) {
624  case DW_FORM_ref1:
625  case DW_FORM_ref2:
626  case DW_FORM_ref4:
627  case DW_FORM_ref8:
628  case DW_FORM_ref_udata: {
629  // Verify all CU relative references are valid CU offsets.
630  Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
631  assert(RefVal);
632  if (RefVal) {
633  auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
634  auto CUOffset = AttrValue.Value.getRawUValue();
635  if (CUOffset >= CUSize) {
636  ++NumErrors;
637  error() << FormEncodingString(Form) << " CU offset "
638  << format("0x%08" PRIx64, CUOffset)
639  << " is invalid (must be less than CU size of "
640  << format("0x%08" PRIx64, CUSize) << "):\n";
641  Die.dump(OS, 0, DumpOpts);
642  dump(Die) << '\n';
643  } else {
644  // Valid reference, but we will verify it points to an actual
645  // DIE later.
646  LocalReferences[*RefVal].insert(Die.getOffset());
647  }
648  }
649  break;
650  }
651  case DW_FORM_ref_addr: {
652  // Verify all absolute DIE references have valid offsets in the
653  // .debug_info section.
654  Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
655  assert(RefVal);
656  if (RefVal) {
657  if (*RefVal >= DieCU->getInfoSection().Data.size()) {
658  ++NumErrors;
659  error() << "DW_FORM_ref_addr offset beyond .debug_info "
660  "bounds:\n";
661  dump(Die) << '\n';
662  } else {
663  // Valid reference, but we will verify it points to an actual
664  // DIE later.
665  CrossUnitReferences[*RefVal].insert(Die.getOffset());
666  }
667  }
668  break;
669  }
670  case DW_FORM_strp: {
671  auto SecOffset = AttrValue.Value.getAsSectionOffset();
672  assert(SecOffset); // DW_FORM_strp is a section offset.
673  if (SecOffset && *SecOffset >= DObj.getStrSection().size()) {
674  ++NumErrors;
675  error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
676  dump(Die) << '\n';
677  }
678  break;
679  }
680  case DW_FORM_strx:
681  case DW_FORM_strx1:
682  case DW_FORM_strx2:
683  case DW_FORM_strx3:
684  case DW_FORM_strx4: {
685  auto Index = AttrValue.Value.getRawUValue();
686  auto DieCU = Die.getDwarfUnit();
687  // Check that we have a valid DWARF v5 string offsets table.
688  if (!DieCU->getStringOffsetsTableContribution()) {
689  ++NumErrors;
691  << " used without a valid string offsets table:\n";
692  dump(Die) << '\n';
693  break;
694  }
695  // Check that the index is within the bounds of the section.
696  unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize();
697  // Use a 64-bit type to calculate the offset to guard against overflow.
698  uint64_t Offset =
699  (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize;
700  if (DObj.getStrOffsetsSection().Data.size() < Offset + ItemSize) {
701  ++NumErrors;
702  error() << FormEncodingString(Form) << " uses index "
703  << format("%" PRIu64, Index) << ", which is too large:\n";
704  dump(Die) << '\n';
705  break;
706  }
707  // Check that the string offset is valid.
708  uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index);
709  if (StringOffset >= DObj.getStrSection().size()) {
710  ++NumErrors;
711  error() << FormEncodingString(Form) << " uses index "
712  << format("%" PRIu64, Index)
713  << ", but the referenced string"
714  " offset is beyond .debug_str bounds:\n";
715  dump(Die) << '\n';
716  }
717  break;
718  }
719  default:
720  break;
721  }
722  return NumErrors;
723 }
724 
725 unsigned DWARFVerifier::verifyDebugInfoReferences(
726  const ReferenceMap &References,
727  llvm::function_ref<DWARFUnit *(uint64_t)> GetUnitForOffset) {
728  auto GetDIEForOffset = [&](uint64_t Offset) {
729  if (DWARFUnit *U = GetUnitForOffset(Offset))
730  return U->getDIEForOffset(Offset);
731  return DWARFDie();
732  };
733  unsigned NumErrors = 0;
734  for (const std::pair<const uint64_t, std::set<uint64_t>> &Pair :
735  References) {
736  if (GetDIEForOffset(Pair.first))
737  continue;
738  ++NumErrors;
739  error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
740  << ". Offset is in between DIEs:\n";
741  for (auto Offset : Pair.second)
742  dump(GetDIEForOffset(Offset)) << '\n';
743  OS << "\n";
744  }
745  return NumErrors;
746 }
747 
748 void DWARFVerifier::verifyDebugLineStmtOffsets() {
749  std::map<uint64_t, DWARFDie> StmtListToDie;
750  for (const auto &CU : DCtx.compile_units()) {
751  auto Die = CU->getUnitDIE();
752  // Get the attribute value as a section offset. No need to produce an
753  // error here if the encoding isn't correct because we validate this in
754  // the .debug_info verifier.
755  auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
756  if (!StmtSectionOffset)
757  continue;
758  const uint64_t LineTableOffset = *StmtSectionOffset;
759  auto LineTable = DCtx.getLineTableForUnit(CU.get());
760  if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
761  if (!LineTable) {
762  ++NumDebugLineErrors;
763  error() << ".debug_line[" << format("0x%08" PRIx64, LineTableOffset)
764  << "] was not able to be parsed for CU:\n";
765  dump(Die) << '\n';
766  continue;
767  }
768  } else {
769  // Make sure we don't get a valid line table back if the offset is wrong.
770  assert(LineTable == nullptr);
771  // Skip this line table as it isn't valid. No need to create an error
772  // here because we validate this in the .debug_info verifier.
773  continue;
774  }
775  auto Iter = StmtListToDie.find(LineTableOffset);
776  if (Iter != StmtListToDie.end()) {
777  ++NumDebugLineErrors;
778  error() << "two compile unit DIEs, "
779  << format("0x%08" PRIx64, Iter->second.getOffset()) << " and "
780  << format("0x%08" PRIx64, Die.getOffset())
781  << ", have the same DW_AT_stmt_list section offset:\n";
782  dump(Iter->second);
783  dump(Die) << '\n';
784  // Already verified this line table before, no need to do it again.
785  continue;
786  }
787  StmtListToDie[LineTableOffset] = Die;
788  }
789 }
790 
791 void DWARFVerifier::verifyDebugLineRows() {
792  for (const auto &CU : DCtx.compile_units()) {
793  auto Die = CU->getUnitDIE();
794  auto LineTable = DCtx.getLineTableForUnit(CU.get());
795  // If there is no line table we will have created an error in the
796  // .debug_info verifier or in verifyDebugLineStmtOffsets().
797  if (!LineTable)
798  continue;
799 
800  // Verify prologue.
801  uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
802  uint32_t FileIndex = 1;
803  StringMap<uint16_t> FullPathMap;
804  for (const auto &FileName : LineTable->Prologue.FileNames) {
805  // Verify directory index.
806  if (FileName.DirIdx > MaxDirIndex) {
807  ++NumDebugLineErrors;
808  error() << ".debug_line["
809  << format("0x%08" PRIx64,
810  *toSectionOffset(Die.find(DW_AT_stmt_list)))
811  << "].prologue.file_names[" << FileIndex
812  << "].dir_idx contains an invalid index: " << FileName.DirIdx
813  << "\n";
814  }
815 
816  // Check file paths for duplicates.
817  std::string FullPath;
818  const bool HasFullPath = LineTable->getFileNameByIndex(
819  FileIndex, CU->getCompilationDir(),
821  assert(HasFullPath && "Invalid index?");
822  (void)HasFullPath;
823  auto It = FullPathMap.find(FullPath);
824  if (It == FullPathMap.end())
825  FullPathMap[FullPath] = FileIndex;
826  else if (It->second != FileIndex) {
827  warn() << ".debug_line["
828  << format("0x%08" PRIx64,
829  *toSectionOffset(Die.find(DW_AT_stmt_list)))
830  << "].prologue.file_names[" << FileIndex
831  << "] is a duplicate of file_names[" << It->second << "]\n";
832  }
833 
834  FileIndex++;
835  }
836 
837  // Verify rows.
838  uint64_t PrevAddress = 0;
839  uint32_t RowIndex = 0;
840  for (const auto &Row : LineTable->Rows) {
841  // Verify row address.
842  if (Row.Address.Address < PrevAddress) {
843  ++NumDebugLineErrors;
844  error() << ".debug_line["
845  << format("0x%08" PRIx64,
846  *toSectionOffset(Die.find(DW_AT_stmt_list)))
847  << "] row[" << RowIndex
848  << "] decreases in address from previous row:\n";
849 
851  if (RowIndex > 0)
852  LineTable->Rows[RowIndex - 1].dump(OS);
853  Row.dump(OS);
854  OS << '\n';
855  }
856 
857  // Verify file index.
858  if (!LineTable->hasFileAtIndex(Row.File)) {
859  ++NumDebugLineErrors;
860  bool isDWARF5 = LineTable->Prologue.getVersion() >= 5;
861  error() << ".debug_line["
862  << format("0x%08" PRIx64,
863  *toSectionOffset(Die.find(DW_AT_stmt_list)))
864  << "][" << RowIndex << "] has invalid file index " << Row.File
865  << " (valid values are [" << (isDWARF5 ? "0," : "1,")
866  << LineTable->Prologue.FileNames.size()
867  << (isDWARF5 ? ")" : "]") << "):\n";
869  Row.dump(OS);
870  OS << '\n';
871  }
872  if (Row.EndSequence)
873  PrevAddress = 0;
874  else
875  PrevAddress = Row.Address.Address;
876  ++RowIndex;
877  }
878  }
879 }
880 
882  DIDumpOptions DumpOpts)
883  : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)), IsObjectFile(false),
884  IsMachOObject(false) {
885  if (const auto *F = DCtx.getDWARFObj().getFile()) {
886  IsObjectFile = F->isRelocatableObject();
887  IsMachOObject = F->isMachO();
888  }
889 }
890 
892  NumDebugLineErrors = 0;
893  OS << "Verifying .debug_line...\n";
894  verifyDebugLineStmtOffsets();
895  verifyDebugLineRows();
896  return NumDebugLineErrors == 0;
897 }
898 
899 unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
900  DataExtractor *StrData,
901  const char *SectionName) {
902  unsigned NumErrors = 0;
903  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), *AccelSection,
904  DCtx.isLittleEndian(), 0);
905  AppleAcceleratorTable AccelTable(AccelSectionData, *StrData);
906 
907  OS << "Verifying " << SectionName << "...\n";
908 
909  // Verify that the fixed part of the header is not too short.
910  if (!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())) {
911  error() << "Section is too small to fit a section header.\n";
912  return 1;
913  }
914 
915  // Verify that the section is not too short.
916  if (Error E = AccelTable.extract()) {
917  error() << toString(std::move(E)) << '\n';
918  return 1;
919  }
920 
921  // Verify that all buckets have a valid hash index or are empty.
922  uint32_t NumBuckets = AccelTable.getNumBuckets();
923  uint32_t NumHashes = AccelTable.getNumHashes();
924 
925  uint64_t BucketsOffset =
926  AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
927  uint64_t HashesBase = BucketsOffset + NumBuckets * 4;
928  uint64_t OffsetsBase = HashesBase + NumHashes * 4;
929  for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
930  uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
931  if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
932  error() << format("Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
933  HashIdx);
934  ++NumErrors;
935  }
936  }
937  uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
938  if (NumAtoms == 0) {
939  error() << "No atoms: failed to read HashData.\n";
940  return 1;
941  }
942  if (!AccelTable.validateForms()) {
943  error() << "Unsupported form: failed to read HashData.\n";
944  return 1;
945  }
946 
947  for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
948  uint64_t HashOffset = HashesBase + 4 * HashIdx;
949  uint64_t DataOffset = OffsetsBase + 4 * HashIdx;
950  uint32_t Hash = AccelSectionData.getU32(&HashOffset);
951  uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
952  if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
953  sizeof(uint64_t))) {
954  error() << format("Hash[%d] has invalid HashData offset: "
955  "0x%08" PRIx64 ".\n",
956  HashIdx, HashDataOffset);
957  ++NumErrors;
958  }
959 
960  uint64_t StrpOffset;
961  uint64_t StringOffset;
962  uint32_t StringCount = 0;
964  unsigned Tag;
965  while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
966  const uint32_t NumHashDataObjects =
967  AccelSectionData.getU32(&HashDataOffset);
968  for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
969  ++HashDataIdx) {
970  std::tie(Offset, Tag) = AccelTable.readAtoms(&HashDataOffset);
971  auto Die = DCtx.getDIEForOffset(Offset);
972  if (!Die) {
973  const uint32_t BucketIdx =
974  NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
975  StringOffset = StrpOffset;
976  const char *Name = StrData->getCStr(&StringOffset);
977  if (!Name)
978  Name = "<NULL>";
979 
980  error() << format(
981  "%s Bucket[%d] Hash[%d] = 0x%08x "
982  "Str[%u] = 0x%08" PRIx64 " DIE[%d] = 0x%08" PRIx64 " "
983  "is not a valid DIE offset for \"%s\".\n",
984  SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
985  HashDataIdx, Offset, Name);
986 
987  ++NumErrors;
988  continue;
989  }
990  if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
991  error() << "Tag " << dwarf::TagString(Tag)
992  << " in accelerator table does not match Tag "
993  << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
994  << "].\n";
995  ++NumErrors;
996  }
997  }
998  ++StringCount;
999  }
1000  }
1001  return NumErrors;
1002 }
1003 
1004 unsigned
1005 DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
1006  // A map from CU offset to the (first) Name Index offset which claims to index
1007  // this CU.
1009  const uint64_t NotIndexed = std::numeric_limits<uint64_t>::max();
1010 
1011  CUMap.reserve(DCtx.getNumCompileUnits());
1012  for (const auto &CU : DCtx.compile_units())
1013  CUMap[CU->getOffset()] = NotIndexed;
1014 
1015  unsigned NumErrors = 0;
1016  for (const DWARFDebugNames::NameIndex &NI : AccelTable) {
1017  if (NI.getCUCount() == 0) {
1018  error() << formatv("Name Index @ {0:x} does not index any CU\n",
1019  NI.getUnitOffset());
1020  ++NumErrors;
1021  continue;
1022  }
1023  for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) {
1024  uint64_t Offset = NI.getCUOffset(CU);
1025  auto Iter = CUMap.find(Offset);
1026 
1027  if (Iter == CUMap.end()) {
1028  error() << formatv(
1029  "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
1030  NI.getUnitOffset(), Offset);
1031  ++NumErrors;
1032  continue;
1033  }
1034 
1035  if (Iter->second != NotIndexed) {
1036  error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but "
1037  "this CU is already indexed by Name Index @ {2:x}\n",
1038  NI.getUnitOffset(), Offset, Iter->second);
1039  continue;
1040  }
1041  Iter->second = NI.getUnitOffset();
1042  }
1043  }
1044 
1045  for (const auto &KV : CUMap) {
1046  if (KV.second == NotIndexed)
1047  warn() << formatv("CU @ {0:x} not covered by any Name Index\n", KV.first);
1048  }
1049 
1050  return NumErrors;
1051 }
1052 
1053 unsigned
1054 DWARFVerifier::verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
1055  const DataExtractor &StrData) {
1056  struct BucketInfo {
1057  uint32_t Bucket;
1058  uint32_t Index;
1059 
1060  constexpr BucketInfo(uint32_t Bucket, uint32_t Index)
1061  : Bucket(Bucket), Index(Index) {}
1062  bool operator<(const BucketInfo &RHS) const { return Index < RHS.Index; }
1063  };
1064 
1065  uint32_t NumErrors = 0;
1066  if (NI.getBucketCount() == 0) {
1067  warn() << formatv("Name Index @ {0:x} does not contain a hash table.\n",
1068  NI.getUnitOffset());
1069  return NumErrors;
1070  }
1071 
1072  // Build up a list of (Bucket, Index) pairs. We use this later to verify that
1073  // each Name is reachable from the appropriate bucket.
1074  std::vector<BucketInfo> BucketStarts;
1075  BucketStarts.reserve(NI.getBucketCount() + 1);
1076  for (uint32_t Bucket = 0, End = NI.getBucketCount(); Bucket < End; ++Bucket) {
1077  uint32_t Index = NI.getBucketArrayEntry(Bucket);
1078  if (Index > NI.getNameCount()) {
1079  error() << formatv("Bucket {0} of Name Index @ {1:x} contains invalid "
1080  "value {2}. Valid range is [0, {3}].\n",
1081  Bucket, NI.getUnitOffset(), Index, NI.getNameCount());
1082  ++NumErrors;
1083  continue;
1084  }
1085  if (Index > 0)
1086  BucketStarts.emplace_back(Bucket, Index);
1087  }
1088 
1089  // If there were any buckets with invalid values, skip further checks as they
1090  // will likely produce many errors which will only confuse the actual root
1091  // problem.
1092  if (NumErrors > 0)
1093  return NumErrors;
1094 
1095  // Sort the list in the order of increasing "Index" entries.
1096  array_pod_sort(BucketStarts.begin(), BucketStarts.end());
1097 
1098  // Insert a sentinel entry at the end, so we can check that the end of the
1099  // table is covered in the loop below.
1100  BucketStarts.emplace_back(NI.getBucketCount(), NI.getNameCount() + 1);
1101 
1102  // Loop invariant: NextUncovered is the (1-based) index of the first Name
1103  // which is not reachable by any of the buckets we processed so far (and
1104  // hasn't been reported as uncovered).
1105  uint32_t NextUncovered = 1;
1106  for (const BucketInfo &B : BucketStarts) {
1107  // Under normal circumstances B.Index be equal to NextUncovered, but it can
1108  // be less if a bucket points to names which are already known to be in some
1109  // bucket we processed earlier. In that case, we won't trigger this error,
1110  // but report the mismatched hash value error instead. (We know the hash
1111  // will not match because we have already verified that the name's hash
1112  // puts it into the previous bucket.)
1113  if (B.Index > NextUncovered) {
1114  error() << formatv("Name Index @ {0:x}: Name table entries [{1}, {2}] "
1115  "are not covered by the hash table.\n",
1116  NI.getUnitOffset(), NextUncovered, B.Index - 1);
1117  ++NumErrors;
1118  }
1119  uint32_t Idx = B.Index;
1120 
1121  // The rest of the checks apply only to non-sentinel entries.
1122  if (B.Bucket == NI.getBucketCount())
1123  break;
1124 
1125  // This triggers if a non-empty bucket points to a name with a mismatched
1126  // hash. Clients are likely to interpret this as an empty bucket, because a
1127  // mismatched hash signals the end of a bucket, but if this is indeed an
1128  // empty bucket, the producer should have signalled this by marking the
1129  // bucket as empty.
1130  uint32_t FirstHash = NI.getHashArrayEntry(Idx);
1131  if (FirstHash % NI.getBucketCount() != B.Bucket) {
1132  error() << formatv(
1133  "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1134  "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1135  NI.getUnitOffset(), B.Bucket, FirstHash,
1136  FirstHash % NI.getBucketCount());
1137  ++NumErrors;
1138  }
1139 
1140  // This find the end of this bucket and also verifies that all the hashes in
1141  // this bucket are correct by comparing the stored hashes to the ones we
1142  // compute ourselves.
1143  while (Idx <= NI.getNameCount()) {
1144  uint32_t Hash = NI.getHashArrayEntry(Idx);
1145  if (Hash % NI.getBucketCount() != B.Bucket)
1146  break;
1147 
1148  const char *Str = NI.getNameTableEntry(Idx).getString();
1149  if (caseFoldingDjbHash(Str) != Hash) {
1150  error() << formatv("Name Index @ {0:x}: String ({1}) at index {2} "
1151  "hashes to {3:x}, but "
1152  "the Name Index hash is {4:x}\n",
1153  NI.getUnitOffset(), Str, Idx,
1154  caseFoldingDjbHash(Str), Hash);
1155  ++NumErrors;
1156  }
1157 
1158  ++Idx;
1159  }
1160  NextUncovered = std::max(NextUncovered, Idx);
1161  }
1162  return NumErrors;
1163 }
1164 
1165 unsigned DWARFVerifier::verifyNameIndexAttribute(
1166  const DWARFDebugNames::NameIndex &NI, const DWARFDebugNames::Abbrev &Abbr,
1168  StringRef FormName = dwarf::FormEncodingString(AttrEnc.Form);
1169  if (FormName.empty()) {
1170  error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1171  "unknown form: {3}.\n",
1172  NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
1173  AttrEnc.Form);
1174  return 1;
1175  }
1176 
1177  if (AttrEnc.Index == DW_IDX_type_hash) {
1178  if (AttrEnc.Form != dwarf::DW_FORM_data8) {
1179  error() << formatv(
1180  "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1181  "uses an unexpected form {2} (should be {3}).\n",
1182  NI.getUnitOffset(), Abbr.Code, AttrEnc.Form, dwarf::DW_FORM_data8);
1183  return 1;
1184  }
1185  }
1186 
1187  // A list of known index attributes and their expected form classes.
1188  // DW_IDX_type_hash is handled specially in the check above, as it has a
1189  // specific form (not just a form class) we should expect.
1190  struct FormClassTable {
1193  StringLiteral ClassName;
1194  };
1195  static constexpr FormClassTable Table[] = {
1196  {dwarf::DW_IDX_compile_unit, DWARFFormValue::FC_Constant, {"constant"}},
1197  {dwarf::DW_IDX_type_unit, DWARFFormValue::FC_Constant, {"constant"}},
1198  {dwarf::DW_IDX_die_offset, DWARFFormValue::FC_Reference, {"reference"}},
1199  {dwarf::DW_IDX_parent, DWARFFormValue::FC_Constant, {"constant"}},
1200  };
1201 
1203  auto Iter = find_if(TableRef, [AttrEnc](const FormClassTable &T) {
1204  return T.Index == AttrEnc.Index;
1205  });
1206  if (Iter == TableRef.end()) {
1207  warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1208  "unknown index attribute: {2}.\n",
1209  NI.getUnitOffset(), Abbr.Code, AttrEnc.Index);
1210  return 0;
1211  }
1212 
1213  if (!DWARFFormValue(AttrEnc.Form).isFormClass(Iter->Class)) {
1214  error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1215  "unexpected form {3} (expected form class {4}).\n",
1216  NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
1217  AttrEnc.Form, Iter->ClassName);
1218  return 1;
1219  }
1220  return 0;
1221 }
1222 
1223 unsigned
1224 DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
1225  if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0) {
1226  warn() << formatv("Name Index @ {0:x}: Verifying indexes of type units is "
1227  "not currently supported.\n",
1228  NI.getUnitOffset());
1229  return 0;
1230  }
1231 
1232  unsigned NumErrors = 0;
1233  for (const auto &Abbrev : NI.getAbbrevs()) {
1234  StringRef TagName = dwarf::TagString(Abbrev.Tag);
1235  if (TagName.empty()) {
1236  warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} references an "
1237  "unknown tag: {2}.\n",
1238  NI.getUnitOffset(), Abbrev.Code, Abbrev.Tag);
1239  }
1241  for (const auto &AttrEnc : Abbrev.Attributes) {
1242  if (!Attributes.insert(AttrEnc.Index).second) {
1243  error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains "
1244  "multiple {2} attributes.\n",
1245  NI.getUnitOffset(), Abbrev.Code, AttrEnc.Index);
1246  ++NumErrors;
1247  continue;
1248  }
1249  NumErrors += verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
1250  }
1251 
1252  if (NI.getCUCount() > 1 && !Attributes.count(dwarf::DW_IDX_compile_unit)) {
1253  error() << formatv("NameIndex @ {0:x}: Indexing multiple compile units "
1254  "and abbreviation {1:x} has no {2} attribute.\n",
1255  NI.getUnitOffset(), Abbrev.Code,
1256  dwarf::DW_IDX_compile_unit);
1257  ++NumErrors;
1258  }
1259  if (!Attributes.count(dwarf::DW_IDX_die_offset)) {
1260  error() << formatv(
1261  "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1262  NI.getUnitOffset(), Abbrev.Code, dwarf::DW_IDX_die_offset);
1263  ++NumErrors;
1264  }
1265  }
1266  return NumErrors;
1267 }
1268 
1270  bool IncludeLinkageName = true) {
1272  if (const char *Str = DIE.getShortName())
1273  Result.emplace_back(Str);
1274  else if (DIE.getTag() == dwarf::DW_TAG_namespace)
1275  Result.emplace_back("(anonymous namespace)");
1276 
1277  if (IncludeLinkageName) {
1278  if (const char *Str = DIE.getLinkageName())
1279  Result.emplace_back(Str);
1280  }
1281 
1282  return Result;
1283 }
1284 
1285 unsigned DWARFVerifier::verifyNameIndexEntries(
1286  const DWARFDebugNames::NameIndex &NI,
1287  const DWARFDebugNames::NameTableEntry &NTE) {
1288  // Verifying type unit indexes not supported.
1289  if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0)
1290  return 0;
1291 
1292  const char *CStr = NTE.getString();
1293  if (!CStr) {
1294  error() << formatv(
1295  "Name Index @ {0:x}: Unable to get string associated with name {1}.\n",
1296  NI.getUnitOffset(), NTE.getIndex());
1297  return 1;
1298  }
1299  StringRef Str(CStr);
1300 
1301  unsigned NumErrors = 0;
1302  unsigned NumEntries = 0;
1303  uint64_t EntryID = NTE.getEntryOffset();
1304  uint64_t NextEntryID = EntryID;
1305  Expected<DWARFDebugNames::Entry> EntryOr = NI.getEntry(&NextEntryID);
1306  for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
1307  EntryOr = NI.getEntry(&NextEntryID)) {
1308  uint32_t CUIndex = *EntryOr->getCUIndex();
1309  if (CUIndex > NI.getCUCount()) {
1310  error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
1311  "invalid CU index ({2}).\n",
1312  NI.getUnitOffset(), EntryID, CUIndex);
1313  ++NumErrors;
1314  continue;
1315  }
1316  uint64_t CUOffset = NI.getCUOffset(CUIndex);
1317  uint64_t DIEOffset = CUOffset + *EntryOr->getDIEUnitOffset();
1318  DWARFDie DIE = DCtx.getDIEForOffset(DIEOffset);
1319  if (!DIE) {
1320  error() << formatv("Name Index @ {0:x}: Entry @ {1:x} references a "
1321  "non-existing DIE @ {2:x}.\n",
1322  NI.getUnitOffset(), EntryID, DIEOffset);
1323  ++NumErrors;
1324  continue;
1325  }
1326  if (DIE.getDwarfUnit()->getOffset() != CUOffset) {
1327  error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1328  "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1329  NI.getUnitOffset(), EntryID, DIEOffset, CUOffset,
1330  DIE.getDwarfUnit()->getOffset());
1331  ++NumErrors;
1332  }
1333  if (DIE.getTag() != EntryOr->tag()) {
1334  error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1335  "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1336  NI.getUnitOffset(), EntryID, DIEOffset, EntryOr->tag(),
1337  DIE.getTag());
1338  ++NumErrors;
1339  }
1340 
1341  auto EntryNames = getNames(DIE);
1342  if (!is_contained(EntryNames, Str)) {
1343  error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1344  "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1345  NI.getUnitOffset(), EntryID, DIEOffset, Str,
1346  make_range(EntryNames.begin(), EntryNames.end()));
1347  ++NumErrors;
1348  }
1349  }
1350  handleAllErrors(EntryOr.takeError(),
1351  [&](const DWARFDebugNames::SentinelError &) {
1352  if (NumEntries > 0)
1353  return;
1354  error() << formatv("Name Index @ {0:x}: Name {1} ({2}) is "
1355  "not associated with any entries.\n",
1356  NI.getUnitOffset(), NTE.getIndex(), Str);
1357  ++NumErrors;
1358  },
1359  [&](const ErrorInfoBase &Info) {
1360  error()
1361  << formatv("Name Index @ {0:x}: Name {1} ({2}): {3}\n",
1362  NI.getUnitOffset(), NTE.getIndex(), Str,
1363  Info.message());
1364  ++NumErrors;
1365  });
1366  return NumErrors;
1367 }
1368 
1369 static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) {
1371  Die.getLocations(DW_AT_location);
1372  if (!Loc) {
1373  consumeError(Loc.takeError());
1374  return false;
1375  }
1376  DWARFUnit *U = Die.getDwarfUnit();
1377  for (const auto &Entry : *Loc) {
1378  DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(),
1379  U->getAddressByteSize());
1381  U->getFormParams().Format);
1382  bool IsInteresting =
1384  return !Op.isError() && (Op.getCode() == DW_OP_addr ||
1385  Op.getCode() == DW_OP_form_tls_address ||
1386  Op.getCode() == DW_OP_GNU_push_tls_address);
1387  });
1388  if (IsInteresting)
1389  return true;
1390  }
1391  return false;
1392 }
1393 
1394 unsigned DWARFVerifier::verifyNameIndexCompleteness(
1395  const DWARFDie &Die, const DWARFDebugNames::NameIndex &NI) {
1396 
1397  // First check, if the Die should be indexed. The code follows the DWARF v5
1398  // wording as closely as possible.
1399 
1400  // "All non-defining declarations (that is, debugging information entries
1401  // with a DW_AT_declaration attribute) are excluded."
1402  if (Die.find(DW_AT_declaration))
1403  return 0;
1404 
1405  // "DW_TAG_namespace debugging information entries without a DW_AT_name
1406  // attribute are included with the name “(anonymous namespace)”.
1407  // All other debugging information entries without a DW_AT_name attribute
1408  // are excluded."
1409  // "If a subprogram or inlined subroutine is included, and has a
1410  // DW_AT_linkage_name attribute, there will be an additional index entry for
1411  // the linkage name."
1412  auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram ||
1413  Die.getTag() == DW_TAG_inlined_subroutine;
1414  auto EntryNames = getNames(Die, IncludeLinkageName);
1415  if (EntryNames.empty())
1416  return 0;
1417 
1418  // We deviate from the specification here, which says:
1419  // "The name index must contain an entry for each debugging information entry
1420  // that defines a named subprogram, label, variable, type, or namespace,
1421  // subject to ..."
1422  // Explicitly exclude all TAGs that we know shouldn't be indexed.
1423  switch (Die.getTag()) {
1424  // Compile units and modules have names but shouldn't be indexed.
1425  case DW_TAG_compile_unit:
1426  case DW_TAG_module:
1427  return 0;
1428 
1429  // Function and template parameters are not globally visible, so we shouldn't
1430  // index them.
1431  case DW_TAG_formal_parameter:
1432  case DW_TAG_template_value_parameter:
1433  case DW_TAG_template_type_parameter:
1434  case DW_TAG_GNU_template_parameter_pack:
1435  case DW_TAG_GNU_template_template_param:
1436  return 0;
1437 
1438  // Object members aren't globally visible.
1439  case DW_TAG_member:
1440  return 0;
1441 
1442  // According to a strict reading of the specification, enumerators should not
1443  // be indexed (and LLVM currently does not do that). However, this causes
1444  // problems for the debuggers, so we may need to reconsider this.
1445  case DW_TAG_enumerator:
1446  return 0;
1447 
1448  // Imported declarations should not be indexed according to the specification
1449  // and LLVM currently does not do that.
1450  case DW_TAG_imported_declaration:
1451  return 0;
1452 
1453  // "DW_TAG_subprogram, DW_TAG_inlined_subroutine, and DW_TAG_label debugging
1454  // information entries without an address attribute (DW_AT_low_pc,
1455  // DW_AT_high_pc, DW_AT_ranges, or DW_AT_entry_pc) are excluded."
1456  case DW_TAG_subprogram:
1457  case DW_TAG_inlined_subroutine:
1458  case DW_TAG_label:
1459  if (Die.findRecursively(
1460  {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
1461  break;
1462  return 0;
1463 
1464  // "DW_TAG_variable debugging information entries with a DW_AT_location
1465  // attribute that includes a DW_OP_addr or DW_OP_form_tls_address operator are
1466  // included; otherwise, they are excluded."
1467  //
1468  // LLVM extension: We also add DW_OP_GNU_push_tls_address to this list.
1469  case DW_TAG_variable:
1470  if (isVariableIndexable(Die, DCtx))
1471  break;
1472  return 0;
1473 
1474  default:
1475  break;
1476  }
1477 
1478  // Now we know that our Die should be present in the Index. Let's check if
1479  // that's the case.
1480  unsigned NumErrors = 0;
1481  uint64_t DieUnitOffset = Die.getOffset() - Die.getDwarfUnit()->getOffset();
1482  for (StringRef Name : EntryNames) {
1483  if (none_of(NI.equal_range(Name), [&](const DWARFDebugNames::Entry &E) {
1484  return E.getDIEUnitOffset() == DieUnitOffset;
1485  })) {
1486  error() << formatv("Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
1487  "name {3} missing.\n",
1488  NI.getUnitOffset(), Die.getOffset(), Die.getTag(),
1489  Name);
1490  ++NumErrors;
1491  }
1492  }
1493  return NumErrors;
1494 }
1495 
1496 unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
1497  const DataExtractor &StrData) {
1498  unsigned NumErrors = 0;
1499  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), AccelSection,
1500  DCtx.isLittleEndian(), 0);
1501  DWARFDebugNames AccelTable(AccelSectionData, StrData);
1502 
1503  OS << "Verifying .debug_names...\n";
1504 
1505  // This verifies that we can read individual name indices and their
1506  // abbreviation tables.
1507  if (Error E = AccelTable.extract()) {
1508  error() << toString(std::move(E)) << '\n';
1509  return 1;
1510  }
1511 
1512  NumErrors += verifyDebugNamesCULists(AccelTable);
1513  for (const auto &NI : AccelTable)
1514  NumErrors += verifyNameIndexBuckets(NI, StrData);
1515  for (const auto &NI : AccelTable)
1516  NumErrors += verifyNameIndexAbbrevs(NI);
1517 
1518  // Don't attempt Entry validation if any of the previous checks found errors
1519  if (NumErrors > 0)
1520  return NumErrors;
1521  for (const auto &NI : AccelTable)
1522  for (const DWARFDebugNames::NameTableEntry &NTE : NI)
1523  NumErrors += verifyNameIndexEntries(NI, NTE);
1524 
1525  if (NumErrors > 0)
1526  return NumErrors;
1527 
1528  for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) {
1529  if (const DWARFDebugNames::NameIndex *NI =
1530  AccelTable.getCUNameIndex(U->getOffset())) {
1531  auto *CU = cast<DWARFCompileUnit>(U.get());
1532  for (const DWARFDebugInfoEntry &Die : CU->dies())
1533  NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
1534  }
1535  }
1536  return NumErrors;
1537 }
1538 
1540  const DWARFObject &D = DCtx.getDWARFObj();
1541  DataExtractor StrData(D.getStrSection(), DCtx.isLittleEndian(), 0);
1542  unsigned NumErrors = 0;
1543  if (!D.getAppleNamesSection().Data.empty())
1544  NumErrors += verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData,
1545  ".apple_names");
1546  if (!D.getAppleTypesSection().Data.empty())
1547  NumErrors += verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData,
1548  ".apple_types");
1549  if (!D.getAppleNamespacesSection().Data.empty())
1550  NumErrors += verifyAppleAccelTable(&D.getAppleNamespacesSection(), &StrData,
1551  ".apple_namespaces");
1552  if (!D.getAppleObjCSection().Data.empty())
1553  NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData,
1554  ".apple_objc");
1555 
1556  if (!D.getNamesSection().Data.empty())
1557  NumErrors += verifyDebugNames(D.getNamesSection(), StrData);
1558  return NumErrors == 0;
1559 }
1560 
1561 raw_ostream &DWARFVerifier::error() const { return WithColor::error(OS); }
1562 
1563 raw_ostream &DWARFVerifier::warn() const { return WithColor::warning(OS); }
1564 
1565 raw_ostream &DWARFVerifier::note() const { return WithColor::note(OS); }
1566 
1567 raw_ostream &DWARFVerifier::dump(const DWARFDie &Die, unsigned indent) const {
1568  Die.dump(OS, indent, DumpOpts);
1569  return OS;
1570 }
llvm::DWARFSection
Definition: DWARFSection.h:16
DWARFFormValue.h
llvm::array_pod_sort
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1499
llvm::DWARFContext::getLineTableForUnit
const DWARFDebugLine::LineTable * getLineTableForUnit(DWARFUnit *U)
Get a pointer to a parsed line table corresponding to a compile unit.
Definition: DWARFContext.cpp:941
llvm::DWARFDie::isValid
bool isValid() const
Definition: DWARFDie.h:51
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::DWARFVerifier::DieRangeInfo::Ranges
std::vector< DWARFAddressRange > Ranges
Sorted DWARFAddressRanges.
Definition: DWARFVerifier.h:41
DWARFCompileUnit.h
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:152
llvm::none_of
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1614
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition: iterator_range.h:53
llvm::DWARFAttribute::Value
DWARFFormValue Value
The form and value for this attribute.
Definition: DWARFAttribute.h:32
llvm::DWARFObject::getStrOffsetsSection
virtual const DWARFSection & getStrOffsetsSection() const
Definition: DWARFObject.h:58
DJB.h
T
llvm::Attribute
Definition: Attributes.h:51
llvm::DWARFAttribute::Attr
dwarf::Attribute Attr
The attribute enumeration of this attribute.
Definition: DWARFAttribute.h:30
llvm::lower_bound
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1710
llvm::DWARFDebugNames::NameTableEntry::getString
const char * getString() const
Return the string referenced by this name table entry or nullptr if the string offset is not valid.
Definition: DWARFAcceleratorTable.h:377
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1030
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::dwarf::Form
Form
Definition: Dwarf.h:131
llvm::SmallDenseSet
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition: DenseSet.h:286
llvm::DWARFFormValue::FC_Constant
@ FC_Constant
Definition: DWARFFormValue.h:32
DWARFDebugLine.h
DWARFContext.h
llvm::DWARFObject::getFile
virtual const object::ObjectFile * getFile() const
Definition: DWARFObject.h:31
llvm::DWARFVerifier::DWARFVerifier
DWARFVerifier(raw_ostream &S, DWARFContext &D, DIDumpOptions DumpOpts=DIDumpOptions::getForSingleDIE())
Definition: DWARFVerifier.cpp:881
llvm::DWARFFormValue::getAsUnsignedConstant
Optional< uint64_t > getAsUnsignedConstant() const
Definition: DWARFFormValue.cpp:721
llvm::StringMap::end
iterator end()
Definition: StringMap.h:203
llvm::DWARFContext
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Definition: DWARFContext.h:53
llvm::DWARFObject::forEachInfoSections
virtual void forEachInfoSections(function_ref< void(const DWARFSection &)> F) const
Definition: DWARFObject.h:36
llvm::DWARFDebugNames::NameIndex::getLocalTUCount
uint32_t getLocalTUCount() const
Definition: DWARFAcceleratorTable.h:429
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
llvm::DWARFDebugNames::NameTableEntry
A single entry in the Name Table (DWARF v5 sect.
Definition: DWARFAcceleratorTable.h:356
error
#define error(X)
Definition: SymbolRecordMapping.cpp:14
llvm::DWARFDebugNames::NameIndex::getBucketCount
uint32_t getBucketCount() const
Definition: DWARFAcceleratorTable.h:439
llvm::Optional
Definition: APInt.h:33
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::DWARFDebugNames::AttributeEncoding::Form
dwarf::Form Form
Definition: DWARFAcceleratorTable.h:258
llvm::DIE
A structured debug information entry.
Definition: DIE.h:739
llvm::dump
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Definition: SparseBitVector.h:876
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::DWARFDebugInfoEntry
DWARFDebugInfoEntry - A DIE with only the minimum required data.
Definition: DWARFDebugInfoEntry.h:23
llvm::AccelTable
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:197
llvm::DWARFFormValue::FC_Reference
@ FC_Reference
Definition: DWARFFormValue.h:35
llvm::DataExtractor::getU64
uint64_t getU64(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint64_t value from *offset_ptr.
Definition: DataExtractor.cpp:117
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:216
llvm::DWARFUnit::getFormParams
const dwarf::FormParams & getFormParams() const
Definition: DWARFUnit.h:282
llvm::DIE::getTag
dwarf::Tag getTag() const
Definition: DIE.h:775
llvm::DWARFDataExtractor
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
Definition: DWARFDataExtractor.h:21
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:104
llvm::DWARFVerifier::handleDebugInfo
bool handleDebugInfo()
Verify the information in the .debug_info and .debug_types sections.
Definition: DWARFVerifier.cpp:377
llvm::dwarf::FormParams::Format
DwarfFormat Format
Definition: Dwarf.h:651
llvm::dwarf::isUnitType
bool isUnitType(uint8_t UnitType)
Definition: Dwarf.h:474
llvm::DWARFDebugNames::Abbrev
Abbreviation describing the encoding of Name Index entries.
Definition: DWARFAcceleratorTable.h:270
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1045
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::DWARFDebugNames::AttributeEncoding
Index attribute and its encoding.
Definition: DWARFAcceleratorTable.h:256
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::WithColor::error
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:75
llvm::DWARFDebugNames::NameIndex::getBucketArrayEntry
uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
Definition: DWARFAcceleratorTable.cpp:654
llvm::AArch64CC::LT
@ LT
Definition: AArch64BaseInfo.h:266
llvm::DWARFObject::forEachTypesSections
virtual void forEachTypesSections(function_ref< void(const DWARFSection &)> F) const
Definition: DWARFObject.h:38
llvm::DWARFUnit::getUnitDIE
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:390
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:250
llvm::DWARFAttribute
Encapsulates a DWARF attribute value and all of the data required to describe the attribute value.
Definition: DWARFAttribute.h:24
llvm::StringLiteral
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition: StringRef.h:890
getNames
static SmallVector< StringRef, 2 > getNames(const DWARFDie &DIE, bool IncludeLinkageName=true)
Definition: DWARFVerifier.cpp:1269
DWARFVerifier.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::DWARFExpression::Operation
This class represents an Operation in the Expression.
Definition: DWARFExpression.h:35
llvm::DWARFDebugAbbrev
Definition: DWARFDebugAbbrev.h:56
llvm::DWARFDebugNames::NameIndex
Represents a single accelerator table within the DWARF v5 .debug_names section.
Definition: DWARFAcceleratorTable.h:388
llvm::DWARFDebugNames::NameIndex::getEntry
Expected< Entry > getEntry(uint64_t *Offset) const
Definition: DWARFAcceleratorTable.cpp:611
DWARFSection.h
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::DWARFDebugNames::NameIndex::getHashArrayEntry
uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
Definition: DWARFAcceleratorTable.cpp:660
llvm::DWARFDebugNames::NameIndex::equal_range
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
Definition: DWARFAcceleratorTable.cpp:787
llvm::DWARFFormValue::getAsSectionOffset
Optional< uint64_t > getAsSectionOffset() const
Definition: DWARFFormValue.cpp:715
llvm::DWARFContext::getNumCompileUnits
unsigned getNumCompileUnits()
Get the number of compile units in this context.
Definition: DWARFContext.h:215
DWARFDie.h
false
Definition: StackSlotColoring.cpp:142
llvm::DWARFDebugNames::NameIndex::getForeignTUCount
uint32_t getForeignTUCount() const
Definition: DWARFAcceleratorTable.h:433
llvm::dwarf::Index
Index
Definition: Dwarf.h:467
llvm::dwarf::toStringRef
StringRef toStringRef(const Optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
Definition: DWARFFormValue.h:186
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::dwarf::toSectionOffset
Optional< uint64_t > toSectionOffset(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
Definition: DWARFFormValue.h:303
llvm::DWARFVerifier::handleDebugLine
bool handleDebugLine()
Verify the information in the .debug_line section.
Definition: DWARFVerifier.cpp:891
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::DWARFObject
Definition: DWARFObject.h:25
llvm::DWARFFormValue
Definition: DWARFFormValue.h:26
llvm::DWARFObject::getRangesSection
virtual const DWARFSection & getRangesSection() const
Definition: DWARFObject.h:48
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::dwarf::DwarfFormat
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
Definition: Dwarf.h:92
FormatVariadic.h
llvm::None
const NoneType None
Definition: None.h:23
llvm::ErrorInfoBase
Base class for error info classes.
Definition: Error.h:48
llvm::dwarf::FormEncodingString
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:105
llvm::DWARFContext::compile_units
compile_unit_range compile_units()
Get compile units in this context.
Definition: DWARFContext.h:172
llvm::DWARFVerifier::handleAccelTables
bool handleAccelTables()
Verify the information in accelerator tables, if they exist.
Definition: DWARFVerifier.cpp:1539
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:108
llvm::DWARFDebugNames::AttributeEncoding::Index
dwarf::Index Index
Definition: DWARFAcceleratorTable.h:257
llvm::DWARFDie::dump
void dump(raw_ostream &OS, unsigned indent=0, DIDumpOptions DumpOpts=DIDumpOptions()) const
Dump the DIE and all of its attributes to the supplied stream.
Definition: DWARFDie.cpp:1071
llvm::DWARFDebugNames::NameTableEntry::getIndex
uint32_t getIndex() const
Return the index of this name in the parent Name Index.
Definition: DWARFAcceleratorTable.h:370
llvm::DWARFVerifier::DieRangeInfo::die_range_info_iterator
std::set< DieRangeInfo >::const_iterator die_range_info_iterator
Definition: DWARFVerifier.h:53
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::DWARFAbbreviationDeclarationSet
Definition: DWARFDebugAbbrev.h:22
llvm::WithColor::warning
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition: WithColor.cpp:77
llvm::DWARFUnit::isMatchingUnitTypeAndTag
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag)
Definition: DWARFUnit.h:371
object
bar al al movzbl eax ret Missed when stored in a memory object
Definition: README.txt:1411
llvm::DWARFObject::getAbbrevSection
virtual StringRef getAbbrevSection() const
Definition: DWARFObject.h:39
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::dwarf::isType
bool isType(Tag T)
Definition: Dwarf.h:112
uint64_t
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
llvm::DWARFVerifier::handleDebugAbbrev
bool handleDebugAbbrev()
Verify the information in any of the following sections, if available: .debug_abbrev,...
Definition: DWARFVerifier.cpp:308
llvm::caseFoldingDjbHash
uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H=5381)
Computes the Bernstein hash after folding the input according to the Dwarf 5 standard case folding ru...
Definition: DJB.cpp:71
llvm::DWARFDie::getAddressRanges
Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
Definition: DWARFDie.cpp:944
llvm::DWARFVerifier::DieRangeInfo::intersects
bool intersects(const DieRangeInfo &RHS) const
Return true if any range in this object intersects with any range in RHS.
Definition: DWARFVerifier.cpp:93
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
llvm::DWARFFormValue::FormClass
FormClass
Definition: DWARFFormValue.h:28
llvm::operator<
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:338
llvm::DWARFDebugLine::Row::dumpTableHeader
static void dumpTableHeader(raw_ostream &OS, unsigned Indent)
Definition: DWARFDebugLine.cpp:486
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::DWARFDie::find
Optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:816
Attributes
AMDGPU Kernel Attributes
Definition: AMDGPULowerKernelAttributes.cpp:254
llvm::DWARFDie::getOffset
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
Definition: DWARFDie.h:67
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1665
llvm::DWARFExpression
Definition: DWARFExpression.h:25
llvm::dwarf::UnitType
UnitType
Constants for unit types in DWARF v5.
Definition: Dwarf.h:460
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
llvm::DataExtractor::isValidOffset
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
Definition: DataExtractor.h:665
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1658
llvm::DWARFDebugNames::SentinelError
Error returned by NameIndex::getEntry to report it has reached the end of the entry list.
Definition: DWARFAcceleratorTable.h:326
llvm::DWARFDataExtractor::getInitialLength
std::pair< uint64_t, dwarf::DwarfFormat > getInitialLength(uint64_t *Off, Error *Err=nullptr) const
Extracts the DWARF "initial length" field, which can either be a 32-bit value smaller than 0xfffffff0...
Definition: DWARFDataExtractor.cpp:15
llvm::DWARFContext::isAddressSizeSupported
static bool isAddressSizeSupported(unsigned AddressSize)
Definition: DWARFContext.h:381
llvm::DWARFDie::findRecursively
Optional< DWARFFormValue > findRecursively(ArrayRef< dwarf::Attribute > Attrs) const
Extract the first value of any attribute in Attrs from this DIE and recurse into any DW_AT_specificat...
Definition: DWARFDie.cpp:840
llvm::DWARFDebugAbbrev::getAbbreviationDeclarationSet
const DWARFAbbreviationDeclarationSet * getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
Definition: DWARFDebugAbbrev.cpp:143
llvm::dwarf::toString
Optional< const char * > toString(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
Definition: DWARFFormValue.h:175
llvm::DataExtractor::getU32
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
Definition: DataExtractor.cpp:108
llvm::Expression
Class representing an expression and its matching format.
Definition: FileCheckImpl.h:237
llvm::DWARFDie::getLocations
Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
Definition: DWARFDie.cpp:975
llvm::DataExtractor::getCStr
const char * getCStr(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
Definition: DataExtractor.h:129
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::DWARFContext::isLittleEndian
bool isLittleEndian() const
Definition: DWARFContext.h:372
llvm::any_of
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1607
llvm::DWARFDie::hasChildren
bool hasChildren() const
Definition: DWARFDie.h:79
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Dwarf.h
llvm::DWARFObject::getStrSection
virtual StringRef getStrSection() const
Definition: DWARFObject.h:47
llvm::DWARFUnit::getContext
DWARFContext & getContext() const
Definition: DWARFUnit.h:279
llvm::DWARFDie::getDwarfUnit
DWARFUnit * getDwarfUnit() const
Definition: DWARFDie.h:54
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::AppleAcceleratorTable
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
Definition: DWARFAcceleratorTable.h:83
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::DWARFFormValue::getRawUValue
uint64_t getRawUValue() const
Definition: DWARFFormValue.h:78
llvm::DataExtractor::getU8
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
Definition: DataExtractor.cpp:80
llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
@ AbsoluteFilePath
llvm::DWARFContext::getDIEForOffset
DWARFDie getDIEForOffset(uint64_t Offset)
Get a DIE given an exact offset.
Definition: DWARFContext.cpp:738
llvm::DWARFObject::getAbbrevDWOSection
virtual StringRef getAbbrevDWOSection() const
Definition: DWARFObject.h:63
llvm::find_if
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1627
llvm::DWARFDebugNames::Entry
DWARF v5-specific implementation of an Accelerator Entry.
Definition: DWARFAcceleratorTable.h:283
WithColor.h
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::DWARFDie::getParent
DWARFDie getParent() const
Get the parent of this DIE object.
Definition: DWARFDie.cpp:1131
llvm::DWARFUnit::getAddressByteSize
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:286
llvm::DWARFAddressRangesVector
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Definition: DWARFAddressRange.h:85
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
uint16_t
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::end
iterator end()
Definition: DenseMap.h:83
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:325
llvm::DWARFDebugNames::NameTableEntry::getEntryOffset
uint64_t getEntryOffset() const
Returns the offset of the first Entry in the list.
Definition: DWARFAcceleratorTable.h:383
llvm::DWARFUnit
Definition: DWARFUnit.h:203
llvm::DWARFDebugNames::NameIndex::getUnitOffset
uint64_t getUnitOffset() const
Definition: DWARFAcceleratorTable.h:466
llvm::SectionName
Definition: DWARFSection.h:21
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Success
#define Success
Definition: AArch64Disassembler.cpp:260
llvm::DWARFVerifier::DieRangeInfo
A class that keeps the address range information for a single DIE.
Definition: DWARFVerifier.h:37
llvm::DWARFUnit::getOffset
uint64_t getOffset() const
Definition: DWARFUnit.h:281
DWARFExpression.h
llvm::DWARFDie::getFullName
void getFullName(raw_string_ostream &, std::string *OriginalFullName=nullptr) const
Definition: DWARFDie.cpp:801
llvm::DWARFDebugNames::Abbrev::Code
uint32_t Code
Abbreviation code.
Definition: DWARFAcceleratorTable.h:271
DWARFUnitIndex.h
llvm::tgtok::Class
@ Class
Definition: TGLexer.h:50
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:599
llvm::DWARFDie::getAttributeValueAsReferencedDie
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
Definition: DWARFDie.cpp:873
llvm::DWARFDebugNames::NameIndex::getNameCount
uint32_t getNameCount() const
Definition: DWARFAcceleratorTable.h:451
llvm::DataExtractor
Definition: DataExtractor.h:41
llvm::AttributeSet
Definition: Attributes.h:266
llvm::DWARFDie::getTag
dwarf::Tag getTag() const
Definition: DWARFDie.h:72
Version
uint64_t Version
Definition: RawMemProfReader.cpp:25
llvm::DWARFDie::attributes
iterator_range< attribute_iterator > attributes() const
Get an iterator range to all attributes in the current DIE only.
Definition: DWARFDie.cpp:1161
llvm::DWARFObject::getRnglistsSection
virtual const DWARFSection & getRnglistsSection() const
Definition: DWARFObject.h:49
llvm::DWARFDebugNames::NameIndex::getNameTableEntry
NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
Definition: DWARFAcceleratorTable.cpp:637
llvm::DWARFFormValue::isFormClass
bool isFormClass(FormClass FC) const
Definition: DWARFFormValue.cpp:212
llvm::DWARFContext::getDWARFObj
const DWARFObject & getDWARFObj() const
Definition: DWARFContext.h:130
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::DWARFFormValue::getForm
dwarf::Form getForm() const
Definition: DWARFFormValue.h:77
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::reserve
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition: DenseMap.h:104
llvm::DWARFFormValue::getAsReference
Optional< uint64_t > getAsReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
Definition: DWARFFormValue.cpp:688
llvm::DWARFVerifier::DieRangeInfo::contains
bool contains(const DieRangeInfo &RHS) const
Return true if ranges in this object contains all ranges within RHS.
Definition: DWARFVerifier.cpp:69
llvm::dwarf::DWARF64
@ DWARF64
Definition: Dwarf.h:92
llvm::DWARFDie
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:43
llvm::WithColor::note
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
Definition: WithColor.cpp:79
llvm::DWARFAddressRange
Definition: DWARFAddressRange.h:22
llvm::DWARFDie::isSubprogramDIE
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
Definition: DWARFDie.cpp:809
llvm::DWARFDebugNames
.debug_names section consists of one or more units.
Definition: DWARFAcceleratorTable.h:231
llvm::DWARFUnit::getDIEForOffset
DWARFDie getDIEForOffset(uint64_t Offset)
Return the DIE object for a given offset inside the unit's DIE vector.
Definition: DWARFUnit.h:479
llvm::dwarf::TagString
StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:21
llvm::DWARFDebugNames::NameIndex::getAbbrevs
const DenseSet< Abbrev, AbbrevMapInfo > & getAbbrevs() const
Definition: DWARFAcceleratorTable.h:453
llvm::DWARFDebugNames::NameIndex::getCUCount
uint32_t getCUCount() const
Definition: DWARFAcceleratorTable.h:425
raw_ostream.h
llvm::DIE::getOffset
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition: DIE.h:777
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:156
llvm::DWARFContext::isSupportedVersion
static bool isSupportedVersion(unsigned version)
Definition: DWARFContext.h:374
llvm::DWARFDebugNames::NameIndex::getCUOffset
uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
Definition: DWARFAcceleratorTable.cpp:587
TableRef
Definition: AMDGPULibCalls.cpp:399
llvm::DWARFSection::Data
StringRef Data
Definition: DWARFSection.h:17
CU
Definition: AArch64AsmBackend.cpp:504
llvm::DWARFVerifier::DieRangeInfo::insert
Optional< DWARFAddressRange > insert(const DWARFAddressRange &R)
Inserts the address range.
Definition: DWARFVerifier.cpp:32
llvm::handleAllErrors
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:968
llvm::dwarf::UnitTypeString
StringRef UnitTypeString(unsigned)
Definition: Dwarf.cpp:576
llvm::DWARFObject::getLineSection
virtual const DWARFSection & getLineSection() const
Definition: DWARFObject.h:45
llvm::dwarf::AttributeString
StringRef AttributeString(unsigned Attribute)
Definition: Dwarf.cpp:72
llvm::DWARFUnit::getVersion
uint16_t getVersion() const
Definition: DWARFUnit.h:285
llvm::DWARFDie::getFirstChild
DWARFDie getFirstChild() const
Get the first child of this DIE object.
Definition: DWARFDie.cpp:1149
isVariableIndexable
static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx)
Definition: DWARFVerifier.cpp:1369
SmallSet.h
llvm::DataExtractor::getU16
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
Definition: DataExtractor.cpp:93
llvm::DIDumpOptions
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:180
llvm::DWARFUnitVector
Describe a collection of units.
Definition: DWARFUnit.h:120