diff --git a/lldb/include/lldb/Symbol/UnwindTable.h b/lldb/include/lldb/Symbol/UnwindTable.h index f0ce7047de2d1..26826e5d1b497 100644 --- a/lldb/include/lldb/Symbol/UnwindTable.h +++ b/lldb/include/lldb/Symbol/UnwindTable.h @@ -57,6 +57,10 @@ class UnwindTable { ArchSpec GetArchitecture(); + /// Called after a SymbolFile has been added to a Module to add any new + /// unwind sections that may now be available. + void Update(); + private: void Dump(Stream &s); diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 30b6b45d3f6b9..86ff43456c7c7 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1046,6 +1046,8 @@ SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { m_symfile_up.reset( SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); m_did_load_symfile = true; + if (m_unwind_table) + m_unwind_table->Update(); } } } diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp index 3c1a5187b1105..11bedf3d6052e 100644 --- a/lldb/source/Symbol/UnwindTable.cpp +++ b/lldb/source/Symbol/UnwindTable.cpp @@ -84,6 +84,51 @@ void UnwindTable::Initialize() { } } +void UnwindTable::Update() { + if (!m_initialized) + return Initialize(); + + std::lock_guard guard(m_mutex); + + ObjectFile *object_file = m_module.GetObjectFile(); + if (!object_file) + return; + + if (!m_object_file_unwind_up) + m_object_file_unwind_up = object_file->CreateCallFrameInfo(); + + SectionList *sl = m_module.GetSectionList(); + if (!sl) + return; + + SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); + if (!m_eh_frame_up && sect) { + m_eh_frame_up = std::make_unique( + *object_file, sect, DWARFCallFrameInfo::EH); + } + + sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true); + if (!m_debug_frame_up && sect) { + m_debug_frame_up = std::make_unique( + *object_file, sect, DWARFCallFrameInfo::DWARF); + } + + sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); + if (!m_compact_unwind_up && sect) { + m_compact_unwind_up = + std::make_unique(*object_file, sect); + } + + sect = sl->FindSectionByType(eSectionTypeARMexidx, true); + if (!m_arm_unwind_up && sect) { + SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true); + if (sect_extab.get()) { + m_arm_unwind_up = + std::make_unique(*object_file, sect, sect_extab); + } + } +} + UnwindTable::~UnwindTable() = default; std::optional diff --git a/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test b/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test new file mode 100644 index 0000000000000..5420213d405e8 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test @@ -0,0 +1,27 @@ +# TODO: When it's possible to run "image show-unwind" without a running +# process, we can remove the unsupported line below, and hard-code an ELF +# triple in the test. +# UNSUPPORTED: system-windows, system-darwin + +# RUN: cd %T +# RUN: %clang_host %S/Inputs/target-symbols-add-unwind.c -g \ +# RUN: -fno-unwind-tables -fno-asynchronous-unwind-tables \ +# RUN: -o target-symbols-add-unwind.debug +# RUN: llvm-objcopy --strip-debug target-symbols-add-unwind.debug \ +# RUN: target-symbols-add-unwind.stripped +# RUN: %lldb target-symbols-add-unwind.stripped -s %s -o quit | FileCheck %s + +process launch --stop-at-entry +image show-unwind -n main +# CHECK-LABEL: image show-unwind -n main +# CHECK-NOT: debug_frame UnwindPlan: + +target symbols add -s target-symbols-add-unwind.stripped target-symbols-add-unwind.debug +# CHECK-LABEL: target symbols add +# CHECK: symbol file {{.*}} has been added to {{.*}} + +image show-unwind -n main +# CHECK-LABEL: image show-unwind -n main +# CHECK: debug_frame UnwindPlan: +# CHECK-NEXT: This UnwindPlan originally sourced from DWARF CFI +# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes.