amccarth created this revision.
amccarth added a reviewer: zturner.
amccarth added a subscriber: lldb-commits.
Now when you do a thread list, you'll see the exception information in the stop
info for the thread that stopped.
I'd like to move the ExceptionRecord.h file to a common place as a separate
patch.
http://reviews.llvm.org/D12126
Files:
source/Plugins/Process/Windows/ExceptionRecord.h
source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
source/Plugins/Process/win-minidump/ProcessWinMiniDump.h
Index: source/Plugins/Process/win-minidump/ProcessWinMiniDump.h
===================================================================
--- source/Plugins/Process/win-minidump/ProcessWinMiniDump.h
+++ source/Plugins/Process/win-minidump/ProcessWinMiniDump.h
@@ -97,6 +97,15 @@
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.
Index: source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
===================================================================
--- source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
+++ source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp
@@ -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 @@
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 @@
m_target.SetArchitecture(DetermineArchitecture());
// TODO(amccarth): Build the module list.
- // TODO(amccarth): Read the exeception record.
+
+ ReadExceptionRecord();
return error;
@@ -146,18 +152,10 @@
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))
+ size_t size = 0;
+ auto thread_list_ptr = static_cast<const MINIDUMP_THREAD_LIST *>(FindDumpStream(ThreadListStream, &size));
+ if (thread_list_ptr)
{
- 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);
const ULONG32 thread_count = thread_list_ptr->NumberOfThreads;
assert(thread_count < std::numeric_limits<int>::max());
for (int i = 0; i < thread_count; ++i) {
@@ -172,6 +170,20 @@
void
ProcessWinMiniDump::RefreshStateAfterStop()
{
+ if (m_data_up && m_data_up->m_exception_sp)
+ {
+ 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 +314,10 @@
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))
+ size_t size = 0;
+ auto system_info_ptr = static_cast<const MINIDUMP_SYSTEM_INFO *>(FindDumpStream(SystemInfoStream, &size));
+ if (system_info_ptr)
{
- 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);
switch (system_info_ptr->ProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
@@ -327,3 +331,33 @@
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;
+}
Index: source/Plugins/Process/Windows/ExceptionRecord.h
===================================================================
--- source/Plugins/Process/Windows/ExceptionRecord.h
+++ source/Plugins/Process/Windows/ExceptionRecord.h
@@ -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 @@
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
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits