[Lldb-commits] [lldb] 5033ea7 - [LLDB][Minidump] Add breakpoint stop reasons to the minidump. (#108448)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 17 15:26:09 PDT 2024
Author: Jacob Lalonde
Date: 2024-10-17T15:26:05-07:00
New Revision: 5033ea73bb01061feb09b3216c74619e1fbefdeb
URL: https://github.com/llvm/llvm-project/commit/5033ea73bb01061feb09b3216c74619e1fbefdeb
DIFF: https://github.com/llvm/llvm-project/commit/5033ea73bb01061feb09b3216c74619e1fbefdeb.diff
LOG: [LLDB][Minidump] Add breakpoint stop reasons to the minidump. (#108448)
Recently my coworker @jeffreytan81 pointed out that Minidumps don't show
breakpoints when collected. This was prior blocked because Minidumps
could only contain 1 exception, now that we support N signals/sections
we can save all the threads stopped on breakpoints.
Added:
lldb/test/API/functionalities/postmortem/minidump-new/linux-x86_64-exceptiondescription.yaml
Modified:
lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
llvm/include/llvm/BinaryFormat/Minidump.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
index f6c16b6e3d96ae..bcac5edbc1a793 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
@@ -75,8 +75,7 @@ Status MinidumpFileBuilder::AddHeaderAndCalculateDirectories() {
StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
if (stop_info_sp) {
const StopReason &stop_reason = stop_info_sp->GetStopReason();
- if (stop_reason == StopReason::eStopReasonException ||
- stop_reason == StopReason::eStopReasonSignal)
+ if (stop_reason != lldb::eStopReasonInvalid)
m_expected_directories++;
}
}
@@ -685,50 +684,45 @@ Status MinidumpFileBuilder::AddExceptions() {
Status error;
for (const ThreadSP &thread_sp : thread_list) {
StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
- bool add_exception = false;
- if (stop_info_sp) {
- switch (stop_info_sp->GetStopReason()) {
- case eStopReasonSignal:
- case eStopReasonException:
- add_exception = true;
- break;
- default:
- break;
- }
- }
- if (add_exception) {
- constexpr size_t minidump_exception_size =
- sizeof(llvm::minidump::ExceptionStream);
- error = AddDirectory(StreamType::Exception, minidump_exception_size);
- if (error.Fail())
- return error;
+ // If we don't have a stop info, or if it's invalid, skip.
+ if (!stop_info_sp ||
+ stop_info_sp->GetStopReason() == lldb::eStopReasonInvalid)
+ continue;
- StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
- RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
- Exception exp_record = {};
- exp_record.ExceptionCode =
- static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
- exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0);
- exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
- exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
- exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0);
- exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
- // exp_record.ExceptionInformation;
-
- ExceptionStream exp_stream;
- exp_stream.ThreadId =
- static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
- exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
- exp_stream.ExceptionRecord = exp_record;
- auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
- if (Iter != m_tid_to_reg_ctx.end()) {
- exp_stream.ThreadContext = Iter->second;
- } else {
- exp_stream.ThreadContext.DataSize = 0;
- exp_stream.ThreadContext.RVA = 0;
- }
- m_data.AppendData(&exp_stream, minidump_exception_size);
+ constexpr size_t minidump_exception_size =
+ sizeof(llvm::minidump::ExceptionStream);
+ error = AddDirectory(StreamType::Exception, minidump_exception_size);
+ if (error.Fail())
+ return error;
+
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ Exception exp_record = {};
+ exp_record.ExceptionCode =
+ static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
+ exp_record.ExceptionFlags =
+ static_cast<llvm::support::ulittle32_t>(Exception::LLDB_FLAG);
+ exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
+ exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
+ exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(1);
+ std::string description = stop_info_sp->GetDescription();
+ // We have 120 bytes to work with and it's unlikely description will
+ // overflow, but we gotta check.
+ memcpy(&exp_record.ExceptionInformation, description.c_str(),
+ std::max(description.size(), Exception::MaxParameterBytes));
+ exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
+ ExceptionStream exp_stream;
+ exp_stream.ThreadId =
+ static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
+ exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
+ exp_stream.ExceptionRecord = exp_record;
+ auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
+ if (Iter != m_tid_to_reg_ctx.end()) {
+ exp_stream.ThreadContext = Iter->second;
+ } else {
+ exp_stream.ThreadContext.DataSize = 0;
+ exp_stream.ThreadContext.RVA = 0;
}
+ m_data.AppendData(&exp_stream, minidump_exception_size);
}
return error;
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
index a4240f871c8a2f..58b284608bd535 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
@@ -175,5 +175,4 @@ class MinidumpFileBuilder {
lldb::FileUP m_core_file;
lldb_private::SaveCoreOptions m_save_core_options;
};
-
#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 5ea3db23f114c4..5b0df72130c161 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -276,8 +276,16 @@ void ProcessMinidump::RefreshStateAfterStop() {
// No stop.
return;
}
-
- stop_info = StopInfo::CreateStopReasonWithSignal(*stop_thread, signo);
+ const char *description = nullptr;
+ if (exception_stream.ExceptionRecord.ExceptionFlags ==
+ llvm::minidump::Exception::LLDB_FLAG)
+ description = reinterpret_cast<const char *>(
+ exception_stream.ExceptionRecord.ExceptionInformation);
+
+ llvm::StringRef description_str(description,
+ Exception::MaxParameterBytes);
+ stop_info = StopInfo::CreateStopReasonWithSignal(
+ *stop_thread, signo, description_str.str().c_str());
} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
stop_info = StopInfoMachException::CreateStopReasonWithMachException(
*stop_thread, exception_stream.ExceptionRecord.ExceptionCode, 2,
diff --git a/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
index 5a0b6e790a424c..8776d72ecbc027 100644
--- a/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
+++ b/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -524,3 +524,23 @@ def test_multiple_exceptions_or_signals(self):
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
stop_description = thread.GetStopDescription(256)
self.assertIn("SIGSEGV", stop_description)
+
+ def test_breakpoint_on_minidump(self):
+ """
+ Test that LLDB breakpoints are recorded in Minidumps
+ """
+ yaml = "linux-x86_64-exceptiondescription.yaml"
+ core = self.getBuildArtifact("breakpoint.core.dmp")
+ self.yaml2obj(yaml, core)
+ try:
+ # Create a target with the object file we just created from YAML
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore(core)
+ self.assertTrue(process, VALID_PROCESS)
+ thread = process.GetThreadAtIndex(0)
+ stop_reason = thread.GetStopDescription(256)
+ self.assertIn("breakpoint 1.1", stop_reason)
+ finally:
+ if os.path.isfile(core):
+ os.unlink(core)
diff --git a/lldb/test/API/functionalities/postmortem/minidump-new/linux-x86_64-exceptiondescription.yaml b/lldb/test/API/functionalities/postmortem/minidump-new/linux-x86_64-exceptiondescription.yaml
new file mode 100644
index 00000000000000..bf26e05cd775ae
--- /dev/null
+++ b/lldb/test/API/functionalities/postmortem/minidump-new/linux-x86_64-exceptiondescription.yaml
@@ -0,0 +1,37 @@
+--- !minidump
+Streams:
+ - Type: SystemInfo
+ Processor Arch: AMD64
+ Processor Level: 6
+ Processor Revision: 15876
+ Number of Processors: 40
+ Platform ID: Linux
+ CSD Version: 'Linux 3.13.0-91-generic'
+ CPU:
+ Vendor ID: GenuineIntel
+ Version Info: 0x00000000
+ Feature Info: 0x00000000
+ - Type: ThreadList
+ Threads:
+ - Thread Id: 0x31F222
+ Context: 00000000000000
+ Stack:
+ Start of Memory Range: 0x7FFFFFFFD660
+ Content: ''
+ - Type: Exception
+ Thread ID: 0x31F222
+ Exception Record:
+ Exception Code: 0x2
+ Exception Flags: 0x4C4C4442
+ Exception Address: 0x555555556671
+ Number of Parameters: 1
+ Parameter 0: 0x696F706B61657262
+ Parameter 1: 0x312E3120746E
+ Parameter 2: 0x1
+ Parameter 3: 0x8000000000000000
+ Parameter 4: 0x200000002
+ Parameter 5: 0x8000000000000002
+ Parameter 7: 0x555555556671
+ Parameter 8: 0x1
+ Thread Context: ''
+...
diff --git a/llvm/include/llvm/BinaryFormat/Minidump.h b/llvm/include/llvm/BinaryFormat/Minidump.h
index 8054e81322a92a..addff42982352f 100644
--- a/llvm/include/llvm/BinaryFormat/Minidump.h
+++ b/llvm/include/llvm/BinaryFormat/Minidump.h
@@ -246,6 +246,8 @@ static_assert(sizeof(Thread) == 48);
struct Exception {
static constexpr size_t MaxParameters = 15;
+ static constexpr size_t MaxParameterBytes = MaxParameters * sizeof(uint64_t);
+ static const uint32_t LLDB_FLAG = 'LLDB';
support::ulittle32_t ExceptionCode;
support::ulittle32_t ExceptionFlags;
More information about the lldb-commits
mailing list