[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