Skip to content

Commit c2efe01

Browse files
committed
[LLDB] Add tests for handling invalid FDE entries and valid CIE markers
This commit introduces new unit tests to verify the handling of invalid Frame Description Entries (FDEs) with invalid CIE ID values for both DWARF32 and DWARF64 formats. Additionally, it includes tests for valid CIE markers in both eh_frame and debug_frame formats, ensuring that the unwind plans are correctly generated or returned as null when encountering invalid entries.
1 parent 59c230c commit c2efe01

File tree

1 file changed

+285
-0
lines changed

1 file changed

+285
-0
lines changed

lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,288 @@ void DWARFCallFrameInfoTest::TestValOffset(DWARFCallFrameInfo::Type type,
380380
TEST_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

Comments
 (0)