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