@@ -380,3 +380,288 @@ void DWARFCallFrameInfoTest::TestValOffset(DWARFCallFrameInfo::Type type,
380380TEST_F (DWARFCallFrameInfoTest, ValOffset_dwarf3) {
381381 TestValOffset (DWARFCallFrameInfo::DWARF, " debug_frame3" );
382382}
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