Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Line
Count
Source (jump to first uncovered line)
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 "llvm/DebugInfo/DWARF/DWARFVerifier.h"
11
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
12
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
13
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
14
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
15
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
17
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
18
#include "llvm/Support/raw_ostream.h"
19
#include <map>
20
#include <set>
21
#include <vector>
22
23
using namespace llvm;
24
using namespace dwarf;
25
using namespace object;
26
27
DWARFVerifier::DieRangeInfo::address_range_iterator
28
40
DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
29
40
  auto Begin = Ranges.begin();
30
40
  auto End = Ranges.end();
31
40
  auto Pos = std::lower_bound(Begin, End, R);
32
40
33
40
  if (
Pos != End40
) {
34
0
    if (Pos->intersects(R))
35
0
      return Pos;
36
0
    
if (0
Pos != Begin0
) {
37
0
      auto Iter = Pos - 1;
38
0
      if (Iter->intersects(R))
39
0
        return Iter;
40
40
    }
41
0
  }
42
40
43
40
  Ranges.insert(Pos, R);
44
40
  return Ranges.end();
45
40
}
46
47
DWARFVerifier::DieRangeInfo::die_range_info_iterator
48
158
DWARFVerifier::DieRangeInfo::insert(const DieRangeInfo &RI) {
49
158
  auto End = Children.end();
50
158
  auto Iter = Children.begin();
51
1.01k
  while (
Iter != End1.01k
) {
52
860
    if (Iter->intersects(RI))
53
2
      return Iter;
54
858
    ++Iter;
55
858
  }
56
156
  Children.insert(RI);
57
156
  return Children.end();
58
158
}
59
60
44
bool DWARFVerifier::DieRangeInfo::contains(const DieRangeInfo &RHS) const {
61
44
  // Both list of ranges are sorted so we can make this fast.
62
44
63
44
  if (
Ranges.empty() || 44
RHS.Ranges.empty()44
)
64
0
    return false;
65
44
66
44
  // Since the ranges are sorted we can advance where we start searching with
67
44
  // this object's ranges as we traverse RHS.Ranges.
68
44
  auto End = Ranges.end();
69
44
  auto Iter = findRange(RHS.Ranges.front());
70
44
71
44
  // Now linearly walk the ranges in this object and see if they contain each
72
44
  // ranges from RHS.Ranges.
73
54
  for (const auto &R : RHS.Ranges) {
74
68
    while (
Iter != End68
) {
75
61
      if (Iter->contains(R))
76
47
        break;
77
14
      ++Iter;
78
14
    }
79
54
    if (Iter == End)
80
7
      return false;
81
37
  }
82
37
  return true;
83
37
}
84
85
892
bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const {
86
892
  if (
Ranges.empty() || 892
RHS.Ranges.empty()329
)
87
649
    return false;
88
243
89
243
  auto End = Ranges.end();
90
243
  auto Iter = findRange(RHS.Ranges.front());
91
254
  for (const auto &R : RHS.Ranges) {
92
254
    if(Iter == End)
93
1
      return false;
94
253
    
if (253
R.HighPC <= Iter->LowPC253
)
95
13
      continue;
96
466
    
while (240
Iter != End466
) {
97
246
      if (Iter->intersects(R))
98
20
        return true;
99
226
      ++Iter;
100
226
    }
101
254
  }
102
243
103
222
  return false;
104
892
}
105
106
bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
107
                                     uint32_t *Offset, unsigned UnitIndex,
