-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lldb] Revive shell test after updating UnwindTable #86770
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
[lldb] Revive shell test after updating UnwindTable #86770
Conversation
In commit 2f63718 Author: Jason Molenda <jmolenda@apple.com> Date: Tue Mar 26 09:07:15 2024 -0700 [lldb] Don't clear a Module's UnwindTable when adding a SymbolFile (llvm#86603) I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame. I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice. This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module.
@llvm/pr-subscribers-lldb Author: Jason Molenda (jasonmolenda) ChangesIn
I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame. I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice. This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module. Full diff: https://github.com/llvm/llvm-project/pull/86770.diff 4 Files Affected:
diff --git a/lldb/include/lldb/Symbol/UnwindTable.h b/lldb/include/lldb/Symbol/UnwindTable.h
index f0ce7047de2d1e..26826e5d1b497c 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 a520523a96521a..9c105b3f0e57a1 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1009,6 +1009,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 3c1a5187b11054..11bedf3d6052e7 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<std::mutex> 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<DWARFCallFrameInfo>(
+ *object_file, sect, DWARFCallFrameInfo::EH);
+ }
+
+ sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
+ if (!m_debug_frame_up && sect) {
+ m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
+ *object_file, sect, DWARFCallFrameInfo::DWARF);
+ }
+
+ sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
+ if (!m_compact_unwind_up && sect) {
+ m_compact_unwind_up =
+ std::make_unique<CompactUnwindInfo>(*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<ArmUnwindInfo>(*object_file, sect, sect_extab);
+ }
+ }
+}
+
UnwindTable::~UnwindTable() = default;
std::optional<AddressRange>
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 00000000000000..5420213d405e86
--- /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.
|
I developed & tested this on aarch64 linux, the only system I have here that runs this shell test. It's a little trickier to test on macOS, we basically only use compact_unwind and it's in the executable binary, not the dSYM SymbolFile. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
In commit 2f63718 Author: Jason Molenda <jmolenda@apple.com> Date: Tue Mar 26 09:07:15 2024 -0700 [lldb] Don't clear a Module's UnwindTable when adding a SymbolFile (llvm#86603) I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame. I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice. This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module. (cherry picked from commit 6a0ec8e)
In commit 2f63718 Author: Jason Molenda <jmolenda@apple.com> Date: Tue Mar 26 09:07:15 2024 -0700 [lldb] Don't clear a Module's UnwindTable when adding a SymbolFile (llvm#86603) I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame. I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice. This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module. (cherry picked from commit 6a0ec8e)
…ate-shell-test [lldb] Revive shell test after updating UnwindTable (llvm#86770)
PR llvm#86603 broke unwinding in for unwind info added via "target symbols add". llvm#86770 attempted to fix this, but the fix was only partial -- it accepted new sources of unwind information, but didn't take into account that the symbol file can alter what lldb percieves as function boundaries. A stripped file will not contain information about private (non-exported) symbols, which will make the public symbols appear very large. If lldb tries to unwind from such a function before symbols are added, then the cached unwind plan will prevent new (correct) unwind plans from being created. target-symbols-add-unwind.test might have caught this, were it not for the fact that the "image show-unwind" command does *not* use cached unwind information (it recomputes it from scratch). The changes in this patch come in three pieces: - Clear cached unwind plans when adding symbols. Since the symbol boundaries can change, we cannot trust anything we've computed previously. - Add a flag to "image show-unwind" to display the cached unwind information (mainly for the use in the test, but I think it's also generally useful). - Rewrite the test to better and more reliably simulate the real-world scenario: I've swapped the running process for a core (minidump) file so it can run anywhere; used the caching version of the show-unwind command; and swapped C for assembly to better control the placement of symbols
PR #86603 broke unwinding in for unwind info added via "target symbols add". #86770 attempted to fix this, but the fix was only partial -- it accepted new sources of unwind information, but didn't take into account that the symbol file can alter what lldb percieves as function boundaries. A stripped file will not contain information about private (non-exported) symbols, which will make the public symbols appear very large. If lldb tries to unwind from such a function before symbols are added, then the cached unwind plan will prevent new (correct) unwind plans from being created. target-symbols-add-unwind.test might have caught this, were it not for the fact that the "image show-unwind" command does *not* use cached unwind information (it recomputes it from scratch). The changes in this patch come in three pieces: - Clear cached unwind plans when adding symbols. Since the symbol boundaries can change, we cannot trust anything we've computed previously. - Add a flag to "image show-unwind" to display the cached unwind information (mainly for the use in the test, but I think it's also generally useful). - Rewrite the test to better and more reliably simulate the real-world scenario: I've swapped the running process for a core (minidump) file so it can run anywhere; used the caching version of the show-unwind command; and swapped C for assembly to better control the placement of symbols
PR llvm#86603 broke unwinding in for unwind info added via "target symbols add". llvm#86770 attempted to fix this, but the fix was only partial -- it accepted new sources of unwind information, but didn't take into account that the symbol file can alter what lldb percieves as function boundaries. A stripped file will not contain information about private (non-exported) symbols, which will make the public symbols appear very large. If lldb tries to unwind from such a function before symbols are added, then the cached unwind plan will prevent new (correct) unwind plans from being created. target-symbols-add-unwind.test might have caught this, were it not for the fact that the "image show-unwind" command does *not* use cached unwind information (it recomputes it from scratch). The changes in this patch come in three pieces: - Clear cached unwind plans when adding symbols. Since the symbol boundaries can change, we cannot trust anything we've computed previously. - Add a flag to "image show-unwind" to display the cached unwind information (mainly for the use in the test, but I think it's also generally useful). - Rewrite the test to better and more reliably simulate the real-world scenario: I've swapped the running process for a core (minidump) file so it can run anywhere; used the caching version of the show-unwind command; and swapped C for assembly to better control the placement of symbols
In
commit 2f63718
Author: Jason Molenda jmolenda@apple.com
Date: Tue Mar 26 09:07:15 2024 -0700
I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame.
I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice.
This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module.