42
42
#include " llvm/Support/raw_ostream.h"
43
43
#include < algorithm>
44
44
#include < cstdint>
45
+ #include < map>
46
+ #include < set>
45
47
#include < string>
46
48
#include < utility>
47
49
#include < vector>
@@ -284,11 +286,30 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
284
286
getStringSection (), isLittleEndian ());
285
287
}
286
288
287
- bool DWARFContext::verify (raw_ostream &OS, DIDumpType DumpType) {
288
- bool Success = true ;
289
- if (DumpType == DIDT_All || DumpType == DIDT_Info) {
289
+ DWARFDie DWARFContext::getDIEForOffset (uint32_t Offset) {
290
+ parseCompileUnits ();
291
+ if (auto *CU = CUs.getUnitForOffset (Offset))
292
+ return CU->getDIEForOffset (Offset);
293
+ return DWARFDie ();
294
+ }
295
+
296
+ namespace {
297
+
298
+ class Verifier {
299
+ raw_ostream &OS;
300
+ DWARFContext &DCtx;
301
+ public:
302
+ Verifier (raw_ostream &S, DWARFContext &D) : OS(S), DCtx(D) {}
303
+
304
+ bool HandleDebugInfo () {
305
+ bool Success = true ;
306
+ // A map that tracks all references (converted absolute references) so we
307
+ // can verify each reference points to a valid DIE and not an offset that
308
+ // lies between to valid DIEs.
309
+ std::map<uint64_t , std::set<uint32_t >> ReferenceToDIEOffsets;
310
+
290
311
OS << " Verifying .debug_info...\n " ;
291
- for (const auto &CU : compile_units ()) {
312
+ for (const auto &CU : DCtx. compile_units ()) {
292
313
unsigned NumDies = CU->getNumDIEs ();
293
314
for (unsigned I = 0 ; I < NumDies; ++I) {
294
315
auto Die = CU->getDIEAtIndex (I);
@@ -299,101 +320,141 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
299
320
const auto Attr = AttrValue.Attr ;
300
321
const auto Form = AttrValue.Value .getForm ();
301
322
switch (Attr) {
302
- case DW_AT_ranges:
303
- // Make sure the offset in the DW_AT_ranges attribute is valid.
304
- if (auto SectionOffset = AttrValue.Value .getAsSectionOffset ()) {
305
- if (*SectionOffset >= getRangeSection ().Data .size ()) {
323
+ case DW_AT_ranges:
324
+ // Make sure the offset in the DW_AT_ranges attribute is valid.
325
+ if (auto SectionOffset = AttrValue.Value .getAsSectionOffset ()) {
326
+ if (*SectionOffset >= DCtx.getRangeSection ().Data .size ()) {
327
+ Success = false ;
328
+ OS << " error: DW_AT_ranges offset is beyond .debug_ranges "
329
+ " bounds:\n " ;
330
+ Die.dump (OS, 0 );
331
+ OS << " \n " ;
332
+ }
333
+ } else {
306
334
Success = false ;
307
- OS << " error: DW_AT_ranges offset is beyond .debug_ranges "
308
- " bounds:\n " ;
335
+ OS << " error: DIE has invalid DW_AT_ranges encoding:\n " ;
309
336
Die.dump (OS, 0 );
310
337
OS << " \n " ;
311
338
}
312
- } else {
313
- Success = false ;
314
- OS << " error: DIE has invalid DW_AT_ranges encoding:\n " ;
315
- Die.dump (OS, 0 );
316
- OS << " \n " ;
317
- }
318
- break ;
319
- case DW_AT_stmt_list:
320
- // Make sure the offset in the DW_AT_stmt_list attribute is valid.
321
- if (auto SectionOffset = AttrValue.Value .getAsSectionOffset ()) {
322
- if (*SectionOffset >= getLineSection ().Data .size ()) {
339
+ break ;
340
+ case DW_AT_stmt_list:
341
+ // Make sure the offset in the DW_AT_stmt_list attribute is valid.
342
+ if (auto SectionOffset = AttrValue.Value .getAsSectionOffset ()) {
343
+ if (*SectionOffset >= DCtx.getLineSection ().Data .size ()) {
344
+ Success = false ;
345
+ OS << " error: DW_AT_stmt_list offset is beyond .debug_line "
346
+ " bounds: "
347
+ << format (" 0x%08" PRIx32, *SectionOffset) << " \n " ;
348
+ CU->getUnitDIE ().dump (OS, 0 );
349
+ OS << " \n " ;
350
+ }
351
+ } else {
323
352
Success = false ;
324
- OS << " error: DW_AT_stmt_list offset is beyond .debug_line "
325
- " bounds: "
326
- << format (" 0x%08" PRIx32, *SectionOffset) << " \n " ;
327
- CU->getUnitDIE ().dump (OS, 0 );
353
+ OS << " error: DIE has invalid DW_AT_stmt_list encoding:\n " ;
354
+ Die.dump (OS, 0 );
328
355
OS << " \n " ;
329
356
}
330
- } else {
331
- Success = false ;
332
- OS << " error: DIE has invalid DW_AT_stmt_list encoding:\n " ;
333
- Die.dump (OS, 0 );
334
- OS << " \n " ;
335
- }
336
- break ;
337
-
338
- default :
339
- break ;
357
+ break ;
358
+
359
+ default :
360
+ break ;
340
361
}
341
362
switch (Form) {
342
- case DW_FORM_ref1:
343
- case DW_FORM_ref2:
344
- case DW_FORM_ref4:
345
- case DW_FORM_ref8:
346
- case DW_FORM_ref_udata: {
347
- // Verify all CU relative references are valid CU offsets.
348
- Optional<uint64_t > RefVal = AttrValue.Value .getAsReference ();
349
- assert (RefVal);
350
- if (RefVal) {
351
- auto DieCU = Die.getDwarfUnit ();
352
- auto CUSize = DieCU->getNextUnitOffset () - DieCU->getOffset ();
353
- auto CUOffset = AttrValue.Value .getRawUValue ();
354
- if (CUOffset >= CUSize) {
363
+ case DW_FORM_ref1:
364
+ case DW_FORM_ref2:
365
+ case DW_FORM_ref4:
366
+ case DW_FORM_ref8:
367
+ case DW_FORM_ref_udata: {
368
+ // Verify all CU relative references are valid CU offsets.
369
+ Optional<uint64_t > RefVal = AttrValue.Value .getAsReference ();
370
+ assert (RefVal);
371
+ if (RefVal) {
372
+ auto DieCU = Die.getDwarfUnit ();
373
+ auto CUSize = DieCU->getNextUnitOffset () - DieCU->getOffset ();
374
+ auto CUOffset = AttrValue.Value .getRawUValue ();
375
+ if (CUOffset >= CUSize) {
376
+ Success = false ;
377
+ OS << " error: " << FormEncodingString (Form) << " CU offset "
378
+ << format (" 0x%08" PRIx32, CUOffset)
379
+ << " is invalid (must be less than CU size of "
380
+ << format (" 0x%08" PRIx32, CUSize) << " ):\n " ;
381
+ Die.dump (OS, 0 );
382
+ OS << " \n " ;
383
+ } else {
384
+ // Valid reference, but we will verify it points to an actual
385
+ // DIE later.
386
+ ReferenceToDIEOffsets[*RefVal].insert (Die.getOffset ());
387
+ }
388
+ }
389
+ break ;
390
+ }
391
+ case DW_FORM_ref_addr: {
392
+ // Verify all absolute DIE references have valid offsets in the
393
+ // .debug_info section.
394
+ Optional<uint64_t > RefVal = AttrValue.Value .getAsReference ();
395
+ assert (RefVal);
396
+ if (RefVal) {
397
+ if (*RefVal >= DCtx.getInfoSection ().Data .size ()) {
398
+ Success = false ;
399
+ OS << " error: DW_FORM_ref_addr offset beyond .debug_info "
400
+ " bounds:\n " ;
401
+ Die.dump (OS, 0 );
402
+ OS << " \n " ;
403
+ } else {
404
+ // Valid reference, but we will verify it points to an actual
405
+ // DIE later.
406
+ ReferenceToDIEOffsets[*RefVal].insert (Die.getOffset ());
407
+ }
408
+ }
409
+ break ;
410
+ }
411
+ case DW_FORM_strp: {
412
+ auto SecOffset = AttrValue.Value .getAsSectionOffset ();
413
+ assert (SecOffset); // DW_FORM_strp is a section offset.
414
+ if (SecOffset && *SecOffset >= DCtx.getStringSection ().size ()) {
355
415
Success = false ;
356
- OS << " error: " << FormEncodingString (Form) << " CU offset "
357
- << format (" 0x%08" PRIx32, CUOffset)
358
- << " is invalid (must be less than CU size of "
359
- << format (" 0x%08" PRIx32, CUSize) << " ):\n " ;
416
+ OS << " error: DW_FORM_strp offset beyond .debug_str bounds:\n " ;
360
417
Die.dump (OS, 0 );
361
418
OS << " \n " ;
362
419
}
420
+ break ;
363
421
}
364
- break ;
365
- }
366
- case DW_FORM_ref_addr: {
367
- // Verify all absolute DIE references have valid offsets in the
368
- // .debug_info section.
369
- Optional<uint64_t > RefVal = AttrValue.Value .getAsReference ();
370
- assert (RefVal);
371
- if (RefVal && *RefVal >= getInfoSection ().Data .size ()) {
372
- Success = false ;
373
- OS << " error: DW_FORM_ref_addr offset beyond .debug_info "
374
- " bounds:\n " ;
375
- Die.dump (OS, 0 );
376
- OS << " \n " ;
377
- }
378
- break ;
379
- }
380
- case DW_FORM_strp: {
381
- auto SecOffset = AttrValue.Value .getAsSectionOffset ();
382
- assert (SecOffset); // DW_FORM_strp is a section offset.
383
- if (SecOffset && *SecOffset >= getStringSection ().size ()) {
384
- Success = false ;
385
- OS << " error: DW_FORM_strp offset beyond .debug_str bounds:\n " ;
386
- Die.dump (OS, 0 );
387
- OS << " \n " ;
388
- }
389
- break ;
390
- }
391
- default :
392
- break ;
422
+ default :
423
+ break ;
393
424
}
394
425
}
395
426
}
396
427
}
428
+
429
+ // Take all references and make sure they point to an actual DIE by
430
+ // getting the DIE by offset and emitting an error
431
+ OS << " Verifying .debug_info references...\n " ;
432
+ for (auto Pair: ReferenceToDIEOffsets) {
433
+ auto Die = DCtx.getDIEForOffset (Pair.first );
434
+ if (Die)
435
+ continue ;
436
+ Success = false ;
437
+ OS << " error: invalid DIE reference " << format (" 0x%08" PRIx64, Pair.first )
438
+ << " . Offset is in between DIEs:\n " ;
439
+ for (auto Offset: Pair.second ) {
440
+ auto ReferencingDie = DCtx.getDIEForOffset (Offset);
441
+ ReferencingDie.dump (OS, 0 );
442
+ OS << " \n " ;
443
+ }
444
+ OS << " \n " ;
445
+ }
446
+ return Success;
447
+ }
448
+ };
449
+
450
+ } // anonymous namespace
451
+
452
+ bool DWARFContext::verify (raw_ostream &OS, DIDumpType DumpType) {
453
+ bool Success = true ;
454
+ Verifier verifier (OS, *this );
455
+ if (DumpType == DIDT_All || DumpType == DIDT_Info) {
456
+ if (!verifier.HandleDebugInfo ())
457
+ Success = false ;
397
458
}
398
459
return Success;
399
460
}
0 commit comments