[Lldb-commits] [lldb] r245495 - Read exception records from Windows mini dump

Adrian McCarthy via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 19 13:43:23 PDT 2015


Author: amccarth
Date: Wed Aug 19 15:43:22 2015
New Revision: 245495

URL: http://llvm.org/viewvc/llvm-project?rev=245495&view=rev
Log:
Read exception records from Windows mini dump

Differential Revision: http://reviews.llvm.org/D12126

Modified:
    lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
    lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
    lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.h

Modified: lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h?rev=245495&r1=245494&r2=245495&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h Wed Aug 19 15:43:22 2015
@@ -14,6 +14,7 @@
 
 #include "lldb/lldb-forward.h"
 #include "lldb/Host/windows/windows.h"
+#include <DbgHelp.h>
 
 #include <memory>
 #include <vector>
@@ -40,6 +41,24 @@ class ExceptionRecord
         m_thread_id = thread_id;
         m_arguments.assign(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters);
     }
+
+    // MINIDUMP_EXCEPTIONs are almost identical to EXCEPTION_RECORDs.
+    ExceptionRecord(const MINIDUMP_EXCEPTION &record, lldb::tid_t thread_id) :
+        m_code(record.ExceptionCode),
+        m_continuable(record.ExceptionFlags == 0),
+        m_next_exception(nullptr),
+        m_exception_addr(static_cast<lldb::addr_t>(record.ExceptionAddress)),
+        m_thread_id(thread_id),
+        m_arguments(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters)
+    {
+        // Set up link to nested exception.
+        if (record.ExceptionRecord)
+        {
+            m_next_exception.reset(new ExceptionRecord(*reinterpret_cast<const MINIDUMP_EXCEPTION *>(record.ExceptionRecord),
+                                                       thread_id));
+        }
+    }
+
     virtual ~ExceptionRecord() {}
 
     DWORD

Modified: lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp?rev=245495&r1=245494&r2=245495&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp (original)
+++ lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp Wed Aug 19 15:43:22 2015
@@ -24,11 +24,15 @@
 #include "lldb/Core/State.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/UnixSignals.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
 #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
 
+#include "../windows/ExceptionRecord.h"  // TODO(amccarth):  move this file to a common location
 #include "ThreadWinMiniDump.h"
 
 using namespace lldb_private;
@@ -45,6 +49,7 @@ public:
     HANDLE m_dump_file;  // handle to the open minidump file
     HANDLE m_mapping;  // handle to the file mapping for the minidump file
     void * m_base_addr;  // base memory address of the minidump
+    std::shared_ptr<ExceptionRecord> m_exception_sp;
 };
 
 ConstString
@@ -129,7 +134,8 @@ ProcessWinMiniDump::DoLoadCore()
 
     m_target.SetArchitecture(DetermineArchitecture());
     // TODO(amccarth):  Build the module list.
-    // TODO(amccarth):  Read the exeception record.
+
+    ReadExceptionRecord();
 
     return error;
 
@@ -146,21 +152,12 @@ ProcessWinMiniDump::GetDynamicLoader()
 bool
 ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
