@@ -168,9 +168,32 @@ bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange &range,
168168 module_sp->GetObjectFile () != &m_objfile)
169169 return false ;
170170
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 ;
174197}
175198
176199bool DWARFCallFrameInfo::GetAddressRange (Address addr, AddressRange &range) {
@@ -522,15 +545,15 @@ void DWARFCallFrameInfo::GetFDEIndex() {
522545 m_fde_index_initialized = true ;
523546}
524547
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 ) {
528551 Log *log = GetLog (LLDBLog::Unwind);
529552 lldb::offset_t offset = dwarf_offset;
530553 lldb::offset_t current_entry = offset;
531554
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 ;
534557
535558 if (!m_cfi_data_initialized)
536559 GetCFIData ();
@@ -550,20 +573,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
550573
551574 // Translate the CIE_id from the eh_frame format, which is relative to the
552575 // 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)
555577 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);
567578
568579 const CIE *cie = GetCIE (cie_offset);
569580 assert (cie != nullptr );
@@ -587,18 +598,15 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
587598 if (cie->augmentation [0 ] == ' z' )
588599 offset += (uint32_t )m_cfi_data.GetULEB128 (&offset);
589600
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 ;
592605
593606 uint32_t code_align = cie->code_align ;
594607 int32_t data_align = cie->data_align ;
595608
596- unwind_plan.SetPlanValidAddressRanges ({range});
597609 UnwindPlan::Row row = cie->initial_row ;
598-
599- unwind_plan.SetRegisterKind (GetRegisterKind ());
600- unwind_plan.SetReturnAddressRegister (cie->return_addr_reg_num );
601-
602610 std::vector<UnwindPlan::Row> stack;
603611
604612 UnwindPlan::Row::AbstractRegisterLocation reg_location;
@@ -618,7 +626,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
618626 // that is computed by taking the current entry's location value and
619627 // adding (delta * code_align). All other values in the new row are
620628 // initially identical to the current row.
621- unwind_plan. AppendRow (row);
629+ fde. rows . push_back (row);
622630 row.SlideOffset (extended_opcode * code_align);
623631 break ;
624632 }
@@ -634,9 +642,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
634642 // state, so we need to convert our eh_frame register number from the
635643 // EH frame info, to a register index
636644
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))
640646 row.SetRegisterInfo (reg_num, reg_location);
641647 else {
642648 // If the register was not set in the first row, remove the
@@ -655,7 +661,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
655661 // specified address as the location. All other values in the new row
656662 // are initially identical to the current row. The new location value
657663 // should always be greater than the current one.
658- unwind_plan. AppendRow (row);
664+ fde. rows . push_back (row);
659665 row.SetOffset (m_cfi_data.GetAddress (&offset) -
660666 startaddr.GetFileAddress ());
661667 break ;
@@ -666,7 +672,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
666672 // takes a single uword argument that represents a constant delta.
667673 // This instruction is identical to DW_CFA_advance_loc except for the
668674 // encoding and size of the delta argument.
669- unwind_plan. AppendRow (row);
675+ fde. rows . push_back (row);
670676 row.SlideOffset (m_cfi_data.GetU8 (&offset) * code_align);
671677 break ;
672678 }
@@ -676,7 +682,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
676682 // takes a single uword argument that represents a constant delta.
677683 // This instruction is identical to DW_CFA_advance_loc except for the
678684 // encoding and size of the delta argument.
679- unwind_plan. AppendRow (row);
685+ fde. rows . push_back (row);
680686 row.SlideOffset (m_cfi_data.GetU16 (&offset) * code_align);
681687 break ;
682688 }
@@ -686,7 +692,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
686692 // takes a single uword argument that represents a constant delta.
687693 // This instruction is identical to DW_CFA_advance_loc except for the
688694 // encoding and size of the delta argument.
689- unwind_plan. AppendRow (row);
695+ fde. rows . push_back (row);
690696 row.SlideOffset (m_cfi_data.GetU32 (&offset) * code_align);
691697 break ;
692698 }
@@ -697,9 +703,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
697703 // number. This instruction is identical to DW_CFA_restore except for
698704 // the encoding and size of the register argument.
699705 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))
703707 row.SetRegisterInfo (reg_num, reg_location);
704708 break ;
705709 }
@@ -762,9 +766,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
762766 }
763767 }
764768 }
765- unwind_plan.AppendRow (row);
766-
767- return true ;
769+ fde.rows .push_back (row);
770+ return fde;
768771}
769772
770773bool DWARFCallFrameInfo::HandleCommonDwarfOpcode (uint8_t primary_opcode,
0 commit comments