Coverage Report

Created: 2019-07-24 05:18

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