Skip to content

[lldb] Disable some unwind plans for discontinuous functions #140927

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 22, 2025

Conversation

labath
Copy link
Collaborator

@labath labath commented May 21, 2025

Basically, disable everything except the eh_frame unwind plan, as that's the only one which supports this right now. The other plans are working with now trying the interpret everything in between the function parts as a part of the function, which is more likely to produce wrong results than correct ones.

I changed the interface for object file plans, to give the implementations a chance to implement this correctly, but I haven't actually converted PECallFrameInfo (its only implementation) to handle that. (from the looks of things, it should be relatively easy to do, if it becomes necessary)

I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used, and it doesn't work for discontinuous functions.

Basically, disable everything except the eh_frame unwind plan, as that's
the only one which supports this right now. The other plans are working
with now trying the interpret everything in between the function parts
as a part of the function, which is more likely to produce wrong results
than correct ones.

I changed the interface for object file plans, to give the
implementations a chance to implement this correctly, but I haven't
actually converted PECallFrameInfo (its only implementation) to handle
that. (from the looks of things, it should be relatively easy to do, if
it becomes necessary)

I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used,
and it doesn't work for discontinuous functions.
@labath labath requested a review from jasonmolenda May 21, 2025 16:26
@labath labath requested a review from JDevlieghere as a code owner May 21, 2025 16:26
@llvmbot llvmbot added the lldb label May 21, 2025
@llvmbot
Copy link
Member

llvmbot commented May 21, 2025

@llvm/pr-subscribers-lldb

Author: Pavel Labath (labath)

Changes

Basically, disable everything except the eh_frame unwind plan, as that's the only one which supports this right now. The other plans are working with now trying the interpret everything in between the function parts as a part of the function, which is more likely to produce wrong results than correct ones.

I changed the interface for object file plans, to give the implementations a chance to implement this correctly, but I haven't actually converted PECallFrameInfo (its only implementation) to handle that. (from the looks of things, it should be relatively easy to do, if it becomes necessary)

I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used, and it doesn't work for discontinuous functions.


Full diff: https://github.com/llvm/llvm-project/pull/140927.diff

7 Files Affected:

  • (modified) lldb/include/lldb/Symbol/CallFrameInfo.h (+4-2)
  • (modified) lldb/include/lldb/Symbol/FuncUnwinders.h (-6)
  • (modified) lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp (+17-18)
  • (modified) lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h (+10-4)
  • (modified) lldb/source/Symbol/FuncUnwinders.cpp (+38-67)
  • (modified) lldb/source/Target/RegisterContextUnwind.cpp (+3-4)
  • (modified) lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp (+28-16)
diff --git a/lldb/include/lldb/Symbol/CallFrameInfo.h b/lldb/include/lldb/Symbol/CallFrameInfo.h
index 7db8722baaf5f..f4c5a5b374871 100644
--- a/lldb/include/lldb/Symbol/CallFrameInfo.h
+++ b/lldb/include/lldb/Symbol/CallFrameInfo.h
@@ -19,8 +19,10 @@ class CallFrameInfo {
 
   virtual bool GetAddressRange(Address addr, AddressRange &range) = 0;
 
-  virtual bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan) = 0;
-  virtual bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan) = 0;
+  virtual std::unique_ptr<UnwindPlan>
+  GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges, const Address &addr) = 0;
+
+  virtual std::unique_ptr<UnwindPlan> GetUnwindPlan(const Address &addr) = 0;
 };
 
 } // namespace lldb_private
diff --git a/lldb/include/lldb/Symbol/FuncUnwinders.h b/lldb/include/lldb/Symbol/FuncUnwinders.h
index c21a1af5c56a2..abb0d8abbc21a 100644
--- a/lldb/include/lldb/Symbol/FuncUnwinders.h
+++ b/lldb/include/lldb/Symbol/FuncUnwinders.h
@@ -51,8 +51,6 @@ class FuncUnwinders {
   std::shared_ptr<const UnwindPlan>
   GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread);
 
