https://github.com/labath updated 
https://github.com/llvm/llvm-project/pull/134806

>From eeaad560a727ea2b113ab3eff218f66a46e30c83 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Fri, 4 Apr 2025 13:36:06 +0200
Subject: [PATCH 1/2] [lldb] Small refactor of eh_frame parsing

.. which prepares us for handling of discontinuous functions. The main
change there is that we can have multiple FDEs contributing towards an
unwind plan of a single function. This patch separates the logic for
parsing of a single FDE from the construction of an UnwindPlan (so that
another patch can change the latter to combine several unwind plans).
---
 lldb/include/lldb/Symbol/DWARFCallFrameInfo.h | 10 ++-
 lldb/source/Symbol/DWARFCallFrameInfo.cpp     | 87 ++++++++++---------
 2 files changed, 53 insertions(+), 44 deletions(-)

diff --git a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h 
b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
index 6cc24a02de257..526f322a770e4 100644
--- a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
+++ b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
@@ -128,8 +128,14 @@ class DWARFCallFrameInfo {
 
   void GetFDEIndex();
 
-  bool FDEToUnwindPlan(dw_offset_t offset, Address startaddr,
-                       UnwindPlan &unwind_plan);
+  // Parsed representation of a Frame Descriptor Entry.
+  struct FDE {
+    AddressRange range;
+    bool for_signal_trap = false;
+    uint32_t return_addr_reg_num = LLDB_INVALID_REGNUM;
+    std::vector<UnwindPlan::Row> rows;
+  };
+  std::optional<FDE> ParseFDE(dw_offset_t offset, const Address &startaddr);
 
   const CIE *GetCIE(dw_offset_t cie_offset);
 
diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp 
b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index dac4cd9745f96..fb57c61d413aa 100644
--- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -168,9 +168,32 @@ bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange 
&range,
       module_sp->GetObjectFile() != &m_objfile)
     return false;
 
-  if (std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range))
-    return FDEToUnwindPlan(entry->data, addr, unwind_plan);
-  return false;
+  std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range);
+  if (!entry)
+    return false;
+
+  std::optional<FDE> fde = ParseFDE(entry->data, addr);
+  if (!fde)
+    return false;
+
+  unwind_plan.SetSourceName(m_type == EH ? "eh_frame CFI" : "DWARF CFI");
+  // In theory the debug_frame info should be valid at all call sites
+  // ("asynchronous unwind info" as it is sometimes called) but in practice
+  // gcc et al all emit call frame info for the prologue and call sites, but
+  // not for the epilogue or all the other locations during the function
+  // reliably.
+  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
+  unwind_plan.SetRegisterKind(GetRegisterKind());
+
+  unwind_plan.SetPlanValidAddressRanges({fde->range});
+  unwind_plan.SetUnwindPlanForSignalTrap(fde->for_signal_trap ? eLazyBoolYes
+                                                              : eLazyBoolNo);
+  unwind_plan.SetReturnAddressRegister(fde->return_addr_reg_num);
+  for (UnwindPlan::Row &row : fde->rows)
+    unwind_plan.AppendRow(std::move(row));
+
+  return true;
 }
 
 bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
@@ -522,15 +545,15 @@ void DWARFCallFrameInfo::GetFDEIndex() {
   m_fde_index_initialized = true;
 }
 
-bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
-                                         Address startaddr,
-                                         UnwindPlan &unwind_plan) {
+std::optional<DWARFCallFrameInfo::FDE>
+DWARFCallFrameInfo::ParseFDE(dw_offset_t dwarf_offset,
+                             const Address &startaddr) {
   Log *log = GetLog(LLDBLog::Unwind);
   lldb::offset_t offset = dwarf_offset;
   lldb::offset_t current_entry = offset;
 
-  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
-    return false;
+  if (!m_section_sp || m_section_sp->IsEncrypted())
+    return std::nullopt;
 
   if (!m_cfi_data_initialized)
     GetCFIData();
@@ -550,20 +573,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
 
   // Translate the CIE_id from the eh_frame format, which is relative to the
   // FDE offset, into a __eh_frame section offset
-  if (m_type == EH) {
-    unwind_plan.SetSourceName("eh_frame CFI");
+  if (m_type == EH)
     cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
-    unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
-  } else {
-    unwind_plan.SetSourceName("DWARF CFI");
-    // In theory the debug_frame info should be valid at all call sites
-    // ("asynchronous unwind info" as it is sometimes called) but in practice
-    // gcc et al all emit call frame info for the prologue and call sites, but
-    // not for the epilogue or all the other locations during the function
-    // reliably.
-    unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
-  }
-  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
 
   const CIE *cie = GetCIE(cie_offset);
   assert(cie != nullptr);
@@ -587,18 +598,15 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
   if (cie->augmentation[0] == 'z')
     offset += (uint32_t)m_cfi_data.GetULEB128(&offset);
 
-  unwind_plan.SetUnwindPlanForSignalTrap(
-    strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo);
+  FDE fde;
+  fde.for_signal_trap = strchr(cie->augmentation, 'S') != nullptr;
+  fde.range = range;
+  fde.return_addr_reg_num = cie->return_addr_reg_num;
 
   uint32_t code_align = cie->code_align;
   int32_t data_align = cie->data_align;
 
-  unwind_plan.SetPlanValidAddressRanges({range});
   UnwindPlan::Row row = cie->initial_row;
-
-  unwind_plan.SetRegisterKind(GetRegisterKind());
-  unwind_plan.SetReturnAddressRegister(cie->return_addr_reg_num);
-
   std::vector<UnwindPlan::Row> stack;
 
   UnwindPlan::Row::AbstractRegisterLocation reg_location;
@@ -618,7 +626,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // that is computed by taking the current entry's location value and
           // adding (delta * code_align). All other values in the new row are
           // initially identical to the current row.
-          unwind_plan.AppendRow(row);
+          fde.rows.push_back(row);
           row.SlideOffset(extended_opcode * code_align);
           break;
         }
@@ -634,9 +642,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // state, so we need to convert our eh_frame register number from the
           // EH frame info, to a register index
 
-          if (unwind_plan.IsValidRowIndex(0) &&
-              unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
-                                                            reg_location))
+          if (fde.rows[0].GetRegisterInfo(reg_num, reg_location))
             row.SetRegisterInfo(reg_num, reg_location);
           else {
             // If the register was not set in the first row, remove the
@@ -655,7 +661,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // specified address as the location. All other values in the new row
           // are initially identical to the current row. The new location value
           // should always be greater than the current one.
-          unwind_plan.AppendRow(row);
+          fde.rows.push_back(row);
           row.SetOffset(m_cfi_data.GetAddress(&offset) -
                         startaddr.GetFileAddress());
           break;
@@ -666,7 +672,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // takes a single uword argument that represents a constant delta.
           // This instruction is identical to DW_CFA_advance_loc except for the
           // encoding and size of the delta argument.
-          unwind_plan.AppendRow(row);
+          fde.rows.push_back(row);
           row.SlideOffset(m_cfi_data.GetU8(&offset) * code_align);
           break;
         }
@@ -676,7 +682,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // takes a single uword argument that represents a constant delta.
           // This instruction is identical to DW_CFA_advance_loc except for the
           // encoding and size of the delta argument.
-          unwind_plan.AppendRow(row);
+          fde.rows.push_back(row);
           row.SlideOffset(m_cfi_data.GetU16(&offset) * code_align);
           break;
         }
@@ -686,7 +692,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // takes a single uword argument that represents a constant delta.
           // This instruction is identical to DW_CFA_advance_loc except for the
           // encoding and size of the delta argument.
-          unwind_plan.AppendRow(row);
+          fde.rows.push_back(row);
           row.SlideOffset(m_cfi_data.GetU32(&offset) * code_align);
           break;
         }
@@ -697,9 +703,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
           // number. This instruction is identical to DW_CFA_restore except for
           // the encoding and size of the register argument.
           uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
-          if (unwind_plan.IsValidRowIndex(0) &&
-              unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
-                                                            reg_location))
+          if (fde.rows[0].GetRegisterInfo(reg_num, reg_location))
             row.SetRegisterInfo(reg_num, reg_location);
           break;
         }
@@ -762,9 +766,8 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
       }
     }
   }
-  unwind_plan.AppendRow(row);
-
-  return true;
+  fde.rows.push_back(row);
+  return fde;
 }
 
 bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,

>From bdeeefdd6b41452dc6799cee5cde60c7086d145e Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Thu, 10 Apr 2025 14:59:09 +0200
Subject: [PATCH 2/2] Update lldb/include/lldb/Symbol/DWARFCallFrameInfo.h

Co-authored-by: Jonas Devlieghere <jo...@devlieghere.com>
---
 lldb/include/lldb/Symbol/DWARFCallFrameInfo.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h 
b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
index 526f322a770e4..679f652c7f2e0 100644
--- a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
+++ b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
@@ -128,7 +128,7 @@ class DWARFCallFrameInfo {
 
   void GetFDEIndex();
 
-  // Parsed representation of a Frame Descriptor Entry.
+  /// Parsed representation of a Frame Descriptor Entry.
   struct FDE {
     AddressRange range;
     bool for_signal_trap = false;

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to