[Lldb-commits] [lldb] [lldb] Small refactor of eh_frame parsing (PR #134806)
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 10 05:59:18 PDT 2025
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/134806
>From f16fb6541556f5e82825207064f5f7bb6b3cd343 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 4 Apr 2025 11:37:34 +0200
Subject: [PATCH 1/4] [lldb] Support negative function offsets in UnwindPlans
These are needed for functions whose entry point is not their lowest
address.
---
lldb/include/lldb/Symbol/UnwindPlan.h | 10 +++++-----
.../UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp | 5 +++--
lldb/source/Symbol/DWARFCallFrameInfo.cpp | 2 +-
lldb/source/Symbol/UnwindPlan.cpp | 6 +++---
lldb/unittests/Symbol/UnwindPlanTest.cpp | 5 +++++
5 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h
index 6640a23a3e868..410289851a879 100644
--- a/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -356,11 +356,11 @@ class UnwindPlan {
void RemoveRegisterInfo(uint32_t reg_num);
- lldb::addr_t GetOffset() const { return m_offset; }
+ int64_t GetOffset() const { return m_offset; }
- void SetOffset(lldb::addr_t offset) { m_offset = offset; }
+ void SetOffset(int64_t offset) { m_offset = offset; }
- void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
+ void SlideOffset(int64_t offset) { m_offset += offset; }
const FAValue &GetCFAValue() const { return m_cfa_value; }
FAValue &GetCFAValue() { return m_cfa_value; }
@@ -420,7 +420,7 @@ class UnwindPlan {
protected:
typedef std::map<uint32_t, AbstractRegisterLocation> collection;
- lldb::addr_t m_offset = 0; // Offset into the function for this row
+ int64_t m_offset = 0; // Offset into the function for this row
FAValue m_cfa_value;
FAValue m_afa_value;
@@ -472,7 +472,7 @@ class UnwindPlan {
// practice, the UnwindPlan for a function with no known start address will be
// the architectural default UnwindPlan which will only have one row.
const UnwindPlan::Row *
- GetRowForFunctionOffset(std::optional<int> offset) const;
+ GetRowForFunctionOffset(std::optional<int64_t> offset) const;
lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 3eaa2f33fce3e..aaff278ca31e2 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -1390,11 +1390,12 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
// If we already have one row for this instruction, we can continue.
while (row_id < unwind_plan.GetRowCount() &&
- unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) {
+ unwind_plan.GetRowAtIndex(row_id)->GetOffset() <=
+ static_cast<int64_t>(offset)) {
row_id++;
}
const UnwindPlan::Row *original_row = unwind_plan.GetRowAtIndex(row_id - 1);
- if (original_row->GetOffset() == offset) {
+ if (original_row->GetOffset() == static_cast<int64_t>(offset)) {
row = *original_row;
continue;
}
diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index 957818e8d077f..dca3f665b0b80 100644
--- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -765,7 +765,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
__FUNCTION__, dwarf_offset, startaddr.GetFileAddress());
break;
}
- lldb::addr_t offset = row.GetOffset();
+ int64_t offset = row.GetOffset();
row = std::move(stack.back());
stack.pop_back();
row.SetOffset(offset);
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index cfa8eefaa55bb..33aba0a859d5c 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -398,10 +398,10 @@ void UnwindPlan::AppendRow(Row row) {
}
struct RowLess {
- bool operator()(addr_t a, const UnwindPlan::RowSP &b) const {
+ bool operator()(int64_t a, const UnwindPlan::RowSP &b) const {
return a < b->GetOffset();
}
- bool operator()(const UnwindPlan::RowSP &a, addr_t b) const {
+ bool operator()(const UnwindPlan::RowSP &a, int64_t b) const {
return a->GetOffset() < b;
}
};
@@ -418,7 +418,7 @@ void UnwindPlan::InsertRow(Row row, bool replace_existing) {
}
const UnwindPlan::Row *
-UnwindPlan::GetRowForFunctionOffset(std::optional<int> offset) const {
+UnwindPlan::GetRowForFunctionOffset(std::optional<int64_t> offset) const {
auto it = offset ? llvm::upper_bound(m_row_list, *offset, RowLess())
: m_row_list.end();
if (it == m_row_list.begin())
diff --git a/lldb/unittests/Symbol/UnwindPlanTest.cpp b/lldb/unittests/Symbol/UnwindPlanTest.cpp
index fa8bb153e9247..08aa5b2dd84bb 100644
--- a/lldb/unittests/Symbol/UnwindPlanTest.cpp
+++ b/lldb/unittests/Symbol/UnwindPlanTest.cpp
@@ -24,6 +24,7 @@ static UnwindPlan::Row make_simple_row(addr_t offset, uint64_t cfa_value) {
TEST(UnwindPlan, InsertRow) {
UnwindPlan::Row row1 = make_simple_row(0, 42);
UnwindPlan::Row row2 = make_simple_row(0, 47);
+ UnwindPlan::Row row3 = make_simple_row(-1, 4242);
UnwindPlan plan(eRegisterKindGeneric);
plan.InsertRow(row1);
@@ -34,6 +35,10 @@ TEST(UnwindPlan, InsertRow) {
plan.InsertRow(row2, /*replace_existing=*/true);
EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(row2));
+
+ EXPECT_THAT(plan.GetRowForFunctionOffset(-1), nullptr);
+ plan.InsertRow(row3);
+ EXPECT_THAT(plan.GetRowForFunctionOffset(-1), testing::Pointee(row3));
}
TEST(UnwindPlan, GetRowForFunctionOffset) {
>From cc60304bd23850516c247d7af27240107a24c4ce Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 4 Apr 2025 12:05:18 +0200
Subject: [PATCH 2/4] [lldb] Remove unused UnwindPlan functions
`GetLSDAAddress` and `GetPersonalityRoutinePtrAddress` are unused and
they create a bit of a problem for discontinuous functions, because the
unwind plan for these consists of multiple eh_frame descriptors and (at
least in theory) each of them could have a different value for these
entities.
We could say we only support functions for which these are always the
same, or create some sort of a Address2LSDA lookup map, but I think it's
better to leave this question to someone who actually needs this.
---
lldb/include/lldb/Symbol/FuncUnwinders.h | 13 --------
lldb/include/lldb/Symbol/UnwindPlan.h | 23 +-------------
lldb/source/Symbol/CompactUnwindInfo.cpp | 12 -------
lldb/source/Symbol/DWARFCallFrameInfo.cpp | 38 +++--------------------
lldb/source/Symbol/FuncUnwinders.cpp | 36 ---------------------
lldb/source/Symbol/UnwindPlan.cpp | 13 --------
6 files changed, 5 insertions(+), 130 deletions(-)
diff --git a/lldb/include/lldb/Symbol/FuncUnwinders.h b/lldb/include/lldb/Symbol/FuncUnwinders.h
index 479ccf87b6e2c..c21a1af5c56a2 100644
--- a/lldb/include/lldb/Symbol/FuncUnwinders.h
+++ b/lldb/include/lldb/Symbol/FuncUnwinders.h
@@ -61,19 +61,6 @@ class FuncUnwinders {
});
}
- // A function may have a Language Specific Data Area specified -- a block of
- // data in
- // the object file which is used in the processing of an exception throw /
- // catch. If any of the UnwindPlans have the address of the LSDA region for
- // this function, this will return it.
- Address GetLSDAAddress(Target &target);
-
- // A function may have a Personality Routine associated with it -- used in the
- // processing of throwing an exception. If any of the UnwindPlans have the
- // address of the personality routine, this will return it. Read the target-
- // pointer at this address to get the personality function address.
- Address GetPersonalityRoutinePtrAddress(Target &target);
-
// The following methods to retrieve specific unwind plans should rarely be
// used. Instead, clients should ask for the *behavior* they are looking for,
// using one of the above UnwindPlan retrieval methods.
diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h
index 410289851a879..cd5451fed6c0c 100644
--- a/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -445,9 +445,7 @@ class UnwindPlan {
m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler),
m_plan_is_valid_at_all_instruction_locations(
rhs.m_plan_is_valid_at_all_instruction_locations),
- m_plan_is_for_signal_trap(rhs.m_plan_is_for_signal_trap),
- m_lsda_address(rhs.m_lsda_address),
- m_personality_func_addr(rhs.m_personality_func_addr) {
+ m_plan_is_for_signal_trap(rhs.m_plan_is_for_signal_trap) {
m_row_list.reserve(rhs.m_row_list.size());
for (const RowSP &row_sp : rhs.m_row_list)
m_row_list.emplace_back(new Row(*row_sp));
@@ -553,22 +551,10 @@ class UnwindPlan {
m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
m_plan_is_for_signal_trap = eLazyBoolCalculate;
- m_lsda_address.Clear();
- m_personality_func_addr.Clear();
}
const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
- Address GetLSDAAddress() const { return m_lsda_address; }
-
- void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
-
- Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; }
-
- void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
- m_personality_func_addr = presonality_func_ptr;
- }
-
private:
std::vector<RowSP> m_row_list;
std::vector<AddressRange> m_plan_valid_ranges;
@@ -583,13 +569,6 @@ class UnwindPlan {
lldb_private::LazyBool m_plan_is_sourced_from_compiler;
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
lldb_private::LazyBool m_plan_is_for_signal_trap;
-
- Address m_lsda_address; // Where the language specific data area exists in the
- // module - used
- // in exception handling.
- Address m_personality_func_addr; // The address of a pointer to the
- // personality function - used in
- // exception handling.
}; // class UnwindPlan
} // namespace lldb_private
diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp b/lldb/source/Symbol/CompactUnwindInfo.cpp
index 3c97d2ca11fbc..cdbbeb554c688 100644
--- a/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -741,9 +741,6 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
- unwind_plan.SetLSDAAddress(function_info.lsda_address);
- unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
-
UnwindPlan::Row row;
const int wordsize = 8;
@@ -1011,9 +1008,6 @@ bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
- unwind_plan.SetLSDAAddress(function_info.lsda_address);
- unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
-
UnwindPlan::Row row;
const int wordsize = 4;
@@ -1306,9 +1300,6 @@ bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target,
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
- unwind_plan.SetLSDAAddress(function_info.lsda_address);
- unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
-
UnwindPlan::Row row;
const int wordsize = 8;
@@ -1437,9 +1428,6 @@ bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target,
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
- unwind_plan.SetLSDAAddress(function_info.lsda_address);
- unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
-
UnwindPlan::Row row;
const int wordsize = 4;
diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index dca3f665b0b80..dac4cd9745f96 100644
--- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -583,43 +583,13 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
m_objfile.GetSectionList());
range.SetByteSize(range_len);
- addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS;
-
- if (cie->augmentation[0] == 'z') {
- uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
- if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) {
- lldb::offset_t saved_offset = offset;
- lsda_data_file_address =
- GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding,
- pc_rel_addr, text_addr, data_addr);
- if (offset - saved_offset != aug_data_len) {
- // There is more in the augmentation region than we know how to process;
- // don't read anything.
- lsda_data_file_address = LLDB_INVALID_ADDRESS;
- }
- offset = saved_offset;
- }
- offset += aug_data_len;
- }
+ // Skip the LSDA, if present.
+ if (cie->augmentation[0] == 'z')
+ offset += (uint32_t)m_cfi_data.GetULEB128(&offset);
+
unwind_plan.SetUnwindPlanForSignalTrap(
strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo);
- Address lsda_data;
- Address personality_function_ptr;
-
- if (lsda_data_file_address != LLDB_INVALID_ADDRESS &&
- cie->personality_loc != LLDB_INVALID_ADDRESS) {
- m_objfile.GetModule()->ResolveFileAddress(lsda_data_file_address,
- lsda_data);
- m_objfile.GetModule()->ResolveFileAddress(cie->personality_loc,
- personality_function_ptr);
- }
-
- if (lsda_data.IsValid() && personality_function_ptr.IsValid()) {
- unwind_plan.SetLSDAAddress(lsda_data);
- unwind_plan.SetPersonalityFunctionPtr(personality_function_ptr);
- }
-
uint32_t code_align = cie->code_align;
int32_t data_align = cie->data_align;
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index a74029d8343c7..11600825e8e38 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -537,39 +537,3 @@ FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
}
return assembly_profiler_sp;
}
-
-Address FuncUnwinders::GetLSDAAddress(Target &target) {
- Address lsda_addr;
-
- std::shared_ptr<const UnwindPlan> unwind_plan_sp =
- GetEHFrameUnwindPlan(target);
- if (unwind_plan_sp.get() == nullptr) {
- unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
- }
- if (unwind_plan_sp.get() == nullptr) {
- unwind_plan_sp = GetObjectFileUnwindPlan(target);
- }
- if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
- lsda_addr = unwind_plan_sp->GetLSDAAddress();
- }
- return lsda_addr;
-}
-
-Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
- Address personality_addr;
-
- std::shared_ptr<const UnwindPlan> unwind_plan_sp =
- GetEHFrameUnwindPlan(target);
- if (unwind_plan_sp.get() == nullptr) {
- unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
- }
- if (unwind_plan_sp.get() == nullptr) {
- unwind_plan_sp = GetObjectFileUnwindPlan(target);
- }
- if (unwind_plan_sp.get() &&
- unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
- personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
- }
-
- return personality_addr;
-}
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index 33aba0a859d5c..137466025c982 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -511,19 +511,6 @@ void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
s.Printf("This UnwindPlan originally sourced from %s\n",
m_source_name.GetCString());
}
- if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
- TargetSP target_sp(thread->CalculateTarget());
- addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
- addr_t personality_func_load_addr =
- m_personality_func_addr.GetLoadAddress(target_sp.get());
-
- if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
- personality_func_load_addr != LLDB_INVALID_ADDRESS) {
- s.Printf("LSDA address 0x%" PRIx64
- ", personality routine is at address 0x%" PRIx64 "\n",
- lsda_load_addr, personality_func_load_addr);
- }
- }
s.Printf("This UnwindPlan is sourced from the compiler: ");
switch (m_plan_is_sourced_from_compiler) {
case eLazyBoolYes:
>From cf678e88eaf957ac0b32808569e15c859384d30f Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 4 Apr 2025 13:36:06 +0200
Subject: [PATCH 3/4] [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 99fca981b2c7fe06d720785e4ffb890e3855fafd Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Thu, 10 Apr 2025 14:59:09 +0200
Subject: [PATCH 4/4] Update lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
Co-authored-by: Jonas Devlieghere <jonas at 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;
More information about the lldb-commits
mailing list