-  Address &GetFirstNonPrologueInsn(Target &target);
-
   const Address &GetFunctionStartAddress() const;
 
   bool ContainsAddress(const Address &addr) const {
@@ -114,10 +112,6 @@ class FuncUnwinders {
   /// The address ranges of the function.
   AddressRanges m_ranges;
 
-  /// The smallest address range covering the entire function.
-  /// DEPRECATED: Use m_ranges instead.
-  AddressRange m_range;
-
   std::recursive_mutex m_mutex;
 
   std::shared_ptr<const UnwindPlan> m_unwind_plan_assembly_sp;
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
index a7c2e4f0b8dbc..4b516b2e954bd 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
@@ -455,27 +455,26 @@ bool PECallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
   return true;
 }
 
-bool PECallFrameInfo::GetUnwindPlan(const Address &addr,
-                                    UnwindPlan &unwind_plan) {
-  return GetUnwindPlan(AddressRange(addr, 1), unwind_plan);
-}
-
-bool PECallFrameInfo::GetUnwindPlan(const AddressRange &range,
-                                    UnwindPlan &unwind_plan) {
-  unwind_plan.Clear();
-
-  unwind_plan.SetSourceName("PE EH info");
-  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
-  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+std::unique_ptr<UnwindPlan> PECallFrameInfo::GetUnwindPlan(
+    llvm::ArrayRef<lldb_private::AddressRange> ranges,
+    const lldb_private::Address &addr) {
+  // Only continuous functions are supported.
+  if (ranges.size() != 1)
+    return nullptr;
+  const AddressRange &range = ranges[0];
 
   const RuntimeFunction *runtime_function =
       FindRuntimeFunctionIntersectsWithRange(range);
   if (!runtime_function)
-    return false;
+    return nullptr;
+
+  auto plan_up = std::make_unique<UnwindPlan>(eRegisterKindLLDB);
+  plan_up->SetSourceName("PE EH info");
+  plan_up->SetSourcedFromCompiler(eLazyBoolYes);
 
   EHProgramBuilder builder(m_object_file, runtime_function->UnwindInfoOffset);
   if (!builder.Build())
-    return false;
+    return nullptr;
 
   std::vector<UnwindPlan::Row> rows;
 
@@ -493,14 +492,14 @@ bool PECallFrameInfo::GetUnwindPlan(const AddressRange &range,
   }
 
   for (auto it = rows.rbegin(); it != rows.rend(); ++it)
-    unwind_plan.AppendRow(std::move(*it));
+    plan_up->AppendRow(std::move(*it));
 
-  unwind_plan.SetPlanValidAddressRanges({AddressRange(
+  plan_up->SetPlanValidAddressRanges({AddressRange(
       m_object_file.GetAddress(runtime_function->StartAddress),
       runtime_function->EndAddress - runtime_function->StartAddress)});
-  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  plan_up->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
 
-  return true;
+  return plan_up;
 }
 
 const RuntimeFunction *PECallFrameInfo::FindRuntimeFunctionIntersectsWithRange(
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
index 7c2a479ecddb5..07999aa7ccae0 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
@@ -9,7 +9,9 @@
 #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_PECALLFRAMEINFO_H
 #define LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_PECALLFRAMEINFO_H
 
+#include "lldb/Core/AddressRange.h"
 #include "lldb/Symbol/CallFrameInfo.h"
+#include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Utility/DataExtractor.h"
 
 class ObjectFilePECOFF;
@@ -31,10 +33,14 @@ class PECallFrameInfo : public virtual lldb_private::CallFrameInfo {
   bool GetAddressRange(lldb_private::Address addr,
                        lldb_private::AddressRange &range) override;
 
-  bool GetUnwindPlan(const lldb_private::Address &addr,
-                     lldb_private::UnwindPlan &unwind_plan) override;
-  bool GetUnwindPlan(const lldb_private::AddressRange &range,
-                     lldb_private::UnwindPlan &unwind_plan) override;
+  std::unique_ptr<lldb_private::UnwindPlan>
+  GetUnwindPlan(const lldb_private::Address &addr) override {
+    return GetUnwindPlan({lldb_private::AddressRange(addr, 1)}, addr);
+  }
+
+  std::unique_ptr<lldb_private::UnwindPlan>
+  GetUnwindPlan(llvm::ArrayRef<lldb_private::AddressRange> ranges,
+                const lldb_private::Address &addr) override;
 
 private:
   const llvm::Win64EH::RuntimeFunction *FindRuntimeFunctionIntersectsWithRange(
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index 12a6d101d9930..fffc35d7f6177 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -31,30 +31,11 @@
 using namespace lldb;
 using namespace lldb_private;
 
-static AddressRange CollapseRanges(llvm::ArrayRef<AddressRange> ranges) {
-  if (ranges.empty())
-    return AddressRange();
-  if (ranges.size() == 1)
-    return ranges[0];
-
-  Address lowest_addr = ranges[0].GetBaseAddress();
-  addr_t highest_addr = lowest_addr.GetFileAddress() + ranges[0].GetByteSize();
-  for (const AddressRange &range : ranges.drop_front()) {
-    Address range_begin = range.GetBaseAddress();
-    addr_t range_end = range_begin.GetFileAddress() + range.GetByteSize();
-    if (range_begin.GetFileAddress() < lowest_addr.GetFileAddress())
-      lowest_addr = range_begin;
-    if (range_end > highest_addr)
-      highest_addr = range_end;
-  }
-  return AddressRange(lowest_addr, highest_addr - lowest_addr.GetFileAddress());
-}
-
 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, Address addr,
                              AddressRanges ranges)
     : m_unwind_table(unwind_table), m_addr(std::move(addr)),
-      m_ranges(std::move(ranges)), m_range(CollapseRanges(m_ranges)),
-      m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
+      m_ranges(std::move(ranges)), m_tried_unwind_plan_assembly(false),
+      m_tried_unwind_plan_eh_frame(false),
       m_tried_unwind_plan_object_file(false),
       m_tried_unwind_plan_debug_frame(false),
       m_tried_unwind_plan_object_file_augmented(false),
@@ -106,8 +87,9 @@ FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) {
     return nullptr;
 
   m_tried_unwind_plan_compact_unwind = true;
-  if (m_range.GetBaseAddress().IsValid()) {
-    Address current_pc(m_range.GetBaseAddress());
+  // Only continuous functions are supported.
+  if (m_ranges.size() == 1) {
+    Address current_pc(m_ranges[0].GetBaseAddress());
     CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
     if (compact_unwind) {
       auto unwind_plan_sp =
@@ -131,14 +113,10 @@ FuncUnwinders::GetObjectFileUnwindPlan(Target &target) {
     return m_unwind_plan_object_file_sp;
 
   m_tried_unwind_plan_object_file = true;
-  if (m_range.GetBaseAddress().IsValid()) {
-    CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo();
-    if (object_file_frame) {
-      auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
-      if (object_file_frame->GetUnwindPlan(m_range, *plan_sp))
-        m_unwind_plan_object_file_sp = std::move(plan_sp);
-    }
-  }
+  if (CallFrameInfo *object_file_frame =
+          m_unwind_table.GetObjectFileUnwindInfo())
+    m_unwind_plan_object_file_sp =
+        object_file_frame->GetUnwindPlan(m_ranges, m_addr);
   return m_unwind_plan_object_file_sp;
 }
 
@@ -178,8 +156,9 @@ FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) {
     return m_unwind_plan_arm_unwind_sp;
 
   m_tried_unwind_plan_arm_unwind = true;
-  if (m_range.GetBaseAddress().IsValid()) {
-    Address current_pc(m_range.GetBaseAddress());
+  // Only continuous functions are supported.
+  if (m_ranges.size() == 1) {
+    Address current_pc = m_ranges[0].GetBaseAddress();
     ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
     if (arm_unwind_info) {
       auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
@@ -215,9 +194,10 @@ FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) {
     return m_unwind_plan_symbol_file_sp;
 
   m_tried_unwind_plan_symbol_file = true;
-  if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {
+  if (SymbolFile *symfile = m_unwind_table.GetSymbolFile();
+      symfile && m_ranges.size() == 1) {
     m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(
-        m_range.GetBaseAddress(),
+        m_ranges[0].GetBaseAddress(),
         RegisterContextToInfo(*thread.GetRegisterContext()));
   }
   return m_unwind_plan_symbol_file_sp;
@@ -242,10 +222,11 @@ FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target,
   // so the UnwindPlan can be used at any instruction in the function.
 
   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp) {
+  // Only continuous functions are supported.
+  if (assembly_profiler_sp && m_ranges.size() == 1) {
     auto plan_sp = std::make_shared<UnwindPlan>(*object_file_unwind_plan);
 
-    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
+    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
                                                             *plan_sp))
       m_unwind_plan_object_file_augmented_sp = std::move(plan_sp);
   }
@@ -280,9 +261,10 @@ FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread) {
   // so the UnwindPlan can be used at any instruction in the function.
 
   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp) {
+  // Only continuous functions are supported.
+  if (assembly_profiler_sp && m_ranges.size() == 1) {
     auto plan_sp = std::make_shared<UnwindPlan>(*eh_frame_plan);
-    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
+    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
                                                             *plan_sp))
       m_unwind_plan_eh_frame_augmented_sp = std::move(plan_sp);
   }
@@ -319,10 +301,11 @@ FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target,
   // function.
 
   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp) {
+  // Only continuous functions are supported.
+  if (assembly_profiler_sp && m_ranges.size() == 1) {
     auto plan_sp = std::make_shared<UnwindPlan>(*debug_frame_plan);
 
-    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
+    if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
                                                             *plan_sp))
       m_unwind_plan_debug_frame_augmented_sp = std::move(plan_sp);
   }
@@ -339,18 +322,19 @@ FuncUnwinders::GetAssemblyUnwindPlan(Target &target, Thread &thread) {
 
   m_tried_unwind_plan_assembly = true;
 
-  // Don't analyze more than 10 megabytes of instructions,
-  // if a function is legitimately larger than that, we'll
-  // miss the epilogue instructions, but guard against a
-  // bogusly large function and analyzing large amounts of
-  // non-instruction data.
-  AddressRange range = m_range;
-  const addr_t func_size =
-      std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
-  range.SetByteSize(func_size);
-
   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp) {
+  // Only continuous functions are supported.
+  if (assembly_profiler_sp && m_ranges.size() == 1) {
+    // Don't analyze more than 10 megabytes of instructions,
+    // if a function is legitimately larger than that, we'll
+    // miss the epilogue instructions, but guard against a
+    // bogusly large function and analyzing large amounts of
+    // non-instruction data.
+    AddressRange range = m_ranges[0];
+    const addr_t func_size =
+        std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
+    range.SetByteSize(func_size);
+
     auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
     if (assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
             range, thread, *plan_sp))
@@ -457,9 +441,9 @@ FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, Thread &thread) {
   m_tried_unwind_fast = true;
 
   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp) {
+  if (assembly_profiler_sp && m_ranges.size() == 1) {
     auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
-    if (assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, *plan_sp))
+    if (assembly_profiler_sp->GetFastUnwindPlan(m_ranges[0], thread, *plan_sp))
       m_unwind_plan_fast_sp = std::move(plan_sp);
   }
   return m_unwind_plan_fast_sp;
@@ -503,19 +487,6 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
   return m_unwind_plan_arch_default_at_func_entry_sp;
 }
 
-Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
-  std::lock_guard<std::recursive_mutex> guard(m_mutex);
-  if (m_first_non_prologue_insn.IsValid())
-    return m_first_non_prologue_insn;
-
-  ExecutionContext exe_ctx(target.shared_from_this(), false);
-  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
-  if (assembly_profiler_sp)
-    assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
-                                               m_first_non_prologue_insn);
-  return m_first_non_prologue_insn;
-}
-
 const Address &FuncUnwinders::GetFunctionStartAddress() const { return m_addr; }
 
 lldb::UnwindAssemblySP
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 1884d8d53a7f6..32ed8e0384412 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -880,10 +880,9 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() {
     CallFrameInfo *object_file_unwind =
         pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo();
     if (object_file_unwind) {
-      auto unwind_plan_sp =
-          std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
-      if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp))
-        return unwind_plan_sp;
+      if (std::unique_ptr<UnwindPlan> plan_up =
+              object_file_unwind->GetUnwindPlan(m_current_pc))
+        return plan_up;
     }
 
     return arch_default_unwind_plan_sp;
diff --git a/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp b/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
index e842df5988867..264678e4c4ed3 100644
--- a/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
+++ b/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
@@ -24,12 +24,10 @@ using namespace lldb;
 
 class PECallFrameInfoTest : public testing::Test {
   SubsystemRAII<FileSystem, ObjectFilePECOFF> subsystems;
-
-protected:
-  void GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) const;
 };
 
-void PECallFrameInfoTest::GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) const {
+static llvm::Expected<std::unique_ptr<UnwindPlan>>
+GetUnwindPlan(addr_t file_addr) {
   llvm::Expected<TestFile> ExpectedFile = TestFile::fromYaml(
       R"(
 --- !COFF
@@ -190,24 +188,34 @@ void PECallFrameInfoTest::GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) cons
 symbols:         []
 ...
 )");
-  ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
+  if (!ExpectedFile)
+    return ExpectedFile.takeError();
 
   ModuleSP module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());
   ObjectFile *object_file = module_sp->GetObjectFile();
-  ASSERT_NE(object_file, nullptr);
+  if (!object_file)
+    return llvm::createStringError("object file is null");
 
   std::unique_ptr<CallFrameInfo> cfi = object_file->CreateCallFrameInfo();
-  ASSERT_NE(cfi.get(), nullptr);
+  if (!cfi)
+    return llvm::createStringError("call frame info is null");
 
   SectionList *sect_list = object_file->GetSectionList();
-  ASSERT_NE(sect_list, nullptr);
-
-  EXPECT_TRUE(cfi->GetUnwindPlan(Address(file_addr, sect_list), plan));
+  if (!sect_list)
+    return llvm::createStringError("section list is null");
+
+  std::unique_ptr<UnwindPlan> plan_up =
+      cfi->GetUnwindPlan(Address(file_addr, sect_list));
+  if (!plan_up)
+    return llvm::createStringError("unwind plan is null");
+  return plan_up;
 }
 
 TEST_F(PECallFrameInfoTest, Basic_eh) {
-  UnwindPlan plan(eRegisterKindLLDB);
-  GetUnwindPlan(0x1001080, plan);
+  llvm::Expected<std::unique_ptr<UnwindPlan>> expected_plan =
+      GetUnwindPlan(0x1001080);
+  ASSERT_THAT_EXPECTED(expected_plan, llvm::Succeeded());
+  UnwindPlan &plan = **expected_plan;
   EXPECT_EQ(plan.GetRowCount(), 7);
 
   UnwindPlan::Row row;
@@ -248,8 +256,10 @@ TEST_F(PECallFrameInfoTest, Basic_eh) {
 }
 
 TEST_F(PECallFrameInfoTest, Chained_eh) {
-  UnwindPlan plan(eRegisterKindLLDB);
-  GetUnwindPlan(0x1001180, plan);
+  llvm::Expected<std::unique_ptr<UnwindPlan>> expected_plan =
+      GetUnwindPlan(0x1001180);
+  ASSERT_THAT_EXPECTED(expected_plan, llvm::Succeeded());
+  UnwindPlan &plan = **expected_plan;
   EXPECT_EQ(plan.GetRowCount(), 2);
 
   UnwindPlan::Row row;
@@ -270,8 +280,10 @@ TEST_F(PECallFrameInfoTest, Chained_eh) {
 }
 
 TEST_F(PECallFrameInfoTest, Frame_reg_eh) {
-  UnwindPlan plan(eRegisterKindLLDB);
-  GetUnwindPlan(0x1001280, plan);
+  llvm::Expected<std::unique_ptr<UnwindPlan>> expected_plan =
+      GetUnwindPlan(0x1001280);
+  ASSERT_THAT_EXPECTED(expected_plan, llvm::Succeeded());
+  UnwindPlan &plan = **expected_plan;
   EXPECT_EQ(plan.GetRowCount(), 11);
 
   UnwindPlan::Row row;

Copy link
Collaborator

@jasonmolenda jasonmolenda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@labath labath merged commit b63c1c4 into llvm:main May 22, 2025
12 checks passed
@labath labath deleted the prop branch May 22, 2025 12:19
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
…0927)

Basically, disable everything except the eh_frame unwind plan, as that's
the only one which supports this right now. The other plans are working
with now trying the interpret everything in between the function parts
as a part of the function, which is more likely to produce wrong results
than correct ones.

I changed the interface for object file plans, to give the
implementations a chance to implement this correctly, but I haven't
actually converted PECallFrameInfo (its only implementation) to handle
that. (from the looks of things, it should be relatively easy to do, if
it becomes necessary)

I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used,
and it doesn't work for discontinuous functions.
ajaden-codes pushed a commit to Jaddyen/llvm-project that referenced this pull request Jun 6, 2025
…0927)

Basically, disable everything except the eh_frame unwind plan, as that's
the only one which supports this right now. The other plans are working
with now trying the interpret everything in between the function parts
as a part of the function, which is more likely to produce wrong results
than correct ones.

I changed the interface for object file plans, to give the
implementations a chance to implement this correctly, but I haven't
actually converted PECallFrameInfo (its only implementation) to handle
that. (from the looks of things, it should be relatively easy to do, if
it becomes necessary)

I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used,
and it doesn't work for discontinuous functions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants