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