@@ -168,9 +168,32 @@ bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange &range,
168
168
module_sp->GetObjectFile () != &m_objfile)
169
169
return false ;
170
170
171
- if (std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange (range))
172
- return FDEToUnwindPlan (entry->data , addr, unwind_plan);
173
- return false ;
171
+ std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange (range);
172
+ if (!entry)
173
+ return false ;
174
+
175
+ std::optional<FDE> fde = ParseFDE (entry->data , addr);
176
+ if (!fde)
177
+ return false ;
178
+
179
+ unwind_plan.SetSourceName (m_type == EH ? " eh_frame CFI" : " DWARF CFI" );
180
+ // In theory the debug_frame info should be valid at all call sites
181
+ // ("asynchronous unwind info" as it is sometimes called) but in practice
182
+ // gcc et al all emit call frame info for the prologue and call sites, but
183
+ // not for the epilogue or all the other locations during the function
184
+ // reliably.
185
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
186
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
187
+ unwind_plan.SetRegisterKind (GetRegisterKind ());
188
+
189
+ unwind_plan.SetPlanValidAddressRanges ({fde->range });
190
+ unwind_plan.SetUnwindPlanForSignalTrap (fde->for_signal_trap ? eLazyBoolYes
191
+ : eLazyBoolNo);
192
+ unwind_plan.SetReturnAddressRegister (fde->return_addr_reg_num );
193
+ for (UnwindPlan::Row &row : fde->rows )
194
+ unwind_plan.AppendRow (std::move (row));
195
+
196
+ return true ;
174
197
}
175
198
176
199
bool DWARFCallFrameInfo::GetAddressRange (Address addr, AddressRange &range) {
@@ -522,15 +545,15 @@ void DWARFCallFrameInfo::GetFDEIndex() {
522
545
m_fde_index_initialized = true ;
523
546
}
524
547
525
- bool DWARFCallFrameInfo::FDEToUnwindPlan ( dw_offset_t dwarf_offset,
526
- Address startaddr ,
527
- UnwindPlan &unwind_plan ) {
548
+ std::optional< DWARFCallFrameInfo::FDE>
549
+ DWARFCallFrameInfo::ParseFDE ( dw_offset_t dwarf_offset ,
550
+ const Address &startaddr ) {
528
551
Log *log = GetLog (LLDBLog::Unwind);
529
552
lldb::offset_t offset = dwarf_offset;
530
553
lldb::offset_t current_entry = offset;
531
554
532
- if (m_section_sp. get () == nullptr || m_section_sp->IsEncrypted ())
533
- return false ;
555
+ if (! m_section_sp || m_section_sp->IsEncrypted ())
556
+ return std::nullopt ;
534
557
535
558
if (!m_cfi_data_initialized)
536
559
GetCFIData ();
@@ -550,20 +573,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
550
573
551
574
// Translate the CIE_id from the eh_frame format, which is relative to the
552
575
// FDE offset, into a __eh_frame section offset
553
- if (m_type == EH) {
554
- unwind_plan.SetSourceName (" eh_frame CFI" );
576
+ if (m_type == EH)
555
577
cie_offset = current_entry + (is_64bit ? 12 : 4 ) - cie_offset;
556
- unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
557
- } else {
558
- unwind_plan.SetSourceName (" DWARF CFI" );
559
- // In theory the debug_frame info should be valid at all call sites
560
- // ("asynchronous unwind info" as it is sometimes called) but in practice
561
- // gcc et al all emit call frame info for the prologue and call sites, but
562
- // not for the epilogue or all the other locations during the function
563
- // reliably.
564
- unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
565
- }
566
- unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
567
578
568
579
const CIE *cie = GetCIE (cie_offset);
569
580
assert (cie != nullptr );
@@ -587,18 +598,15 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
587
598
if (cie->augmentation [0 ] == ' z' )
588
599
offset += (uint32_t )m_cfi_data.GetULEB128 (&offset);
589
600
590
- unwind_plan.SetUnwindPlanForSignalTrap (
591
- strchr (cie->augmentation , ' S' ) ? eLazyBoolYes : eLazyBoolNo);
601
+ FDE fde;
602
+ fde.for_signal_trap = strchr (cie->augmentation , ' S' ) != nullptr ;
603
+ fde.range = range;
604
+ fde.return_addr_reg_num = cie->return_addr_reg_num ;
592
605
593
606
uint32_t code_align = cie->code_align ;
594
607
int32_t data_align = cie->data_align ;
595
608
596
- unwind_plan.SetPlanValidAddressRanges ({range});
597
609
UnwindPlan::Row row = cie->initial_row ;
598
-
599
- unwind_plan.SetRegisterKind (GetRegisterKind ());
600
- unwind_plan.SetReturnAddressRegister (cie->return_addr_reg_num );
601
-
602
610
std::vector<UnwindPlan::Row> stack;
603
611
604
612
UnwindPlan::Row::AbstractRegisterLocation reg_location;
@@ -618,7 +626,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
618
626
// that is computed by taking the current entry's location value and
619
627
// adding (delta * code_align). All other values in the new row are
620
628
// initially identical to the current row.
621
- unwind_plan. AppendRow (row);
629
+ fde. rows . push_back (row);
622
630
row.SlideOffset (extended_opcode * code_align);
623
631
break ;
624
632
}
@@ -634,9 +642,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
634
642
// state, so we need to convert our eh_frame register number from the
635
643
// EH frame info, to a register index
636
644
637
- if (unwind_plan.IsValidRowIndex (0 ) &&
638
- unwind_plan.GetRowAtIndex (0 )->GetRegisterInfo (reg_num,
639
- reg_location))
645
+ if (fde.rows [0 ].GetRegisterInfo (reg_num, reg_location))
640
646
row.SetRegisterInfo (reg_num, reg_location);
641
647
else {
642
648
// If the register was not set in the first row, remove the
@@ -655,7 +661,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
655
661
// specified address as the location. All other values in the new row
656
662
// are initially identical to the current row. The new location value
657
663
// should always be greater than the current one.
658
- unwind_plan. AppendRow (row);
664
+ fde. rows . push_back (row);
659
665
row.SetOffset (m_cfi_data.GetAddress (&offset) -
660
666
startaddr.GetFileAddress ());
661
667
break ;
@@ -666,7 +672,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
666
672
// takes a single uword argument that represents a constant delta.
667
673
// This instruction is identical to DW_CFA_advance_loc except for the
668
674
// encoding and size of the delta argument.
669
- unwind_plan. AppendRow (row);
675
+ fde. rows . push_back (row);
670
676
row.SlideOffset (m_cfi_data.GetU8 (&offset) * code_align);
671
677
break ;
672
678
}
@@ -676,7 +682,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
676
682
// takes a single uword argument that represents a constant delta.
677
683
// This instruction is identical to DW_CFA_advance_loc except for the
678
684
// encoding and size of the delta argument.
679
- unwind_plan. AppendRow (row);
685
+ fde. rows . push_back (row);
680
686
row.SlideOffset (m_cfi_data.GetU16 (&offset) * code_align);
681
687
break ;
682
688
}
@@ -686,7 +692,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
686
692
// takes a single uword argument that represents a constant delta.
687
693
// This instruction is identical to DW_CFA_advance_loc except for the
688
694
// encoding and size of the delta argument.
689
- unwind_plan. AppendRow (row);
695
+ fde. rows . push_back (row);
690
696
row.SlideOffset (m_cfi_data.GetU32 (&offset) * code_align);
691
697
break ;
692
698
}
@@ -697,9 +703,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
697
703
// number. This instruction is identical to DW_CFA_restore except for
698
704
// the encoding and size of the register argument.
699
705
uint32_t reg_num = (uint32_t )m_cfi_data.GetULEB128 (&offset);
700
- if (unwind_plan.IsValidRowIndex (0 ) &&
701
- unwind_plan.GetRowAtIndex (0 )->GetRegisterInfo (reg_num,
702
- reg_location))
706
+ if (fde.rows [0 ].GetRegisterInfo (reg_num, reg_location))
703
707
row.SetRegisterInfo (reg_num, reg_location);
704
708
break ;
705
709
}
@@ -762,9 +766,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
762
766
}
763
767
}
764
768
}
765
- unwind_plan.AppendRow (row);
766
-
767
- return true ;
769
+ fde.rows .push_back (row);
770
+ return fde;
768
771
}
769
772
770
773
bool DWARFCallFrameInfo::HandleCommonDwarfOpcode (uint8_t primary_opcode,
0 commit comments