Index: cmake/LLDBDependencies.cmake =================================================================== --- cmake/LLDBDependencies.cmake +++ cmake/LLDBDependencies.cmake @@ -73,7 +73,7 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) list(APPEND LLDB_USED_LIBS lldbPluginProcessWindows - lldbPluginProcessElfCore + lldbPluginProcessWinMiniDump lldbPluginJITLoaderGDB Ws2_32 Rpcrt4 Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -59,6 +59,7 @@ #if defined(_MSC_VER) #include "lldb/Host/windows/windows.h" #include "Plugins/Process/Windows/ProcessWindows.h" +#include "Plugins/Process/win-minidump/ProcessWinMiniDump.h" #endif #if !defined(LLDB_DISABLE_PYTHON) @@ -246,6 +247,9 @@ JITLoaderGDB::Initialize(); ProcessElfCore::Initialize(); +#if defined(_MSC_VER) + ProcessWinMiniDump::Initialize(); +#endif MemoryHistoryASan::Initialize(); AddressSanitizerRuntime::Initialize(); @@ -347,6 +351,9 @@ JITLoaderGDB::Terminate(); ProcessElfCore::Terminate(); +#if defined(_MSC_VER) + ProcessWinMiniDump::Terminate(); +#endif MemoryHistoryASan::Terminate(); AddressSanitizerRuntime::Terminate(); SymbolVendorELF::Terminate(); Index: source/Plugins/Process/CMakeLists.txt =================================================================== --- source/Plugins/Process/CMakeLists.txt +++ source/Plugins/Process/CMakeLists.txt @@ -13,3 +13,4 @@ add_subdirectory(Utility) add_subdirectory(mach-core) add_subdirectory(elf-core) +add_subdirectory(win-minidump) Index: source/Plugins/Process/win-minidump/CMakeLists.txt =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories(../Utility) + +add_lldb_library(lldbPluginProcessWinMiniDump + ProcessWinMiniDump.cpp + RegisterContextWindowsMiniDump.cpp + ThreadWinMiniDump.cpp + ) Index: source/Plugins/Process/win-minidump/ProcessWinMiniDump.h =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/ProcessWinMiniDump.h @@ -0,0 +1,107 @@ +//===-- ProcessWinMiniDump.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessWinMiniDump_h_ +#define liblldb_ProcessWinMiniDump_h_ + +#include +#include + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Target/Process.h" + +struct ThreadData; + +class ProcessWinMiniDump : public lldb_private::Process +{ +public: + static lldb::ProcessSP + CreateInstance (lldb_private::Target& target, + lldb_private::Listener &listener, + const lldb_private::FileSpec *crash_file_path); + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + ProcessWinMiniDump(lldb_private::Target& target, + lldb_private::Listener &listener, + const lldb_private::FileSpec &core_file); + + virtual + ~ProcessWinMiniDump(); + + bool + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; + + lldb_private::Error + DoLoadCore() override; + + lldb_private::DynamicLoader * + GetDynamicLoader() override; + + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + lldb_private::Error + DoDestroy() override; + + void + RefreshStateAfterStop() override; + + bool + IsAlive() override; + + size_t + ReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + + size_t + DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + + lldb::addr_t + GetImageInfoAddress() override; + + lldb_private::ArchSpec + GetArchitecture(); + +protected: + void + Clear(); + + bool + UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + +private: + lldb_private::Error + MapMiniDumpIntoMemory(const char *file); + + lldb_private::ArchSpec + DetermineArchitecture(); + + // 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. + class Data; + std::unique_ptr m_data_up; +}; + +#endif // liblldb_ProcessWinMiniDump_h_ Index: source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/ProcessWinMiniDump.cpp @@ -0,0 +1,329 @@ +//===-- ProcessWinMiniDump.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessWinMiniDump.h" + +#include "lldb/Host/windows/windows.h" +#include + +#include +#include + +#include + +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/State.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/UnixSignals.h" +#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" + +#include "ThreadWinMiniDump.h" + +using namespace lldb_private; + +// Encapsulates the private data for ProcessWinMiniDump. +// TODO(amccarth): Determine if we need a mutex for access. +class ProcessWinMiniDump::Data +{ +public: + Data(); + ~Data(); + + FileSpec m_core_file; + 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 +}; + +ConstString +ProcessWinMiniDump::GetPluginNameStatic() +{ + static ConstString g_name("win-minidump"); + return g_name; +} + +const char * +ProcessWinMiniDump::GetPluginDescriptionStatic() +{ + return "Windows minidump plug-in."; +} + +void +ProcessWinMiniDump::Terminate() +{ + PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); +} + + +lldb::ProcessSP +ProcessWinMiniDump::CreateInstance(Target &target, Listener &listener, const FileSpec *crash_file) +{ + lldb::ProcessSP process_sp; + if (crash_file) + { + process_sp.reset(new ProcessWinMiniDump(target, listener, *crash_file)); + } + return process_sp; +} + +bool +ProcessWinMiniDump::CanDebug(Target &target, bool plugin_specified_by_name) +{ + // TODO(amccarth): Eventually, this needs some actual logic. + return true; +} + +ProcessWinMiniDump::ProcessWinMiniDump(Target& target, Listener &listener, + const FileSpec &core_file) : + Process(target, listener), + m_data_up(new Data) +{ + m_data_up->m_core_file = core_file; +} + +ProcessWinMiniDump::~ProcessWinMiniDump() +{ + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); +} + +ConstString +ProcessWinMiniDump::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ProcessWinMiniDump::GetPluginVersion() +{ + return 1; +} + + +Error +ProcessWinMiniDump::DoLoadCore() +{ + Error error; + + error = MapMiniDumpIntoMemory(m_data_up->m_core_file.GetCString()); + if (error.Fail()) + { + return error; + } + + m_target.SetArchitecture(DetermineArchitecture()); + // TODO(amccarth): Build the module list. + // TODO(amccarth): Read the exeception record. + + return error; + +} + +DynamicLoader * +ProcessWinMiniDump::GetDynamicLoader() +{ + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); + return m_dyld_ap.get(); +} + +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(static_cast(m_data_up->m_base_addr) + dir->Location.Rva)); + auto thread_list_ptr = static_cast(ptr); + const ULONG32 thread_count = thread_list_ptr->NumberOfThreads; + assert(thread_count < std::numeric_limits::max()); + for (int i = 0; i < thread_count; ++i) { + std::shared_ptr thread_sp(new ThreadWinMiniDump(*this, thread_list_ptr->Threads[i].ThreadId)); + new_thread_list.AddThread(thread_sp); + } + } + + return new_thread_list.GetSize(false) > 0; +} + +void +ProcessWinMiniDump::RefreshStateAfterStop() +{ +} + +Error +ProcessWinMiniDump::DoDestroy() +{ + return Error(); +} + +bool +ProcessWinMiniDump::IsAlive() +{ + return true; +} + +size_t +ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) +{ + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since in core files we have it all cached our our core file anyway. + return DoReadMemory(addr, buf, size, error); +} + +size_t +ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) +{ + // TODO + return 0; +} + +void +ProcessWinMiniDump::Clear() +{ + m_thread_list.Clear(); +} + +void +ProcessWinMiniDump::Initialize() +{ + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() + { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + }); +} + +lldb::addr_t +ProcessWinMiniDump::GetImageInfoAddress() +{ + Target *target = &GetTarget(); + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(target); + + if (addr.IsValid()) + return addr.GetLoadAddress(target); + return LLDB_INVALID_ADDRESS; +} + +ArchSpec +ProcessWinMiniDump::GetArchitecture() +{ + // TODO + return ArchSpec(); +} + + +ProcessWinMiniDump::Data::Data() : + m_dump_file(INVALID_HANDLE_VALUE), + m_mapping(NULL), + m_base_addr(nullptr) +{ +} + +ProcessWinMiniDump::Data::~Data() +{ + if (m_base_addr) + { + ::UnmapViewOfFile(m_base_addr); + m_base_addr = nullptr; + } + if (m_mapping) + { + ::CloseHandle(m_mapping); + m_mapping = NULL; + } + if (m_dump_file != INVALID_HANDLE_VALUE) + { + ::CloseHandle(m_dump_file); + m_dump_file = INVALID_HANDLE_VALUE; + } +} + +Error +ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file) +{ + Error error; + + m_data_up->m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (m_data_up->m_dump_file == INVALID_HANDLE_VALUE) + { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + m_data_up->m_mapping = ::CreateFileMapping(m_data_up->m_dump_file, NULL, + PAGE_READONLY, 0, 0, NULL); + if (m_data_up->m_mapping == NULL) + { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + m_data_up->m_base_addr = ::MapViewOfFile(m_data_up->m_mapping, FILE_MAP_READ, 0, 0, 0); + if (m_data_up->m_base_addr == NULL) + { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + return error; +} + + +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(static_cast(m_data_up->m_base_addr) + dir->Location.Rva)); + auto system_info_ptr = static_cast(ptr); + switch (system_info_ptr->ProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + return ArchSpec(eArchTypeCOFF, IMAGE_FILE_MACHINE_I386, LLDB_INVALID_CPUTYPE); + case PROCESSOR_ARCHITECTURE_AMD64: + return ArchSpec(eArchTypeCOFF, IMAGE_FILE_MACHINE_AMD64, LLDB_INVALID_CPUTYPE); + default: + break; + } + } + + return ArchSpec(); // invalid or unknown +} Index: source/Plugins/Process/win-minidump/RegisterContextWindowsMiniDump.h =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/RegisterContextWindowsMiniDump.h @@ -0,0 +1,73 @@ +//===-- RegisterContextWindowsMiniDump.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextWindowsMiniDump_H_ +#define liblldb_RegisterContextWindowsMiniDump_H_ + +#include "lldb/lldb-forward.h" +#include "lldb/Target/RegisterContext.h" + + +namespace lldb_private +{ + +class Thread; + +class RegisterContextWindowsMiniDump : public lldb_private::RegisterContext +{ + public: + RegisterContextWindowsMiniDump(Thread &thread, uint32_t concrete_frame_idx); + + virtual ~RegisterContextWindowsMiniDump(); + + void + InvalidateAllRegisters() override; + + size_t + GetRegisterCount() override; + + const RegisterInfo * + GetRegisterInfoAtIndex(size_t reg) override; + + size_t + GetRegisterSetCount() override; + + const RegisterSet * + GetRegisterSet(size_t reg_set) override; + + bool + ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + + bool + WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + + uint32_t NumSupportedHardwareBreakpoints() override; + + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + + uint32_t NumSupportedHardwareWatchpoints() override; + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; + + bool ClearHardwareWatchpoint(uint32_t hw_index) override; + + bool HardwareSingleStep(bool enable) override; +}; + +} + +#endif // #ifndef liblldb_RegisterContextWindowsMiniDump_H_ Index: source/Plugins/Process/win-minidump/RegisterContextWindowsMiniDump.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/RegisterContextWindowsMiniDump.cpp @@ -0,0 +1,146 @@ +//===-- RegisterContextWindowsMiniDump.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-private-types.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Host/windows/HostThreadWindows.h" +#include "lldb/Host/windows/windows.h" + +#include "RegisterContextWindowsMiniDump.h" + +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +// This is a do-nothing stub implementation for now. + +RegisterContextWindowsMiniDump::RegisterContextWindowsMiniDump(Thread &thread, uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx) +{ +} + +RegisterContextWindowsMiniDump::~RegisterContextWindowsMiniDump() +{ +} + +void +RegisterContextWindowsMiniDump::InvalidateAllRegisters() +{ +} + +size_t +RegisterContextWindowsMiniDump::GetRegisterCount() +{ + return 0; +} + +const RegisterInfo * +RegisterContextWindowsMiniDump::GetRegisterInfoAtIndex(size_t reg) +{ + return nullptr; +} + +size_t +RegisterContextWindowsMiniDump::GetRegisterSetCount() +{ + return 0; +} + +const RegisterSet * +RegisterContextWindowsMiniDump::GetRegisterSet(size_t reg_set) +{ + return nullptr; +} + +bool +RegisterContextWindowsMiniDump::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) +{ + return false; +} + +bool +RegisterContextWindowsMiniDump::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) +{ + return false; +} + +bool +RegisterContextWindowsMiniDump::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextWindowsMiniDump::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) +{ + return false; +} + +uint32_t +RegisterContextWindowsMiniDump::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} + +uint32_t +RegisterContextWindowsMiniDump::NumSupportedHardwareBreakpoints() +{ + // Support for hardware breakpoints not yet implemented. + return 0; +} + +uint32_t +RegisterContextWindowsMiniDump::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) +{ + return 0; +} + +bool +RegisterContextWindowsMiniDump::ClearHardwareBreakpoint(uint32_t hw_idx) +{ + return false; +} + +uint32_t +RegisterContextWindowsMiniDump::NumSupportedHardwareWatchpoints() +{ + // Support for hardware watchpoints not yet implemented. + return 0; +} + +uint32_t +RegisterContextWindowsMiniDump::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) +{ + return 0; +} + +bool +RegisterContextWindowsMiniDump::ClearHardwareWatchpoint(uint32_t hw_index) +{ + return false; +} + +bool +RegisterContextWindowsMiniDump::HardwareSingleStep(bool enable) +{ + return false; +} Index: source/Plugins/Process/win-minidump/ThreadWinMiniDump.h =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/ThreadWinMiniDump.h @@ -0,0 +1,51 @@ +//===-- ThreadWinMiniDump.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadWinMiniDump_h_ +#define liblldb_ThreadWinMiniDump_h_ + +#include + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Target/Thread.h" + +class ThreadWinMiniDump : public lldb_private::Thread +{ +public: + ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid); + + virtual + ~ThreadWinMiniDump(); + + void + RefreshStateAfterStop() override; + + lldb::RegisterContextSP + GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + + void + ClearStackFrames() override; + + const char * + GetName() override; + + void + SetName(const char *name); + +protected: + std::string m_thread_name; + lldb::RegisterContextSP m_reg_context_sp; + + bool CalculateStopInfo() override; +}; + +#endif Index: source/Plugins/Process/win-minidump/ThreadWinMiniDump.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/win-minidump/ThreadWinMiniDump.cpp @@ -0,0 +1,80 @@ +//===-- ThreadWinMiniDump.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ThreadWinMiniDump.h" + +// Windows includes +#include "lldb/Host/windows/windows.h" +#include + +#include "ProcessWinMiniDump.h" +#include "RegisterContextWindowsMiniDump.h" + +using namespace lldb; +using namespace lldb_private; + +// This is a minimal implementation in order to get something running. It will +// be fleshed out as more mini-dump functionality is added. + +ThreadWinMiniDump::ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid) : + Thread(process, tid), + m_thread_name() +{ +} + +ThreadWinMiniDump::~ThreadWinMiniDump() +{ +} + +void +ThreadWinMiniDump::RefreshStateAfterStop() +{ +} + +lldb::RegisterContextSP +ThreadWinMiniDump::GetRegisterContext() +{ + if (m_reg_context_sp.get() == NULL) { + m_reg_context_sp = CreateRegisterContextForFrame (NULL); + } + return m_reg_context_sp; +} + +lldb::RegisterContextSP +ThreadWinMiniDump::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) +{ + const uint32_t concrete_frame_idx = (frame) ? frame->GetConcreteFrameIndex() : 0; + RegisterContextSP reg_ctx_sp(new RegisterContextWindowsMiniDump(*this, concrete_frame_idx)); + return reg_ctx_sp; +} + +void +ThreadWinMiniDump::ClearStackFrames() +{ +} + +const char * +ThreadWinMiniDump::GetName() +{ + return m_thread_name.empty() ? nullptr : m_thread_name.c_str(); +} + +void +ThreadWinMiniDump::SetName(const char *name) +{ + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); +} + +bool ThreadWinMiniDump::CalculateStopInfo() +{ + return false; +}