@@ -380,3 +380,288 @@ void DWARFCallFrameInfoTest::TestValOffset(DWARFCallFrameInfo::Type type,
380
380
TEST_F (DWARFCallFrameInfoTest, ValOffset_dwarf3) {
381
381
TestValOffset (DWARFCallFrameInfo::DWARF, " debug_frame3" );
382
382
}
383
+
384
+ // Test that we correctly handle invalid FDE entries that have CIE ID values
385
+ TEST_F (DWARFCallFrameInfoTest, InvalidFDEWithCIEID_dwarf32) {
386
+ // Create an FDE with cie_offset of 0xFFFFFFFF (DW_CIE_ID) which is invalid
387
+ auto ExpectedFile = TestFile::fromYaml (R"(
388
+ --- !ELF
389
+ FileHeader:
390
+ Class: ELFCLASS64
391
+ Data: ELFDATA2LSB
392
+ Type: ET_REL
393
+ Machine: EM_X86_64
394
+ Sections:
395
+ - Name: .text
396
+ Type: SHT_PROGBITS
397
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
398
+ Address: 0x0000000000000260
399
+ AddressAlign: 0x0000000000000010
400
+ Content: 554889E5897DFC8B45FC5DC3
401
+ - Name: .debug_frame
402
+ Type: SHT_PROGBITS
403
+ AddressAlign: 0x0000000000000008
404
+ # First, a valid CIE
405
+ # 00000000 0000000000000014 ffffffff CIE
406
+ # Version: 3
407
+ # Augmentation: ""
408
+ # Code alignment factor: 1
409
+ # Data alignment factor: -8
410
+ # Return address column: 16
411
+ Content: 14000000FFFFFFFF03000178100C0708900100000000000018000000FFFFFFFF60020000000000000C00000000000000
412
+ # Then an invalid FDE with CIE pointer = 0xFFFFFFFF (which would make it look like a CIE)
413
+ # 00000018 0000000000000018 ffffffff FDE cie=ffffffff pc=0000000000000260..000000000000026c
414
+ # The cie offset of 0xFFFFFFFF is invalid for an FDE in debug_frame
415
+ Symbols:
416
+ - Name: test_invalid
417
+ Type: STT_FUNC
418
+ Section: .text
419
+ Value: 0x0000000000000260
420
+ Size: 0x000000000000000C
421
+ Binding: STB_GLOBAL
422
+ ...
423
+ )" );
424
+ ASSERT_THAT_EXPECTED (ExpectedFile, llvm::Succeeded ());
425
+
426
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec ());
427
+ SectionList *list = module_sp->GetSectionList ();
428
+ ASSERT_NE (nullptr , list);
429
+
430
+ auto section_sp = list->FindSectionByType (eSectionTypeDWARFDebugFrame, false );
431
+ ASSERT_NE (nullptr , section_sp);
432
+
433
+ DWARFCallFrameInfo cfi (*module_sp->GetObjectFile (), section_sp,
434
+ DWARFCallFrameInfo::DWARF);
435
+
436
+ // This should trigger our assertion or return nullptr because the FDE is
437
+ // invalid
438
+ const Symbol *sym = module_sp->FindFirstSymbolWithNameAndType (
439
+ ConstString (" test_invalid" ), eSymbolTypeAny);
440
+ ASSERT_NE (nullptr , sym);
441
+
442
+ std::unique_ptr<UnwindPlan> plan_up = cfi.GetUnwindPlan (sym->GetAddress ());
443
+ // The plan should be null because we have an invalid FDE
444
+ EXPECT_EQ (nullptr , plan_up);
445
+ }
446
+
447
+ // Test that we correctly handle invalid FDE entries that have CIE ID values
448
+ TEST_F (DWARFCallFrameInfoTest, InvalidFDEWithCIEID_dwarf64) {
449
+ // Create an FDE with cie_offset of 0xFFFFFFFFFFFFFFFF (DW64_CIE_ID) which is
450
+ // invalid
451
+ auto ExpectedFile = TestFile::fromYaml (R"(
452
+ --- !ELF
453
+ FileHeader:
454
+ Class: ELFCLASS64
455
+ Data: ELFDATA2LSB
456
+ Type: ET_REL
457
+ Machine: EM_X86_64
458
+ Sections:
459
+ - Name: .text
460
+ Type: SHT_PROGBITS
461
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
462
+ Address: 0x0000000000000260
463
+ AddressAlign: 0x0000000000000010
464
+ Content: 554889E5897DFC8B45FC5DC3
465
+ - Name: .debug_frame
466
+ Type: SHT_PROGBITS
467
+ AddressAlign: 0x0000000000000008
468
+ # DWARF64 format CIE
469
+ # Initial length: 0xFFFFFFFF followed by 64-bit length
470
+ # 00000000 ffffffff 0000000000000014 ffffffffffffffff CIE
471
+ Content: FFFFFFFF1400000000000000FFFFFFFFFFFFFFFF03000178100C0708900100000000FFFFFFFF1800000000000000FFFFFFFFFFFFFFFF60020000000000000C00000000000000
472
+ # DWARF64 FDE with invalid CIE pointer = 0xFFFFFFFFFFFFFFFF
473
+ # Initial length: 0xFFFFFFFF, followed by 64-bit length (0x18)
474
+ # Then 64-bit CIE pointer: 0xFFFFFFFFFFFFFFFF (which is DW64_CIE_ID, invalid for FDE)
475
+ Symbols:
476
+ - Name: test_invalid64
477
+ Type: STT_FUNC
478
+ Section: .text
479
+ Value: 0x0000000000000260
480
+ Size: 0x000000000000000C
481
+ Binding: STB_GLOBAL
482
+ ...
483
+ )" );
484
+ ASSERT_THAT_EXPECTED (ExpectedFile, llvm::Succeeded ());
485
+
486
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec ());
487
+ SectionList *list = module_sp->GetSectionList ();
488
+ ASSERT_NE (nullptr , list);
489
+
490
+ auto section_sp = list->FindSectionByType (eSectionTypeDWARFDebugFrame, false );
491
+ ASSERT_NE (nullptr , section_sp);
492
+
493
+ DWARFCallFrameInfo cfi (*module_sp->GetObjectFile (), section_sp,
494
+ DWARFCallFrameInfo::DWARF);
495
+
496
+ const Symbol *sym = module_sp->FindFirstSymbolWithNameAndType (
497
+ ConstString (" test_invalid64" ), eSymbolTypeAny);
498
+ ASSERT_NE (nullptr , sym);
499
+
500
+ std::unique_ptr<UnwindPlan> plan_up = cfi.GetUnwindPlan (sym->GetAddress ());
501
+ // The plan should be null because we have an invalid FDE
502
+ EXPECT_EQ (nullptr , plan_up);
503
+ }
504
+
505
+ // Test valid CIE markers in eh_frame format
506
+ TEST_F (DWARFCallFrameInfoTest, ValidCIEMarkers_eh_frame) {
507
+ auto ExpectedFile = TestFile::fromYaml (R"(
508
+ --- !ELF
509
+ FileHeader:
510
+ Class: ELFCLASS64
511
+ Data: ELFDATA2LSB
512
+ Type: ET_DYN
513
+ Machine: EM_X86_64
514
+ Entry: 0x0000000000000260
515
+ Sections:
516
+ - Name: .text
517
+ Type: SHT_PROGBITS
518
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
519
+ Address: 0x0000000000000260
520
+ AddressAlign: 0x0000000000000010
521
+ Content: 554889E5897DFC8B45FC5DC3
522
+ - Name: .eh_frame
523
+ Type: SHT_X86_64_UNWIND
524
+ Flags: [ SHF_ALLOC ]
525
+ Address: 0x0000000000000290
526
+ AddressAlign: 0x0000000000000008
527
+ # eh_frame content
528
+ # CIE + FDE that works with address 0x260
529
+ Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C000000B0FFFFFF0C00000000410E108602430D0600000000000000
530
+ Symbols:
531
+ - Name: simple_function
532
+ Type: STT_FUNC
533
+ Section: .text
534
+ Value: 0x0000000000000260
535
+ Size: 0x000000000000000F
536
+ Binding: STB_GLOBAL
537
+ ...
538
+ )" );
539
+ ASSERT_THAT_EXPECTED (ExpectedFile, llvm::Succeeded ());
540
+
541
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec ());
542
+ SectionList *list = module_sp->GetSectionList ();
543
+ ASSERT_NE (nullptr , list);
544
+
545
+ auto section_sp = list->FindSectionByType (eSectionTypeEHFrame, false );
546
+ ASSERT_NE (nullptr , section_sp);
547
+
548
+ DWARFCallFrameInfo cfi (*module_sp->GetObjectFile (), section_sp,
549
+ DWARFCallFrameInfo::EH);
550
+
551
+ const Symbol *sym = module_sp->FindFirstSymbolWithNameAndType (
552
+ ConstString (" simple_function" ), eSymbolTypeAny);
553
+ ASSERT_NE (nullptr , sym);
554
+
555
+ std::unique_ptr<UnwindPlan> plan_up = cfi.GetUnwindPlan (sym->GetAddress ());
556
+ // Should succeed with valid CIE and FDE
557
+ ASSERT_NE (nullptr , plan_up);
558
+ EXPECT_GE (plan_up->GetRowCount (), 1 );
559
+ }
560
+
561
+ // Test valid CIE markers in debug_frame DWARF32 format
562
+ TEST_F (DWARFCallFrameInfoTest, ValidCIEMarkers_dwarf32) {
563
+ auto ExpectedFile = TestFile::fromYaml (R"(
564
+ --- !ELF
565
+ FileHeader:
566
+ Class: ELFCLASS64
567
+ Data: ELFDATA2LSB
568
+ Type: ET_REL
569
+ Machine: EM_X86_64
570
+ Sections:
571
+ - Name: .text
572
+ Type: SHT_PROGBITS
573
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
574
+ Address: 0x0000000000001130
575
+ AddressAlign: 0x0000000000000010
576
+ Content: 554889E5897DFC8B45FC83C0015DC3
577
+ - Name: .debug_frame
578
+ Type: SHT_PROGBITS
579
+ AddressAlign: 0x0000000000000008
580
+ # debug_frame content in DWARF32 format
581
+ # CIE (length=0x14, CIE_id=0xFFFFFFFF, version=4)
582
+ # FDE (length=0x24, CIE_offset=0)
583
+ Content: 14000000FFFFFFFF040008000178100C0708900100000000240000000000000030110000000000000F00000000000000410E108602430D064A0C070800000000
584
+ Symbols:
585
+ - Name: simple_function
586
+ Type: STT_FUNC
587
+ Section: .text
588
+ Value: 0x0000000000001130
589
+ Size: 0x000000000000000F
590
+ Binding: STB_GLOBAL
591
+ ...
592
+ )" );
593
+ ASSERT_THAT_EXPECTED (ExpectedFile, llvm::Succeeded ());
594
+
595
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec ());
596
+ SectionList *list = module_sp->GetSectionList ();
597
+ ASSERT_NE (nullptr , list);
598
+
599
+ auto section_sp = list->FindSectionByType (eSectionTypeDWARFDebugFrame, false );
600
+ ASSERT_NE (nullptr , section_sp);
601
+
602
+ DWARFCallFrameInfo cfi (*module_sp->GetObjectFile (), section_sp,
603
+ DWARFCallFrameInfo::DWARF);
604
+
605
+ const Symbol *sym = module_sp->FindFirstSymbolWithNameAndType (
606
+ ConstString (" simple_function" ), eSymbolTypeAny);
607
+ ASSERT_NE (nullptr , sym);
608
+
609
+ std::unique_ptr<UnwindPlan> plan_up = cfi.GetUnwindPlan (sym->GetAddress ());
610
+ // Should succeed with valid CIE and FDE
611
+ ASSERT_NE (nullptr , plan_up);
612
+ EXPECT_GE (plan_up->GetRowCount (), 1 );
613
+ }
614
+
615
+ // Test valid CIE markers in debug_frame DWARF64 format
616
+ TEST_F (DWARFCallFrameInfoTest, ValidCIEMarkers_dwarf64) {
617
+ auto ExpectedFile = TestFile::fromYaml (R"(
618
+ --- !ELF
619
+ FileHeader:
620
+ Class: ELFCLASS64
621
+ Data: ELFDATA2LSB
622
+ Type: ET_REL
623
+ Machine: EM_X86_64
624
+ Sections:
625
+ - Name: .text
626
+ Type: SHT_PROGBITS
627
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
628
+ Address: 0x0000000000001130
629
+ AddressAlign: 0x0000000000000010
630
+ Content: 554889E5897DFC8B45FC83C0015DC3
631
+ - Name: .debug_frame
632
+ Type: SHT_PROGBITS
633
+ AddressAlign: 0x0000000000000008
634
+ # debug_frame content in DWARF64 format
635
+ # CIE: length_marker=0xFFFFFFFF, length=0x14, CIE_id=0xFFFFFFFFFFFFFFFF, version=4
636
+ # FDE: length_marker=0xFFFFFFFF, length=0x24, CIE_offset=0x0 (points to CIE)
637
+ Content: FFFFFFFF1400000000000000FFFFFFFFFFFFFFFF040008000178100C07089001FFFFFFFF2400000000000000000000000000000030110000000000000F00000000000000410E108602430D064A0C0708
638
+ Symbols:
639
+ - Name: simple_function
640
+ Type: STT_FUNC
641
+ Section: .text
642
+ Value: 0x0000000000001130
643
+ Size: 0x000000000000000F
644
+ Binding: STB_GLOBAL
645
+ ...
646
+ )" );
647
+ ASSERT_THAT_EXPECTED (ExpectedFile, llvm::Succeeded ());
648
+
649
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec ());
650
+ SectionList *list = module_sp->GetSectionList ();
651
+ ASSERT_NE (nullptr , list);
652
+
653
+ auto section_sp = list->FindSectionByType (eSectionTypeDWARFDebugFrame, false );
654
+ ASSERT_NE (nullptr , section_sp);
655
+
656
+ DWARFCallFrameInfo cfi (*module_sp->GetObjectFile (), section_sp,
657
+ DWARFCallFrameInfo::DWARF);
658
+
659
+ const Symbol *sym = module_sp->FindFirstSymbolWithNameAndType (
660
+ ConstString (" simple_function" ), eSymbolTypeAny);
661
+ ASSERT_NE (nullptr , sym);
662
+
663
+ std::unique_ptr<UnwindPlan> plan_up = cfi.GetUnwindPlan (sym->GetAddress ());
664
+ // Should succeed with valid CIE and FDE
665
+ ASSERT_NE (nullptr , plan_up);
666
+ EXPECT_GE (plan_up->GetRowCount (), 1 );
667
+ }
0 commit comments