108
32
                                     uint8_t &UnitType, bool &isUnitDWARF64) {
109
32
  uint32_t AbbrOffset, Length;
110
32
  uint8_t AddrSize = 0;
111
32
  uint16_t Version;
112
32
  bool Success = true;
113
32
114
32
  bool ValidLength = false;
115
32
  bool ValidVersion = false;
116
32
  bool ValidAddrSize = false;
117
32
  bool ValidType = true;
118
32
  bool ValidAbbrevOffset = true;
119
32
120
32
  uint32_t OffsetStart = *Offset;
121
32
  Length = DebugInfoData.getU32(Offset);
122
32
  if (
Length == UINT32_MAX32
) {
123
0
    isUnitDWARF64 = true;
124
0
    OS << format(
125
0
        "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
126
0
        UnitIndex);
127
0
    return false;
128
0
  }
129
32
  Version = DebugInfoData.getU16(Offset);
130
32
131
32
  if (
Version >= 532
) {
132
8
    UnitType = DebugInfoData.getU8(Offset);
133
8
    AddrSize = DebugInfoData.getU8(Offset);
134
8
    AbbrOffset = DebugInfoData.getU32(Offset);
135
8
    ValidType = DWARFUnit::isValidUnitType(UnitType);
136
32
  } else {
137
24
    UnitType = 0;
138
24
    AbbrOffset = DebugInfoData.getU32(Offset);
139
24
    AddrSize = DebugInfoData.getU8(Offset);
140
24
  }
141
32
142
32
  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
143
1
    ValidAbbrevOffset = false;
144
32
145
32
  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
146
32
  ValidVersion = DWARFContext::isSupportedVersion(Version);
147
24
  ValidAddrSize = AddrSize == 4 || AddrSize == 8;
148
32
  if (
!ValidLength || 32
!ValidVersion30
||
!ValidAddrSize29
||
!ValidAbbrevOffset28
||
149
32
      
!ValidType28
) {
150
4
    Success = false;
151
4
    OS << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, OffsetStart);
152
4
    if (!ValidLength)
153
2
      OS << "\tError: The length for this unit is too "
154
2
            "large for the .debug_info provided.\n";
155
4
    if (!ValidVersion)
156
1
      OS << "\tError: The 16 bit unit header version is not valid.\n";
157
4
    if (!ValidType)
158
2
      OS << "\tError: The unit type encoding is not valid.\n";
159
4
    if (!ValidAbbrevOffset)
160
1
      OS << "\tError: The offset into the .debug_abbrev section is "
161
1
            "not valid.\n";
162
4
    if (!ValidAddrSize)
163
1
      OS << "\tError: The address size is unsupported.\n";
164
4
  }
165
32
  *Offset = OffsetStart + Length + 4;
166
32
  return Success;
167
32
}
168
169
28
bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit) {
170
28
  uint32_t NumUnitErrors = 0;
171
28
  unsigned NumDies = Unit.getNumDIEs();
172
229
  for (unsigned I = 0; 
I < NumDies229
;
++I201
) {
173
201
    auto Die = Unit.getDIEAtIndex(I);
174
201
    if (Die.getTag() == DW_TAG_null)
175
45
      continue;
176
156
    
for (auto AttrValue : Die.attributes()) 156
{
177
685
      NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
178
685
      NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
179
685
    }
180
201
  }
181
28
182
28
  if (DWARFDie 
Die28
= Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false)) {
183
27
    DieRangeInfo RI;
184
27
    NumUnitErrors += verifyDieRanges(Die, RI);
185
28
  } else {
186
1
    OS << "error: Compilation unit without unit DIE.\n";
187
1
    NumUnitErrors++;
188
1
  }
189
28
190
28
  return NumUnitErrors == 0;
191
28
}
192
193
26
unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
194
26
  unsigned NumErrors = 0;
195
26
  if (
Abbrev26
) {
196
26
    const DWARFAbbreviationDeclarationSet *AbbrDecls =
197
26
        Abbrev->getAbbreviationDeclarationSet(0);
198
57
    for (auto AbbrDecl : *AbbrDecls) {
199
57
      SmallDenseSet<uint16_t> AttributeSet;
200
183
      for (auto Attribute : AbbrDecl.attributes()) {
201
183
        auto Result = AttributeSet.insert(Attribute.Attr);
202
183
        if (
!Result.second183
) {
203
2
          OS << "Error: Abbreviation declaration contains multiple "
204
2
             << AttributeString(Attribute.Attr) << " attributes.\n";
205
2
          AbbrDecl.dump(OS);
206
2
          ++NumErrors;
207
2
        }
208
183
      }
209
57
    }
210
26
  }
211
26
  return NumErrors;