-    assert(m_data_up != nullptr);
-    assert(m_data_up->m_base_addr != 0);
-
-    MINIDUMP_DIRECTORY *dir = nullptr;
-    void *ptr = nullptr;
-    ULONG size = 0;
-    if (::MiniDumpReadDumpStream(m_data_up->m_base_addr, ThreadListStream, &dir, &ptr, &size))
-    {
-        assert(dir->StreamType == ThreadListStream);
-        assert(size == dir->Location.DataSize);
-        assert(ptr == static_cast<void*>(static_cast<char*>(m_data_up->m_base_addr) + dir->Location.Rva));
-        auto thread_list_ptr = static_cast<const MINIDUMP_THREAD_LIST *>(ptr);
+    size_t size = 0;
+    auto thread_list_ptr = static_cast<const MINIDUMP_THREAD_LIST *>(FindDumpStream(ThreadListStream, &size));
+    if (thread_list_ptr)
+    {
         const ULONG32 thread_count = thread_list_ptr->NumberOfThreads;
-        assert(thread_count < std::numeric_limits<int>::max());
-        for (int i = 0; i < thread_count; ++i) {
+        for (ULONG32 i = 0; i < thread_count; ++i) {
             std::shared_ptr<ThreadWinMiniDump> thread_sp(new ThreadWinMiniDump(*this, thread_list_ptr->Threads[i].ThreadId));
             new_thread_list.AddThread(thread_sp);
         }
@@ -172,6 +169,20 @@ ProcessWinMiniDump::UpdateThreadList(Thr
 void
 ProcessWinMiniDump::RefreshStateAfterStop()
 {
+    if (!m_data_up) return;
+    if (!m_data_up->m_exception_sp) return;
+
+    auto active_exception = m_data_up->m_exception_sp;
+    std::string desc;
+    llvm::raw_string_ostream desc_stream(desc);
+    desc_stream << "Exception "
+                << llvm::format_hex(active_exception->GetExceptionCode(), 8)
+                << " encountered at address "
+                << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
+    m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
+    auto stop_thread = m_thread_list.GetSelectedThread();
+    auto stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
+    stop_thread->SetStopInfo(stop_info);
 }
 
 Error
@@ -302,18 +313,10 @@ ProcessWinMiniDump::MapMiniDumpIntoMemor
 ArchSpec
 ProcessWinMiniDump::DetermineArchitecture()
 {
-    assert(m_data_up != nullptr);
-    assert(m_data_up->m_base_addr != 0);
-
-    MINIDUMP_DIRECTORY *dir = nullptr;
-    void *ptr = nullptr;
-    ULONG size = 0;
-    if (::MiniDumpReadDumpStream(m_data_up->m_base_addr, SystemInfoStream, &dir, &ptr, &size))
-    {
-        assert(dir->StreamType == SystemInfoStream);
-        assert(size == dir->Location.DataSize);
-        assert(ptr == static_cast<void*>(static_cast<char*>(m_data_up->m_base_addr) + dir->Location.Rva));
-        auto system_info_ptr = static_cast<const MINIDUMP_SYSTEM_INFO *>(ptr);
+    size_t size = 0;
+    auto system_info_ptr = static_cast<const MINIDUMP_SYSTEM_INFO *>(FindDumpStream(SystemInfoStream, &size));
+    if (system_info_ptr)
+    {
         switch (system_info_ptr->ProcessorArchitecture)
         {
         case PROCESSOR_ARCHITECTURE_INTEL:
@@ -327,3 +330,33 @@ ProcessWinMiniDump::DetermineArchitectur
 
     return ArchSpec();  // invalid or unknown
 }
+
+void
+ProcessWinMiniDump::ReadExceptionRecord() {
+    size_t size = 0;
+    auto exception_stream_ptr = static_cast<MINIDUMP_EXCEPTION_STREAM*>(FindDumpStream(ExceptionStream, &size));
+    if (exception_stream_ptr)
+    {
+        m_data_up->m_exception_sp.reset(new ExceptionRecord(exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId));
+    }
+}
+
+void *
+ProcessWinMiniDump::FindDumpStream(unsigned stream_number, size_t *size_out) {
+    void *stream = nullptr;
+    *size_out = 0;
+
+    assert(m_data_up != nullptr);
+    assert(m_data_up->m_base_addr != 0);
+
+    MINIDUMP_DIRECTORY *dir = nullptr;
+    if (::MiniDumpReadDumpStream(m_data_up->m_base_addr, stream_number, &dir, nullptr, nullptr) &&
+        dir != nullptr && dir->Location.DataSize > 0)
+    {
+        assert(dir->StreamType == stream_number);
+        *size_out = dir->Location.DataSize;
+        stream = static_cast<void*>(static_cast<char*>(m_data_up->m_base_addr) + dir->Location.Rva);
+    }
+
+    return stream;
+}

Modified: lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.h?rev=245495&r1=245494&r2=245495&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.h (original)
+++ lldb/trunk/source/Plugins/Process/win-minidump/ProcessWinMiniDump.h Wed Aug 19 15:43:22 2015
@@ -97,6 +97,15 @@ private:
     lldb_private::ArchSpec
     DetermineArchitecture();
 
+    void
+    ReadExceptionRecord();
+
+    // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant
+    // checks.  If there's a failure (e.g., if the requested stream doesn't exist),
+    // the function returns nullptr and sets *size_out to 0.
+    void *
+    FindDumpStream(unsigned stream_number, size_t *size_out);
+
     // Isolate the data to keep Windows-specific types out of this header.  Can't
     // use the typical pimpl idiom because the implementation of this class also
     // needs access to public and protected members of the base class.




More information about the lldb-commits mailing list