LLVM  7.0.0svn
DWARFVerifier.cpp
Go to the documentation of this file.
1 //===- DWARFVerifier.cpp --------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "SyntaxHighlighting.h"
22 #include <map>
23 #include <set>
24 #include <vector>
25 
26 using namespace llvm;
27 using namespace dwarf;
28 using namespace object;
29 using namespace syntax;
30 
33  auto Begin = Ranges.begin();
34  auto End = Ranges.end();
35  auto Pos = std::lower_bound(Begin, End, R);
36 
37  if (Pos != End) {
38  if (Pos->intersects(R))
39  return Pos;
40  if (Pos != Begin) {
41  auto Iter = Pos - 1;
42  if (Iter->intersects(R))
43  return Iter;
44  }
45  }
46 
47  Ranges.insert(Pos, R);
48  return Ranges.end();
49 }
50 
53  auto End = Children.end();
54  auto Iter = Children.begin();
55  while (Iter != End) {
56  if (Iter->intersects(RI))
57  return Iter;
58  ++Iter;
59  }
60  Children.insert(RI);
61  return Children.end();
62 }
63 
65  // Both list of ranges are sorted so we can make this fast.
66 
67  if (Ranges.empty() || RHS.Ranges.empty())
68  return false;
69 
70  // Since the ranges are sorted we can advance where we start searching with
71  // this object's ranges as we traverse RHS.Ranges.
72  auto End = Ranges.end();
73  auto Iter = findRange(RHS.Ranges.front());
74 
75  // Now linearly walk the ranges in this object and see if they contain each
76  // ranges from RHS.Ranges.
77  for (const auto &R : RHS.Ranges) {
78  while (Iter != End) {
79  if (Iter->contains(R))
80  break;
81  ++Iter;
82  }
83  if (Iter == End)
84  return false;
85  }
86  return true;
87 }
88 
90  if (Ranges.empty() || RHS.Ranges.empty())
91  return false;
92 
93  auto End = Ranges.end();
94  auto Iter = findRange(RHS.Ranges.front());
95  for (const auto &R : RHS.Ranges) {
96  if(Iter == End)
97  return false;
98  if (R.HighPC <= Iter->LowPC)
99  continue;
100  while (Iter != End) {
101  if (Iter->intersects(R))
102  return true;
103  ++Iter;
104  }
105  }
106 
107  return false;
108 }
109 
110 bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
111  uint32_t *Offset, unsigned UnitIndex,
112  uint8_t &UnitType, bool &isUnitDWARF64) {
113  uint32_t AbbrOffset, Length;
114  uint8_t AddrSize = 0;
115  uint16_t Version;
116  bool Success = true;
117 
118  bool ValidLength = false;
119  bool ValidVersion = false;
120  bool ValidAddrSize = false;
121  bool ValidType = true;
122  bool ValidAbbrevOffset = true;
123 
124  uint32_t OffsetStart = *Offset;
125  Length = DebugInfoData.getU32(Offset);
126  if (Length == UINT32_MAX) {
127  isUnitDWARF64 = true;
128  OS << format(
129  "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
130  UnitIndex);
131  return false;
132  }
133  Version = DebugInfoData.getU16(Offset);
134 
135  if (Version >= 5) {
136  UnitType = DebugInfoData.getU8(Offset);
137  AddrSize = DebugInfoData.getU8(Offset);
138  AbbrOffset = DebugInfoData.getU32(Offset);
139  ValidType = dwarf::isUnitType(UnitType);
140  } else {
141  UnitType = 0;
142  AbbrOffset = DebugInfoData.getU32(Offset);
143  AddrSize = DebugInfoData.getU8(Offset);
144  }
145 
146  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
147  ValidAbbrevOffset = false;
148 
149  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
150  ValidVersion = DWARFContext::isSupportedVersion(Version);
151  ValidAddrSize = AddrSize == 4 || AddrSize == 8;
152  if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
153  !ValidType) {
154  Success = false;
155  error() << format("Units[%d] - start offset: 0x%08x \n", UnitIndex,
156  OffsetStart);
157  if (!ValidLength)
158  note() << "The length for this unit is too "
159  "large for the .debug_info provided.\n";
160  if (!ValidVersion)
161  note() << "The 16 bit unit header version is not valid.\n";
162  if (!ValidType)
163  note() << "The unit type encoding is not valid.\n";
164  if (!ValidAbbrevOffset)
165  note() << "The offset into the .debug_abbrev section is "
166  "not valid.\n";
167  if (!ValidAddrSize)
168  note() << "The address size is unsupported.\n";
169  }
170  *Offset = OffsetStart + Length + 4;
171  return Success;
172 }
173 
174 bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit, uint8_t UnitType) {
175  uint32_t NumUnitErrors = 0;
176  unsigned NumDies = Unit.getNumDIEs();
177  for (unsigned I = 0; I < NumDies; ++I) {
178  auto Die = Unit.getDIEAtIndex(I);
179  if (Die.getTag() == DW_TAG_null)
180  continue;
181  for (auto AttrValue : Die.attributes()) {
182  NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
183  NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
184  }
185  }
186 
187  DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
188  if (!Die) {
189  error() << "Compilation unit without DIE.\n";
190  NumUnitErrors++;
191  return NumUnitErrors == 0;
192  }
193 
194  if (!dwarf::isUnitType(Die.getTag())) {
195  error() << "Compilation unit root DIE is not a unit DIE: "
196  << dwarf::TagString(Die.getTag()) << ".\n";
197  NumUnitErrors++;
198  }
199 
200  if (UnitType != 0 &&
201  !DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) {
202  error() << "Compilation unit type (" << dwarf::UnitTypeString(UnitType)
203  << ") and root DIE (" << dwarf::TagString(Die.getTag())
204  << ") do not match.\n";
205  NumUnitErrors++;
206  }
207 
208  DieRangeInfo RI;
209  NumUnitErrors += verifyDieRanges(Die, RI);
210 
211  return NumUnitErrors == 0;
212 }
213 
214 unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
215  unsigned NumErrors = 0;
216  if (Abbrev) {
217  const DWARFAbbreviationDeclarationSet *AbbrDecls =
219  for (auto AbbrDecl : *AbbrDecls) {
221  for (auto Attribute : AbbrDecl.attributes()) {
222  auto Result = AttributeSet.insert(Attribute.Attr);
223  if (!Result.second) {
224  error() << "Abbreviation declaration contains multiple "
225  << AttributeString(Attribute.Attr) << " attributes.\n";
226  AbbrDecl.dump(OS);
227  ++NumErrors;
228  }
229  }
230  }
231  }
232  return NumErrors;
233 }
234 
236  OS << "Verifying .debug_abbrev...\n";
237 
238  const DWARFObject &DObj = DCtx.getDWARFObj();
239  bool noDebugAbbrev = DObj.getAbbrevSection().empty();
240  bool noDebugAbbrevDWO = DObj.getAbbrevDWOSection().empty();
241 
242  if (noDebugAbbrev && noDebugAbbrevDWO) {
243  return true;
244  }
245 
246  unsigned NumErrors = 0;
247  if (!noDebugAbbrev)
248  NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
249 
250  if (!noDebugAbbrevDWO)
251  NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
252  return NumErrors == 0;
253 }
254 
256  OS << "Verifying .debug_info Unit Header Chain...\n";
257 
258  const DWARFObject &DObj = DCtx.getDWARFObj();
259  DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(),
260  DCtx.isLittleEndian(), 0);
261  uint32_t NumDebugInfoErrors = 0;
262  uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
263  uint8_t UnitType = 0;
264  bool isUnitDWARF64 = false;
265  bool isHeaderChainValid = true;
266  bool hasDIE = DebugInfoData.isValidOffset(Offset);
269  while (hasDIE) {
270  OffsetStart = Offset;
271  if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
272  isUnitDWARF64)) {
273  isHeaderChainValid = false;
274  if (isUnitDWARF64)
275  break;
276  } else {
277  std::unique_ptr<DWARFUnit> Unit;
278  switch (UnitType) {
279  case dwarf::DW_UT_type:
280  case dwarf::DW_UT_split_type: {
281  Unit.reset(new DWARFTypeUnit(
282  DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
283  &DObj.getRangeSection(), DObj.getStringSection(),
285  DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
286  nullptr));
287  break;
288  }
289  case dwarf::DW_UT_skeleton:
290  case dwarf::DW_UT_split_compile:
291  case dwarf::DW_UT_compile:
292  case dwarf::DW_UT_partial:
293  // UnitType = 0 means that we are
294  // verifying a compile unit in DWARF v4.
295  case 0: {
296  Unit.reset(new DWARFCompileUnit(
297  DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
298  &DObj.getRangeSection(), DObj.getStringSection(),
300  DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
301  nullptr));
302  break;
303  }
304  default: { llvm_unreachable("Invalid UnitType."); }
305  }
306  Unit->extract(DebugInfoData, &OffsetStart);
307  if (!verifyUnitContents(*Unit, UnitType))
308  ++NumDebugInfoErrors;
309  }
310  hasDIE = DebugInfoData.isValidOffset(Offset);
311  ++UnitIdx;
312  }
313  if (UnitIdx == 0 && !hasDIE) {
314  warn() << ".debug_info is empty.\n";
315  isHeaderChainValid = true;
316  }
317  NumDebugInfoErrors += verifyDebugInfoReferences();
318  return (isHeaderChainValid && NumDebugInfoErrors == 0);
319 }
320 
321 unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
322  DieRangeInfo &ParentRI) {
323  unsigned NumErrors = 0;
324 
325  if (!Die.isValid())
326  return NumErrors;
327 
329 
330  // Build RI for this DIE and check that ranges within this DIE do not
331  // overlap.
332  DieRangeInfo RI(Die);
333  for (auto Range : Ranges) {
334  if (!Range.valid()) {
335  ++NumErrors;
336  error() << "Invalid address range " << Range << "\n";
337  continue;
338  }
339 
340  // Verify that ranges don't intersect.
341  const auto IntersectingRange = RI.insert(Range);
342  if (IntersectingRange != RI.Ranges.end()) {
343  ++NumErrors;
344  error() << "DIE has overlapping address ranges: " << Range << " and "
345  << *IntersectingRange << "\n";
346  break;
347  }
348  }
349 
350  // Verify that children don't intersect.
351  const auto IntersectingChild = ParentRI.insert(RI);
352  if (IntersectingChild != ParentRI.Children.end()) {
353  ++NumErrors;
354  error() << "DIEs have overlapping address ranges:";
355  Die.dump(OS, 0);
356  IntersectingChild->Die.dump(OS, 0);
357  OS << "\n";
358  }
359 
360  // Verify that ranges are contained within their parent.
361  bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
362  !(Die.getTag() == DW_TAG_subprogram &&
363  ParentRI.Die.getTag() == DW_TAG_subprogram);
364  if (ShouldBeContained && !ParentRI.contains(RI)) {
365  ++NumErrors;
366  error() << "DIE address ranges are not "
367  "contained in its parent's ranges:";
368  Die.dump(OS, 0);
369  ParentRI.Die.dump(OS, 0);
370  OS << "\n";
371  }
372 
373  // Recursively check children.
374  for (DWARFDie Child : Die)
375  NumErrors += verifyDieRanges(Child, RI);
376 
377  return NumErrors;
378 }
379 
380 unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
381  DWARFAttribute &AttrValue) {
382  unsigned NumErrors = 0;
383  auto ReportError = [&](const Twine &TitleMsg) {
384  ++NumErrors;
385  error() << TitleMsg << '\n';
386  Die.dump(OS, 0, DumpOpts);
387  OS << "\n";
388  };
389 
390  const DWARFObject &DObj = DCtx.getDWARFObj();
391  const auto Attr = AttrValue.Attr;
392  switch (Attr) {
393  case DW_AT_ranges:
394  // Make sure the offset in the DW_AT_ranges attribute is valid.
395  if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
396  if (*SectionOffset >= DObj.getRangeSection().Data.size())
397  ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
398  break;
399  }
400  ReportError("DIE has invalid DW_AT_ranges encoding:");
401  break;
402  case DW_AT_stmt_list:
403  // Make sure the offset in the DW_AT_stmt_list attribute is valid.
404  if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
405  if (*SectionOffset >= DObj.getLineSection().Data.size())
406  ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
407  llvm::formatv("{0:x8}", *SectionOffset));
408  break;
409  }
410  ReportError("DIE has invalid DW_AT_stmt_list encoding:");
411  break;
412  case DW_AT_location: {
413  auto VerifyLocation = [&](StringRef D) {
414  DWARFUnit *U = Die.getDwarfUnit();
415  DataExtractor Data(D, DCtx.isLittleEndian(), 0);
416  DWARFExpression Expression(Data, U->getVersion(),
417  U->getAddressByteSize());
418  bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
419  return Op.isError();
420  });
421  if (Error)
422  ReportError("DIE contains invalid DWARF expression:");
423  };
424  if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) {
425  // Verify inlined location.
426  VerifyLocation(llvm::toStringRef(*Expr));
427  } else if (auto LocOffset = AttrValue.Value.getAsUnsignedConstant()) {
428  // Verify location list.
429  if (auto DebugLoc = DCtx.getDebugLoc())
430  if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset))
431  for (const auto &Entry : LocList->Entries)
432  VerifyLocation({Entry.Loc.data(), Entry.Loc.size()});
433  }
434  break;
435  }
436 
437  default:
438  break;
439  }
440  return NumErrors;
441 }
442 
443 unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
444  DWARFAttribute &AttrValue) {
445  const DWARFObject &DObj = DCtx.getDWARFObj();
446  unsigned NumErrors = 0;
447  const auto Form = AttrValue.Value.getForm();
448  switch (Form) {
449  case DW_FORM_ref1:
450  case DW_FORM_ref2:
451  case DW_FORM_ref4:
452  case DW_FORM_ref8:
453  case DW_FORM_ref_udata: {
454  // Verify all CU relative references are valid CU offsets.
455  Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
456  assert(RefVal);
457  if (RefVal) {
458  auto DieCU = Die.getDwarfUnit();
459  auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
460  auto CUOffset = AttrValue.Value.getRawUValue();
461  if (CUOffset >= CUSize) {
462  ++NumErrors;
463  error() << FormEncodingString(Form) << " CU offset "
464  << format("0x%08" PRIx64, CUOffset)
465  << " is invalid (must be less than CU size of "
466  << format("0x%08" PRIx32, CUSize) << "):\n";
467  Die.dump(OS, 0, DumpOpts);
468  OS << "\n";
469  } else {
470  // Valid reference, but we will verify it points to an actual
471  // DIE later.
472  ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
473  }
474  }
475  break;
476  }
477  case DW_FORM_ref_addr: {
478  // Verify all absolute DIE references have valid offsets in the
479  // .debug_info section.
480  Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
481  assert(RefVal);
482  if (RefVal) {
483  if (*RefVal >= DObj.getInfoSection().Data.size()) {
484  ++NumErrors;
485  error() << "DW_FORM_ref_addr offset beyond .debug_info "
486  "bounds:\n";
487  Die.dump(OS, 0, DumpOpts);
488  OS << "\n";
489  } else {
490  // Valid reference, but we will verify it points to an actual
491  // DIE later.
492  ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
493  }
494  }
495  break;
496  }
497  case DW_FORM_strp: {
498  auto SecOffset = AttrValue.Value.getAsSectionOffset();
499  assert(SecOffset); // DW_FORM_strp is a section offset.
500  if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
501  ++NumErrors;
502  error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
503  Die.dump(OS, 0, DumpOpts);
504  OS << "\n";
505  }
506  break;
507  }
508  default:
509  break;
510  }
511  return NumErrors;
512 }
513 
514 unsigned DWARFVerifier::verifyDebugInfoReferences() {
515  // Take all references and make sure they point to an actual DIE by
516  // getting the DIE by offset and emitting an error
517  OS << "Verifying .debug_info references...\n";
518  unsigned NumErrors = 0;
519  for (auto Pair : ReferenceToDIEOffsets) {
520  auto Die = DCtx.getDIEForOffset(Pair.first);
521  if (Die)
522  continue;
523  ++NumErrors;
524  error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
525  << ". Offset is in between DIEs:\n";
526  for (auto Offset : Pair.second) {
527  auto ReferencingDie = DCtx.getDIEForOffset(Offset);
528  ReferencingDie.dump(OS, 0, DumpOpts);
529  OS << "\n";
530  }
531  OS << "\n";
532  }
533  return NumErrors;
534 }
535 
536 void DWARFVerifier::verifyDebugLineStmtOffsets() {
537  std::map<uint64_t, DWARFDie> StmtListToDie;
538  for (const auto &CU : DCtx.compile_units()) {
539  auto Die = CU->getUnitDIE();
540  // Get the attribute value as a section offset. No need to produce an
541  // error here if the encoding isn't correct because we validate this in
542  // the .debug_info verifier.
543  auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
544  if (!StmtSectionOffset)
545  continue;
546  const uint32_t LineTableOffset = *StmtSectionOffset;
547  auto LineTable = DCtx.getLineTableForUnit(CU.get());
548  if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
549  if (!LineTable) {
550  ++NumDebugLineErrors;
551  error() << ".debug_line[" << format("0x%08" PRIx32, LineTableOffset)
552  << "] was not able to be parsed for CU:\n";
553  Die.dump(OS, 0, DumpOpts);
554  OS << '\n';
555  continue;
556  }
557  } else {
558  // Make sure we don't get a valid line table back if the offset is wrong.
559  assert(LineTable == nullptr);
560  // Skip this line table as it isn't valid. No need to create an error
561  // here because we validate this in the .debug_info verifier.
562  continue;
563  }
564  auto Iter = StmtListToDie.find(LineTableOffset);
565  if (Iter != StmtListToDie.end()) {
566  ++NumDebugLineErrors;
567  error() << "two compile unit DIEs, "
568  << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
569  << format("0x%08" PRIx32, Die.getOffset())
570  << ", have the same DW_AT_stmt_list section offset:\n";
571  Iter->second.dump(OS, 0, DumpOpts);
572  Die.dump(OS, 0, DumpOpts);
573  OS << '\n';
574  // Already verified this line table before, no need to do it again.
575  continue;
576  }
577  StmtListToDie[LineTableOffset] = Die;
578  }
579 }
580 
581 void DWARFVerifier::verifyDebugLineRows() {
582  for (const auto &CU : DCtx.compile_units()) {
583  auto Die = CU->getUnitDIE();
584  auto LineTable = DCtx.getLineTableForUnit(CU.get());
585  // If there is no line table we will have created an error in the
586  // .debug_info verifier or in verifyDebugLineStmtOffsets().
587  if (!LineTable)
588  continue;
589 
590  // Verify prologue.
591  uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
592  uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
593  uint32_t FileIndex = 1;
594  StringMap<uint16_t> FullPathMap;
595  for (const auto &FileName : LineTable->Prologue.FileNames) {
596  // Verify directory index.
597  if (FileName.DirIdx > MaxDirIndex) {
598  ++NumDebugLineErrors;
599  error() << ".debug_line["
600  << format("0x%08" PRIx64,
601  *toSectionOffset(Die.find(DW_AT_stmt_list)))
602  << "].prologue.file_names[" << FileIndex
603  << "].dir_idx contains an invalid index: " << FileName.DirIdx
604  << "\n";
605  }
606 
607  // Check file paths for duplicates.
608  std::string FullPath;
609  const bool HasFullPath = LineTable->getFileNameByIndex(
610  FileIndex, CU->getCompilationDir(),
612  assert(HasFullPath && "Invalid index?");
613  (void)HasFullPath;
614  auto It = FullPathMap.find(FullPath);
615  if (It == FullPathMap.end())
616  FullPathMap[FullPath] = FileIndex;
617  else if (It->second != FileIndex) {
618  warn() << ".debug_line["
619  << format("0x%08" PRIx64,
620  *toSectionOffset(Die.find(DW_AT_stmt_list)))
621  << "].prologue.file_names[" << FileIndex
622  << "] is a duplicate of file_names[" << It->second << "]\n";
623  }
624 
625  FileIndex++;
626  }
627 
628  // Verify rows.
629  uint64_t PrevAddress = 0;
630  uint32_t RowIndex = 0;
631  for (const auto &Row : LineTable->Rows) {
632  // Verify row address.
633  if (Row.Address < PrevAddress) {
634  ++NumDebugLineErrors;
635  error() << ".debug_line["
636  << format("0x%08" PRIx64,
637  *toSectionOffset(Die.find(DW_AT_stmt_list)))
638  << "] row[" << RowIndex
639  << "] decreases in address from previous row:\n";
640 
642  if (RowIndex > 0)
643  LineTable->Rows[RowIndex - 1].dump(OS);
644  Row.dump(OS);
645  OS << '\n';
646  }
647 
648  // Verify file index.
649  if (Row.File > MaxFileIndex) {
650  ++NumDebugLineErrors;
651  error() << ".debug_line["
652  << format("0x%08" PRIx64,
653  *toSectionOffset(Die.find(DW_AT_stmt_list)))
654  << "][" << RowIndex << "] has invalid file index " << Row.File
655  << " (valid values are [1," << MaxFileIndex << "]):\n";
657  Row.dump(OS);
658  OS << '\n';
659  }
660  if (Row.EndSequence)
661  PrevAddress = 0;
662  else
663  PrevAddress = Row.Address;
664  ++RowIndex;
665  }
666  }
667 }
668 
670  NumDebugLineErrors = 0;
671  OS << "Verifying .debug_line...\n";
672  verifyDebugLineStmtOffsets();
673  verifyDebugLineRows();
674  return NumDebugLineErrors == 0;
675 }
676 
677 unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
678  DataExtractor *StrData,
679  const char *SectionName) {
680  unsigned NumErrors = 0;
681  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), *AccelSection,
682  DCtx.isLittleEndian(), 0);
683  AppleAcceleratorTable AccelTable(AccelSectionData, *StrData);
684 
685  OS << "Verifying " << SectionName << "...\n";
686 
687  // Verify that the fixed part of the header is not too short.
688  if (!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())) {
689  error() << "Section is too small to fit a section header.\n";
690  return 1;
691  }
692 
693  // Verify that the section is not too short.
694  if (Error E = AccelTable.extract()) {
695  error() << toString(std::move(E)) << '\n';
696  return 1;
697  }
698 
699  // Verify that all buckets have a valid hash index or are empty.
700  uint32_t NumBuckets = AccelTable.getNumBuckets();
701  uint32_t NumHashes = AccelTable.getNumHashes();
702 
703  uint32_t BucketsOffset =
704  AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
705  uint32_t HashesBase = BucketsOffset + NumBuckets * 4;
706  uint32_t OffsetsBase = HashesBase + NumHashes * 4;
707  for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
708  uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
709  if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
710  error() << format("Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
711  HashIdx);
712  ++NumErrors;
713  }
714  }
715  uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
716  if (NumAtoms == 0) {
717  error() << "No atoms: failed to read HashData.\n";
718  return 1;
719  }
720  if (!AccelTable.validateForms()) {
721  error() << "Unsupported form: failed to read HashData.\n";
722  return 1;
723  }
724 
725  for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
726  uint32_t HashOffset = HashesBase + 4 * HashIdx;
727  uint32_t DataOffset = OffsetsBase + 4 * HashIdx;
728  uint32_t Hash = AccelSectionData.getU32(&HashOffset);
729  uint32_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
730  if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
731  sizeof(uint64_t))) {
732  error() << format("Hash[%d] has invalid HashData offset: 0x%08x.\n",
733  HashIdx, HashDataOffset);
734  ++NumErrors;
735  }
736 
737  uint32_t StrpOffset;
738  uint32_t StringOffset;
739  uint32_t StringCount = 0;
740  unsigned Offset;
741  unsigned Tag;
742  while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
743  const uint32_t NumHashDataObjects =
744  AccelSectionData.getU32(&HashDataOffset);
745  for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
746  ++HashDataIdx) {
747  std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset);
748  auto Die = DCtx.getDIEForOffset(Offset);
749  if (!Die) {
750  const uint32_t BucketIdx =
751  NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
752  StringOffset = StrpOffset;
753  const char *Name = StrData->getCStr(&StringOffset);
754  if (!Name)
755  Name = "<NULL>";
756 
757  error() << format(
758  "%s Bucket[%d] Hash[%d] = 0x%08x "
759  "Str[%u] = 0x%08x "
760  "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
761  SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
762  HashDataIdx, Offset, Name);
763 
764  ++NumErrors;
765  continue;
766  }
767  if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
768  error() << "Tag " << dwarf::TagString(Tag)
769  << " in accelerator table does not match Tag "
770  << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
771  << "].\n";
772  ++NumErrors;
773  }
774  }
775  ++StringCount;
776  }
777  }
778  return NumErrors;
779 }
780 
782  const DWARFObject &D = DCtx.getDWARFObj();
783  DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
784  unsigned NumErrors = 0;
785  if (!D.getAppleNamesSection().Data.empty())
786  NumErrors +=
787  verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData, ".apple_names");
788  if (!D.getAppleTypesSection().Data.empty())
789  NumErrors +=
790  verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData, ".apple_types");
792  NumErrors += verifyAppleAccelTable(&D.getAppleNamespacesSection(), &StrData,
793  ".apple_namespaces");
794  if (!D.getAppleObjCSection().Data.empty())
795  NumErrors +=
796  verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData, ".apple_objc");
797  return NumErrors == 0;
798 }
799 
800 raw_ostream &DWARFVerifier::error() const {
801  return WithColor(OS, syntax::Error).get() << "error: ";
802 }
803 
804 raw_ostream &DWARFVerifier::warn() const {
805  return WithColor(OS, syntax::Warning).get() << "warning: ";
806 }
807 
808 raw_ostream &DWARFVerifier::note() const {
809  return WithColor(OS, syntax::Note).get() << "note: ";
810 }
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag)
Definition: DWARFUnit.h:341
DWARFUnit * getDwarfUnit() const
Definition: DWARFDie.h:54
bool isValid() const
Definition: DWARFDie.h:51
dwarf::Attribute Attr
The attribute enumeration of this attribute.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
virtual StringRef getAbbrevSection() const
Definition: DWARFObject.h:39
bool isUnitType(uint8_t UnitType)
Definition: Dwarf.h:335
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:197
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
bool handleDebugLine()
Verify the information in the .debug_line section.
iterator find(StringRef Key)
Definition: StringMap.h:335
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
#define error(X)
A debug info location.
Definition: DebugLoc.h:34
This class represents an Operation in the Expression.
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
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:447
virtual StringRef getAbbrevDWOSection() const
Definition: DWARFObject.h:58
virtual const DWARFSection & getAppleTypesSection() const
Definition: DWARFObject.h:68
bool handleDebugInfo()
Verify the information in the .debug_info section.
dwarf::Form getForm() const
DWARFFormValue Value
The form and value for this attribute.
uint32_t getNextUnitOffset() const
Definition: DWARFUnit.h:311
Optional< uint64_t > getAsReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
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:81
uint64_t getRawUValue() const
Optional< ArrayRef< uint8_t > > getAsBlock() const
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:105
uint32_t getOffset() const
Get the absolute offset into the debug info or types section.
Definition: DWARFDie.h:67
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:321
std::set< DieRangeInfo > Children
Sorted DWARFAddressRangeInfo.
Definition: DWARFVerifier.h:43
unsigned getNumDIEs()
Returns the number of DIEs in the unit.
Definition: DWARFUnit.h:410
std::vector< DWARFAddressRange > Ranges
Sorted DWARFAddressRanges.
Definition: DWARFVerifier.h:40
Encapsulates a DWARF attribute value and all of the data required to describe the attribute value...
StringRef AttributeString(unsigned Attribute)
Definition: Dwarf.cpp:72
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
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:910
uint16_t getVersion() const
Definition: DWARFUnit.h:319
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:73
Utility class that carries the DWARF compile/type unit and the debug info entry in an object...
Definition: DWARFDie.h:43
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
virtual const DWARFSection & getStringOffsetSection() const
Definition: DWARFObject.h:54
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool handleDebugAbbrev()
Verify the information in any of the following sections, if available: .debug_abbrev, debug_abbrev.dwo.
A class that keeps the address range information for a single DIE.
Definition: DWARFVerifier.h:36
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:821
bool contains(const DieRangeInfo &RHS) const
Return true if ranges in this object contains all ranges within RHS.
static const unsigned End
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
Optional< uint64_t > getAsUnsignedConstant() const
virtual StringRef getStringSection() const
Definition: DWARFObject.h:46
std::vector< DWARFAddressRange >::const_iterator address_range_iterator
Definition: DWARFVerifier.h:53
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition: StringExtras.h:43
#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:321
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:382
Concrete instance of DWARFUnitSection, specialized for one Unit type.
Definition: DWARFUnit.h:71
address_range_iterator insert(const DWARFAddressRange &R)
Inserts the address range.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static void dumpTableHeader(raw_ostream &OS)
Optional< const char * > toString(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
Implements a dense probed hash-table based set with some number of buckets stored inline...
Definition: DenseSet.h:239
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:222
StringRef UnitTypeString(unsigned)
Definition: Dwarf.cpp:469
virtual const DWARFSection & getAppleNamespacesSection() const
Definition: DWARFObject.h:69
#define Success
virtual const DWARFSection & getInfoSection() const
Definition: DWARFObject.h:36
virtual const DWARFSection & getLineSection() const
Definition: DWARFObject.h:44
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
static bool isSupportedVersion(unsigned version)
Definition: DWARFContext.h:291
DWARFDie getDIEAtIndex(unsigned Index)
Return the DIE object at the given index.
Definition: DWARFUnit.h:426
dwarf::Tag getTag() const
Definition: DWARFDie.h:72
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:67
const char * getCStr(uint32_t *offset_ptr) const
Extract a C string from *offset_ptr.
std::set< DieRangeInfo >::const_iterator die_range_info_iterator
Definition: DWARFVerifier.h:54
bool isValidOffset(uint32_t offset) const
Test the validity of offset.
virtual const DWARFSection & getRangeSection() const
Definition: DWARFObject.h:47
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:282
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, const char *ErrorMsg)
Optional< uint64_t > getAsSectionOffset() const
const uint64_t Version
Definition: InstrProf.h:867
iterator end()
Definition: StringMap.h:320
DWARFAddressRangesVector getAddressRanges() const
Get the address ranges for this DIE.
Definition: DWARFDie.cpp:364