212
26
}
213
214
29
bool DWARFVerifier::handleDebugAbbrev() {
215
29
  OS << "Verifying .debug_abbrev...\n";
216
29
217
29
  const DWARFObject &DObj = DCtx.getDWARFObj();
218
29
  bool noDebugAbbrev = DObj.getAbbrevSection().empty();
219
29
  bool noDebugAbbrevDWO = DObj.getAbbrevDWOSection().empty();
220
29
221
29
  if (
noDebugAbbrev && 29
noDebugAbbrevDWO4
) {
222
4
    return true;
223
4
  }
224
25
225
25
  unsigned NumErrors = 0;
226
25
  if (!noDebugAbbrev)
227
25
    NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
228
25
229
25
  if (!noDebugAbbrevDWO)
230
1
    NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
231
29
  return NumErrors == 0;
232
29
}
233
234
29
bool DWARFVerifier::handleDebugInfo() {
235
29
  OS << "Verifying .debug_info Unit Header Chain...\n";
236
29
237
29
  const DWARFObject &DObj = DCtx.getDWARFObj();
238
29
  DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(),
239
29
                                   DCtx.isLittleEndian(), 0);
240
29
  uint32_t NumDebugInfoErrors = 0;
241
29
  uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
242
29
  uint8_t UnitType = 0;
243
29
  bool isUnitDWARF64 = false;
244
29
  bool isHeaderChainValid = true;
245
29
  bool hasDIE = DebugInfoData.isValidOffset(Offset);
246
61
  while (
hasDIE61
) {
247
32
    OffsetStart = Offset;
248
32
    if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
249
32
                          isUnitDWARF64)) {
250
4
      isHeaderChainValid = false;
251
4
      if (isUnitDWARF64)
252
0
        break;
253
28
    } else {
254
28
      std::unique_ptr<DWARFUnit> Unit;
255
28
      switch (UnitType) {
256
0
      case dwarf::DW_UT_type:
257
0
      case dwarf::DW_UT_split_type: {
258
0
        DWARFUnitSection<DWARFTypeUnit> TUSection{};
259
0
        Unit.reset(new DWARFTypeUnit(
260
0
            DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
261
0
            &DObj.getRangeSection(), DObj.getStringSection(),
262
0
            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
263
0
            DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
264
0
            nullptr));
265
0
        break;
266
0
      }
267
28
      case dwarf::DW_UT_skeleton:
268
28
      case dwarf::DW_UT_split_compile:
269
28
      case dwarf::DW_UT_compile:
270
28
      case dwarf::DW_UT_partial:
271
28
      // UnitType = 0 means that we are
272
28
      // verifying a compile unit in DWARF v4.
273
28
      case 0: {
274
28
        DWARFUnitSection<DWARFCompileUnit> CUSection{};
275
28
        Unit.reset(new DWARFCompileUnit(
276
28
            DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
277
28
            &DObj.getRangeSection(), DObj.getStringSection(),
278
28
            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
279
28
            DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
280
28
            nullptr));
281
28
        break;
282
28
      }
283
0
      
default: { 0
llvm_unreachable0
("Invalid UnitType."); }
284
28
      }
285
28
      Unit->extract(DebugInfoData, &OffsetStart);
286
28
      if (!verifyUnitContents(*Unit))
287
13
        ++NumDebugInfoErrors;
288
28
    }
289
32
    hasDIE = DebugInfoData.isValidOffset(Offset);
290
32
    ++UnitIdx;
291
32
  }
292
29
  
if (29
UnitIdx == 0 && 29
!hasDIE5
) {
293
5
    OS << "Warning: .debug_info is empty.\n";
294
5
    isHeaderChainValid = true;
295
5
  }
296
29
  NumDebugInfoErrors += verifyDebugInfoReferences();
297
27
  return (isHeaderChainValid && NumDebugInfoErrors == 0);
298
29
}
299
300
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
301
158
                                        DieRangeInfo &ParentRI) {
302
158
  unsigned NumErrors = 0;
303
158
304
158
  if (!Die.isValid())
305
0
    return NumErrors;
306
158
307
158
  DWARFAddressRangesVector Ranges = Die.getAddressRanges();
308
158
309
158
  // Build RI for this DIE and check that ranges within this DIE do not
310
158
  // overlap.
311
158
  DieRangeInfo RI(Die);
312
42
  for (auto Range : Ranges) {
313
42
    if (
!Range.valid()42
) {
314
2
      ++NumErrors;
315
2
      OS << format("error: Invalid address range [0x%08" PRIx64
316
2
                   " - 0x%08" PRIx64 "].\n",
317
2
                   Range.LowPC, Range.HighPC);
318
2
      continue;
319
2
    }
320
40
321
40
    // Verify that ranges don't intersect.
322
40
    const auto IntersectingRange = RI.insert(Range);
323
40
    if (
IntersectingRange != RI.Ranges.end()40
) {
324
0
      ++NumErrors;
325
0
      OS << format("error: DIE has overlapping address ranges: [0x%08" PRIx64
326
0
                   " - 0x%08" PRIx64 "] and [0x%08" PRIx64 " - 0x%08" PRIx64
327
0
                   "].\n",
328
0
                   Range.LowPC, Range.HighPC, IntersectingRange->LowPC,
329
0
                   IntersectingRange->HighPC);
330
0
      break;
331
0
    }
332
158
  }
333
158
334
158
  // Verify that children don't intersect.
335
158
  const auto IntersectingChild = ParentRI.insert(RI);
336
158
  if (
IntersectingChild != ParentRI.Children.end()158
) {
337
2
    ++NumErrors;
338
2
    OS << "error: DIEs have overlapping address ranges:";
339
2
    Die.dump(OS, 0);
340
2
    IntersectingChild->Die.dump(OS, 0);
341
2
    OS << "\n";
342
2
  }
343
158
344
158
  // Verify that ranges are contained within their parent.
345
42
  bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
346
31
                           !(Die.getTag() == DW_TAG_subprogram &&
347
31
                             ParentRI.Die.getTag() == DW_TAG_subprogram);
348
158
  if (
ShouldBeContained && 158
!ParentRI.contains(RI)30
) {
349
2
    ++NumErrors;
350
2
    OS << "error: DIE address ranges are not "
351
2
          "contained in its parent's ranges:";
352
2
    Die.dump(OS, 0);
353
2
    ParentRI.Die.dump(OS, 0);
354
2
    OS << "\n";
355
2
  }
356
158
357
158
  // Recursively check children.
358
158
  for (DWARFDie Child : Die)
359
131
    NumErrors += verifyDieRanges(Child, RI);
360
158
361
158
  return NumErrors;
362
158
}
363
364
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
365
685
                                                 DWARFAttribute &AttrValue) {
366
685
  const DWARFObject &DObj = DCtx.getDWARFObj();
367
685
  unsigned NumErrors = 0;
368
685
  const auto Attr = AttrValue.Attr;
369
685
  switch (Attr) {
370
1
  case DW_AT_ranges:
371
1
    // Make sure the offset in the DW_AT_ranges attribute is valid.
372
1
    if (auto 
SectionOffset1
= AttrValue.Value.getAsSectionOffset()) {
373
1
      if (
*SectionOffset >= DObj.getRangeSection().Data.size()1
) {
374
1
        ++NumErrors;
375
1
        OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
376
1
              "bounds:\n";
377
1
        Die.dump(OS, 0, DumpOpts);
378
1
        OS << "\n";
379
1
      }
380
0
    } else {
381
0
      ++NumErrors;
382
0
      OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
383
0
      Die.dump(OS, 0, DumpOpts);
384
0
      OS << "\n";
385
0
    }
386
1
    break;
387
11
  case DW_AT_stmt_list:
388
11
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
389
11
    if (auto 
SectionOffset11
= AttrValue.Value.getAsSectionOffset()) {
390
10
      if (
*SectionOffset >= DObj.getLineSection().Data.size()10
) {
391
1
        ++NumErrors;
392
1
        OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
393
1
              "bounds: "
394
1
           << format("0x%08" PRIx64, *SectionOffset) << "\n";
395
1
        Die.dump(OS, 0, DumpOpts);
396
1
        OS << "\n";
397
1
      }
398
11
    } else {
399
1
      ++NumErrors;
400
1
      OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
401
1
      Die.dump(OS, 0, DumpOpts);
402
1
      OS << "\n";
403
1
    }
404
11
    break;
405
685
406
673
  default:
407
673
    break;
408
685
  }
409
685
  return NumErrors;
410
685
}
411
412
unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
413
685
                                            DWARFAttribute &AttrValue) {
414
685
  const DWARFObject &DObj = DCtx.getDWARFObj();
415
685
  unsigned NumErrors = 0;
416
685
  const auto Form = AttrValue.Value.getForm();
417
685
  switch (Form) {
418
119
  case DW_FORM_ref1:
419
119
  case DW_FORM_ref2:
420
119
  case DW_FORM_ref4:
421
119
  case DW_FORM_ref8:
422
119
  case DW_FORM_ref_udata: {
423
119
    // Verify all CU relative references are valid CU offsets.
424
119
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
425
119
    assert(RefVal);
426
119
    if (
RefVal119
) {
427
119
      auto DieCU = Die.getDwarfUnit();
428
119
      auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
429
119
      auto CUOffset = AttrValue.Value.getRawUValue();
430
119
      if (
CUOffset >= CUSize119
) {
431
1
        ++NumErrors;
432
1
        OS << "error: " << FormEncodingString(Form) << " CU offset "
433
1
           << format("0x%08" PRIx64, CUOffset)
434
1
           << " is invalid (must be less than CU size of "
435
1
           << format("0x%08" PRIx32, CUSize) << "):\n";
436
1
        Die.dump(OS, 0, DumpOpts);
437
1
        OS << "\n";
438
119
      } else {
439
118
        // Valid reference, but we will verify it points to an actual
440
118
        // DIE later.
441
118
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
442
118
      }
443
119
    }
444
119
    break;
445
119
  }
446
2
  case DW_FORM_ref_addr: {
447
2
    // Verify all absolute DIE references have valid offsets in the
448
2
    // .debug_info section.
449
2
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
450
2
    assert(RefVal);
451
2
    if (
RefVal2
) {
452
2
      if (
*RefVal >= DObj.getInfoSection().Data.size()2
) {
453
1
        ++NumErrors;
454
1
        OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
455
1
              "bounds:\n";
456
1
        Die.dump(OS, 0, DumpOpts);
457
1
        OS << "\n";
458
2
      } else {
459
1
        // Valid reference, but we will verify it points to an actual
460
1
        // DIE later.
461
1
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
462
1
      }
463
2
    }
464
2
    break;
465
119
  }
466
153
  case DW_FORM_strp: {
467
153
    auto SecOffset = AttrValue.Value.getAsSectionOffset();
468
153
    assert(SecOffset); // DW_FORM_strp is a section offset.
469
153
    if (
SecOffset && 153
*SecOffset >= DObj.getStringSection().size()153
) {
470
1
      ++NumErrors;
471
1
      OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
472
1
      Die.dump(OS, 0, DumpOpts);
473
1
      OS << "\n";
474
1
    }
475
153
    break;
476
119
  }
477
411
  default:
478
411
    break;
479
685
  }
480
685
  return NumErrors;
481
685
}
482
483
29
unsigned DWARFVerifier::verifyDebugInfoReferences() {
484
29
  // Take all references and make sure they point to an actual DIE by
485
29
  // getting the DIE by offset and emitting an error
486
29
  OS << "Verifying .debug_info references...\n";
487
29
  unsigned NumErrors = 0;
488
37
  for (auto Pair : ReferenceToDIEOffsets) {
489
37
    auto Die = DCtx.getDIEForOffset(Pair.first);
490
37
    if (Die)
491
36
      continue;
492
1
    ++NumErrors;
493
1
    OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
494
1
       << ". Offset is in between DIEs:\n";
495
1
    for (auto Offset : Pair.second) {
496
1
      auto ReferencingDie = DCtx.getDIEForOffset(Offset);
497
1
      ReferencingDie.dump(OS, 0, DumpOpts);
498
1
      OS << "\n";
499
1
    }
500
37
    OS << "\n";
501
37
  }
502
29
  return NumErrors;
503
29
}
504
505
19
void DWARFVerifier::verifyDebugLineStmtOffsets() {
506
19
  std::map<uint64_t, DWARFDie> StmtListToDie;
507
21
  for (const auto &CU : DCtx.compile_units()) {
508
21
    auto Die = CU->getUnitDIE();
509
21
    // Get the attribute value as a section offset. No need to produce an
510
21
    // error here if the encoding isn't correct because we validate this in
511
21
    // the .debug_info verifier.
512
21
    auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
513
21
    if (!StmtSectionOffset)
514
14
      continue;
515
7
    const uint32_t LineTableOffset = *StmtSectionOffset;
516
7
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
517
7
    if (
LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()7
) {
518
6
      if (
!LineTable6
) {
519
0
        ++NumDebugLineErrors;
520
0
        OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
521
0
           << "] was not able to be parsed for CU:\n";
522
0
        Die.dump(OS, 0, DumpOpts);
523
0
        OS << '\n';
524
0
        continue;
525
0
      }
526
1
    } else {
527
1
      // Make sure we don't get a valid line table back if the offset is wrong.
528
1
      assert(LineTable == nullptr);
529
1
      // Skip this line table as it isn't valid. No need to create an error
530
1
      // here because we validate this in the .debug_info verifier.
531
1
      continue;
532
1
    }
533
6
    auto Iter = StmtListToDie.find(LineTableOffset);
534
6
    if (
Iter != StmtListToDie.end()6
) {
535
1
      ++NumDebugLineErrors;
536
1
      OS << "error: two compile unit DIEs, "
537
1
         << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
538
1
         << format("0x%08" PRIx32, Die.getOffset())
539
1
         << ", have the same DW_AT_stmt_list section offset:\n";
540
1
      Iter->second.dump(OS, 0, DumpOpts);
541
1
      Die.dump(OS, 0, DumpOpts);
542
1
      OS << '\n';
543
1
      // Already verified this line table before, no need to do it again.
544
1
      continue;
545
1
    }
546
5
    StmtListToDie[LineTableOffset] = Die;
547
5
  }
548
19
}
549
550
19
void DWARFVerifier::verifyDebugLineRows() {
551
21
  for (const auto &CU : DCtx.compile_units()) {
552
21
    auto Die = CU->getUnitDIE();
553
21
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
554
21
    // If there is no line table we will have created an error in the
555
21
    // .debug_info verifier or in verifyDebugLineStmtOffsets().
556
21
    if (!LineTable)
557
15
      continue;
558
6
559
6
    // Verify prologue.
560
6
    uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
561
6
    uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
562
6
    uint32_t FileIndex = 1;
563
6
    StringMap<uint16_t> FullPathMap;
564
7
    for (const auto &FileName : LineTable->Prologue.FileNames) {
565
7
      // Verify directory index.
566
7
      if (
FileName.DirIdx > MaxDirIndex7
) {
567
1
        ++NumDebugLineErrors;
568
1
        OS << "error: .debug_line["
569
1
           << format("0x%08" PRIx64,
570
1
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
571
1
           << "].prologue.file_names[" << FileIndex
572
1
           << "].dir_idx contains an invalid index: " << FileName.DirIdx
573
1
           << "\n";
574
1
      }
575
7
576
7
      // Check file paths for duplicates.
577
7
      std::string FullPath;
578
7
      const bool HasFullPath = LineTable->getFileNameByIndex(
579
7
          FileIndex, CU->getCompilationDir(),
580
7
          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
581
7
      assert(HasFullPath && "Invalid index?");
582
7
      (void)HasFullPath;
583
7
      auto It = FullPathMap.find(FullPath);
584
7
      if (It == FullPathMap.end())
585
6
        FullPathMap[FullPath] = FileIndex;
586
1
      else 
if (1
It->second != FileIndex1
) {
587
1
        OS << "warning: .debug_line["
588
1
           << format("0x%08" PRIx64,
589
1
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
590
1
           << "].prologue.file_names[" << FileIndex
591
1
           << "] is a duplicate of file_names[" << It->second << "]\n";
592
1
      }
593
7
594
7
      FileIndex++;
595
7
    }
596
6
597
6
    // Verify rows.
598
6
    uint64_t PrevAddress = 0;
599
6
    uint32_t RowIndex = 0;
600
12
    for (const auto &Row : LineTable->Rows) {
601
12
      // Verify row address.
602
12
      if (
Row.Address < PrevAddress12
) {
603
1
        ++NumDebugLineErrors;
604
1
        OS << "error: .debug_line["
605
1
           << format("0x%08" PRIx64,
606
1
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
607
1
           << "] row[" << RowIndex
608
1
           << "] decreases in address from previous row:\n";
609
1
610
1
        DWARFDebugLine::Row::dumpTableHeader(OS);
611
1
        if (RowIndex > 0)
612
1
          LineTable->Rows[RowIndex - 1].dump(OS);
613
1
        Row.dump(OS);
614
1
        OS << '\n';
615
1
      }
616
12
617
12
      // Verify file index.
618
12
      if (
Row.File > MaxFileIndex12
) {
619
1
        ++NumDebugLineErrors;
620
1
        OS << "error: .debug_line["
621
1
           << format("0x%08" PRIx64,
622
1
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
623
1
           << "][" << RowIndex << "] has invalid file index " << Row.File
624
1
           << " (valid values are [1," << MaxFileIndex << "]):\n";
625
1
        DWARFDebugLine::Row::dumpTableHeader(OS);
626
1
        Row.dump(OS);
627
1
        OS << '\n';
628
1
      }
629
12
      if (Row.EndSequence)
630
6
        PrevAddress = 0;
631
12
      else
632
6
        PrevAddress = Row.Address;
633
12
      ++RowIndex;
634
12
    }
635
21
  }
636
19
}
637
638
19
bool DWARFVerifier::handleDebugLine() {
639
19
  NumDebugLineErrors = 0;
640
19
  OS << "Verifying .debug_line...\n";
641
19
  verifyDebugLineStmtOffsets();
642
19
  verifyDebugLineRows();
643
19
  return NumDebugLineErrors == 0;
644
19
}
645
646
unsigned DWARFVerifier::verifyAccelTable(const DWARFSection *AccelSection,
647
                                         DataExtractor *StrData,
648
8
                                         const char *SectionName) {
649
8
  unsigned NumErrors = 0;
650
8
  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), *AccelSection,
651
8
                                      DCtx.isLittleEndian(), 0);
652
8
  DWARFAcceleratorTable AccelTable(AccelSectionData, *StrData);
653
8
654
8
  OS << "Verifying " << SectionName << "...\n";
655
8
  // Verify that the fixed part of the header is not too short.
656
8
657
8
  if (
!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())8
) {
658
0
    OS << "\terror: Section is too small to fit a section header.\n";
659
0
    return 1;
660
0
  }
661
8
  // Verify that the section is not too short.
662
8
  
if (8
!AccelTable.extract()8
) {
663
1
    OS << "\terror: Section is smaller than size described in section header.\n";
664
1
    return 1;
665
1
  }
666
7
  // Verify that all buckets have a valid hash index or are empty.
667
7
  uint32_t NumBuckets = AccelTable.getNumBuckets();
668
7
  uint32_t NumHashes = AccelTable.getNumHashes();
669
7
670
7
  uint32_t BucketsOffset =
671
7
      AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
672
7
  uint32_t HashesBase = BucketsOffset + NumBuckets * 4;
673
7
  uint32_t OffsetsBase = HashesBase + NumHashes * 4;
674
42
  for (uint32_t BucketIdx = 0; 
BucketIdx < NumBuckets42
;
++BucketIdx35
) {
675
35
    uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
676
35
    if (
HashIdx >= NumHashes && 35
HashIdx != UINT32_MAX6
) {
677
1
      OS << format("\terror: Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
678
1
                   HashIdx);
679
1
      ++NumErrors;
680
1
    }
681
35
  }
682
7
  uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
683
7
  if (
NumAtoms == 07
) {
684
1
    OS << "\terror: no atoms; failed to read HashData.\n";
685
1
    return 1;
686
1
  }
687
6
  
if (6
!AccelTable.validateForms()6
) {
688
1
    OS << "\terror: unsupported form; failed to read HashData.\n";
689
1
    return 1;
690
1
  }
691
5
692
57
  
for (uint32_t HashIdx = 0; 5
HashIdx < NumHashes57
;
++HashIdx52
) {
693
52
    uint32_t HashOffset = HashesBase + 4 * HashIdx;
694
52
    uint32_t DataOffset = OffsetsBase + 4 * HashIdx;
695
52
    uint32_t Hash = AccelSectionData.getU32(&HashOffset);
696
52
    uint32_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
697
52
    if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
698
52
                                                     sizeof(uint64_t))) {
699
1
      OS << format("\terror: Hash[%d] has invalid HashData offset: 0x%08x.\n",
700
1
                   HashIdx, HashDataOffset);
701
1
      ++NumErrors;
702
1
    }
703
52
704
52
    uint32_t StrpOffset;
705
52
    uint32_t StringOffset;
706
52
    uint32_t StringCount = 0;
707
52
    unsigned Offset;
708
52
    unsigned Tag;
709
104
    while (
(StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0104
) {
710
52
      const uint32_t NumHashDataObjects =
711
52
          AccelSectionData.getU32(&HashDataOffset);
712
123
      for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
713
71
           
++HashDataIdx71
) {
714
71
        std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset);
715
71
        auto Die = DCtx.getDIEForOffset(Offset);
716
71
        if (
!Die71
) {
717
1
          const uint32_t BucketIdx =
718
1
              NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
719
1
          StringOffset = StrpOffset;
720
1
          const char *Name = StrData->getCStr(&StringOffset);
721
1
          if (!Name)
722
0
            Name = "<NULL>";
723
1
724
1
          OS << format(
725
1
              "\terror: %s Bucket[%d] Hash[%d] = 0x%08x "
726
1
              "Str[%u] = 0x%08x "
727
1
              "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
728
1
              SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
729
1
              HashDataIdx, Offset, Name);
730
1
731
1
          ++NumErrors;
732
1
          continue;
733
1
        }
734
70
        
if (70
(Tag != dwarf::DW_TAG_null) && 70
(Die.getTag() != Tag)7
) {
735
1
          OS << "\terror: Tag " << dwarf::TagString(Tag)
736
1
             << " in accelerator table does not match Tag "
737
1
             << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
738
1
             << "].\n";
739
1
          ++NumErrors;
740
1
        }
741
71
      }
742
52
      ++StringCount;
743
52
    }
744
52
  }
745
8
  return NumErrors;
746
8
}
747
748
29
bool DWARFVerifier::handleAccelTables() {
749
29
  const DWARFObject &D = DCtx.getDWARFObj();
750
29
  DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
751
29
  unsigned NumErrors = 0;
752
29
  if (!D.getAppleNamesSection().Data.empty())
753
4
    NumErrors +=
754
4
        verifyAccelTable(&D.getAppleNamesSection(), &StrData, ".apple_names");
755
29
  if (!D.getAppleTypesSection().Data.empty())
756
2
    NumErrors +=
757
2
        verifyAccelTable(&D.getAppleTypesSection(), &StrData, ".apple_types");
758
29
  if (!D.getAppleNamespacesSection().Data.empty())
759
1
    NumErrors += verifyAccelTable(&D.getAppleNamespacesSection(), &StrData,
760
1
                                  ".apple_namespaces");
761
29
  if (!D.getAppleObjCSection().Data.empty())
762
1
    NumErrors +=
763
1
        verifyAccelTable(&D.getAppleObjCSection(), &StrData, ".apple_objc");
764
29
  return NumErrors == 0;
765
29
}