diff options
author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
---|---|---|
committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Plugins/Process/Windows | |
parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
Diffstat (limited to 'lldb/source/Plugins/Process/Windows')
36 files changed, 3427 insertions, 3680 deletions
diff --git a/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h b/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h index 79dae3fca4e..e99a75e023e 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h +++ b/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h @@ -10,15 +10,14 @@ #ifndef liblldb_Plugins_Process_Windows_ExceptionRecord_H_ #define liblldb_Plugins_Process_Windows_ExceptionRecord_H_ -#include "lldb/lldb-forward.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-forward.h" #include <DbgHelp.h> #include <memory> #include <vector> -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- // ExceptionRecord @@ -26,73 +25,55 @@ namespace lldb_private // ExceptionRecord defines an interface which allows implementors to receive // notification of events that happen in a debugged process. //---------------------------------------------------------------------- -class ExceptionRecord -{ - public: - ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) - { - m_code = record.ExceptionCode; - m_continuable = (record.ExceptionFlags == 0); - if (record.ExceptionRecord) - m_next_exception.reset(new ExceptionRecord(*record.ExceptionRecord, thread_id)); - m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress); - m_thread_id = thread_id; - m_arguments.assign(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters); - } +class ExceptionRecord { +public: + ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) { + m_code = record.ExceptionCode; + m_continuable = (record.ExceptionFlags == 0); + if (record.ExceptionRecord) + m_next_exception.reset( + new ExceptionRecord(*record.ExceptionRecord, thread_id)); + m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress); + 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), + // 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)); - } + 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() {} + virtual ~ExceptionRecord() {} - DWORD - GetExceptionCode() const - { - return m_code; - } - bool - IsContinuable() const - { - return m_continuable; - } - const ExceptionRecord * - GetNextException() const - { - return m_next_exception.get(); - } - lldb::addr_t - GetExceptionAddress() const - { - return m_exception_addr; - } + DWORD + GetExceptionCode() const { return m_code; } + bool IsContinuable() const { return m_continuable; } + const ExceptionRecord *GetNextException() const { + return m_next_exception.get(); + } + lldb::addr_t GetExceptionAddress() const { return m_exception_addr; } - lldb::tid_t - GetThreadID() const - { - return m_thread_id; - } + lldb::tid_t GetThreadID() const { return m_thread_id; } - private: - DWORD m_code; - bool m_continuable; - std::shared_ptr<ExceptionRecord> m_next_exception; - lldb::addr_t m_exception_addr; - lldb::tid_t m_thread_id; - std::vector<ULONG_PTR> m_arguments; +private: + DWORD m_code; + bool m_continuable; + std::shared_ptr<ExceptionRecord> m_next_exception; + lldb::addr_t m_exception_addr; + lldb::tid_t m_thread_id; + std::vector<ULONG_PTR> m_arguments; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/NtStructures.h b/lldb/source/Plugins/Process/Windows/Common/NtStructures.h index 6c688d9068d..6826b98c769 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NtStructures.h +++ b/lldb/source/Plugins/Process/Windows/Common/NtStructures.h @@ -15,18 +15,17 @@ // This describes the layout of a TEB (Thread Environment Block) for a 64-bit // process. It's adapted from the 32-bit TEB in winternl.h. Currently, we care // only about the position of the TlsSlots. -struct TEB64 -{ - ULONG64 Reserved1[12]; - ULONG64 ProcessEnvironmentBlock; - ULONG64 Reserved2[399]; - BYTE Reserved3[1952]; - ULONG64 TlsSlots[64]; - BYTE Reserved4[8]; - ULONG64 Reserved5[26]; - ULONG64 ReservedForOle; // Windows 2000 only - ULONG64 Reserved6[4]; - ULONG64 TlsExpansionSlots; +struct TEB64 { + ULONG64 Reserved1[12]; + ULONG64 ProcessEnvironmentBlock; + ULONG64 Reserved2[399]; + BYTE Reserved3[1952]; + ULONG64 TlsSlots[64]; + BYTE Reserved4[8]; + ULONG64 Reserved5[26]; + ULONG64 ReservedForOle; // Windows 2000 only + ULONG64 Reserved6[4]; + ULONG64 TlsExpansionSlots; }; #endif diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 2c3f9fbecf9..62533651d83 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -23,78 +23,63 @@ using namespace lldb; using namespace lldb_private; -namespace lldb_private -{ +namespace lldb_private { //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) - : lldb_private::Process(target_sp, listener_sp) -{ -} +ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp) + : lldb_private::Process(target_sp, listener_sp) {} -ProcessWindows::~ProcessWindows() -{ -} +ProcessWindows::~ProcessWindows() {} -size_t -ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("GetSTDOUT unsupported on Windows"); - return 0; +size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) { + error.SetErrorString("GetSTDOUT unsupported on Windows"); + return 0; } -size_t -ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("GetSTDERR unsupported on Windows"); - return 0; +size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) { + error.SetErrorString("GetSTDERR unsupported on Windows"); + return 0; } -size_t -ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("PutSTDIN unsupported on Windows"); - return 0; +size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, + Error &error) { + error.SetErrorString("PutSTDIN unsupported on Windows"); + return 0; } //------------------------------------------------------------------------------ // ProcessInterface protocol. - -lldb::addr_t -ProcessWindows::GetImageInfoAddress() -{ - Target &target = GetTarget(); - ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(&target); - if (addr.IsValid()) - return addr.GetLoadAddress(&target); - else - return LLDB_INVALID_ADDRESS; +lldb::addr_t ProcessWindows::GetImageInfoAddress() { + Target &target = GetTarget(); + ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(&target); + if (addr.IsValid()) + return addr.GetLoadAddress(&target); + else + return LLDB_INVALID_ADDRESS; } -// The Windows page protection bits are NOT independent masks that can be bitwise-ORed +// The Windows page protection bits are NOT independent masks that can be +// bitwise-ORed // together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE | PAGE_READ). -// To test for an access type, it's necessary to test for any of the bits that provide +// To test for an access type, it's necessary to test for any of the bits that +// provide // that access type. -bool -ProcessWindows::IsPageReadable(uint32_t protect) -{ - return (protect & PAGE_NOACCESS) == 0; +bool ProcessWindows::IsPageReadable(uint32_t protect) { + return (protect & PAGE_NOACCESS) == 0; } -bool -ProcessWindows::IsPageWritable(uint32_t protect) -{ - return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY)) != 0; +bool ProcessWindows::IsPageWritable(uint32_t protect) { + return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | + PAGE_READWRITE | PAGE_WRITECOPY)) != 0; } -bool -ProcessWindows::IsPageExecutable(uint32_t protect) -{ - return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0; +bool ProcessWindows::IsPageExecutable(uint32_t protect) { + return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY)) != 0; } - } diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h index 0ee42e2ae1f..bf96180488c 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h @@ -11,42 +11,38 @@ #define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ // Other libraries and framework includes -#include "lldb/lldb-forward.h" #include "lldb/Core/Error.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { -class ProcessWindows : public lldb_private::Process -{ +class ProcessWindows : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessWindows(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp); + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - ~ProcessWindows(); + ~ProcessWindows(); - size_t GetSTDOUT(char *buf, size_t buf_size, lldb_private::Error &error) override; - size_t GetSTDERR(char *buf, size_t buf_size, lldb_private::Error &error) override; - size_t PutSTDIN(const char *buf, size_t buf_size, lldb_private::Error &error) override; + size_t GetSTDOUT(char *buf, size_t buf_size, + lldb_private::Error &error) override; + size_t GetSTDERR(char *buf, size_t buf_size, + lldb_private::Error &error) override; + size_t PutSTDIN(const char *buf, size_t buf_size, + lldb_private::Error &error) override; - lldb::addr_t GetImageInfoAddress() override; + lldb::addr_t GetImageInfoAddress() override; protected: - // These decode the page protection bits. - static bool - IsPageReadable(uint32_t protect); + // These decode the page protection bits. + static bool IsPageReadable(uint32_t protect); - static bool - IsPageWritable(uint32_t protect); + static bool IsPageWritable(uint32_t protect); - static bool - IsPageExecutable(uint32_t protect); + static bool IsPageExecutable(uint32_t protect); }; - } -#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ +#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp index 47722c5146b..242c1996bdd 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp @@ -18,177 +18,151 @@ using namespace lldb; using namespace lldb_private; - // We want to avoid global constructors where code needs to be run so here we // control access to our static g_log_sp by hiding it in a singleton function // that will construct the static g_log_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = nullptr; +static Log *g_log = nullptr; static llvm::ManagedStatic<std::once_flag> g_once_flag; -void -ProcessWindowsLog::Initialize() -{ - static ConstString g_name("windows"); - - std::call_once(*g_once_flag, [](){ - Log::Callbacks log_callbacks = { - DisableLog, - EnableLog, - ListLogCategories - }; - - Log::RegisterLogChannel(g_name, log_callbacks); - RegisterPluginName(g_name); - }); -} +void ProcessWindowsLog::Initialize() { + static ConstString g_name("windows"); -void -ProcessWindowsLog::Terminate() -{ -} + std::call_once(*g_once_flag, []() { + Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; -Log * -ProcessWindowsLog::GetLog() -{ - return (g_log_enabled) ? g_log : nullptr; + Log::RegisterLogChannel(g_name, log_callbacks); + RegisterPluginName(g_name); + }); } -bool -ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) -{ - Log *log = GetLog(); - if (!log) - return false; +void ProcessWindowsLog::Terminate() {} - uint32_t log_mask = log->GetMask().Get(); - if (req == LogMaskReq::All) - return ((log_mask & mask) == mask); - else - return (log_mask & mask); +Log *ProcessWindowsLog::GetLog() { return (g_log_enabled) ? g_log : nullptr; } + +bool ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) { + Log *log = GetLog(); + if (!log) + return false; + + uint32_t log_mask = log->GetMask().Get(); + if (req == LogMaskReq::All) + return ((log_mask & mask) == mask); + else + return (log_mask & mask); } -static uint32_t -GetFlagBits(const char *arg) -{ - if (::strcasecmp(arg, "all") == 0 ) return WINDOWS_LOG_ALL; - else if (::strcasecmp(arg, "break") == 0 ) return WINDOWS_LOG_BREAKPOINTS; - else if (::strcasecmp(arg, "event") == 0 ) return WINDOWS_LOG_EVENT; - else if (::strcasecmp(arg, "exception") == 0 ) return WINDOWS_LOG_EXCEPTION; - else if (::strcasecmp(arg, "memory") == 0 ) return WINDOWS_LOG_MEMORY; - else if (::strcasecmp(arg, "process") == 0 ) return WINDOWS_LOG_PROCESS; - else if (::strcasecmp(arg, "registers") == 0 ) return WINDOWS_LOG_REGISTERS; - else if (::strcasecmp(arg, "step") == 0 ) return WINDOWS_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0 ) return WINDOWS_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0 ) return WINDOWS_LOG_VERBOSE; - return 0; +static uint32_t GetFlagBits(const char *arg) { + if (::strcasecmp(arg, "all") == 0) + return WINDOWS_LOG_ALL; + else if (::strcasecmp(arg, "break") == 0) + return WINDOWS_LOG_BREAKPOINTS; + else if (::strcasecmp(arg, "event") == 0) + return WINDOWS_LOG_EVENT; + else if (::strcasecmp(arg, "exception") == 0) + return WINDOWS_LOG_EXCEPTION; + else if (::strcasecmp(arg, "memory") == 0) + return WINDOWS_LOG_MEMORY; + else if (::strcasecmp(arg, "process") == 0) + return WINDOWS_LOG_PROCESS; + else if (::strcasecmp(arg, "registers") == 0) + return WINDOWS_LOG_REGISTERS; + else if (::strcasecmp(arg, "step") == 0) + return WINDOWS_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + return WINDOWS_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + return WINDOWS_LOG_VERBOSE; + return 0; } -void -ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) -{ - Log *log (GetLog()); - if (log) - { - uint32_t flag_bits = 0; - - if (args[0] != nullptr) - { - flag_bits = log->GetMask().Get(); - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits &= ~bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - } +void ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) { + Log *log(GetLog()); + if (log) { + uint32_t flag_bits = 0; - log->GetMask().Reset(flag_bits); - if (flag_bits == 0) - { - g_log_enabled = false; - log->SetStream(lldb::StreamSP()); + if (args[0] != nullptr) { + flag_bits = log->GetMask().Get(); + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits &= ~bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); } + } } - return; -} - -Log * -ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); + log->GetMask().Reset(flag_bits); + if (flag_bits == 0) { + g_log_enabled = false; + log->SetStream(lldb::StreamSP()); } + } + return; +} + +Log *ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, + const char **args, Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits = 0; + if (g_log) + flag_bits = g_log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log) - { - bool got_unknown_category = false; - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits |= bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } + + if (g_log) { + bool got_unknown_category = false; + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits |= bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListLogCategories(feedback_strm); } - if (flag_bits == 0) - flag_bits = WINDOWS_LOG_ALL; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - g_log_enabled = true; + } } - return g_log; + if (flag_bits == 0) + flag_bits = WINDOWS_LOG_ALL; + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + g_log_enabled = true; + } + return g_log; } -void -ProcessWindowsLog::ListLogCategories(Stream *strm) -{ - strm->Printf("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " break - log breakpoints\n" - " event - log low level debugger events\n" - " exception - log exception information\n" - " memory - log memory reads and writes\n" - " process - log process events and activities\n" - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n", - ProcessWindowsLog::m_pluginname); +void ProcessWindowsLog::ListLogCategories(Stream *strm) { + strm->Printf("Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " break - log breakpoints\n" + " event - log low level debugger events\n" + " exception - log exception information\n" + " memory - log memory reads and writes\n" + " process - log process events and activities\n" + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n", + ProcessWindowsLog::m_pluginname); } const char *ProcessWindowsLog::m_pluginname = ""; diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h index d798d131fae..cbb99e8d907 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h @@ -12,85 +12,80 @@ #include "lldb/Core/Log.h" -#define WINDOWS_LOG_VERBOSE (1u << 0) -#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations -#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions -#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations -#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls -#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations -#define WINDOWS_LOG_STEP (1u << 5) // Log step operations -#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations -#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events -#define WINDOWS_LOG_ALL (UINT32_MAX) - -enum class LogMaskReq -{ - All, - Any -}; - -class ProcessWindowsLog -{ - static const char *m_pluginname; +#define WINDOWS_LOG_VERBOSE (1u << 0) +#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations +#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions +#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations +#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls +#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations +#define WINDOWS_LOG_STEP (1u << 5) // Log step operations +#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations +#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events +#define WINDOWS_LOG_ALL (UINT32_MAX) + +enum class LogMaskReq { All, Any }; + +class ProcessWindowsLog { + static const char *m_pluginname; public: - // --------------------------------------------------------------------- - // Public Static Methods - // --------------------------------------------------------------------- - static void - Initialize(); - - static void - Terminate(); - - static void - RegisterPluginName(const char *pluginName) - { - m_pluginname = pluginName; - } - - static void - RegisterPluginName(lldb_private::ConstString pluginName) - { - m_pluginname = pluginName.GetCString(); - } - - static bool - TestLogFlags(uint32_t mask, LogMaskReq req); - - static lldb_private::Log * - GetLog(); - - static void - DisableLog(const char **args, lldb_private::Stream *feedback_strm); - - static lldb_private::Log * - EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options, - const char **args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories(lldb_private::Stream *strm); + // --------------------------------------------------------------------- + // Public Static Methods + // --------------------------------------------------------------------- + static void Initialize(); + + static void Terminate(); + + static void RegisterPluginName(const char *pluginName) { + m_pluginname = pluginName; + } + + static void RegisterPluginName(lldb_private::ConstString pluginName) { + m_pluginname = pluginName.GetCString(); + } + + static bool TestLogFlags(uint32_t mask, LogMaskReq req); + + static lldb_private::Log *GetLog(); + + static void DisableLog(const char **args, + lldb_private::Stream *feedback_strm); + + static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, + uint32_t log_options, const char **args, + lldb_private::Stream *feedback_strm); + + static void ListLogCategories(lldb_private::Stream *strm); }; -#define WINLOGF_IF(Flags, Req, Method, ...) \ - { \ - if (ProcessWindowsLog::TestLogFlags(Flags, Req)) \ - { \ - Log *log = ProcessWindowsLog::GetLog(); \ - if (log) \ - log->Method(__VA_ARGS__); \ - } \ - } - -#define WINLOG_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Printf, __VA_ARGS__) -#define WINLOG_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Printf, __VA_ARGS__) -#define WINLOGV_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Verbose, __VA_ARGS__) -#define WINLOGV_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Verbose, __VA_ARGS__) -#define WINLOGD_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Debug, __VA_ARGS__) -#define WINLOGD_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Debug, __VA_ARGS__) -#define WINERR_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Error, __VA_ARGS__) -#define WINERR_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Error, __VA_ARGS__) -#define WINWARN_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Warning, __VA_ARGS__) -#define WINWARN_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Warning, __VA_ARGS__) - -#endif // liblldb_ProcessWindowsLog_h_ +#define WINLOGF_IF(Flags, Req, Method, ...) \ + { \ + if (ProcessWindowsLog::TestLogFlags(Flags, Req)) { \ + Log *log = ProcessWindowsLog::GetLog(); \ + if (log) \ + log->Method(__VA_ARGS__); \ + } \ + } + +#define WINLOG_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Printf, __VA_ARGS__) +#define WINLOG_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Printf, __VA_ARGS__) +#define WINLOGV_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Verbose, __VA_ARGS__) +#define WINLOGV_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Verbose, __VA_ARGS__) +#define WINLOGD_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Debug, __VA_ARGS__) +#define WINLOGD_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Debug, __VA_ARGS__) +#define WINERR_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Error, __VA_ARGS__) +#define WINERR_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Error, __VA_ARGS__) +#define WINWARN_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Warning, __VA_ARGS__) +#define WINWARN_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Warning, __VA_ARGS__) + +#endif // liblldb_ProcessWindowsLog_h_ diff --git a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp index d61675f09b1..73bcd4ac38a 100644 --- a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#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 "lldb/lldb-private-types.h" #include "ProcessWindowsLog.h" #include "RegisterContextWindows.h" @@ -27,129 +27,110 @@ const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows::RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) - , m_context() - , m_context_stale(true) -{ -} +RegisterContextWindows::RegisterContextWindows(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), m_context(), + m_context_stale(true) {} -RegisterContextWindows::~RegisterContextWindows() -{ -} +RegisterContextWindows::~RegisterContextWindows() {} -void -RegisterContextWindows::InvalidateAllRegisters() -{ - m_context_stale = true; +void RegisterContextWindows::InvalidateAllRegisters() { + m_context_stale = true; } -bool -RegisterContextWindows::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - if (!CacheAllRegisterValues()) - return false; - if (data_sp->GetByteSize() < sizeof(m_context)) - { - data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); - } - memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); - return true; +bool RegisterContextWindows::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + if (!CacheAllRegisterValues()) + return false; + if (data_sp->GetByteSize() < sizeof(m_context)) { + data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); + } + memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); + return true; } -bool -RegisterContextWindows::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - assert(data_sp->GetByteSize() >= sizeof(m_context)); - memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); +bool RegisterContextWindows::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + assert(data_sp->GetByteSize() >= sizeof(m_context)); + memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - if (!::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) - return false; + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + if (!::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), + &m_context)) + return false; - return true; + return true; } -uint32_t -RegisterContextWindows::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); +uint32_t RegisterContextWindows::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); + 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; - } + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } //------------------------------------------------------------------ // Subclasses can these functions if desired //------------------------------------------------------------------ -uint32_t -RegisterContextWindows::NumSupportedHardwareBreakpoints() -{ - // Support for hardware breakpoints not yet implemented. - return 0; +uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() { + // Support for hardware breakpoints not yet implemented. + return 0; } -uint32_t -RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) -{ - return 0; +uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + return 0; } -bool -RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) -{ - return false; +bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) { + return false; } -uint32_t -RegisterContextWindows::NumSupportedHardwareWatchpoints() -{ - // Support for hardware watchpoints not yet implemented. - return 0; +uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() { + // Support for hardware watchpoints not yet implemented. + return 0; } -uint32_t -RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) -{ - return 0; +uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, bool read, + bool write) { + return 0; } -bool -RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { + return false; } -bool -RegisterContextWindows::HardwareSingleStep(bool enable) -{ - return false; -} +bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } -bool -RegisterContextWindows::CacheAllRegisterValues() -{ - if (!m_context_stale) - return true; - - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - memset(&m_context, 0, sizeof(m_context)); - m_context.ContextFlags = kWinContextFlags; - if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) - { - WINERR_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext failed with error %u while caching register values.", - ::GetLastError()); - return false; - } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext successfully updated the register values.", ::GetLastError()); - m_context_stale = false; +bool RegisterContextWindows::CacheAllRegisterValues() { + if (!m_context_stale) return true; + + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + memset(&m_context, 0, sizeof(m_context)); + m_context.ContextFlags = kWinContextFlags; + if (!::GetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), + &m_context)) { + WINERR_IFALL( + WINDOWS_LOG_REGISTERS, + "GetThreadContext failed with error %u while caching register values.", + ::GetLastError()); + return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, + "GetThreadContext successfully updated the register values.", + ::GetLastError()); + m_context_stale = false; + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h index 66b7a9004ea..bd09295c2f2 100644 --- a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h @@ -10,57 +10,57 @@ #ifndef liblldb_RegisterContextWindows_H_ #define liblldb_RegisterContextWindows_H_ -#include "lldb/lldb-forward.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows : public lldb_private::RegisterContext -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows : public lldb_private::RegisterContext { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows(); + virtual ~RegisterContextWindows(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - void InvalidateAllRegisters() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + void InvalidateAllRegisters() override; - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool WriteAllRegisterValues(const 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 ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - //------------------------------------------------------------------ - // Subclasses can override these functions if desired - //------------------------------------------------------------------ - uint32_t NumSupportedHardwareBreakpoints() override; + //------------------------------------------------------------------ + // Subclasses can override these functions if desired + //------------------------------------------------------------------ + uint32_t NumSupportedHardwareBreakpoints() override; - uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - uint32_t NumSupportedHardwareWatchpoints() override; + uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write) override; - bool ClearHardwareWatchpoint(uint32_t hw_index) override; + bool ClearHardwareWatchpoint(uint32_t hw_index) override; - bool HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; - protected: - virtual bool CacheAllRegisterValues(); +protected: + virtual bool CacheAllRegisterValues(); - CONTEXT m_context; - bool m_context_stale; + CONTEXT m_context; + bool m_context_stale; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp index dcb6f0c7243..fe05f3068bb 100644 --- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp @@ -16,83 +16,66 @@ #include "lldb/Host/windows/windows.h" #include "lldb/Target/RegisterContext.h" -#include "TargetThreadWindows.h" #include "ProcessWindows.h" #include "ProcessWindowsLog.h" +#include "TargetThreadWindows.h" #include "UnwindLLDB.h" using namespace lldb; using namespace lldb_private; -TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, const HostThread &thread) - : Thread(process, thread.GetNativeThread().GetThreadId()) - , m_host_thread(thread) -{ -} +TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, + const HostThread &thread) + : Thread(process, thread.GetNativeThread().GetThreadId()), + m_host_thread(thread) {} -TargetThreadWindows::~TargetThreadWindows() -{ - DestroyThread(); -} +TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } -void -TargetThreadWindows::RefreshStateAfterStop() -{ - ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - SetState(eStateStopped); - GetRegisterContext()->InvalidateIfNeeded(false); +void TargetThreadWindows::RefreshStateAfterStop() { + ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); + SetState(eStateStopped); + GetRegisterContext()->InvalidateIfNeeded(false); } -void -TargetThreadWindows::WillResume(lldb::StateType resume_state) -{ -} +void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} -void -TargetThreadWindows::DidStop() -{ -} +void TargetThreadWindows::DidStop() {} -bool -TargetThreadWindows::CalculateStopInfo() -{ - SetStopInfo(m_stop_info_sp); - return true; +bool TargetThreadWindows::CalculateStopInfo() { + SetStopInfo(m_stop_info_sp); + return true; } -Unwind * -TargetThreadWindows::GetUnwinder() -{ - // FIXME: Implement an unwinder based on the Windows unwinder exposed through DIA SDK. - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); +Unwind *TargetThreadWindows::GetUnwinder() { + // FIXME: Implement an unwinder based on the Windows unwinder exposed through + // DIA SDK. + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + return m_unwinder_ap.get(); } -bool -TargetThreadWindows::DoResume() -{ - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return true; +bool TargetThreadWindows::DoResume() { + StateType resume_state = GetTemporaryResumeState(); + StateType current_state = GetState(); + if (resume_state == current_state) + return true; - if (resume_state == eStateStepping) - { - uint32_t flags_index = GetRegisterContext()->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - uint64_t flags_value = GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); - flags_value |= 0x100; // Set the trap flag on the CPU - GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); - } + if (resume_state == eStateStepping) { + uint32_t flags_index = + GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + uint64_t flags_value = + GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); + flags_value |= 0x100; // Set the trap flag on the CPU + GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); + } - if (resume_state == eStateStepping || resume_state == eStateRunning) - { - DWORD previous_suspend_count = 0; - HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); - do - { - previous_suspend_count = ::ResumeThread(thread_handle); - } while (previous_suspend_count > 0); - } - return true; + if (resume_state == eStateStepping || resume_state == eStateRunning) { + DWORD previous_suspend_count = 0; + HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); + do { + previous_suspend_count = ::ResumeThread(thread_handle); + } while (previous_suspend_count > 0); + } + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h index 701b56b6d26..ea6d636dbab 100644 --- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h @@ -11,39 +11,33 @@ #define liblldb_Plugins_Process_Windows_TargetThreadWindows_H_ //#include "ForwardDecl.h" -#include "lldb/lldb-forward.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; class HostThread; class StackFrame; -class TargetThreadWindows : public lldb_private::Thread -{ - public: - TargetThreadWindows(ProcessWindows &process, const HostThread &thread); - virtual ~TargetThreadWindows(); - - // lldb_private::Thread overrides - void RefreshStateAfterStop() override; - void WillResume(lldb::StateType resume_state) override; - void DidStop() override; - bool CalculateStopInfo() override; - Unwind *GetUnwinder() override; - - bool DoResume(); - - HostThread - GetHostThread() const - { - return m_host_thread; - } - - private: - HostThread m_host_thread; +class TargetThreadWindows : public lldb_private::Thread { +public: + TargetThreadWindows(ProcessWindows &process, const HostThread &thread); + virtual ~TargetThreadWindows(); + + // lldb_private::Thread overrides + void RefreshStateAfterStop() override; + void WillResume(lldb::StateType resume_state) override; + void DidStop() override; + bool CalculateStopInfo() override; + Unwind *GetUnwinder() override; + + bool DoResume(); + + HostThread GetHostThread() const { return m_host_thread; } + +private: + HostThread m_host_thread; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp index 3a9c31a0b77..942b4e97c40 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" -#include "RegisterContext_x86.h" #include "RegisterContextWindows_x64.h" +#include "RegisterContext_x86.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" @@ -26,302 +26,317 @@ using namespace lldb_private; #define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary -namespace -{ +namespace { -// This enum defines the layout of the global RegisterInfo array. This is necessary because -// lldb register sets are defined in terms of indices into the register array. As such, the -// order of RegisterInfos defined in global registers array must match the order defined here. -// When defining the register set layouts, these values can appear in an arbitrary order, and that +// This enum defines the layout of the global RegisterInfo array. This is +// necessary because +// lldb register sets are defined in terms of indices into the register array. +// As such, the +// order of RegisterInfos defined in global registers array must match the order +// defined here. +// When defining the register set layouts, these values can appear in an +// arbitrary order, and that // determines the order that register values are displayed in a dump. -enum RegisterIndex -{ - eRegisterIndexRax, - eRegisterIndexRbx, - eRegisterIndexRcx, - eRegisterIndexRdx, - eRegisterIndexRdi, - eRegisterIndexRsi, - eRegisterIndexR8, - eRegisterIndexR9, - eRegisterIndexR10, - eRegisterIndexR11, - eRegisterIndexR12, - eRegisterIndexR13, - eRegisterIndexR14, - eRegisterIndexR15, - eRegisterIndexRbp, - eRegisterIndexRsp, - eRegisterIndexRip, - eRegisterIndexRflags +enum RegisterIndex { + eRegisterIndexRax, + eRegisterIndexRbx, + eRegisterIndexRcx, + eRegisterIndexRdx, + eRegisterIndexRdi, + eRegisterIndexRsi, + eRegisterIndexR8, + eRegisterIndexR9, + eRegisterIndexR10, + eRegisterIndexR11, + eRegisterIndexR12, + eRegisterIndexR13, + eRegisterIndexR14, + eRegisterIndexR15, + eRegisterIndexRbp, + eRegisterIndexRsp, + eRegisterIndexRip, + eRegisterIndexRflags }; // Array of all register information supported by Windows x86 RegisterInfo g_register_infos[] = { - // Macro auto defines most stuff eh_frame DWARF GENERIC + // Macro auto defines most stuff eh_frame DWARF + // GENERIC // GDB LLDB VALUE REGS INVALIDATE REGS - // ================================ ========================= ====================== ========================= + // ================================ ========================= + // ====================== ========================= // =================== ================= ========== =============== {DEFINE_GPR(rax, nullptr), - {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rax_x86_64}, + {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rax_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rbx, nullptr), - {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, + {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rcx, nullptr), - {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, + {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rdx, nullptr), - {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, + {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rdi, nullptr), - {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, + {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rsi, nullptr), - {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, + {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r8, nullptr), - {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r8_x86_64}, + {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r8_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r9, nullptr), - {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r9_x86_64}, + {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r9_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r10, nullptr), - {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r10_x86_64}, + {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r10_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r11, nullptr), - {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r11_x86_64}, + {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r11_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r12, nullptr), - {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r12_x86_64}, + {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r12_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r13, nullptr), - {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r13_x86_64}, + {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r13_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r14, nullptr), - {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r14_x86_64}, + {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r14_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r15, nullptr), - {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r15_x86_64}, + {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r15_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rbp, "fp"), - {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, + {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rsp, "sp"), - {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, + {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rip, "pc"), - {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_rip_x86_64}, + {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, lldb_rip_x86_64}, nullptr, nullptr}, {DEFINE_GPR_BIN(eflags, "flags"), - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, nullptr, nullptr}, }; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -// Array of lldb register numbers used to define the set of all General Purpose Registers -uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, eRegisterIndexRdx, - eRegisterIndexRdi, eRegisterIndexRsi, eRegisterIndexR8, eRegisterIndexR9, - eRegisterIndexR10, eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, - eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, eRegisterIndexRsp, - eRegisterIndexRip, eRegisterIndexRflags}; +// Array of lldb register numbers used to define the set of all General Purpose +// Registers +uint32_t g_gpr_reg_indices[] = { + eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, + eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi, + eRegisterIndexR8, eRegisterIndexR9, eRegisterIndexR10, + eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, + eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, + eRegisterIndexRsp, eRegisterIndexRip, eRegisterIndexRflags}; RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, + {"General Purpose Registers", "gpr", + llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, }; } //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows_x64::RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) -{ -} +RegisterContextWindows_x64::RegisterContextWindows_x64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows(thread, concrete_frame_idx) {} -RegisterContextWindows_x64::~RegisterContextWindows_x64() -{ -} +RegisterContextWindows_x64::~RegisterContextWindows_x64() {} -size_t -RegisterContextWindows_x64::GetRegisterCount() -{ - return llvm::array_lengthof(g_register_infos); +size_t RegisterContextWindows_x64::GetRegisterCount() { + return llvm::array_lengthof(g_register_infos); } const RegisterInfo * -RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; +RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextWindows_x64::GetRegisterSetCount() -{ - return llvm::array_lengthof(g_register_sets); +size_t RegisterContextWindows_x64::GetRegisterSetCount() { + return llvm::array_lengthof(g_register_sets); } -const RegisterSet * -RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) -{ - return &g_register_sets[reg_set]; +const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) { + return &g_register_sets[reg_set]; } -bool -RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - reg_value.SetUInt64(m_context.Rax); - break; - case lldb_rbx_x86_64: - reg_value.SetUInt64(m_context.Rbx); - break; - case lldb_rcx_x86_64: - reg_value.SetUInt64(m_context.Rcx); - break; - case lldb_rdx_x86_64: - reg_value.SetUInt64(m_context.Rdx); - break; - case lldb_rdi_x86_64: - reg_value.SetUInt64(m_context.Rdi); - break; - case lldb_rsi_x86_64: - reg_value.SetUInt64(m_context.Rsi); - break; - case lldb_r8_x86_64: - reg_value.SetUInt64(m_context.R8); - break; - case lldb_r9_x86_64: - reg_value.SetUInt64(m_context.R9); - break; - case lldb_r10_x86_64: - reg_value.SetUInt64(m_context.R10); - break; - case lldb_r11_x86_64: - reg_value.SetUInt64(m_context.R11); - break; - case lldb_r12_x86_64: - reg_value.SetUInt64(m_context.R12); - break; - case lldb_r13_x86_64: - reg_value.SetUInt64(m_context.R13); - break; - case lldb_r14_x86_64: - reg_value.SetUInt64(m_context.R14); - break; - case lldb_r15_x86_64: - reg_value.SetUInt64(m_context.R15); - break; - case lldb_rbp_x86_64: - reg_value.SetUInt64(m_context.Rbp); - break; - case lldb_rsp_x86_64: - reg_value.SetUInt64(m_context.Rsp); - break; - case lldb_rip_x86_64: - reg_value.SetUInt64(m_context.Rip); - break; - case lldb_rflags_x86_64: - reg_value.SetUInt64(m_context.EFlags); - break; - } - return true; + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + reg_value.SetUInt64(m_context.Rax); + break; + case lldb_rbx_x86_64: + reg_value.SetUInt64(m_context.Rbx); + break; + case lldb_rcx_x86_64: + reg_value.SetUInt64(m_context.Rcx); + break; + case lldb_rdx_x86_64: + reg_value.SetUInt64(m_context.Rdx); + break; + case lldb_rdi_x86_64: + reg_value.SetUInt64(m_context.Rdi); + break; + case lldb_rsi_x86_64: + reg_value.SetUInt64(m_context.Rsi); + break; + case lldb_r8_x86_64: + reg_value.SetUInt64(m_context.R8); + break; + case lldb_r9_x86_64: + reg_value.SetUInt64(m_context.R9); + break; + case lldb_r10_x86_64: + reg_value.SetUInt64(m_context.R10); + break; + case lldb_r11_x86_64: + reg_value.SetUInt64(m_context.R11); + break; + case lldb_r12_x86_64: + reg_value.SetUInt64(m_context.R12); + break; + case lldb_r13_x86_64: + reg_value.SetUInt64(m_context.R13); + break; + case lldb_r14_x86_64: + reg_value.SetUInt64(m_context.R14); + break; + case lldb_r15_x86_64: + reg_value.SetUInt64(m_context.R15); + break; + case lldb_rbp_x86_64: + reg_value.SetUInt64(m_context.Rbp); + break; + case lldb_rsp_x86_64: + reg_value.SetUInt64(m_context.Rsp); + break; + case lldb_rip_x86_64: + reg_value.SetUInt64(m_context.Rip); + break; + case lldb_rflags_x86_64: + reg_value.SetUInt64(m_context.EFlags); + break; + } + return true; } -bool -RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - m_context.Rax = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_context.Rbx = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_context.Rcx = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_context.Rdx = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_context.Rdi = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_context.Rsi = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_context.R8 = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_context.R9 = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_context.R10 = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_context.R11 = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_context.R12 = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_context.R13 = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_context.R14 = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_context.R15 = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_context.Rbp = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_context.Rsp = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_context.Rip = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_context.EFlags = reg_value.GetAsUInt64(); - break; - } + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + m_context.Rax = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_context.Rbx = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_context.Rcx = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_context.Rdx = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_context.Rdi = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_context.Rsi = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_context.R8 = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_context.R9 = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_context.R10 = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_context.R11 = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_context.R12 = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_context.R13 = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_context.R14 = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_context.R15 = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_context.Rbp = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_context.Rsp = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_context.Rip = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_context.EFlags = reg_value.GetAsUInt64(); + break; + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h index e69179d99c6..62cedc8fbab 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h @@ -10,38 +10,38 @@ #ifndef liblldb_RegisterContextWindows_x64_H_ #define liblldb_RegisterContextWindows_x64_H_ -#include "lldb/lldb-forward.h" #include "RegisterContextWindows.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows_x64 : public RegisterContextWindows -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows_x64 : public RegisterContextWindows { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows_x64(); + virtual ~RegisterContextWindows_x64(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + size_t GetRegisterCount() override; - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const RegisterSet *GetRegisterSet(size_t reg_set) override; + const RegisterSet *GetRegisterSet(size_t reg_set) override; - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp index 11733eee7cb..04b6ab317ca 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "ProcessWindowsLog.h" -#include "RegisterContext_x86.h" #include "RegisterContextWindows_x86.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" @@ -26,150 +26,178 @@ using namespace lldb_private; #define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary -namespace -{ +namespace { -// This enum defines the layout of the global RegisterInfo array. This is necessary because -// lldb register sets are defined in terms of indices into the register array. As such, the -// order of RegisterInfos defined in global registers array must match the order defined here. -// When defining the register set layouts, these values can appear in an arbitrary order, and that +// This enum defines the layout of the global RegisterInfo array. This is +// necessary because +// lldb register sets are defined in terms of indices into the register array. +// As such, the +// order of RegisterInfos defined in global registers array must match the order +// defined here. +// When defining the register set layouts, these values can appear in an +// arbitrary order, and that // determines the order that register values are displayed in a dump. -enum RegisterIndex -{ - eRegisterIndexEax, - eRegisterIndexEbx, - eRegisterIndexEcx, - eRegisterIndexEdx, - eRegisterIndexEdi, - eRegisterIndexEsi, - eRegisterIndexEbp, - eRegisterIndexEsp, - eRegisterIndexEip, - eRegisterIndexEflags +enum RegisterIndex { + eRegisterIndexEax, + eRegisterIndexEbx, + eRegisterIndexEcx, + eRegisterIndexEdx, + eRegisterIndexEdi, + eRegisterIndexEsi, + eRegisterIndexEbp, + eRegisterIndexEsp, + eRegisterIndexEip, + eRegisterIndexEflags }; // Array of all register information supported by Windows x86 -RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff eh_frame DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS -// ============================== ======================= =================== ========================= =================== ================= ========== =============== - { DEFINE_GPR(eax, nullptr), { ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_eax_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ebx, nullptr), { ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_ebx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ecx, nullptr), { ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_ecx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(edx, nullptr), { ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_edx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(edi, nullptr), { ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_edi_i386 }, nullptr, nullptr}, - { DEFINE_GPR(esi, nullptr), { ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_esi_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ebp, "fp"), { ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, lldb_ebp_i386 }, nullptr, nullptr}, - { DEFINE_GPR(esp, "sp"), { ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, lldb_esp_i386 }, nullptr, nullptr}, - { DEFINE_GPR(eip, "pc"), { ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_eip_i386 }, nullptr, nullptr}, - { DEFINE_GPR_BIN(eflags, "flags"), { ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_eflags_i386}, nullptr, nullptr}, +RegisterInfo g_register_infos[] = { + // Macro auto defines most stuff eh_frame DWARF + // GENERIC GDB LLDB + // VALUE REGS INVALIDATE REGS + // ============================== ======================= + // =================== ========================= =================== + // ================= ========== =============== + {DEFINE_GPR(eax, nullptr), + {ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_eax_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ebx, nullptr), + {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_ebx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ecx, nullptr), + {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_ecx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(edx, nullptr), + {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_edx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(edi, nullptr), + {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_edi_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(esi, nullptr), + {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_esi_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ebp, "fp"), + {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, lldb_ebp_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(esp, "sp"), + {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, lldb_esp_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(eip, "pc"), + {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, lldb_eip_i386}, + nullptr, + nullptr}, + {DEFINE_GPR_BIN(eflags, "flags"), + {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, lldb_eflags_i386}, + nullptr, + nullptr}, }; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -// Array of lldb register numbers used to define the set of all General Purpose Registers -uint32_t g_gpr_reg_indices[] = -{ - eRegisterIndexEax, - eRegisterIndexEbx, - eRegisterIndexEcx, - eRegisterIndexEdx, - eRegisterIndexEdi, - eRegisterIndexEsi, - eRegisterIndexEbp, - eRegisterIndexEsp, - eRegisterIndexEip, - eRegisterIndexEflags -}; +// Array of lldb register numbers used to define the set of all General Purpose +// Registers +uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx, + eRegisterIndexEcx, eRegisterIndexEdx, + eRegisterIndexEdi, eRegisterIndexEsi, + eRegisterIndexEbp, eRegisterIndexEsp, + eRegisterIndexEip, eRegisterIndexEflags}; RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, + {"General Purpose Registers", "gpr", + llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, }; } //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows_x86::RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) -{ -} +RegisterContextWindows_x86::RegisterContextWindows_x86( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows(thread, concrete_frame_idx) {} -RegisterContextWindows_x86::~RegisterContextWindows_x86() -{ -} +RegisterContextWindows_x86::~RegisterContextWindows_x86() {} -size_t -RegisterContextWindows_x86::GetRegisterCount() -{ - return llvm::array_lengthof(g_register_infos); +size_t RegisterContextWindows_x86::GetRegisterCount() { + return llvm::array_lengthof(g_register_infos); } const RegisterInfo * -RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; +RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextWindows_x86::GetRegisterSetCount() -{ - return llvm::array_lengthof(g_register_sets); +size_t RegisterContextWindows_x86::GetRegisterSetCount() { + return llvm::array_lengthof(g_register_sets); } -const RegisterSet * -RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) -{ - return &g_register_sets[reg_set]; +const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) { + return &g_register_sets[reg_set]; } -bool -RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; - - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) - { - case lldb_eax_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); - case lldb_ebx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); - case lldb_ecx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); - case lldb_edx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); - case lldb_edi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); - case lldb_esi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); - case lldb_ebp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); - case lldb_esp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); - case lldb_eip_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); - case lldb_eflags_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value); - default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); - break; - } +bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) return false; + + uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + switch (reg) { + case lldb_eax_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); + case lldb_ebx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); + case lldb_ecx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); + case lldb_edx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); + case lldb_edi_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); + case lldb_esi_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); + case lldb_ebp_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); + case lldb_esp_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); + case lldb_eip_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); + case lldb_eflags_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, + reg_value); + default: + WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); + break; + } + return false; } -bool -RegisterContextWindows_x86::ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, - RegisterValue ®_value) const -{ - if ((m_context.ContextFlags & flags_required) != flags_required) - { - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", reg_name); - return false; - } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, reg_name); - reg_value.SetUInt32(value); - return true; +bool RegisterContextWindows_x86::ReadRegisterHelper( + DWORD flags_required, const char *reg_name, DWORD value, + RegisterValue ®_value) const { + if ((m_context.ContextFlags & flags_required) != flags_required) { + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", + reg_name); + return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, + reg_name); + reg_value.SetUInt32(value); + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h index 6c29d54dcae..1e3910b5edd 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h @@ -10,42 +10,40 @@ #ifndef liblldb_RegisterContextWindows_x86_H_ #define liblldb_RegisterContextWindows_x86_H_ -#include "lldb/lldb-forward.h" #include "RegisterContextWindows.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows_x86 : public RegisterContextWindows -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows_x86 : public RegisterContextWindows { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows_x86(); + virtual ~RegisterContextWindows_x86(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + size_t GetRegisterCount() override; - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const RegisterSet *GetRegisterSet(size_t reg_set) override; + const RegisterSet *GetRegisterSet(size_t reg_set) override; - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; private: - bool - ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, RegisterValue ®_value) const; + bool ReadRegisterHelper(DWORD flags_required, const char *reg_name, + DWORD value, RegisterValue ®_value) const; }; - } #endif // #ifndef liblldb_RegisterContextWindows_x86_H_ diff --git a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp index 2823474cbd5..4dcd7894e4d 100644 --- a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp @@ -1,4 +1,5 @@ -//===-- DebuggerThread.DebuggerThread --------------------------------------*- C++ -*-===// +//===-- DebuggerThread.DebuggerThread --------------------------------------*- +//C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,8 +22,8 @@ #include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" -#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Process.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" @@ -33,517 +34,518 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -struct DebugLaunchContext -{ - DebugLaunchContext(DebuggerThread *thread, const ProcessLaunchInfo &launch_info) - : m_thread(thread) - , m_launch_info(launch_info) - { - } - DebuggerThread *m_thread; - ProcessLaunchInfo m_launch_info; +namespace { +struct DebugLaunchContext { + DebugLaunchContext(DebuggerThread *thread, + const ProcessLaunchInfo &launch_info) + : m_thread(thread), m_launch_info(launch_info) {} + DebuggerThread *m_thread; + ProcessLaunchInfo m_launch_info; }; -struct DebugAttachContext -{ - DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, const ProcessAttachInfo &attach_info) - : m_thread(thread) - , m_pid(pid) - , m_attach_info(attach_info) - { - } - DebuggerThread *m_thread; - lldb::pid_t m_pid; - ProcessAttachInfo m_attach_info; +struct DebugAttachContext { + DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, + const ProcessAttachInfo &attach_info) + : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} + DebuggerThread *m_thread; + lldb::pid_t m_pid; + ProcessAttachInfo m_attach_info; }; } DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) - : m_debug_delegate(debug_delegate) - , m_image_file(nullptr) - , m_debugging_ended_event(nullptr) - , m_is_shutting_down(false) - , m_pid_to_detach(0) - , m_detached(false) -{ - m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + : m_debug_delegate(debug_delegate), m_image_file(nullptr), + m_debugging_ended_event(nullptr), m_is_shutting_down(false), + m_pid_to_detach(0), m_detached(false) { + m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); } -DebuggerThread::~DebuggerThread() -{ - ::CloseHandle(m_debugging_ended_event); -} +DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } -Error -DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) -{ - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str()); +Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread::DebugLaunch launching '%s'", + launch_info.GetExecutableFile().GetPath().c_str()); - Error error; - DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", - DebuggerThreadLaunchRoutine, context, &error)); + Error error; + DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); + HostThread slave_thread(ThreadLauncher::LaunchThread( + "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, + context, &error)); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DebugLaunch couldn't launch debugger thread. %s", error.AsCString()); - } + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DebugLaunch couldn't launch debugger thread. %s", + error.AsCString()); + } - return error; + return error; } -Error -DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid); - - Error error; - DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); - HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", - DebuggerThreadAttachRoutine, context, &error)); +Error DebuggerThread::DebugAttach(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid, - error.AsCString()); - } + Error error; + DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); + HostThread slave_thread(ThreadLauncher::LaunchThread( + "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, + context, &error)); - return error; -} + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid, + error.AsCString()); + } -lldb::thread_result_t -DebuggerThread::DebuggerThreadLaunchRoutine(void *data) -{ - DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); - lldb::thread_result_t result = context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); - delete context; - return result; + return error; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadAttachRoutine(void *data) -{ - DebugAttachContext *context = static_cast<DebugAttachContext *>(data); - lldb::thread_result_t result = - context->m_thread->DebuggerThreadAttachRoutine(context->m_pid, context->m_attach_info); - delete context; - return result; +lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { + DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); + lldb::thread_result_t result = + context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); + delete context; + return result; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info) -{ - // Grab a shared_ptr reference to this so that we know it won't get deleted until after the - // thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to launch '%s' on background thread.", - launch_info.GetExecutableFile().GetPath().c_str()); - - Error error; - ProcessLauncherWindows launcher; - HostProcess process(launcher.LaunchProcess(launch_info, error)); - // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug - // loop and wait until we get the create process debug notification. Note that if the process - // was created successfully, we can throw away the process handle we got from CreateProcess - // because Windows will give us another (potentially more useful?) handle when it sends us the - // CREATE_PROCESS_DEBUG_EVENT. - if (error.Success()) - DebugLoop(); - else - m_debug_delegate->OnDebuggerError(error, 0); - - return 0; +lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { + DebugAttachContext *context = static_cast<DebugAttachContext *>(data); + lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( + context->m_pid, context->m_attach_info); + delete context; + return result; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - // Grab a shared_ptr reference to this so that we know it won't get deleted until after the - // thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to process '%u' on background thread.", - (DWORD)pid); - - if (!DebugActiveProcess((DWORD)pid)) - { - Error error(::GetLastError(), eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, 0); - return 0; - } - - // The attach was successful, enter the debug loop. From here on out, this is no different than - // a create process operation, so all the same comments in DebugLaunch should apply from this - // point out. +lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( + const ProcessLaunchInfo &launch_info) { + // Grab a shared_ptr reference to this so that we know it won't get deleted + // until after the + // thread routine has exited. + std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread preparing to launch '%s' on background thread.", + launch_info.GetExecutableFile().GetPath().c_str()); + + Error error; + ProcessLauncherWindows launcher; + HostProcess process(launcher.LaunchProcess(launch_info, error)); + // If we couldn't create the process, notify waiters immediately. Otherwise + // enter the debug + // loop and wait until we get the create process debug notification. Note + // that if the process + // was created successfully, we can throw away the process handle we got from + // CreateProcess + // because Windows will give us another (potentially more useful?) handle when + // it sends us the + // CREATE_PROCESS_DEBUG_EVENT. + if (error.Success()) DebugLoop(); + else + m_debug_delegate->OnDebuggerError(error, 0); - return 0; + return 0; } -Error -DebuggerThread::StopDebugging(bool terminate) -{ - Error error; +lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( + lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + // Grab a shared_ptr reference to this so that we know it won't get deleted + // until after the + // thread routine has exited. + std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - lldb::pid_t pid = m_process.GetProcessId(); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to " + "process '%u' on background thread.", + (DWORD)pid); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging('%s') called (inferior=%I64u).", - (terminate ? "true" : "false"), pid); - - // Set m_is_shutting_down to true if it was false. Return if it was already true. - bool expected = false; - if (!m_is_shutting_down.compare_exchange_strong(expected, true)) - return error; - - // Make a copy of the process, since the termination sequence will reset - // DebuggerThread's internal copy and it needs to remain open for the Wait operation. - HostProcess process_copy = m_process; - lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); - - if (terminate) - { - // Initiate the termination before continuing the exception, so that the next debug - // event we get is the exit process event, and not some other event. - BOOL terminate_suceeded = TerminateProcess(handle, 0); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging called TerminateProcess(0x%p, 0) (inferior=%I64u), success='%s'", - handle, pid, (terminate_suceeded ? "true" : "false")); - } + if (!DebugActiveProcess((DWORD)pid)) { + Error error(::GetLastError(), eErrorTypeWin32); + m_debug_delegate->OnDebuggerError(error, 0); + return 0; + } - // If we're stuck waiting for an exception to continue (e.g. the user is at a breakpoint - // messing around in the debugger), continue it now. But only AFTER calling TerminateProcess - // to make sure that the very next call to WaitForDebugEvent is an exit process event. - if (m_active_exception.get()) - { - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, - "StopDebugging masking active exception"); + // The attach was successful, enter the debug loop. From here on out, this is + // no different than + // a create process operation, so all the same comments in DebugLaunch should + // apply from this + // point out. + DebugLoop(); - ContinueAsyncException(ExceptionResult::MaskException); - } + return 0; +} - if (!terminate) - { - // Indicate that we want to detach. - m_pid_to_detach = GetProcess().GetProcessId(); +Error DebuggerThread::StopDebugging(bool terminate) { + Error error; - // Force a fresh break so that the detach can happen from the debugger thread. - if (!::DebugBreakProcess(GetProcess().GetNativeProcess().GetSystemHandle())) - { - error.SetError(::GetLastError(), eErrorTypeWin32); - } - } + lldb::pid_t pid = m_process.GetProcessId(); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging waiting for detach from process %u to complete.", pid); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging('%s') called (inferior=%I64u).", + (terminate ? "true" : "false"), pid); - DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); - if (wait_result != WAIT_OBJECT_0) - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u", - m_debugging_ended_event, wait_result); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging detach from process %u completed successfully.", pid); - } + // Set m_is_shutting_down to true if it was false. Return if it was already + // true. + bool expected = false; + if (!m_is_shutting_down.compare_exchange_strong(expected, true)) + return error; - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging encountered an error while trying to stop process %u. %s", - pid, error.AsCString()); + // Make a copy of the process, since the termination sequence will reset + // DebuggerThread's internal copy and it needs to remain open for the Wait + // operation. + HostProcess process_copy = m_process; + lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); + + if (terminate) { + // Initiate the termination before continuing the exception, so that the + // next debug + // event we get is the exit process event, and not some other event. + BOOL terminate_suceeded = TerminateProcess(handle, 0); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging called " + "TerminateProcess(0x%p, 0) " + "(inferior=%I64u), success='%s'", + handle, pid, (terminate_suceeded ? "true" : "false")); + } + + // If we're stuck waiting for an exception to continue (e.g. the user is at a + // breakpoint + // messing around in the debugger), continue it now. But only AFTER calling + // TerminateProcess + // to make sure that the very next call to WaitForDebugEvent is an exit + // process event. + if (m_active_exception.get()) { + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, + "StopDebugging masking active exception"); + + ContinueAsyncException(ExceptionResult::MaskException); + } + + if (!terminate) { + // Indicate that we want to detach. + m_pid_to_detach = GetProcess().GetProcessId(); + + // Force a fresh break so that the detach can happen from the debugger + // thread. + if (!::DebugBreakProcess( + GetProcess().GetNativeProcess().GetSystemHandle())) { + error.SetError(::GetLastError(), eErrorTypeWin32); } - return error; + } + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging waiting for detach from process %u to complete.", + pid); + + DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); + if (wait_result != WAIT_OBJECT_0) { + error.SetError(GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u", + m_debugging_ended_event, wait_result); + } else { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging detach from process %u completed successfully.", + pid); + } + + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error " + "while trying to stop process %u. %s", + pid, error.AsCString()); + } + return error; } -void -DebuggerThread::ContinueAsyncException(ExceptionResult result) -{ - if (!m_active_exception.get()) - return; +void DebuggerThread::ContinueAsyncException(ExceptionResult result) { + if (!m_active_exception.get()) + return; - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, - "ContinueAsyncException called for inferior process %I64u, broadcasting.", - m_process.GetProcessId()); + WINLOG_IFANY( + WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, + "ContinueAsyncException called for inferior process %I64u, broadcasting.", + m_process.GetProcessId()); - m_active_exception.reset(); - m_exception_pred.SetValue(result, eBroadcastAlways); + m_active_exception.reset(); + m_exception_pred.SetValue(result, eBroadcastAlways); } -void -DebuggerThread::FreeProcessHandles() -{ - m_process = HostProcess(); - m_main_thread = HostThread(); - if (m_image_file) - { - ::CloseHandle(m_image_file); - m_image_file = nullptr; - } +void DebuggerThread::FreeProcessHandles() { + m_process = HostProcess(); + m_main_thread = HostThread(); + if (m_image_file) { + ::CloseHandle(m_image_file); + m_image_file = nullptr; + } } -void -DebuggerThread::DebugLoop() -{ - DEBUG_EVENT dbe = {0}; - bool should_debug = true; - WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); - while (should_debug) - { - WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); - BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); - if (wait_result) - { - DWORD continue_status = DBG_CONTINUE; - switch (dbe.dwDebugEventCode) - { - case EXCEPTION_DEBUG_EVENT: - { - ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); - - if (status == ExceptionResult::MaskException) - continue_status = DBG_CONTINUE; - else if (status == ExceptionResult::SendToApplication) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - - break; - } - case CREATE_THREAD_DEBUG_EVENT: - continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); - break; - case CREATE_PROCESS_DEBUG_EVENT: - continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); - break; - case EXIT_THREAD_DEBUG_EVENT: - continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); - break; - case EXIT_PROCESS_DEBUG_EVENT: - continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); - should_debug = false; - break; - case LOAD_DLL_DEBUG_EVENT: - continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); - break; - case UNLOAD_DLL_DEBUG_EVENT: - continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); - break; - case OUTPUT_DEBUG_STRING_EVENT: - continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); - break; - case RIP_EVENT: - continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); - if (dbe.u.RipInfo.dwType == SLE_ERROR) - should_debug = false; - break; - } - - WINLOGD_IFALL(WINDOWS_LOG_EVENT, "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.", - dbe.dwProcessId, dbe.dwThreadId, continue_status, ::GetCurrentThreadId()); - - ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); - - if (m_detached) - { - should_debug = false; - } - } - else - { - WINERR_IFALL(WINDOWS_LOG_EVENT, - "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u", - ::GetCurrentThreadId(), ::GetLastError()); - - should_debug = false; - } +void DebuggerThread::DebugLoop() { + DEBUG_EVENT dbe = {0}; + bool should_debug = true; + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); + while (should_debug) { + WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); + BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); + if (wait_result) { + DWORD continue_status = DBG_CONTINUE; + switch (dbe.dwDebugEventCode) { + case EXCEPTION_DEBUG_EVENT: { + ExceptionResult status = + HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); + + if (status == ExceptionResult::MaskException) + continue_status = DBG_CONTINUE; + else if (status == ExceptionResult::SendToApplication) + continue_status = DBG_EXCEPTION_NOT_HANDLED; + + break; + } + case CREATE_THREAD_DEBUG_EVENT: + continue_status = + HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); + break; + case CREATE_PROCESS_DEBUG_EVENT: + continue_status = + HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); + break; + case EXIT_THREAD_DEBUG_EVENT: + continue_status = + HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); + break; + case EXIT_PROCESS_DEBUG_EVENT: + continue_status = + HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); + should_debug = false; + break; + case LOAD_DLL_DEBUG_EVENT: + continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); + break; + case UNLOAD_DLL_DEBUG_EVENT: + continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); + break; + case OUTPUT_DEBUG_STRING_EVENT: + continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); + break; + case RIP_EVENT: + continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); + if (dbe.u.RipInfo.dwType == SLE_ERROR) + should_debug = false; + break; + } + + WINLOGD_IFALL( + WINDOWS_LOG_EVENT, + "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.", + dbe.dwProcessId, dbe.dwThreadId, continue_status, + ::GetCurrentThreadId()); + + ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); + + if (m_detached) { + should_debug = false; + } + } else { + WINERR_IFALL( + WINDOWS_LOG_EVENT, + "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u", + ::GetCurrentThreadId(), ::GetLastError()); + + should_debug = false; } - FreeProcessHandles(); + } + FreeProcessHandles(); - WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); - SetEvent(m_debugging_ended_event); + WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); + SetEvent(m_debugging_ended_event); } ExceptionResult -DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id) -{ - if (m_is_shutting_down) - { - // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic exception that - // we use simply to wake up the DebuggerThread so that we can close out the debug loop. - if (m_pid_to_detach != 0 && info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) - { - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS, - "Breakpoint exception is cue to detach from process 0x%x", - m_pid_to_detach.load()); - ::DebugActiveProcessStop(m_pid_to_detach); - m_detached = true; - } - - // Don't perform any blocking operations while we're shutting down. That will - // cause TerminateProcess -> WaitForSingleObject to time out. - return ExceptionResult::SendToApplication; +DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, + DWORD thread_id) { + if (m_is_shutting_down) { + // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic + // exception that + // we use simply to wake up the DebuggerThread so that we can close out the + // debug loop. + if (m_pid_to_detach != 0 && + info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | + WINDOWS_LOG_PROCESS, + "Breakpoint exception is cue to detach from process 0x%x", + m_pid_to_detach.load()); + ::DebugActiveProcessStop(m_pid_to_detach); + m_detached = true; } - bool first_chance = (info.dwFirstChance != 0); + // Don't perform any blocking operations while we're shutting down. That + // will + // cause TerminateProcess -> WaitForSingleObject to time out. + return ExceptionResult::SendToApplication; + } + + bool first_chance = (info.dwFirstChance != 0); - m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id)); - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, - "HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x", - first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id); + m_active_exception.reset( + new ExceptionRecord(info.ExceptionRecord, thread_id)); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "HandleExceptionEvent encountered %s chance exception 0x%x on " + "thread 0x%x", + first_chance ? "first" : "second", + info.ExceptionRecord.ExceptionCode, thread_id); - ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, - *m_active_exception); - m_exception_pred.SetValue(result, eBroadcastNever); + ExceptionResult result = + m_debug_delegate->OnDebugException(first_chance, *m_active_exception); + m_exception_pred.SetValue(result, eBroadcastNever); - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, - "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger"); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred " + "!= BreakInDebugger"); - m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result); + m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, + result); - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, - "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", - m_exception_pred.GetValue()); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", + m_exception_pred.GetValue()); - return result; + return result; } DWORD -DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u", - thread_id, m_process.GetProcessId()); - HostThread thread(info.hThread); - thread.GetNativeThread().SetOwnsHandle(false); - m_debug_delegate->OnCreateThread(thread); - return DBG_CONTINUE; +DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u", + thread_id, m_process.GetProcessId()); + HostThread thread(info.hThread); + thread.GetNativeThread().SetOwnsHandle(false); + m_debug_delegate->OnCreateThread(thread); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id) -{ - uint32_t process_id = ::GetProcessId(info.hProcess); - - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, "HandleCreateProcessEvent process %u spawned", process_id); - - std::string thread_name; - llvm::raw_string_ostream name_stream(thread_name); - name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; - name_stream.flush(); - ThisThread::SetName(thread_name.c_str()); - - // info.hProcess and info.hThread are closed automatically by Windows when - // EXIT_PROCESS_DEBUG_EVENT is received. - m_process = HostProcess(info.hProcess); - ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); - m_main_thread = HostThread(info.hThread); - m_main_thread.GetNativeThread().SetOwnsHandle(false); - m_image_file = info.hFile; - - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); - m_debug_delegate->OnDebuggerConnected(load_addr); - - return DBG_CONTINUE; +DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, + DWORD thread_id) { + uint32_t process_id = ::GetProcessId(info.hProcess); + + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, + "HandleCreateProcessEvent process %u spawned", process_id); + + std::string thread_name; + llvm::raw_string_ostream name_stream(thread_name); + name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; + name_stream.flush(); + ThisThread::SetName(thread_name.c_str()); + + // info.hProcess and info.hThread are closed automatically by Windows when + // EXIT_PROCESS_DEBUG_EVENT is received. + m_process = HostProcess(info.hProcess); + ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); + m_main_thread = HostThread(info.hThread); + m_main_thread.GetNativeThread().SetOwnsHandle(false); + m_image_file = info.hFile; + + lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); + m_debug_delegate->OnDebuggerConnected(load_addr); + + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleExitThreadEvent Thread %u exited with code %u in process %I64u", - thread_id, info.dwExitCode, m_process.GetProcessId()); - m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); - return DBG_CONTINUE; +DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY( + WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleExitThreadEvent Thread %u exited with code %u in process %I64u", + thread_id, info.dwExitCode, m_process.GetProcessId()); + m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleExitProcessEvent process %I64u exited with code %u", - m_process.GetProcessId(), info.dwExitCode); +DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleExitProcessEvent process %I64u exited with code %u", + m_process.GetProcessId(), info.dwExitCode); - m_debug_delegate->OnExitProcess(info.dwExitCode); + m_debug_delegate->OnExitProcess(info.dwExitCode); - FreeProcessHandles(); - return DBG_CONTINUE; + FreeProcessHandles(); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id) -{ - if (info.hFile == nullptr) - { - // Not sure what this is, so just ignore it. - WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has a NULL file handle, returning...", - m_process.GetProcessId()); - return DBG_CONTINUE; - } - - std::vector<wchar_t> buffer(1); - DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); - if (required_size > 0) - { - buffer.resize(required_size + 1); - required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size, VOLUME_NAME_DOS); - std::string path_str_utf8; - llvm::convertWideToUTF8(buffer.data(), path_str_utf8); - llvm::StringRef path_str = path_str_utf8; - const char *path = path_str.data(); - if (path_str.startswith("\\\\?\\")) - path += 4; - - FileSpec file_spec(path, false); - ModuleSpec module_spec(file_spec); - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); - - WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL '%s' loaded at address 0x%p...", - m_process.GetProcessId(), path, info.lpBaseOfDll); - - m_debug_delegate->OnLoadDll(module_spec, load_addr); - } - else - { - WINERR_IFALL(WINDOWS_LOG_EVENT, - "Inferior %I64u - HandleLoadDllEvent Error %u occurred calling GetFinalPathNameByHandle", - m_process.GetProcessId(), ::GetLastError()); - } - // Windows does not automatically close info.hFile, so we need to do it. - ::CloseHandle(info.hFile); +DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, + DWORD thread_id) { + if (info.hFile == nullptr) { + // Not sure what this is, so just ignore it. + WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has " + "a NULL file handle, returning...", + m_process.GetProcessId()); return DBG_CONTINUE; + } + + std::vector<wchar_t> buffer(1); + DWORD required_size = + GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); + if (required_size > 0) { + buffer.resize(required_size + 1); + required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], + required_size, VOLUME_NAME_DOS); + std::string path_str_utf8; + llvm::convertWideToUTF8(buffer.data(), path_str_utf8); + llvm::StringRef path_str = path_str_utf8; + const char *path = path_str.data(); + if (path_str.startswith("\\\\?\\")) + path += 4; + + FileSpec file_spec(path, false); + ModuleSpec module_spec(file_spec); + lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); + + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL " + "'%s' loaded at address 0x%p...", + m_process.GetProcessId(), path, info.lpBaseOfDll); + + m_debug_delegate->OnLoadDll(module_spec, load_addr); + } else { + WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent Error " + "%u occurred calling " + "GetFinalPathNameByHandle", + m_process.GetProcessId(), ::GetLastError()); + } + // Windows does not automatically close info.hFile, so we need to do it. + ::CloseHandle(info.hFile); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFALL(WINDOWS_LOG_EVENT, - "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.", - m_process.GetProcessId(), info.lpBaseOfDll); - - m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); - return DBG_CONTINUE; +DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFALL(WINDOWS_LOG_EVENT, + "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.", + m_process.GetProcessId(), info.lpBaseOfDll); + + m_debug_delegate->OnUnloadDll( + reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id) -{ - return DBG_CONTINUE; +DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, + DWORD thread_id) { + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) -{ - WINERR_IFALL(WINDOWS_LOG_EVENT, - "HandleRipEvent encountered error %u (type=%u) in process %I64u thread %u", - info.dwError, info.dwType, m_process.GetProcessId(), thread_id); +DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { + WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %u " + "(type=%u) in process %I64u thread %u", + info.dwError, info.dwType, m_process.GetProcessId(), thread_id); - Error error(info.dwError, eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, info.dwType); + Error error(info.dwError, eErrorTypeWin32); + m_debug_delegate->OnDebuggerError(error, info.dwType); - return DBG_CONTINUE; + return DBG_CONTINUE; } diff --git a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h index 6a261941395..fb536b4cc11 100644 --- a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h +++ b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h @@ -19,8 +19,7 @@ #include "lldb/Host/Predicate.h" #include "lldb/Host/windows/windows.h" -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- // DebuggerThread @@ -28,72 +27,76 @@ namespace lldb_private // Debugs a single process, notifying listeners as appropriate when interesting // things occur. //---------------------------------------------------------------------- -class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> -{ - public: - DebuggerThread(DebugDelegateSP debug_delegate); - virtual ~DebuggerThread(); - - Error DebugLaunch(const ProcessLaunchInfo &launch_info); - Error DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info); - - HostProcess - GetProcess() const - { - return m_process; - } - HostThread - GetMainThread() const - { - return m_main_thread; - } - std::weak_ptr<ExceptionRecord> - GetActiveException() - { - return m_active_exception; - } - - Error StopDebugging(bool terminate); - - void ContinueAsyncException(ExceptionResult result); - - private: - void FreeProcessHandles(); - void DebugLoop(); - ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id); - DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id); - - DebugDelegateSP m_debug_delegate; - - HostProcess m_process; // The process being debugged. - HostThread m_main_thread; // The main thread of the inferior. - HANDLE m_image_file; // The image file of the process being debugged. - - ExceptionRecordSP m_active_exception; // The current exception waiting to be handled - - Predicate<ExceptionResult> m_exception_pred; // A predicate which gets signalled when an exception - // is finished processing and the debug loop can be - // continued. - - HANDLE m_debugging_ended_event; // An event which gets signalled by the debugger thread when it - // exits the debugger loop and is detached from the inferior. - - std::atomic<DWORD> m_pid_to_detach; // Signals the loop to detach from the process (specified by pid). - std::atomic<bool> m_is_shutting_down; // Signals the debug loop to stop processing certain types of - // events that block shutdown. - bool m_detached; // Indicates we've detached from the inferior process and the debug loop can exit. - - static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data); - lldb::thread_result_t DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info); - static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data); - lldb::thread_result_t DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &launch_info); +class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> { +public: + DebuggerThread(DebugDelegateSP debug_delegate); + virtual ~DebuggerThread(); + + Error DebugLaunch(const ProcessLaunchInfo &launch_info); + Error DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info); + + HostProcess GetProcess() const { return m_process; } + HostThread GetMainThread() const { return m_main_thread; } + std::weak_ptr<ExceptionRecord> GetActiveException() { + return m_active_exception; + } + + Error StopDebugging(bool terminate); + + void ContinueAsyncException(ExceptionResult result); + +private: + void FreeProcessHandles(); + void DebugLoop(); + ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id); + DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id); + DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id); + + DebugDelegateSP m_debug_delegate; + + HostProcess m_process; // The process being debugged. + HostThread m_main_thread; // The main thread of the inferior. + HANDLE m_image_file; // The image file of the process being debugged. + + ExceptionRecordSP + m_active_exception; // The current exception waiting to be handled + + Predicate<ExceptionResult> + m_exception_pred; // A predicate which gets signalled when an exception + // is finished processing and the debug loop can be + // continued. + + HANDLE m_debugging_ended_event; // An event which gets signalled by the + // debugger thread when it + // exits the debugger loop and is detached from the inferior. + + std::atomic<DWORD> m_pid_to_detach; // Signals the loop to detach from the + // process (specified by pid). + std::atomic<bool> m_is_shutting_down; // Signals the debug loop to stop + // processing certain types of + // events that block shutdown. + bool m_detached; // Indicates we've detached from the inferior process and the + // debug loop can exit. + + static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data); + lldb::thread_result_t + DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info); + static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data); + lldb::thread_result_t + DebuggerThreadAttachRoutine(lldb::pid_t pid, + const ProcessAttachInfo &launch_info); }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h b/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h index a782597555e..cfe1b79cee1 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h +++ b/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h @@ -14,17 +14,18 @@ // ExceptionResult is returned by the debug delegate to specify how it processed // the exception. -enum class ExceptionResult -{ - BreakInDebugger, // Break in the debugger and give the user a chance to interact with - // the program before continuing. - MaskException, // Eat the exception and don't let the application know it occurred. - SendToApplication // Send the exception to the application to be handled as if there were - // no debugger attached. +enum class ExceptionResult { + BreakInDebugger, // Break in the debugger and give the user a chance to + // interact with + // the program before continuing. + MaskException, // Eat the exception and don't let the application know it + // occurred. + SendToApplication // Send the exception to the application to be handled as if + // there were + // no debugger attached. }; -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; diff --git a/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h b/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h index 6d864de7ed4..e88e0ada053 100644 --- a/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h +++ b/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h @@ -15,8 +15,7 @@ #include "lldb/lldb-types.h" #include <string> -namespace lldb_private -{ +namespace lldb_private { class Error; class HostThread; @@ -26,20 +25,21 @@ class HostThread; // IDebugDelegate defines an interface which allows implementors to receive // notification of events that happen in a debugged process. //---------------------------------------------------------------------- -class IDebugDelegate -{ - public: - virtual ~IDebugDelegate() {} +class IDebugDelegate { +public: + virtual ~IDebugDelegate() {} - virtual void OnExitProcess(uint32_t exit_code) = 0; - virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0; - virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) = 0; - virtual void OnCreateThread(const HostThread &thread) = 0; - virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0; - virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) = 0; - virtual void OnUnloadDll(lldb::addr_t module_addr) = 0; - virtual void OnDebugString(const std::string &string) = 0; - virtual void OnDebuggerError(const Error &error, uint32_t type) = 0; + virtual void OnExitProcess(uint32_t exit_code) = 0; + virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0; + virtual ExceptionResult OnDebugException(bool first_chance, + const ExceptionRecord &record) = 0; + virtual void OnCreateThread(const HostThread &thread) = 0; + virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0; + virtual void OnLoadDll(const ModuleSpec &module_spec, + lldb::addr_t module_addr) = 0; + virtual void OnUnloadDll(lldb::addr_t module_addr) = 0; + virtual void OnDebugString(const std::string &string) = 0; + virtual void OnDebuggerError(const Error &error, uint32_t type) = 0; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp index a0ac9725c75..af18999f431 100644 --- a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp @@ -14,78 +14,60 @@ using namespace lldb; using namespace lldb_private; LocalDebugDelegate::LocalDebugDelegate(ProcessWP process) - : m_process(process) -{ -} + : m_process(process) {} -void -LocalDebugDelegate::OnExitProcess(uint32_t exit_code) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnExitProcess(exit_code); +void LocalDebugDelegate::OnExitProcess(uint32_t exit_code) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnExitProcess(exit_code); } -void -LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebuggerConnected(image_base); +void LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebuggerConnected(image_base); } ExceptionResult -LocalDebugDelegate::OnDebugException(bool first_chance, const ExceptionRecord &record) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - return process->OnDebugException(first_chance, record); - else - return ExceptionResult::MaskException; +LocalDebugDelegate::OnDebugException(bool first_chance, + const ExceptionRecord &record) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + return process->OnDebugException(first_chance, record); + else + return ExceptionResult::MaskException; } -void -LocalDebugDelegate::OnCreateThread(const HostThread &thread) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnCreateThread(thread); +void LocalDebugDelegate::OnCreateThread(const HostThread &thread) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnCreateThread(thread); } -void -LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnExitThread(thread_id, exit_code); +void LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, + uint32_t exit_code) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnExitThread(thread_id, exit_code); } -void -LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnLoadDll(module_spec, module_addr); +void LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnLoadDll(module_spec, module_addr); } -void -LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnUnloadDll(module_addr); +void LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnUnloadDll(module_addr); } -void -LocalDebugDelegate::OnDebugString(const std::string &string) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebugString(string); +void LocalDebugDelegate::OnDebugString(const std::string &string) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebugString(string); } -void -LocalDebugDelegate::OnDebuggerError(const Error &error, uint32_t type) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebuggerError(error, type); +void LocalDebugDelegate::OnDebuggerError(const Error &error, uint32_t type) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebuggerError(error, type); } -ProcessWindowsLiveSP -LocalDebugDelegate::GetProcessPointer() -{ - ProcessSP process = m_process.lock(); - return std::static_pointer_cast<ProcessWindowsLive>(process); +ProcessWindowsLiveSP LocalDebugDelegate::GetProcessPointer() { + ProcessSP process = m_process.lock(); + return std::static_pointer_cast<ProcessWindowsLive>(process); } diff --git a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h index ec2f9418142..17e760c4453 100644 --- a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h +++ b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h @@ -16,8 +16,7 @@ #include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindowsLive; typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; @@ -26,9 +25,11 @@ typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; // LocalDebugDelegate // // LocalDebugDelegate creates a connection between a ProcessWindowsLive and the -// debug driver. This serves to decouple ProcessWindowsLive from the debug driver. +// debug driver. This serves to decouple ProcessWindowsLive from the debug +// driver. // It would be possible to get a similar decoupling by just having -// ProcessWindowsLive implement this interface directly. There are two reasons why +// ProcessWindowsLive implement this interface directly. There are two reasons +// why // we don't do this: // // 1) In the future when we add support for local debugging through LLGS, and we @@ -42,26 +43,26 @@ typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; // driver), so this adapter serves as a way to transparently hold the // ProcessSP while still keeping it decoupled from the driver. //---------------------------------------------------------------------- -class LocalDebugDelegate : public IDebugDelegate -{ - public: - explicit LocalDebugDelegate(lldb::ProcessWP process); +class LocalDebugDelegate : public IDebugDelegate { +public: + explicit LocalDebugDelegate(lldb::ProcessWP process); - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) override; - void OnCreateThread(const HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &message) override; - void OnDebuggerError(const Error &error, uint32_t type) override; + void OnExitProcess(uint32_t exit_code) override; + void OnDebuggerConnected(lldb::addr_t image_base) override; + ExceptionResult OnDebugException(bool first_chance, + const ExceptionRecord &record) override; + void OnCreateThread(const HostThread &thread) override; + void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; + void OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) override; + void OnUnloadDll(lldb::addr_t module_addr) override; + void OnDebugString(const std::string &message) override; + void OnDebuggerError(const Error &error, uint32_t type) override; - private: - ProcessWindowsLiveSP - GetProcessPointer(); +private: + ProcessWindowsLiveSP GetProcessPointer(); - lldb::ProcessWP m_process; + lldb::ProcessWP m_process; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp index 300e0caa437..9bfa247c2ed 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp @@ -24,9 +24,9 @@ #include "lldb/Core/Section.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" -#include "lldb/Host/HostProcess.h" #include "lldb/Host/HostNativeProcessBase.h" #include "lldb/Host/HostNativeThreadBase.h" +#include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/HostThreadWindows.h" @@ -56,1014 +56,991 @@ using namespace lldb_private; #define BOOL_STR(b) ((b) ? "true" : "false") -namespace -{ - -std::string -GetProcessExecutableName(HANDLE process_handle) -{ - std::vector<wchar_t> file_name; - DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit - DWORD copied = 0; - do - { - file_name_size *= 2; - file_name.resize(file_name_size); - copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), file_name_size); - } while (copied >= file_name_size); - file_name.resize(copied); - std::string result; - llvm::convertWideToUTF8(file_name.data(), result); - return result; +namespace { + +std::string GetProcessExecutableName(HANDLE process_handle) { + std::vector<wchar_t> file_name; + DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit + DWORD copied = 0; + do { + file_name_size *= 2; + file_name.resize(file_name_size); + copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), + file_name_size); + } while (copied >= file_name_size); + file_name.resize(copied); + std::string result; + llvm::convertWideToUTF8(file_name.data(), result); + return result; } -std::string -GetProcessExecutableName(DWORD pid) -{ - std::string file_name; - HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (process_handle != NULL) - { - file_name = GetProcessExecutableName(process_handle); - ::CloseHandle(process_handle); - } - return file_name; +std::string GetProcessExecutableName(DWORD pid) { + std::string file_name; + HANDLE process_handle = + ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (process_handle != NULL) { + file_name = GetProcessExecutableName(process_handle); + ::CloseHandle(process_handle); + } + return file_name; } -} // anonymous namespace +} // anonymous namespace -namespace lldb_private -{ +namespace lldb_private { -// We store a pointer to this class in the ProcessWindows, so that we don't expose Windows +// We store a pointer to this class in the ProcessWindows, so that we don't +// expose Windows // OS specific types and implementation details from a public header file. -class ProcessWindowsData -{ - public: - ProcessWindowsData(bool stop_at_entry) - : m_stop_at_entry(stop_at_entry) - , m_initial_stop_event(nullptr) - , m_initial_stop_received(false) - { - m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - - ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } - - lldb_private::Error m_launch_error; - lldb_private::DebuggerThreadSP m_debugger; - StopInfoSP m_pending_stop_info; - HANDLE m_initial_stop_event; - bool m_stop_at_entry; - bool m_initial_stop_received; - std::map<lldb::tid_t, HostThread> m_new_threads; - std::set<lldb::tid_t> m_exited_threads; +class ProcessWindowsData { +public: + ProcessWindowsData(bool stop_at_entry) + : m_stop_at_entry(stop_at_entry), m_initial_stop_event(nullptr), + m_initial_stop_received(false) { + m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + } + + ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } + + lldb_private::Error m_launch_error; + lldb_private::DebuggerThreadSP m_debugger; + StopInfoSP m_pending_stop_info; + HANDLE m_initial_stop_event; + bool m_stop_at_entry; + bool m_initial_stop_received; + std::map<lldb::tid_t, HostThread> m_new_threads; + std::set<lldb::tid_t> m_exited_threads; }; } //------------------------------------------------------------------------------ // Static functions. -ProcessSP -ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *) -{ - return ProcessSP(new ProcessWindowsLive(target_sp, listener_sp)); +ProcessSP ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *) { + return ProcessSP(new ProcessWindowsLive(target_sp, listener_sp)); } -void -ProcessWindowsLive::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - }); +void ProcessWindowsLive::Initialize() { + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) - : lldb_private::ProcessWindows(target_sp, listener_sp) -{ -} +ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp) + : lldb_private::ProcessWindows(target_sp, listener_sp) {} -ProcessWindowsLive::~ProcessWindowsLive() -{ -} +ProcessWindowsLive::~ProcessWindowsLive() {} -void -ProcessWindowsLive::Terminate() -{ -} +void ProcessWindowsLive::Terminate() {} -lldb_private::ConstString -ProcessWindowsLive::GetPluginNameStatic() -{ - static ConstString g_name("windows"); - return g_name; +lldb_private::ConstString ProcessWindowsLive::GetPluginNameStatic() { + static ConstString g_name("windows"); + return g_name; } -const char * -ProcessWindowsLive::GetPluginDescriptionStatic() -{ - return "Process plugin for Windows"; +const char *ProcessWindowsLive::GetPluginDescriptionStatic() { + return "Process plugin for Windows"; } -Error -ProcessWindowsLive::EnableBreakpointSite(BreakpointSite *bp_site) -{ - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%x)", - bp_site->GetID(), bp_site->GetLoadAddress()); - - Error error = EnableSoftwareBreakpoint(bp_site); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", error.AsCString()); - } - return error; +Error ProcessWindowsLive::EnableBreakpointSite(BreakpointSite *bp_site) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, + "EnableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site->GetID(), bp_site->GetLoadAddress()); + + Error error = EnableSoftwareBreakpoint(bp_site); + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", + error.AsCString()); + } + return error; } -Error -ProcessWindowsLive::DisableBreakpointSite(BreakpointSite *bp_site) -{ - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%x)", - bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); +Error ProcessWindowsLive::DisableBreakpointSite(BreakpointSite *bp_site) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, + "DisableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); - Error error = DisableSoftwareBreakpoint(bp_site); + Error error = DisableSoftwareBreakpoint(bp_site); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", error.AsCString()); - } - return error; + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", + error.AsCString()); + } + return error; } -bool -ProcessWindowsLive::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - // Add all the threads that were previously running and for which we did not detect a thread - // exited event. - int new_size = 0; - int continued_threads = 0; - int exited_threads = 0; - int new_threads = 0; - - for (ThreadSP old_thread : old_thread_list.Threads()) - { - lldb::tid_t old_thread_id = old_thread->GetID(); - auto exited_thread_iter = m_session_data->m_exited_threads.find(old_thread_id); - if (exited_thread_iter == m_session_data->m_exited_threads.end()) - { - new_thread_list.AddThread(old_thread); - ++new_size; - ++continued_threads; - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and is still running.", - old_thread_id); - } - else - { - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and has exited.", - old_thread_id); - ++exited_threads; - } - } - - // Also add all the threads that are new since the last time we broke into the debugger. - for (const auto &thread_info : m_session_data->m_new_threads) - { - ThreadSP thread(new TargetThreadWindowsLive(*this, thread_info.second)); - thread->SetID(thread_info.first); - new_thread_list.AddThread(thread); - ++new_size; - ++new_threads; - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u is new since last update.", thread_info.first); +bool ProcessWindowsLive::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + // Add all the threads that were previously running and for which we did not + // detect a thread + // exited event. + int new_size = 0; + int continued_threads = 0; + int exited_threads = 0; + int new_threads = 0; + + for (ThreadSP old_thread : old_thread_list.Threads()) { + lldb::tid_t old_thread_id = old_thread->GetID(); + auto exited_thread_iter = + m_session_data->m_exited_threads.find(old_thread_id); + if (exited_thread_iter == m_session_data->m_exited_threads.end()) { + new_thread_list.AddThread(old_thread); + ++new_size; + ++continued_threads; + WINLOGV_IFALL( + WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u was running and is still running.", + old_thread_id); + } else { + WINLOGV_IFALL(WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u was running and has exited.", + old_thread_id); + ++exited_threads; } - - WINLOG_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", - new_threads, continued_threads, exited_threads); - - m_session_data->m_new_threads.clear(); - m_session_data->m_exited_threads.clear(); - - return new_size > 0; + } + + // Also add all the threads that are new since the last time we broke into the + // debugger. + for (const auto &thread_info : m_session_data->m_new_threads) { + ThreadSP thread(new TargetThreadWindowsLive(*this, thread_info.second)); + thread->SetID(thread_info.first); + new_thread_list.AddThread(thread); + ++new_size; + ++new_threads; + WINLOGV_IFALL(WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u is new since last update.", + thread_info.first); + } + + WINLOG_IFALL( + WINDOWS_LOG_THREAD, + "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", + new_threads, continued_threads, exited_threads); + + m_session_data->m_new_threads.clear(); + m_session_data->m_exited_threads.clear(); + + return new_size > 0; } -Error -ProcessWindowsLive::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) -{ - // Even though m_session_data is accessed here, it is before a debugger thread has been - // kicked off. So there's no race conditions, and it shouldn't be necessary to acquire - // the mutex. - - Error result; - if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) - { - StreamString stream; - stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can only be used for debug launches.", - launch_info.GetExecutableFile().GetPath().c_str()); - std::string message = stream.GetString(); - result.SetErrorString(message.c_str()); - - WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); - return result; - } - - bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); - m_session_data.reset(new ProcessWindowsData(stop_at_entry)); - - SetPrivateState(eStateLaunching); - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - m_session_data->m_debugger.reset(new DebuggerThread(delegate)); - DebuggerThreadSP debugger = m_session_data->m_debugger; - - // Kick off the DebugLaunch asynchronously and wait for it to complete. - result = debugger->DebugLaunch(launch_info); - if (result.Fail()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), result.AsCString()); - return result; - } - - HostProcess process; - Error error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), error.AsCString()); - return error; - } - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", - launch_info.GetExecutableFile().GetPath().c_str()); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state - // should already be set to eStateStopped as a result of hitting the initial breakpoint. If - // it was not set, the breakpoint should have already been resumed from and the private state - // should already be eStateRunning. - launch_info.SetProcessID(process.GetProcessId()); - SetID(process.GetProcessId()); - +Error ProcessWindowsLive::DoLaunch(Module *exe_module, + ProcessLaunchInfo &launch_info) { + // Even though m_session_data is accessed here, it is before a debugger thread + // has been + // kicked off. So there's no race conditions, and it shouldn't be necessary + // to acquire + // the mutex. + + Error result; + if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { + StreamString stream; + stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can " + "only be used for debug launches.", + launch_info.GetExecutableFile().GetPath().c_str()); + std::string message = stream.GetString(); + result.SetErrorString(message.c_str()); + + WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); return result; + } + + bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); + m_session_data.reset(new ProcessWindowsData(stop_at_entry)); + + SetPrivateState(eStateLaunching); + DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); + m_session_data->m_debugger.reset(new DebuggerThread(delegate)); + DebuggerThreadSP debugger = m_session_data->m_debugger; + + // Kick off the DebugLaunch asynchronously and wait for it to complete. + result = debugger->DebugLaunch(launch_info); + if (result.Fail()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", + launch_info.GetExecutableFile().GetPath().c_str(), + result.AsCString()); + return result; + } + + HostProcess process; + Error error = WaitForDebuggerConnection(debugger, process); + if (error.Fail()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", + launch_info.GetExecutableFile().GetPath().c_str(), + error.AsCString()); + return error; + } + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", + launch_info.GetExecutableFile().GetPath().c_str()); + + // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the + // private state + // should already be set to eStateStopped as a result of hitting the initial + // breakpoint. If + // it was not set, the breakpoint should have already been resumed from and + // the private state + // should already be eStateRunning. + launch_info.SetProcessID(process.GetProcessId()); + SetID(process.GetProcessId()); + + return result; } -Error -ProcessWindowsLive::DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - m_session_data.reset(new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - DebuggerThreadSP debugger(new DebuggerThread(delegate)); - - m_session_data->m_debugger = debugger; +Error ProcessWindowsLive::DoAttachToProcessWithID( + lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + m_session_data.reset( + new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - DWORD process_id = static_cast<DWORD>(pid); - Error error = debugger->DebugAttach(process_id, attach_info); - if (error.Fail()) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach. %s", - error.AsCString()); - return error; - } - - HostProcess process; - error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DoAttachToProcessWithID encountered an error waiting for the debugger to connect. %s", - error.AsCString()); - return error; - } + DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); + DebuggerThreadSP debugger(new DebuggerThread(delegate)); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID successfully attached to process with pid=%u", - process_id); + m_session_data->m_debugger = debugger; - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state - // should already be set to eStateStopped as a result of hitting the initial breakpoint. If - // it was not set, the breakpoint should have already been resumed from and the private state - // should already be eStateRunning. - SetID(process.GetProcessId()); + DWORD process_id = static_cast<DWORD>(pid); + Error error = debugger->DebugAttach(process_id, attach_info); + if (error.Fail()) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " + "error occurred initiating the " + "asynchronous attach. %s", + error.AsCString()); + return error; + } + + HostProcess process; + error = WaitForDebuggerConnection(debugger, process); + if (error.Fail()) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " + "error waiting for the debugger to " + "connect. %s", + error.AsCString()); return error; + } + + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoAttachToProcessWithID successfully attached to process with pid=%u", + process_id); + + // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the + // private state + // should already be set to eStateStopped as a result of hitting the initial + // breakpoint. If + // it was not set, the breakpoint should have already been resumed from and + // the private state + // should already be eStateRunning. + SetID(process.GetProcessId()); + return error; } -Error -ProcessWindowsLive::WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process) -{ - Error result; - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection Waiting for loader breakpoint."); - - // Block this function until we receive the initial stop from the process. - if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0) - { - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection hit loader breakpoint, returning."); +Error ProcessWindowsLive::WaitForDebuggerConnection(DebuggerThreadSP debugger, + HostProcess &process) { + Error result; + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, + "WaitForDebuggerConnection Waiting for loader breakpoint."); + + // Block this function until we receive the initial stop from the process. + if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == + WAIT_OBJECT_0) { + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, + "WaitForDebuggerConnection hit loader breakpoint, returning."); + + process = debugger->GetProcess(); + return m_session_data->m_launch_error; + } else + return Error(::GetLastError(), eErrorTypeWin32); +} - process = debugger->GetProcess(); - return m_session_data->m_launch_error; +Error ProcessWindowsLive::DoResume() { + llvm::sys::ScopedLock lock(m_mutex); + Error error; + + StateType private_state = GetPrivateState(); + if (private_state == eStateStopped || private_state == eStateCrashed) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoResume called for process %I64u while state is %u. Resuming...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); + + ExceptionRecordSP active_exception = + m_session_data->m_debugger->GetActiveException().lock(); + if (active_exception) { + // Resume the process and continue processing debug events. Mask + // the exception so that from the process's view, there is no + // indication that anything happened. + m_session_data->m_debugger->ContinueAsyncException( + ExceptionResult::MaskException); } - else - return Error(::GetLastError(), eErrorTypeWin32); -} -Error -ProcessWindowsLive::DoResume() -{ - llvm::sys::ScopedLock lock(m_mutex); - Error error; + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, + "DoResume resuming %u threads.", m_thread_list.GetSize()); - StateType private_state = GetPrivateState(); - if (private_state == eStateStopped || private_state == eStateCrashed) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u while state is %u. Resuming...", - m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); - - ExceptionRecordSP active_exception = - m_session_data->m_debugger->GetActiveException().lock(); - if (active_exception) - { - // Resume the process and continue processing debug events. Mask - // the exception so that from the process's view, there is no - // indication that anything happened. - m_session_data->m_debugger->ContinueAsyncException( - ExceptionResult::MaskException); - } - - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, "DoResume resuming %u threads.", - m_thread_list.GetSize()); - - for (int i = 0; i < m_thread_list.GetSize(); ++i) - { - auto thread = std::static_pointer_cast<TargetThreadWindowsLive>( - m_thread_list.GetThreadAtIndex(i)); - thread->DoResume(); - } - - SetPrivateState(eStateRunning); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u but state is %u. Returning...", - m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); + for (int i = 0; i < m_thread_list.GetSize(); ++i) { + auto thread = std::static_pointer_cast<TargetThreadWindowsLive>( + m_thread_list.GetThreadAtIndex(i)); + thread->DoResume(); } - return error; -} + SetPrivateState(eStateRunning); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "DoResume called for process %I64u but state is %u. Returning...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); + } + return error; +} //------------------------------------------------------------------------------ // ProcessInterface protocol. -lldb_private::ConstString -ProcessWindowsLive::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessWindowsLive::GetPluginVersion() -{ - return 1; +lldb_private::ConstString ProcessWindowsLive::GetPluginName() { + return GetPluginNameStatic(); } -Error -ProcessWindowsLive::DoDetach(bool keep_stopped) -{ - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire the lock only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which - // will also acquire the lock. Thus we have to release the lock before - // calling StopDebugging(). - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "DoDetach called while state = %u, but there is no active session.", - private_state); - return Error(); - } - - debugger_thread = m_session_data->m_debugger; - } +uint32_t ProcessWindowsLive::GetPluginVersion() { return 1; } - Error error; - if (private_state != eStateExited && private_state != eStateDetached) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoDetach called for process %I64u while state = %u. Detaching...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - error = debugger_thread->StopDebugging(false); - if (error.Success()) - { - SetPrivateState(eStateDetached); - } - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DoDetach called for process %I64u while state = %u, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - } +Error ProcessWindowsLive::DoDetach(bool keep_stopped) { + DebuggerThreadSP debugger_thread; + StateType private_state; + { + // Acquire the lock only long enough to get the DebuggerThread. + // StopDebugging() will trigger a call back into ProcessWindows which + // will also acquire the lock. Thus we have to release the lock before + // calling StopDebugging(). + llvm::sys::ScopedLock lock(m_mutex); - return error; -} + private_state = GetPrivateState(); -Error -ProcessWindowsLive::DoDestroy() -{ - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire this lock inside an inner scope, only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which will acquire the lock - // again, so we need to not deadlock. - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called while state = %u, but there is no active session.", - private_state); - return Error(); - } - - debugger_thread = m_session_data->m_debugger; + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "DoDetach called while state = %u, but there is no active session.", + private_state); + return Error(); } - Error error; - if (private_state != eStateExited && private_state != eStateDetached) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = %u. Shutting down...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - error = debugger_thread->StopDebugging(true); - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DoDestroy called for process %I64u while state = %u, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); + debugger_thread = m_session_data->m_debugger; + } + + Error error; + if (private_state != eStateExited && private_state != eStateDetached) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoDetach called for process %I64u while state = %u. Detaching...", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + error = debugger_thread->StopDebugging(false); + if (error.Success()) { + SetPrivateState(eStateDetached); } - return error; + // By the time StopDebugging returns, there is no more debugger thread, so + // we can be assured that no other thread will race for the session data. + m_session_data.reset(); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, "DoDetach called for process %I64u while state = " + "%u, but cannot destroy in this state.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + } + + return error; } -void -ProcessWindowsLive::RefreshStateAfterStop() -{ +Error ProcessWindowsLive::DoDestroy() { + DebuggerThreadSP debugger_thread; + StateType private_state; + { + // Acquire this lock inside an inner scope, only long enough to get the + // DebuggerThread. + // StopDebugging() will trigger a call back into ProcessWindows which will + // acquire the lock + // again, so we need to not deadlock. llvm::sys::ScopedLock lock(m_mutex); - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called with no active session. Returning..."); - return; - } - - m_thread_list.RefreshStateAfterStop(); + private_state = GetPrivateState(); - std::weak_ptr<ExceptionRecord> exception_record = m_session_data->m_debugger->GetActiveException(); - ExceptionRecordSP active_exception = exception_record.lock(); - if (!active_exception) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called for process %I64u but there is no " - "active exception. Why is the process stopped?", - m_session_data->m_debugger->GetProcess().GetProcessId()); - return; + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "DoDestroy called while state = %u, but there is no active session.", + private_state); + return Error(); } - StopInfoSP stop_info; - m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - ThreadSP stop_thread = m_thread_list.GetSelectedThread(); - if (!stop_thread) - return; - - switch (active_exception->GetExceptionCode()) - { - case EXCEPTION_SINGLE_STEP: - { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - const uint64_t pc = register_context->GetPC(); - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site && site->ValidForThisThread(stop_thread.get())) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, - "Single-stepped onto a breakpoint in process %I64u at " - "address 0x%I64x with breakpoint site %d", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); - stop_thread->SetStopInfo(stop_info); - } - else - { - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, - "RefreshStateAfterStop single stepping thread %u", stop_thread->GetID()); - stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); - stop_thread->SetStopInfo(stop_info); - } - return; - } - - case EXCEPTION_BREAKPOINT: - { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - - // The current EIP is AFTER the BP opcode, which is one byte. - uint64_t pc = register_context->GetPC() - 1; - - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "RefreshStateAfterStop detected breakpoint in process %I64u at " - "address 0x%I64x with breakpoint site %d", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); - - if (site->ValidForThisThread(stop_thread.get())) - { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.", - site->GetID(), stop_thread->GetID()); - - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( - *stop_thread, site->GetID()); - register_context->SetPC(pc); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "Breakpoint site %d is not valid for this thread, creating empty stop info.", - site->GetID()); - } - stop_thread->SetStopInfo(stop_info); - return; - } - else - { - // The thread hit a hard-coded breakpoint like an `int 3` or `__debugbreak()`. - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "No breakpoint site matches for this thread. __debugbreak()? " - "Creating stop info with the exception."); - // FALLTHROUGH: We'll treat this as a generic exception record in the default case. - } - } - - default: - { - 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); - stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); - WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str()); - return; - } - } + debugger_thread = m_session_data->m_debugger; + } + + Error error; + if (private_state != eStateExited && private_state != eStateDetached) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = " + "%u. Shutting down...", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + error = debugger_thread->StopDebugging(true); + + // By the time StopDebugging returns, there is no more debugger thread, so + // we can be assured that no other thread will race for the session data. + m_session_data.reset(); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = " + "%u, but cannot destroy in this state.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + } + + return error; } -bool -ProcessWindowsLive::IsAlive() -{ - StateType state = GetPrivateState(); - switch (state) - { - case eStateCrashed: - case eStateDetached: - case eStateUnloaded: - case eStateExited: - case eStateInvalid: - return false; - default: - return true; +void ProcessWindowsLive::RefreshStateAfterStop() { + llvm::sys::ScopedLock lock(m_mutex); + + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "RefreshStateAfterStop called with no active session. Returning..."); + return; + } + + m_thread_list.RefreshStateAfterStop(); + + std::weak_ptr<ExceptionRecord> exception_record = + m_session_data->m_debugger->GetActiveException(); + ExceptionRecordSP active_exception = exception_record.lock(); + if (!active_exception) { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "RefreshStateAfterStop called for process %I64u but there is no " + "active exception. Why is the process stopped?", + m_session_data->m_debugger->GetProcess().GetProcessId()); + return; + } + + StopInfoSP stop_info; + m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); + ThreadSP stop_thread = m_thread_list.GetSelectedThread(); + if (!stop_thread) + return; + + switch (active_exception->GetExceptionCode()) { + case EXCEPTION_SINGLE_STEP: { + RegisterContextSP register_context = stop_thread->GetRegisterContext(); + const uint64_t pc = register_context->GetPC(); + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + if (site && site->ValidForThisThread(stop_thread.get())) { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | + WINDOWS_LOG_STEP, + "Single-stepped onto a breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, + site->GetID()); + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, + site->GetID()); + stop_thread->SetStopInfo(stop_info); + } else { + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, + "RefreshStateAfterStop single stepping thread %u", + stop_thread->GetID()); + stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); + stop_thread->SetStopInfo(stop_info); } -} - -Error -ProcessWindowsLive::DoHalt(bool &caused_stop) -{ - Error error; - StateType state = GetPrivateState(); - if (state == eStateStopped) - caused_stop = false; - else - { - llvm::sys::ScopedLock lock(m_mutex); - caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess().GetNativeProcess().GetSystemHandle()); - if (!caused_stop) - { - error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoHalt called DebugBreakProcess, but it failed with error %u", - error.GetError()); - } + return; + } + + case EXCEPTION_BREAKPOINT: { + RegisterContextSP register_context = stop_thread->GetRegisterContext(); + + // The current EIP is AFTER the BP opcode, which is one byte. + uint64_t pc = register_context->GetPC() - 1; + + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + if (site) { + WINLOG_IFANY( + WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "RefreshStateAfterStop detected breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, + site->GetID()); + + if (site->ValidForThisThread(stop_thread.get())) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is valid for this thread (0x%I64x), " + "creating stop info.", + site->GetID(), stop_thread->GetID()); + + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( + *stop_thread, site->GetID()); + register_context->SetPC(pc); + } else { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is not valid for this thread, " + "creating empty stop info.", + site->GetID()); + } + stop_thread->SetStopInfo(stop_info); + return; + } else { + // The thread hit a hard-coded breakpoint like an `int 3` or + // `__debugbreak()`. + WINLOG_IFALL( + WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "No breakpoint site matches for this thread. __debugbreak()? " + "Creating stop info with the exception."); + // FALLTHROUGH: We'll treat this as a generic exception record in the + // default case. } - return error; -} - -void -ProcessWindowsLive::DidLaunch() -{ - ArchSpec arch_spec; - DidAttach(arch_spec); + } + + default: { + 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); + stop_info = StopInfo::CreateStopReasonWithException( + *stop_thread, desc_stream.str().c_str()); + stop_thread->SetStopInfo(stop_info); + WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str()); + return; + } + } } -void -ProcessWindowsLive::DidAttach(ArchSpec &arch_spec) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // The initial stop won't broadcast the state change event, so account for that here. - if (m_session_data && GetPrivateState() == eStateStopped && m_session_data->m_stop_at_entry) - RefreshStateAfterStop(); +bool ProcessWindowsLive::IsAlive() { + StateType state = GetPrivateState(); + switch (state) { + case eStateCrashed: + case eStateDetached: + case eStateUnloaded: + case eStateExited: + case eStateInvalid: + return false; + default: + return true; + } } -size_t -ProcessWindowsLive::DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - Error &error) -{ +Error ProcessWindowsLive::DoHalt(bool &caused_stop) { + Error error; + StateType state = GetPrivateState(); + if (state == eStateStopped) + caused_stop = false; + else { llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) - return 0; - - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory attempting to read %u bytes from address 0x%I64x", size, vm_addr); - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, buf, size, &bytes_read)) - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", error.GetError()); + caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() + .GetNativeProcess() + .GetSystemHandle()); + if (!caused_stop) { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "DoHalt called DebugBreakProcess, but it failed with error %u", + error.GetError()); } - return bytes_read; + } + return error; } -size_t -ProcessWindowsLive::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) -{ - llvm::sys::ScopedLock lock(m_mutex); - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, vm_addr); +void ProcessWindowsLive::DidLaunch() { + ArchSpec arch_spec; + DidAttach(arch_spec); +} - if (!m_session_data) - { - WINERR_IFANY(WINDOWS_LOG_MEMORY, "DoWriteMemory cannot write, there is no active debugger connection."); - return 0; - } +void ProcessWindowsLive::DidAttach(ArchSpec &arch_spec) { + llvm::sys::ScopedLock lock(m_mutex); - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_written = 0; - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) - FlushInstructionCache(handle, addr, bytes_written); - else - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", error.GetError()); - } - return bytes_written; + // The initial stop won't broadcast the state change event, so account for + // that here. + if (m_session_data && GetPrivateState() == eStateStopped && + m_session_data->m_stop_at_entry) + RefreshStateAfterStop(); } -Error -ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) -{ - Error error; - llvm::sys::ScopedLock lock(m_mutex); - info.Clear(); +size_t ProcessWindowsLive::DoReadMemory(lldb::addr_t vm_addr, void *buf, + size_t size, Error &error) { + llvm::sys::ScopedLock lock(m_mutex); + + if (!m_session_data) + return 0; + + WINLOG_IFALL(WINDOWS_LOG_MEMORY, + "DoReadMemory attempting to read %u bytes from address 0x%I64x", + size, vm_addr); + + HostProcess process = m_session_data->m_debugger->GetProcess(); + void *addr = reinterpret_cast<void *>(vm_addr); + SIZE_T bytes_read = 0; + if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, + buf, size, &bytes_read)) { + error.SetError(GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", + error.GetError()); + } + return bytes_read; +} - if (!m_session_data) - { - error.SetErrorString("GetMemoryRegionInfo called with no debugging session."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); - return error; - } - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (handle == nullptr || handle == LLDB_INVALID_PROCESS) - { - error.SetErrorString("GetMemoryRegionInfo called with an invalid target process."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); - return error; - } +size_t ProcessWindowsLive::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, + size_t size, Error &error) { + llvm::sys::ScopedLock lock(m_mutex); + WINLOG_IFALL( + WINDOWS_LOG_MEMORY, + "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, + vm_addr); + + if (!m_session_data) { + WINERR_IFANY( + WINDOWS_LOG_MEMORY, + "DoWriteMemory cannot write, there is no active debugger connection."); + return 0; + } + + HostProcess process = m_session_data->m_debugger->GetProcess(); + void *addr = reinterpret_cast<void *>(vm_addr); + SIZE_T bytes_written = 0; + lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); + if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) + FlushInstructionCache(handle, addr, bytes_written); + else { + error.SetError(GetLastError(), eErrorTypeWin32); + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", + error.GetError()); + } + return bytes_written; +} - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); - - void *addr = reinterpret_cast<void *>(vm_addr); - MEMORY_BASIC_INFORMATION mem_info = {0}; - SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); - if (result == 0) - { - if (::GetLastError() == ERROR_INVALID_PARAMETER) - { - // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an address - // past the highest accessible address. We should return a range from the vm_addr - // to LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - return error; - } - else - { - error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_MEMORY, - "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", - error.GetError(), vm_addr); - return error; - } - } +Error ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, + MemoryRegionInfo &info) { + Error error; + llvm::sys::ScopedLock lock(m_mutex); + info.Clear(); - // Protect bits are only valid for MEM_COMMIT regions. - if (mem_info.State == MEM_COMMIT) { - const bool readable = IsPageReadable(mem_info.Protect); - const bool executable = IsPageExecutable(mem_info.Protect); - const bool writable = IsPageWritable(mem_info.Protect); - info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - } - else - { - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); + if (!m_session_data) { + error.SetErrorString( + "GetMemoryRegionInfo called with no debugging session."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); + return error; + } + HostProcess process = m_session_data->m_debugger->GetProcess(); + lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); + if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { + error.SetErrorString( + "GetMemoryRegionInfo called with an invalid target process."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); + return error; + } + + WINLOG_IFALL(WINDOWS_LOG_MEMORY, + "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); + + void *addr = reinterpret_cast<void *>(vm_addr); + MEMORY_BASIC_INFORMATION mem_info = {0}; + SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); + if (result == 0) { + if (::GetLastError() == ERROR_INVALID_PARAMETER) { + // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an + // address + // past the highest accessible address. We should return a range from the + // vm_addr + // to LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + return error; + } else { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while " + "getting memory region info for address " + "0x%I64x", + error.GetError(), vm_addr); + return error; } + } + + // Protect bits are only valid for MEM_COMMIT regions. + if (mem_info.State == MEM_COMMIT) { + const bool readable = IsPageReadable(mem_info.Protect); + const bool executable = IsPageExecutable(mem_info.Protect); + const bool writable = IsPageWritable(mem_info.Protect); + info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + info.SetExecutable(executable ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + } else { + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + } + + // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. + if (mem_info.State != MEM_FREE) { + info.GetRange().SetRangeBase( + reinterpret_cast<addr_t>(mem_info.AllocationBase)); + info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + + mem_info.RegionSize); + info.SetMapped(MemoryRegionInfo::eYes); + } else { + // In the unmapped case we need to return the distance to the next block of + // memory. + // VirtualQueryEx nearly does that except that it gives the distance from + // the start + // of the page containing vm_addr. + SYSTEM_INFO data; + GetSystemInfo(&data); + DWORD page_offset = vm_addr % data.dwPageSize; + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); + info.SetMapped(MemoryRegionInfo::eNo); + } + + error.SetError(::GetLastError(), eErrorTypeWin32); + WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: " + "readable=%s, executable=%s, writable=%s", + BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), + BOOL_STR(info.GetWritable())); + return error; +} - // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. - if (mem_info.State != MEM_FREE) { - info.GetRange().SetRangeBase(reinterpret_cast<addr_t>(mem_info.AllocationBase)); - info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + mem_info.RegionSize); - info.SetMapped(MemoryRegionInfo::eYes); - } - else - { - // In the unmapped case we need to return the distance to the next block of memory. - // VirtualQueryEx nearly does that except that it gives the distance from the start - // of the page containing vm_addr. - SYSTEM_INFO data; - GetSystemInfo(&data); - DWORD page_offset = vm_addr % data.dwPageSize; - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); - info.SetMapped(MemoryRegionInfo::eNo); - } +bool ProcessWindowsLive::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + if (plugin_specified_by_name) + return true; - error.SetError(::GetLastError(), eErrorTypeWin32); - WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s", - BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable())); - return error; + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target_sp->GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + // However, if there is no executable module, we return true since we might be + // preparing to attach. + return true; } -bool -ProcessWindowsLive::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - // However, if there is no executable module, we return true since we might be preparing to attach. - return true; +void ProcessWindowsLive::OnExitProcess(uint32_t exit_code) { + // No need to acquire the lock since m_session_data isn't accessed. + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %u exited with code %u", GetID(), + exit_code); + + TargetSP target = m_target_sp.lock(); + if (target) { + ModuleSP executable_module = target->GetExecutableModule(); + ModuleList unloaded_modules; + unloaded_modules.Append(executable_module); + target->ModulesDidUnload(unloaded_modules, true); + } + + SetProcessExitStatus(GetID(), true, 0, exit_code); + SetPrivateState(eStateExited); } -void -ProcessWindowsLive::OnExitProcess(uint32_t exit_code) -{ - // No need to acquire the lock since m_session_data isn't accessed. - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %u exited with code %u", GetID(), exit_code); - - TargetSP target = m_target_sp.lock(); - if (target) - { - ModuleSP executable_module = target->GetExecutableModule(); - ModuleList unloaded_modules; - unloaded_modules.Append(executable_module); - target->ModulesDidUnload(unloaded_modules, true); - } +void ProcessWindowsLive::OnDebuggerConnected(lldb::addr_t image_base) { + DebuggerThreadSP debugger = m_session_data->m_debugger; - SetProcessExitStatus(GetID(), true, 0, exit_code); - SetPrivateState(eStateExited); -} + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "Debugger connected to process %I64u. Image base = 0x%I64x", + debugger->GetProcess().GetProcessId(), image_base); -void -ProcessWindowsLive::OnDebuggerConnected(lldb::addr_t image_base) -{ - DebuggerThreadSP debugger = m_session_data->m_debugger; - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Debugger connected to process %I64u. Image base = 0x%I64x", - debugger->GetProcess().GetProcessId(), image_base); - - ModuleSP module = GetTarget().GetExecutableModule(); - if (!module) - { - // During attach, we won't have the executable module, so find it now. - const DWORD pid = debugger->GetProcess().GetProcessId(); - const std::string file_name = GetProcessExecutableName(pid); - if (file_name.empty()) - { - return; - } - - FileSpec executable_file(file_name, true); - ModuleSpec module_spec(executable_file); - Error error; - module = GetTarget().GetSharedModule(module_spec, &error); - if (!module) - { - return; - } - - GetTarget().SetExecutableModule(module, false); + ModuleSP module = GetTarget().GetExecutableModule(); + if (!module) { + // During attach, we won't have the executable module, so find it now. + const DWORD pid = debugger->GetProcess().GetProcessId(); + const std::string file_name = GetProcessExecutableName(pid); + if (file_name.empty()) { + return; } - bool load_addr_changed; - module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); + FileSpec executable_file(file_name, true); + ModuleSpec module_spec(executable_file); + Error error; + module = GetTarget().GetSharedModule(module_spec, &error); + if (!module) { + return; + } - // Add the main executable module to the list of pending module loads. We can't call - // GetTarget().ModulesDidLoad() here because we still haven't returned from DoLaunch() / DoAttach() yet - // so the target may not have set the process instance to `this` yet. - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wmain_thread = debugger->GetMainThread().GetNativeThread(); - m_session_data->m_new_threads[wmain_thread.GetThreadId()] = debugger->GetMainThread(); + GetTarget().SetExecutableModule(module, false); + } + + bool load_addr_changed; + module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); + + ModuleList loaded_modules; + loaded_modules.Append(module); + GetTarget().ModulesDidLoad(loaded_modules); + + // Add the main executable module to the list of pending module loads. We + // can't call + // GetTarget().ModulesDidLoad() here because we still haven't returned from + // DoLaunch() / DoAttach() yet + // so the target may not have set the process instance to `this` yet. + llvm::sys::ScopedLock lock(m_mutex); + const HostThreadWindows &wmain_thread = + debugger->GetMainThread().GetNativeThread(); + m_session_data->m_new_threads[wmain_thread.GetThreadId()] = + debugger->GetMainThread(); } ExceptionResult -ProcessWindowsLive::OnDebugException(bool first_chance, const ExceptionRecord &record) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // FIXME: Without this check, occasionally when running the test suite there is - // an issue where m_session_data can be null. It's not clear how this could happen - // but it only surfaces while running the test suite. In order to properly diagnose - // this, we probably need to first figure allow the test suite to print out full - // lldb logs, and then add logging to the process plugin. - if (!m_session_data) - { - WINERR_IFANY(WINDOWS_LOG_EXCEPTION, - "Debugger thread reported exception 0x%x at address 0x%I64x, but there is no session.", - record.GetExceptionCode(), record.GetExceptionAddress()); - return ExceptionResult::SendToApplication; - } - - if (!first_chance) - { - // Any second chance exception is an application crash by definition. - SetPrivateState(eStateCrashed); - } - - ExceptionResult result = ExceptionResult::SendToApplication; - switch (record.GetExceptionCode()) - { - case EXCEPTION_BREAKPOINT: - // Handle breakpoints at the first chance. - result = ExceptionResult::BreakInDebugger; - - if (!m_session_data->m_initial_stop_received) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, - "Hit loader breakpoint at address 0x%I64x, setting initial stop event.", - record.GetExceptionAddress()); - m_session_data->m_initial_stop_received = true; - ::SetEvent(m_session_data->m_initial_stop_event); - } - else - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, - "Hit non-loader breakpoint at address 0x%I64x.", - record.GetExceptionAddress()); - } - SetPrivateState(eStateStopped); - break; - case EXCEPTION_SINGLE_STEP: - result = ExceptionResult::BreakInDebugger; - SetPrivateState(eStateStopped); - break; - default: - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, - "Debugger thread reported exception 0x%x at address 0x%I64x (first_chance=%s)", - record.GetExceptionCode(), record.GetExceptionAddress(), BOOL_STR(first_chance)); - // For non-breakpoints, give the application a chance to handle the exception first. - if (first_chance) - result = ExceptionResult::SendToApplication; - else - result = ExceptionResult::BreakInDebugger; +ProcessWindowsLive::OnDebugException(bool first_chance, + const ExceptionRecord &record) { + llvm::sys::ScopedLock lock(m_mutex); + + // FIXME: Without this check, occasionally when running the test suite there + // is + // an issue where m_session_data can be null. It's not clear how this could + // happen + // but it only surfaces while running the test suite. In order to properly + // diagnose + // this, we probably need to first figure allow the test suite to print out + // full + // lldb logs, and then add logging to the process plugin. + if (!m_session_data) { + WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " + "0x%x at address 0x%I64x, but there is " + "no session.", + record.GetExceptionCode(), record.GetExceptionAddress()); + return ExceptionResult::SendToApplication; + } + + if (!first_chance) { + // Any second chance exception is an application crash by definition. + SetPrivateState(eStateCrashed); + } + + ExceptionResult result = ExceptionResult::SendToApplication; + switch (record.GetExceptionCode()) { + case EXCEPTION_BREAKPOINT: + // Handle breakpoints at the first chance. + result = ExceptionResult::BreakInDebugger; + + if (!m_session_data->m_initial_stop_received) { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address " + "0x%I64x, setting initial stop " + "event.", + record.GetExceptionAddress()); + m_session_data->m_initial_stop_received = true; + ::SetEvent(m_session_data->m_initial_stop_event); + } else { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, + "Hit non-loader breakpoint at address 0x%I64x.", + record.GetExceptionAddress()); } + SetPrivateState(eStateStopped); + break; + case EXCEPTION_SINGLE_STEP: + result = ExceptionResult::BreakInDebugger; + SetPrivateState(eStateStopped); + break; + default: + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " + "0x%x at address 0x%I64x " + "(first_chance=%s)", + record.GetExceptionCode(), record.GetExceptionAddress(), + BOOL_STR(first_chance)); + // For non-breakpoints, give the application a chance to handle the + // exception first. + if (first_chance) + result = ExceptionResult::SendToApplication; + else + result = ExceptionResult::BreakInDebugger; + } - return result; + return result; } -void -ProcessWindowsLive::OnCreateThread(const HostThread &new_thread) -{ - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); - m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; +void ProcessWindowsLive::OnCreateThread(const HostThread &new_thread) { + llvm::sys::ScopedLock lock(m_mutex); + const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); + m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; } -void -ProcessWindowsLive::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // On a forced termination, we may get exit thread events after the session - // data has been cleaned up. - if (!m_session_data) - return; - - // A thread may have started and exited before the debugger stopped allowing a refresh. - // Just remove it from the new threads list in that case. - auto iter = m_session_data->m_new_threads.find(thread_id); - if (iter != m_session_data->m_new_threads.end()) - m_session_data->m_new_threads.erase(iter); - else - m_session_data->m_exited_threads.insert(thread_id); +void ProcessWindowsLive::OnExitThread(lldb::tid_t thread_id, + uint32_t exit_code) { + llvm::sys::ScopedLock lock(m_mutex); + + // On a forced termination, we may get exit thread events after the session + // data has been cleaned up. + if (!m_session_data) + return; + + // A thread may have started and exited before the debugger stopped allowing a + // refresh. + // Just remove it from the new threads list in that case. + auto iter = m_session_data->m_new_threads.find(thread_id); + if (iter != m_session_data->m_new_threads.end()) + m_session_data->m_new_threads.erase(iter); + else + m_session_data->m_exited_threads.insert(thread_id); } -void -ProcessWindowsLive::OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) -{ - // Confusingly, there is no Target::AddSharedModule. Instead, calling GetSharedModule() with - // a new module will add it to the module list and return a corresponding ModuleSP. - Error error; - ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); - bool load_addr_changed = false; - module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); +void ProcessWindowsLive::OnLoadDll(const ModuleSpec &module_spec, + lldb::addr_t module_addr) { + // Confusingly, there is no Target::AddSharedModule. Instead, calling + // GetSharedModule() with + // a new module will add it to the module list and return a corresponding + // ModuleSP. + Error error; + ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); + bool load_addr_changed = false; + module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); + + ModuleList loaded_modules; + loaded_modules.Append(module); + GetTarget().ModulesDidLoad(loaded_modules); } -void -ProcessWindowsLive::OnUnloadDll(lldb::addr_t module_addr) -{ - Address resolved_addr; - if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) - { - ModuleSP module = resolved_addr.GetModule(); - if (module) - { - ModuleList unloaded_modules; - unloaded_modules.Append(module); - GetTarget().ModulesDidUnload(unloaded_modules, false); - } +void ProcessWindowsLive::OnUnloadDll(lldb::addr_t module_addr) { + Address resolved_addr; + if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { + ModuleSP module = resolved_addr.GetModule(); + if (module) { + ModuleList unloaded_modules; + unloaded_modules.Append(module); + GetTarget().ModulesDidUnload(unloaded_modules, false); } + } } -void -ProcessWindowsLive::OnDebugString(const std::string &string) -{ -} - -void -ProcessWindowsLive::OnDebuggerError(const Error &error, uint32_t type) -{ - llvm::sys::ScopedLock lock(m_mutex); - - if (m_session_data->m_initial_stop_received) - { - // This happened while debugging. Do we shutdown the debugging session, try to continue, - // or do something else? - WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. Unexpected behavior may result. %s", - error.GetError(), error.AsCString()); - } - else - { - // If we haven't actually launched the process yet, this was an error launching the - // process. Set the internal error and signal the initial stop event so that the DoLaunch - // method wakes up and returns a failure. - m_session_data->m_launch_error = error; - ::SetEvent(m_session_data->m_initial_stop_event); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred launching the process before the initial stop. %s", - error.GetError(), error.AsCString()); - return; - } +void ProcessWindowsLive::OnDebugString(const std::string &string) {} + +void ProcessWindowsLive::OnDebuggerError(const Error &error, uint32_t type) { + llvm::sys::ScopedLock lock(m_mutex); + + if (m_session_data->m_initial_stop_received) { + // This happened while debugging. Do we shutdown the debugging session, try + // to continue, + // or do something else? + WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. " + "Unexpected behavior may result. %s", + error.GetError(), error.AsCString()); + } else { + // If we haven't actually launched the process yet, this was an error + // launching the + // process. Set the internal error and signal the initial stop event so + // that the DoLaunch + // method wakes up and returns a failure. + m_session_data->m_launch_error = error; + ::SetEvent(m_session_data->m_initial_stop_event); + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "Error %u occurred launching the process before the initial stop. %s", + error.GetError(), error.AsCString()); + return; + } } diff --git a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h index 657877f529b..89d69f6f043 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h +++ b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h @@ -19,10 +19,10 @@ // Other libraries and framework includes #include "ForwardDecl.h" #include "IDebugDelegate.h" -#include "lldb/lldb-forward.h" #include "lldb/Core/Error.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-forward.h" #include "llvm/Support/Mutex.h" @@ -30,96 +30,100 @@ class ProcessMonitor; -namespace lldb_private -{ +namespace lldb_private { class HostProcess; class ProcessWindowsData; -class ProcessWindowsLive : public lldb_private::ProcessWindows, public lldb_private::IDebugDelegate -{ +class ProcessWindowsLive : public lldb_private::ProcessWindows, + public lldb_private::IDebugDelegate { public: - //------------------------------------------------------------------ - // Static functions. - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *); - - static void - Initialize(); - - static void - Terminate(); - - static lldb_private::ConstString - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessWindowsLive(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp); - - ~ProcessWindowsLive(); - - // lldb_private::Process overrides - lldb_private::ConstString GetPluginName() override; - uint32_t GetPluginVersion() override; - - lldb_private::Error EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - lldb_private::Error DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error DoDetach(bool keep_stopped) override; - lldb_private::Error DoLaunch(lldb_private::Module *exe_module, lldb_private::ProcessLaunchInfo &launch_info) override; - lldb_private::Error DoAttachToProcessWithID(lldb::pid_t pid, - const lldb_private::ProcessAttachInfo &attach_info) override; - lldb_private::Error DoResume() override; - lldb_private::Error DoDestroy() override; - lldb_private::Error DoHalt(bool &caused_stop) override; - - void DidLaunch() override; - void DidAttach(lldb_private::ArchSpec &arch_spec) override; - - void RefreshStateAfterStop() override; - - bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; - bool - DestroyRequiresHalt() override - { - return false; - } - bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override; - bool IsAlive() override; - - size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, lldb_private::Error &error) override; - size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, lldb_private::Error &error) override; - lldb_private::Error GetMemoryRegionInfo(lldb::addr_t vm_addr, lldb_private::MemoryRegionInfo &info) override; - - // IDebugDelegate overrides. - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, const lldb_private::ExceptionRecord &record) override; - void OnCreateThread(const lldb_private::HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &string) override; - void OnDebuggerError(const lldb_private::Error &error, uint32_t type) override; - - private: - lldb_private::Error WaitForDebuggerConnection(lldb_private::DebuggerThreadSP debugger, - lldb_private::HostProcess &process); - - llvm::sys::Mutex m_mutex; - - // Data for the active debugging session. - std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data; + //------------------------------------------------------------------ + // Static functions. + //------------------------------------------------------------------ + static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *); + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + + ~ProcessWindowsLive(); + + // lldb_private::Process overrides + lldb_private::ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + lldb_private::Error + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + lldb_private::Error + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + + lldb_private::Error DoDetach(bool keep_stopped) override; + lldb_private::Error + DoLaunch(lldb_private::Module *exe_module, + lldb_private::ProcessLaunchInfo &launch_info) override; + lldb_private::Error DoAttachToProcessWithID( + lldb::pid_t pid, + const lldb_private::ProcessAttachInfo &attach_info) override; + lldb_private::Error DoResume() override; + lldb_private::Error DoDestroy() override; + lldb_private::Error DoHalt(bool &caused_stop) override; + + void DidLaunch() override; + void DidAttach(lldb_private::ArchSpec &arch_spec) override; + + void RefreshStateAfterStop() override; + + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + bool DestroyRequiresHalt() override { return false; } + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + bool IsAlive() override; + + size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error) override; + size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t vm_addr, + lldb_private::MemoryRegionInfo &info) override; + + // IDebugDelegate overrides. + void OnExitProcess(uint32_t exit_code) override; + void OnDebuggerConnected(lldb::addr_t image_base) override; + ExceptionResult + OnDebugException(bool first_chance, + const lldb_private::ExceptionRecord &record) override; + void OnCreateThread(const lldb_private::HostThread &thread) override; + void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; + void OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) override; + void OnUnloadDll(lldb::addr_t module_addr) override; + void OnDebugString(const std::string &string) override; + void OnDebuggerError(const lldb_private::Error &error, + uint32_t type) override; + +private: + lldb_private::Error + WaitForDebuggerConnection(lldb_private::DebuggerThreadSP debugger, + lldb_private::HostProcess &process); + + llvm::sys::Mutex m_mutex; + + // Data for the active debugging session. + std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data; }; - } -#endif // liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_ +#endif // liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_ diff --git a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp index 52b32716e67..b965a6cc3dc 100644 --- a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp @@ -16,9 +16,9 @@ #include "lldb/Host/windows/windows.h" #include "lldb/Target/RegisterContext.h" -#include "TargetThreadWindowsLive.h" #include "ProcessWindows.h" #include "ProcessWindowsLog.h" +#include "TargetThreadWindowsLive.h" #include "UnwindLLDB.h" #if defined(_WIN64) @@ -30,118 +30,95 @@ using namespace lldb; using namespace lldb_private; -TargetThreadWindowsLive::TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread) - : TargetThreadWindows(process, thread) - , m_host_thread(thread) -{ -} +TargetThreadWindowsLive::TargetThreadWindowsLive(ProcessWindows &process, + const HostThread &thread) + : TargetThreadWindows(process, thread), m_host_thread(thread) {} -TargetThreadWindowsLive::~TargetThreadWindowsLive() -{ - DestroyThread(); -} +TargetThreadWindowsLive::~TargetThreadWindowsLive() { DestroyThread(); } -void -TargetThreadWindowsLive::RefreshStateAfterStop() -{ - ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - SetState(eStateStopped); - GetRegisterContext()->InvalidateIfNeeded(false); +void TargetThreadWindowsLive::RefreshStateAfterStop() { + ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); + SetState(eStateStopped); + GetRegisterContext()->InvalidateIfNeeded(false); } -void -TargetThreadWindowsLive::WillResume(lldb::StateType resume_state) -{ -} +void TargetThreadWindowsLive::WillResume(lldb::StateType resume_state) {} -void -TargetThreadWindowsLive::DidStop() -{ -} +void TargetThreadWindowsLive::DidStop() {} -RegisterContextSP -TargetThreadWindowsLive::GetRegisterContext() -{ - if (!m_reg_context_sp) - m_reg_context_sp = CreateRegisterContextForFrameIndex(0); +RegisterContextSP TargetThreadWindowsLive::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrameIndex(0); - return m_reg_context_sp; + return m_reg_context_sp; } RegisterContextSP -TargetThreadWindowsLive::CreateRegisterContextForFrame(StackFrame *frame) -{ - return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex()); +TargetThreadWindowsLive::CreateRegisterContextForFrame(StackFrame *frame) { + return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex()); } RegisterContextSP -TargetThreadWindowsLive::CreateRegisterContextForFrameIndex(uint32_t idx) -{ - if (!m_reg_context_sp) - { - ArchSpec arch = HostInfo::GetArchitecture(); - switch (arch.GetMachine()) - { - case llvm::Triple::x86: +TargetThreadWindowsLive::CreateRegisterContextForFrameIndex(uint32_t idx) { + if (!m_reg_context_sp) { + ArchSpec arch = HostInfo::GetArchitecture(); + switch (arch.GetMachine()) { + case llvm::Triple::x86: #if defined(_WIN64) - // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 +// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 #else - m_reg_context_sp.reset(new RegisterContextWindowsLive_x86(*this, idx)); + m_reg_context_sp.reset(new RegisterContextWindowsLive_x86(*this, idx)); #endif - break; - case llvm::Triple::x86_64: + break; + case llvm::Triple::x86_64: #if defined(_WIN64) - m_reg_context_sp.reset(new RegisterContextWindowsLive_x64(*this, idx)); + m_reg_context_sp.reset(new RegisterContextWindowsLive_x64(*this, idx)); #else - // LLDB is 32-bit, but the target process is 64-bit. We probably can't debug this. +// LLDB is 32-bit, but the target process is 64-bit. We probably can't debug +// this. #endif - default: - break; - } + default: + break; } - return m_reg_context_sp; + } + return m_reg_context_sp; } -bool -TargetThreadWindowsLive::CalculateStopInfo() -{ - SetStopInfo(m_stop_info_sp); - return true; +bool TargetThreadWindowsLive::CalculateStopInfo() { + SetStopInfo(m_stop_info_sp); + return true; } -Unwind * -TargetThreadWindowsLive::GetUnwinder() -{ - // FIXME: Implement an unwinder based on the Windows unwinder exposed through DIA SDK. - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); +Unwind *TargetThreadWindowsLive::GetUnwinder() { + // FIXME: Implement an unwinder based on the Windows unwinder exposed through + // DIA SDK. + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + return m_unwinder_ap.get(); } -bool -TargetThreadWindowsLive::DoResume() -{ - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return true; - - if (resume_state == eStateStepping) - { - uint32_t flags_index = GetRegisterContext()->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - uint64_t flags_value = GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); - flags_value |= 0x100; // Set the trap flag on the CPU - GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); - } - - if (resume_state == eStateStepping || resume_state == eStateRunning) - { - DWORD previous_suspend_count = 0; - HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); - do - { - previous_suspend_count = ::ResumeThread(thread_handle); - } while (previous_suspend_count > 0); - } +bool TargetThreadWindowsLive::DoResume() { + StateType resume_state = GetTemporaryResumeState(); + StateType current_state = GetState(); + if (resume_state == current_state) return true; + + if (resume_state == eStateStepping) { + uint32_t flags_index = + GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + uint64_t flags_value = + GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); + flags_value |= 0x100; // Set the trap flag on the CPU + GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); + } + + if (resume_state == eStateStepping || resume_state == eStateRunning) { + DWORD previous_suspend_count = 0; + HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); + do { + previous_suspend_count = ::ResumeThread(thread_handle); + } while (previous_suspend_count > 0); + } + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h index 15262b9e942..47e09247a63 100644 --- a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h +++ b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h @@ -10,45 +10,40 @@ #ifndef liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_ #define liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_ -#include "lldb/lldb-forward.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/TargetThreadWindows.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; class HostThread; class StackFrame; -class TargetThreadWindowsLive : public lldb_private::TargetThreadWindows -{ - public: - TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread); - virtual ~TargetThreadWindowsLive(); - - // lldb_private::Thread overrides - void RefreshStateAfterStop() override; - void WillResume(lldb::StateType resume_state) override; - void DidStop() override; - lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame) override; - bool CalculateStopInfo() override; - Unwind *GetUnwinder() override; - - bool DoResume(); - - HostThread - GetHostThread() const - { - return m_host_thread; - } - - private: - lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx); - - HostThread m_host_thread; +class TargetThreadWindowsLive : public lldb_private::TargetThreadWindows { +public: + TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread); + virtual ~TargetThreadWindowsLive(); + + // lldb_private::Thread overrides + void RefreshStateAfterStop() override; + void WillResume(lldb::StateType resume_state) override; + void DidStop() override; + lldb::RegisterContextSP GetRegisterContext() override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + bool CalculateStopInfo() override; + Unwind *GetUnwinder() override; + + bool DoResume(); + + HostThread GetHostThread() const { return m_host_thread; } + +private: + lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx); + + HostThread m_host_thread; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp index e74647ab68f..33237110991 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp @@ -7,165 +7,160 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "RegisterContextWindowsLive_x64.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; using namespace lldb_private; -RegisterContextWindowsLive_x64::RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows_x64(thread, concrete_frame_idx) -{ -} - -RegisterContextWindowsLive_x64::~RegisterContextWindowsLive_x64() -{ -} +RegisterContextWindowsLive_x64::RegisterContextWindowsLive_x64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows_x64(thread, concrete_frame_idx) {} +RegisterContextWindowsLive_x64::~RegisterContextWindowsLive_x64() {} -bool -RegisterContextWindowsLive_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - reg_value.SetUInt64(m_context.Rax); - break; - case lldb_rbx_x86_64: - reg_value.SetUInt64(m_context.Rbx); - break; - case lldb_rcx_x86_64: - reg_value.SetUInt64(m_context.Rcx); - break; - case lldb_rdx_x86_64: - reg_value.SetUInt64(m_context.Rdx); - break; - case lldb_rdi_x86_64: - reg_value.SetUInt64(m_context.Rdi); - break; - case lldb_rsi_x86_64: - reg_value.SetUInt64(m_context.Rsi); - break; - case lldb_r8_x86_64: - reg_value.SetUInt64(m_context.R8); - break; - case lldb_r9_x86_64: - reg_value.SetUInt64(m_context.R9); - break; - case lldb_r10_x86_64: - reg_value.SetUInt64(m_context.R10); - break; - case lldb_r11_x86_64: - reg_value.SetUInt64(m_context.R11); - break; - case lldb_r12_x86_64: - reg_value.SetUInt64(m_context.R12); - break; - case lldb_r13_x86_64: - reg_value.SetUInt64(m_context.R13); - break; - case lldb_r14_x86_64: - reg_value.SetUInt64(m_context.R14); - break; - case lldb_r15_x86_64: - reg_value.SetUInt64(m_context.R15); - break; - case lldb_rbp_x86_64: - reg_value.SetUInt64(m_context.Rbp); - break; - case lldb_rsp_x86_64: - reg_value.SetUInt64(m_context.Rsp); - break; - case lldb_rip_x86_64: - reg_value.SetUInt64(m_context.Rip); - break; - case lldb_rflags_x86_64: - reg_value.SetUInt64(m_context.EFlags); - break; - } - return true; + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + reg_value.SetUInt64(m_context.Rax); + break; + case lldb_rbx_x86_64: + reg_value.SetUInt64(m_context.Rbx); + break; + case lldb_rcx_x86_64: + reg_value.SetUInt64(m_context.Rcx); + break; + case lldb_rdx_x86_64: + reg_value.SetUInt64(m_context.Rdx); + break; + case lldb_rdi_x86_64: + reg_value.SetUInt64(m_context.Rdi); + break; + case lldb_rsi_x86_64: + reg_value.SetUInt64(m_context.Rsi); + break; + case lldb_r8_x86_64: + reg_value.SetUInt64(m_context.R8); + break; + case lldb_r9_x86_64: + reg_value.SetUInt64(m_context.R9); + break; + case lldb_r10_x86_64: + reg_value.SetUInt64(m_context.R10); + break; + case lldb_r11_x86_64: + reg_value.SetUInt64(m_context.R11); + break; + case lldb_r12_x86_64: + reg_value.SetUInt64(m_context.R12); + break; + case lldb_r13_x86_64: + reg_value.SetUInt64(m_context.R13); + break; + case lldb_r14_x86_64: + reg_value.SetUInt64(m_context.R14); + break; + case lldb_r15_x86_64: + reg_value.SetUInt64(m_context.R15); + break; + case lldb_rbp_x86_64: + reg_value.SetUInt64(m_context.Rbp); + break; + case lldb_rsp_x86_64: + reg_value.SetUInt64(m_context.Rsp); + break; + case lldb_rip_x86_64: + reg_value.SetUInt64(m_context.Rip); + break; + case lldb_rflags_x86_64: + reg_value.SetUInt64(m_context.EFlags); + break; + } + return true; } -bool -RegisterContextWindowsLive_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - m_context.Rax = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_context.Rbx = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_context.Rcx = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_context.Rdx = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_context.Rdi = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_context.Rsi = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_context.R8 = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_context.R9 = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_context.R10 = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_context.R11 = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_context.R12 = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_context.R13 = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_context.R14 = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_context.R15 = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_context.Rbp = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_context.Rsp = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_context.Rip = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_context.EFlags = reg_value.GetAsUInt64(); - break; - } + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + m_context.Rax = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_context.Rbx = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_context.Rcx = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_context.Rdx = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_context.Rdi = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_context.Rsi = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_context.R8 = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_context.R9 = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_context.R10 = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_context.R11 = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_context.R12 = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_context.R13 = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_context.R14 = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_context.R15 = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_context.Rbp = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_context.Rsp = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_context.Rip = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_context.EFlags = reg_value.GetAsUInt64(); + break; + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } diff --git a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h index bd250a994d3..84425c4fa82 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h +++ b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h @@ -10,30 +10,30 @@ #ifndef liblldb_RegisterContextWindowsLive_x64_H_ #define liblldb_RegisterContextWindowsLive_x64_H_ -#include "lldb/lldb-forward.h" #include "../../Common/x64/RegisterContextWindows_x64.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsLive_x64 : public RegisterContextWindows_x64 -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindowsLive_x64 : public RegisterContextWindows_x64 { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindowsLive_x64(); + virtual ~RegisterContextWindowsLive_x64(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp index f2decc72d16..0e7412051ae 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextWindowsLive_x86.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextWindowsLive_x86.cpp ------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,94 +8,101 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "ProcessWindowsLog.h" #include "RegisterContextWindowsLive_x86.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; -namespace lldb_private -{ +namespace lldb_private { -RegisterContextWindowsLive_x86::RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows_x86(thread, concrete_frame_idx) -{ -} - -RegisterContextWindowsLive_x86::~RegisterContextWindowsLive_x86() -{ -} +RegisterContextWindowsLive_x86::RegisterContextWindowsLive_x86( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows_x86(thread, concrete_frame_idx) {} +RegisterContextWindowsLive_x86::~RegisterContextWindowsLive_x86() {} -bool -RegisterContextWindowsLive_x86::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x86::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) - { - case lldb_eax_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX", reg_value.GetAsUInt32()); - m_context.Eax = reg_value.GetAsUInt32(); - break; - case lldb_ebx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX", reg_value.GetAsUInt32()); - m_context.Ebx = reg_value.GetAsUInt32(); - break; - case lldb_ecx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX", reg_value.GetAsUInt32()); - m_context.Ecx = reg_value.GetAsUInt32(); - break; - case lldb_edx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX", reg_value.GetAsUInt32()); - m_context.Edx = reg_value.GetAsUInt32(); - break; - case lldb_edi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI", reg_value.GetAsUInt32()); - m_context.Edi = reg_value.GetAsUInt32(); - break; - case lldb_esi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI", reg_value.GetAsUInt32()); - m_context.Esi = reg_value.GetAsUInt32(); - break; - case lldb_ebp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP", reg_value.GetAsUInt32()); - m_context.Ebp = reg_value.GetAsUInt32(); - break; - case lldb_esp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP", reg_value.GetAsUInt32()); - m_context.Esp = reg_value.GetAsUInt32(); - break; - case lldb_eip_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP", reg_value.GetAsUInt32()); - m_context.Eip = reg_value.GetAsUInt32(); - break; - case lldb_eflags_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS", reg_value.GetAsUInt32()); - m_context.EFlags = reg_value.GetAsUInt32(); - break; - default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to unknown register %u", reg_value.GetAsUInt32(), - reg); - } + uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + switch (reg) { + case lldb_eax_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX", + reg_value.GetAsUInt32()); + m_context.Eax = reg_value.GetAsUInt32(); + break; + case lldb_ebx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX", + reg_value.GetAsUInt32()); + m_context.Ebx = reg_value.GetAsUInt32(); + break; + case lldb_ecx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX", + reg_value.GetAsUInt32()); + m_context.Ecx = reg_value.GetAsUInt32(); + break; + case lldb_edx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX", + reg_value.GetAsUInt32()); + m_context.Edx = reg_value.GetAsUInt32(); + break; + case lldb_edi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI", + reg_value.GetAsUInt32()); + m_context.Edi = reg_value.GetAsUInt32(); + break; + case lldb_esi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI", + reg_value.GetAsUInt32()); + m_context.Esi = reg_value.GetAsUInt32(); + break; + case lldb_ebp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP", + reg_value.GetAsUInt32()); + m_context.Ebp = reg_value.GetAsUInt32(); + break; + case lldb_esp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP", + reg_value.GetAsUInt32()); + m_context.Esp = reg_value.GetAsUInt32(); + break; + case lldb_eip_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP", + reg_value.GetAsUInt32()); + m_context.Eip = reg_value.GetAsUInt32(); + break; + case lldb_eflags_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS", + reg_value.GetAsUInt32()); + m_context.EFlags = reg_value.GetAsUInt32(); + break; + default: + WINWARN_IFALL(WINDOWS_LOG_REGISTERS, + "Write value 0x%x to unknown register %u", + reg_value.GetAsUInt32(), reg); + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h index 9554f017408..e9b8ecd58f5 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h +++ b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h @@ -10,27 +10,25 @@ #ifndef liblldb_RegisterContextWindowsLive_x86_H_ #define liblldb_RegisterContextWindowsLive_x86_H_ -#include "lldb/lldb-forward.h" #include "../../Common/x86/RegisterContextWindows_x86.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsLive_x86 : public RegisterContextWindows_x86 -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindowsLive_x86 : public RegisterContextWindows_x86 { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindowsLive_x86(); + virtual ~RegisterContextWindowsLive_x86(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsLive_x86_H_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp index 05839667688..e7b2dab8ce2 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp @@ -13,9 +13,9 @@ #include <DbgHelp.h> #include <assert.h> -#include <stdlib.h> #include <memory> #include <mutex> +#include <stdlib.h> #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" #include "lldb/Core/DataBufferHeap.h" @@ -47,664 +47,589 @@ using namespace lldb_private; // code, keeping non-portable types out of the header files. // TODO(amccarth): Determine if we need a mutex for access. Given that this is // postmortem debugging, I don't think so. -class ProcessWinMiniDump::Impl -{ +class ProcessWinMiniDump::Impl { public: - Impl(const FileSpec &core_file, ProcessWinMiniDump *self); - ~Impl(); + Impl(const FileSpec &core_file, ProcessWinMiniDump *self); + ~Impl(); - Error - DoLoadCore(); + Error DoLoadCore(); - bool - UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list); + bool UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list); - void - RefreshStateAfterStop(); + void RefreshStateAfterStop(); - size_t - DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error); + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error); - Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info); + Error GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo &info); private: - // Describes a range of memory captured in the mini dump. - struct Range - { - lldb::addr_t start; // virtual address of the beginning of the range - size_t size; // size of the range in bytes - const uint8_t *ptr; // absolute pointer to the first byte of the range - }; - - // If the mini dump has a memory range that contains the desired address, it - // returns true with the details of the range in *range_out. Otherwise, it - // returns false. - bool - FindMemoryRange(lldb::addr_t addr, Range *range_out) const; - - lldb_private::Error - MapMiniDumpIntoMemory(); - - lldb_private::ArchSpec - DetermineArchitecture(); - - void - ReadExceptionRecord(); - - void - ReadMiscInfo(); - - void - ReadModuleList(); - - // 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) const; - - // Getting a string out of a mini dump is a chore. You're usually given a - // relative virtual address (RVA), which points to a counted string that's in - // Windows Unicode (UTF-16). This wrapper handles all the redirection and - // returns a UTF-8 copy of the string. - std::string - GetMiniDumpString(RVA rva) const; - - ProcessWinMiniDump *m_self; // non-owning back pointer - 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 - std::shared_ptr<ExceptionRecord> m_exception_sp; - bool m_is_wow64; // minidump is of a 32-bit process captured with a 64-bit debugger + // Describes a range of memory captured in the mini dump. + struct Range { + lldb::addr_t start; // virtual address of the beginning of the range + size_t size; // size of the range in bytes + const uint8_t *ptr; // absolute pointer to the first byte of the range + }; + + // If the mini dump has a memory range that contains the desired address, it + // returns true with the details of the range in *range_out. Otherwise, it + // returns false. + bool FindMemoryRange(lldb::addr_t addr, Range *range_out) const; + + lldb_private::Error MapMiniDumpIntoMemory(); + + lldb_private::ArchSpec DetermineArchitecture(); + + void ReadExceptionRecord(); + + void ReadMiscInfo(); + + void ReadModuleList(); + + // 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) const; + + // Getting a string out of a mini dump is a chore. You're usually given a + // relative virtual address (RVA), which points to a counted string that's in + // Windows Unicode (UTF-16). This wrapper handles all the redirection and + // returns a UTF-8 copy of the string. + std::string GetMiniDumpString(RVA rva) const; + + ProcessWinMiniDump *m_self; // non-owning back pointer + 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 + std::shared_ptr<ExceptionRecord> m_exception_sp; + bool m_is_wow64; // minidump is of a 32-bit process captured with a 64-bit + // debugger }; -ProcessWinMiniDump::Impl::Impl(const FileSpec &core_file, ProcessWinMiniDump *self) - : m_self(self), - m_core_file(core_file), - m_dump_file(INVALID_HANDLE_VALUE), - m_mapping(NULL), - m_base_addr(nullptr), - m_exception_sp(), - m_is_wow64(false) -{ -} - -ProcessWinMiniDump::Impl::~Impl() -{ - 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::Impl::DoLoadCore() -{ - Error error = MapMiniDumpIntoMemory(); - if (error.Fail()) - { - return error; - } - - m_self->GetTarget().SetArchitecture(DetermineArchitecture()); - ReadMiscInfo(); // notably for process ID - ReadModuleList(); - ReadExceptionRecord(); - +ProcessWinMiniDump::Impl::Impl(const FileSpec &core_file, + ProcessWinMiniDump *self) + : m_self(self), m_core_file(core_file), m_dump_file(INVALID_HANDLE_VALUE), + m_mapping(NULL), m_base_addr(nullptr), m_exception_sp(), + m_is_wow64(false) {} + +ProcessWinMiniDump::Impl::~Impl() { + 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::Impl::DoLoadCore() { + Error error = MapMiniDumpIntoMemory(); + if (error.Fail()) { return error; - -} - -bool -ProcessWinMiniDump::Impl::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - 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; - for (ULONG32 i = 0; i < thread_count; ++i) { - const auto &mini_dump_thread = thread_list_ptr->Threads[i]; - auto thread_sp = std::make_shared<ThreadWinMiniDump>(*m_self, mini_dump_thread.ThreadId); - if (mini_dump_thread.ThreadContext.DataSize >= sizeof(CONTEXT)) - { - const CONTEXT *context = reinterpret_cast<const CONTEXT *>(static_cast<const char *>(m_base_addr) + - mini_dump_thread.ThreadContext.Rva); - - if (m_is_wow64) - { - // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. - // If the minidump was captured with a 64-bit debugger, then the CONTEXT - // we just grabbed from the mini_dump_thread is the one for the 64-bit - // "native" process rather than the 32-bit "guest" process we care about. - // In this case, we can get the 32-bit CONTEXT from the TEB (Thread - // Environment Block) of the 64-bit process. - Error error; - TEB64 wow64teb = {0}; - m_self->ReadMemory(mini_dump_thread.Teb, &wow64teb, sizeof(wow64teb), error); - if (error.Success()) - { - // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure - // that includes the 32-bit CONTEXT (after a ULONG). - // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx - const size_t addr = wow64teb.TlsSlots[1]; - Range range = {0}; - if (FindMemoryRange(addr, &range)) - { - lldbassert(range.start <= addr); - const size_t offset = addr - range.start + sizeof(ULONG); - if (offset < range.size) - { - const size_t overlap = range.size - offset; - if (overlap >= sizeof(CONTEXT)) - { - context = reinterpret_cast<const CONTEXT *>(range.ptr + offset); - } - } - } - } - - // NOTE: We don't currently use the TEB for anything else. If we need it in - // the future, the 32-bit TEB is located according to the address stored in the - // first slot of the 64-bit TEB (wow64teb.Reserved1[0]). + } + + m_self->GetTarget().SetArchitecture(DetermineArchitecture()); + ReadMiscInfo(); // notably for process ID + ReadModuleList(); + ReadExceptionRecord(); + + return error; +} + +bool ProcessWinMiniDump::Impl::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + 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; + for (ULONG32 i = 0; i < thread_count; ++i) { + const auto &mini_dump_thread = thread_list_ptr->Threads[i]; + auto thread_sp = std::make_shared<ThreadWinMiniDump>( + *m_self, mini_dump_thread.ThreadId); + if (mini_dump_thread.ThreadContext.DataSize >= sizeof(CONTEXT)) { + const CONTEXT *context = reinterpret_cast<const CONTEXT *>( + static_cast<const char *>(m_base_addr) + + mini_dump_thread.ThreadContext.Rva); + + if (m_is_wow64) { + // On Windows, a 32-bit process can run on a 64-bit machine under + // WOW64. + // If the minidump was captured with a 64-bit debugger, then the + // CONTEXT + // we just grabbed from the mini_dump_thread is the one for the 64-bit + // "native" process rather than the 32-bit "guest" process we care + // about. + // In this case, we can get the 32-bit CONTEXT from the TEB (Thread + // Environment Block) of the 64-bit process. + Error error; + TEB64 wow64teb = {0}; + m_self->ReadMemory(mini_dump_thread.Teb, &wow64teb, sizeof(wow64teb), + error); + if (error.Success()) { + // Slot 1 of the thread-local storage in the 64-bit TEB points to a + // structure + // that includes the 32-bit CONTEXT (after a ULONG). + // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx + const size_t addr = wow64teb.TlsSlots[1]; + Range range = {0}; + if (FindMemoryRange(addr, &range)) { + lldbassert(range.start <= addr); + const size_t offset = addr - range.start + sizeof(ULONG); + if (offset < range.size) { + const size_t overlap = range.size - offset; + if (overlap >= sizeof(CONTEXT)) { + context = + reinterpret_cast<const CONTEXT *>(range.ptr + offset); } - - thread_sp->SetContext(context); + } } - new_thread_list.AddThread(thread_sp); - } - } - - return new_thread_list.GetSize(false) > 0; -} + } -void -ProcessWinMiniDump::Impl::RefreshStateAfterStop() -{ - if (!m_exception_sp) - return; - - auto active_exception = 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_self->m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - auto stop_thread = m_self->m_thread_list.GetSelectedThread(); - auto stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); -} - -size_t -ProcessWinMiniDump::Impl::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - // I don't have a sense of how frequently this is called or how many memory - // ranges a mini dump typically has, so I'm not sure if searching for the - // appropriate range linearly each time is stupid. Perhaps we should build - // an index for faster lookups. - Range range = {0}; - if (!FindMemoryRange(addr, &range)) - { - return 0; - } - - // There's at least some overlap between the beginning of the desired range - // (addr) and the current range. Figure out where the overlap begins and - // how much overlap there is, then copy it to the destination buffer. - lldbassert(range.start <= addr); - const size_t offset = addr - range.start; - lldbassert(offset < range.size); - const size_t overlap = std::min(size, range.size - offset); - std::memcpy(buf, range.ptr + offset, overlap); - return overlap; -} - -Error -ProcessWinMiniDump::Impl::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) -{ - Error error; - size_t size; - info.Clear(); - const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>(FindDumpStream(MemoryInfoListStream, &size)); - if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) - { - error.SetErrorString("the mini dump contains no memory range information"); - return error; - } - - if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO)) - { - error.SetErrorString("the entries in the mini dump memory info list are smaller than expected"); - return error; - } - - if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries) - { - error.SetErrorString("the mini dump memory info list is incomplete"); - return error; - } - - const MINIDUMP_MEMORY_INFO *next_entry = nullptr; - - for (int i = 0; i < list->NumberOfEntries; ++i) - { - const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(list) + - list->SizeOfHeader + i * list->SizeOfEntry); - const auto head = entry->BaseAddress; - const auto tail = head + entry->RegionSize; - if (head <= load_addr && load_addr < tail) - { - info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head : load_addr); - info.GetRange().SetRangeEnd(tail); - info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(IsPageExecutable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - return error; - } - else if (head > load_addr && (next_entry == nullptr || head < next_entry->BaseAddress) ) - { - // In case there is no region containing load_addr keep track of the nearest region - // after load_addr so we can return the distance to it. - next_entry = entry; + // NOTE: We don't currently use the TEB for anything else. If we + // need it in + // the future, the 32-bit TEB is located according to the address + // stored in the + // first slot of the 64-bit TEB (wow64teb.Reserved1[0]). } - } - - // No containing region found. Create an unmapped region that extends to the next region - // or LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(load_addr); - info.GetRange().SetRangeEnd((next_entry != nullptr)?next_entry->BaseAddress:LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - - // Note that the memory info list doesn't seem to contain ranges in kernel space, - // so if you're walking a stack that has kernel frames, the stack may appear - // truncated. - return error; -} -bool -ProcessWinMiniDump::Impl::FindMemoryRange(lldb::addr_t addr, Range *range_out) const -{ - size_t stream_size = 0; - auto mem_list_stream = static_cast<const MINIDUMP_MEMORY_LIST *>(FindDumpStream(MemoryListStream, &stream_size)); - if (mem_list_stream) - { - for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) - { - const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = mem_list_stream->MemoryRanges[i]; - const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory; - const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; - const size_t range_size = loc_desc.DataSize; - if (range_start <= addr && addr < range_start + range_size) - { - range_out->start = range_start; - range_out->size = range_size; - range_out->ptr = reinterpret_cast<const uint8_t *>(m_base_addr) + loc_desc.Rva; - return true; - } - } - } - - // Some mini dumps have a Memory64ListStream that captures all the heap - // memory. We can't exactly use the same loop as above, because the mini - // dump uses slightly different data structures to describe those. - auto mem_list64_stream = static_cast<const MINIDUMP_MEMORY64_LIST *>(FindDumpStream(Memory64ListStream, &stream_size)); - if (mem_list64_stream) - { - size_t base_rva = mem_list64_stream->BaseRva; - for (ULONG32 i = 0; i < mem_list64_stream->NumberOfMemoryRanges; ++i) { - const MINIDUMP_MEMORY_DESCRIPTOR64 &mem_desc = mem_list64_stream->MemoryRanges[i]; - const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; - const size_t range_size = mem_desc.DataSize; - if (range_start <= addr && addr < range_start + range_size) - { - range_out->start = range_start; - range_out->size = range_size; - range_out->ptr = reinterpret_cast<const uint8_t *>(m_base_addr) + base_rva; - return true; - } - base_rva += range_size; - } + thread_sp->SetContext(context); + } + new_thread_list.AddThread(thread_sp); } + } + + return new_thread_list.GetSize(false) > 0; +} + +void ProcessWinMiniDump::Impl::RefreshStateAfterStop() { + if (!m_exception_sp) + return; + + auto active_exception = 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_self->m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); + auto stop_thread = m_self->m_thread_list.GetSelectedThread(); + auto stop_info = StopInfo::CreateStopReasonWithException( + *stop_thread, desc_stream.str().c_str()); + stop_thread->SetStopInfo(stop_info); +} + +size_t ProcessWinMiniDump::Impl::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Error &error) { + // I don't have a sense of how frequently this is called or how many memory + // ranges a mini dump typically has, so I'm not sure if searching for the + // appropriate range linearly each time is stupid. Perhaps we should build + // an index for faster lookups. + Range range = {0}; + if (!FindMemoryRange(addr, &range)) { + return 0; + } + + // There's at least some overlap between the beginning of the desired range + // (addr) and the current range. Figure out where the overlap begins and + // how much overlap there is, then copy it to the destination buffer. + lldbassert(range.start <= addr); + const size_t offset = addr - range.start; + lldbassert(offset < range.size); + const size_t overlap = std::min(size, range.size - offset); + std::memcpy(buf, range.ptr + offset, overlap); + return overlap; +} + +Error ProcessWinMiniDump::Impl::GetMemoryRegionInfo( + lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) { + Error error; + size_t size; + info.Clear(); + const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>( + FindDumpStream(MemoryInfoListStream, &size)); + if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) { + error.SetErrorString("the mini dump contains no memory range information"); + return error; + } - return false; -} + if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO)) { + error.SetErrorString("the entries in the mini dump memory info list are " + "smaller than expected"); + return error; + } -Error -ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory() -{ - Error error; - const char *file = m_core_file.GetCString(); - std::wstring wfile; - if (!llvm::ConvertUTF8toWide(file, wfile)) - { - error.SetErrorString("Error converting path to UTF-16"); - return error; + if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries) { + error.SetErrorString("the mini dump memory info list is incomplete"); + return error; + } + + const MINIDUMP_MEMORY_INFO *next_entry = nullptr; + + for (int i = 0; i < list->NumberOfEntries; ++i) { + const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>( + reinterpret_cast<const char *>(list) + list->SizeOfHeader + + i * list->SizeOfEntry); + const auto head = entry->BaseAddress; + const auto tail = head + entry->RegionSize; + if (head <= load_addr && load_addr < tail) { + info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head + : load_addr); + info.GetRange().SetRangeEnd(tail); + info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetExecutable(IsPageExecutable(entry->Protect) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + return error; + } else if (head > load_addr && + (next_entry == nullptr || head < next_entry->BaseAddress)) { + // In case there is no region containing load_addr keep track of the + // nearest region + // after load_addr so we can return the distance to it. + next_entry = entry; } - m_dump_file = - ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (m_dump_file == INVALID_HANDLE_VALUE) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + } + + // No containing region found. Create an unmapped region that extends to the + // next region + // or LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(load_addr); + info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->BaseAddress + : LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + + // Note that the memory info list doesn't seem to contain ranges in kernel + // space, + // so if you're walking a stack that has kernel frames, the stack may appear + // truncated. + return error; +} + +bool ProcessWinMiniDump::Impl::FindMemoryRange(lldb::addr_t addr, + Range *range_out) const { + size_t stream_size = 0; + auto mem_list_stream = static_cast<const MINIDUMP_MEMORY_LIST *>( + FindDumpStream(MemoryListStream, &stream_size)); + if (mem_list_stream) { + for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) { + const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = + mem_list_stream->MemoryRanges[i]; + const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory; + const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; + const size_t range_size = loc_desc.DataSize; + if (range_start <= addr && addr < range_start + range_size) { + range_out->start = range_start; + range_out->size = range_size; + range_out->ptr = + reinterpret_cast<const uint8_t *>(m_base_addr) + loc_desc.Rva; + return true; + } } - - m_mapping = ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL); - if (m_mapping == NULL) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - - m_base_addr = ::MapViewOfFile(m_mapping, FILE_MAP_READ, 0, 0, 0); - if (m_base_addr == nullptr) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + } + + // Some mini dumps have a Memory64ListStream that captures all the heap + // memory. We can't exactly use the same loop as above, because the mini + // dump uses slightly different data structures to describe those. + auto mem_list64_stream = static_cast<const MINIDUMP_MEMORY64_LIST *>( + FindDumpStream(Memory64ListStream, &stream_size)); + if (mem_list64_stream) { + size_t base_rva = mem_list64_stream->BaseRva; + for (ULONG32 i = 0; i < mem_list64_stream->NumberOfMemoryRanges; ++i) { + const MINIDUMP_MEMORY_DESCRIPTOR64 &mem_desc = + mem_list64_stream->MemoryRanges[i]; + const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; + const size_t range_size = mem_desc.DataSize; + if (range_start <= addr && addr < range_start + range_size) { + range_out->start = range_start; + range_out->size = range_size; + range_out->ptr = + reinterpret_cast<const uint8_t *>(m_base_addr) + base_rva; + return true; + } + base_rva += range_size; } + } - return error; + return false; } -ArchSpec -ProcessWinMiniDump::Impl::DetermineArchitecture() -{ - 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: - if (system_info_ptr->ProcessorLevel == 6) - { - return ArchSpec("i686-pc-windows"); - } - else - { - return ArchSpec("i386-pc-windows"); - } - break; - case PROCESSOR_ARCHITECTURE_AMD64: - return ArchSpec("x86_64-pc-windows"); - default: - break; - } - } +Error ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory() { + Error error; + const char *file = m_core_file.GetCString(); + std::wstring wfile; + if (!llvm::ConvertUTF8toWide(file, wfile)) { + error.SetErrorString("Error converting path to UTF-16"); + return error; + } + m_dump_file = ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_dump_file == INVALID_HANDLE_VALUE) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } - return ArchSpec(); // invalid or unknown -} + m_mapping = + ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL); + if (m_mapping == NULL) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } -void -ProcessWinMiniDump::Impl::ReadExceptionRecord() -{ - size_t size = 0; - auto exception_stream_ptr = static_cast<MINIDUMP_EXCEPTION_STREAM*>(FindDumpStream(ExceptionStream, &size)); - if (exception_stream_ptr) - { - m_exception_sp.reset( - new ExceptionRecord(exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump has no exception record."); - // TODO: See if we can recover the exception from the TEB. + m_base_addr = ::MapViewOfFile(m_mapping, FILE_MAP_READ, 0, 0, 0); + if (m_base_addr == nullptr) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + return error; +} + +ArchSpec ProcessWinMiniDump::Impl::DetermineArchitecture() { + 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: + if (system_info_ptr->ProcessorLevel == 6) { + return ArchSpec("i686-pc-windows"); + } else { + return ArchSpec("i386-pc-windows"); + } + break; + case PROCESSOR_ARCHITECTURE_AMD64: + return ArchSpec("x86_64-pc-windows"); + default: + break; } -} - -void -ProcessWinMiniDump::Impl::ReadMiscInfo() -{ - size_t size = 0; - const auto misc_info_ptr = static_cast<MINIDUMP_MISC_INFO*>(FindDumpStream(MiscInfoStream, &size)); - if (!misc_info_ptr || size < sizeof(MINIDUMP_MISC_INFO)) { - return; + } + + return ArchSpec(); // invalid or unknown +} + +void ProcessWinMiniDump::Impl::ReadExceptionRecord() { + size_t size = 0; + auto exception_stream_ptr = static_cast<MINIDUMP_EXCEPTION_STREAM *>( + FindDumpStream(ExceptionStream, &size)); + if (exception_stream_ptr) { + m_exception_sp.reset(new ExceptionRecord( + exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); + } else { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump has no exception record."); + // TODO: See if we can recover the exception from the TEB. + } +} + +void ProcessWinMiniDump::Impl::ReadMiscInfo() { + size_t size = 0; + const auto misc_info_ptr = + static_cast<MINIDUMP_MISC_INFO *>(FindDumpStream(MiscInfoStream, &size)); + if (!misc_info_ptr || size < sizeof(MINIDUMP_MISC_INFO)) { + return; + } + + if ((misc_info_ptr->Flags1 & MINIDUMP_MISC1_PROCESS_ID) != 0) { + // This misc info record has the process ID. + m_self->SetID(misc_info_ptr->ProcessId); + } +} + +void ProcessWinMiniDump::Impl::ReadModuleList() { + size_t size = 0; + auto module_list_ptr = static_cast<MINIDUMP_MODULE_LIST *>( + FindDumpStream(ModuleListStream, &size)); + if (!module_list_ptr || module_list_ptr->NumberOfModules == 0) { + return; + } + + for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) { + const auto &module = module_list_ptr->Modules[i]; + const auto file_name = GetMiniDumpString(module.ModuleNameRva); + const auto file_spec = FileSpec(file_name, true); + if (FileSpec::Compare(file_spec, FileSpec("wow64.dll", false), false) == + 0) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump is for a WOW64 process."); + m_is_wow64 = true; } + ModuleSpec module_spec = file_spec; - if ((misc_info_ptr->Flags1 & MINIDUMP_MISC1_PROCESS_ID) != 0) { - // This misc info record has the process ID. - m_self->SetID(misc_info_ptr->ProcessId); + lldb::ModuleSP module_sp = m_self->GetTarget().GetSharedModule(module_spec); + if (!module_sp) { + continue; } + bool load_addr_changed = false; + module_sp->SetLoadAddress(m_self->GetTarget(), module.BaseOfImage, false, + load_addr_changed); + } } -void -ProcessWinMiniDump::Impl::ReadModuleList() -{ - size_t size = 0; - auto module_list_ptr = static_cast<MINIDUMP_MODULE_LIST*>(FindDumpStream(ModuleListStream, &size)); - if (!module_list_ptr || module_list_ptr->NumberOfModules == 0) - { - return; - } +void *ProcessWinMiniDump::Impl::FindDumpStream(unsigned stream_number, + size_t *size_out) const { + void *stream = nullptr; + *size_out = 0; - for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) - { - const auto &module = module_list_ptr->Modules[i]; - const auto file_name = GetMiniDumpString(module.ModuleNameRva); - const auto file_spec = FileSpec(file_name, true); - if (FileSpec::Compare(file_spec, FileSpec("wow64.dll", false), false) == 0) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump is for a WOW64 process."); - m_is_wow64 = true; - } - ModuleSpec module_spec = file_spec; + MINIDUMP_DIRECTORY *dir = nullptr; + if (::MiniDumpReadDumpStream(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_base_addr) + + dir->Location.Rva); + } - lldb::ModuleSP module_sp = m_self->GetTarget().GetSharedModule(module_spec); - if (!module_sp) - { - continue; - } - bool load_addr_changed = false; - module_sp->SetLoadAddress(m_self->GetTarget(), module.BaseOfImage, false, load_addr_changed); - } + return stream; } -void * -ProcessWinMiniDump::Impl::FindDumpStream(unsigned stream_number, size_t *size_out) const -{ - void *stream = nullptr; - *size_out = 0; - - MINIDUMP_DIRECTORY *dir = nullptr; - if (::MiniDumpReadDumpStream(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_base_addr) + dir->Location.Rva); - } - - return stream; -} - -std::string -ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const -{ - std::string result; - if (!m_base_addr) - { - return result; - } - auto md_string = reinterpret_cast<const MINIDUMP_STRING *>(static_cast<const char *>(m_base_addr) + rva); - auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer); - const auto source_length = ::wcslen(md_string->Buffer); - const auto source_end = source_start + source_length; - result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length); // worst case length - auto result_start = reinterpret_cast<UTF8 *>(&result[0]); - const auto result_end = result_start + result.size(); - ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion); - const auto result_size = std::distance(reinterpret_cast<UTF8 *>(&result[0]), result_start); - result.resize(result_size); // shrink to actual length +std::string ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const { + std::string result; + if (!m_base_addr) { return result; + } + auto md_string = reinterpret_cast<const MINIDUMP_STRING *>( + static_cast<const char *>(m_base_addr) + rva); + auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer); + const auto source_length = ::wcslen(md_string->Buffer); + const auto source_end = source_start + source_length; + result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * + source_length); // worst case length + auto result_start = reinterpret_cast<UTF8 *>(&result[0]); + const auto result_end = result_start + result.size(); + ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, + strictConversion); + const auto result_size = + std::distance(reinterpret_cast<UTF8 *>(&result[0]), result_start); + result.resize(result_size); // shrink to actual length + return result; } -ConstString -ProcessWinMiniDump::GetPluginNameStatic() -{ - static ConstString g_name("win-minidump"); - return g_name; +ConstString ProcessWinMiniDump::GetPluginNameStatic() { + static ConstString g_name("win-minidump"); + return g_name; } -const char * -ProcessWinMiniDump::GetPluginDescriptionStatic() -{ - return "Windows minidump plug-in."; +const char *ProcessWinMiniDump::GetPluginDescriptionStatic() { + return "Windows minidump plug-in."; } -void -ProcessWinMiniDump::Terminate() -{ - PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); +void ProcessWinMiniDump::Terminate() { + PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); } -lldb::ProcessSP -ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file) -{ - lldb::ProcessSP process_sp; - if (crash_file) - { - process_sp.reset(new ProcessWinMiniDump(target_sp, listener_sp, *crash_file)); - } - return process_sp; +lldb::ProcessSP ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *crash_file) { + lldb::ProcessSP process_sp; + if (crash_file) { + process_sp.reset( + new ProcessWinMiniDump(target_sp, listener_sp, *crash_file)); + } + return process_sp; } -bool -ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - // TODO(amccarth): Eventually, this needs some actual logic. - return true; +bool ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + // TODO(amccarth): Eventually, this needs some actual logic. + return true; } -ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) - : ProcessWindows(target_sp, listener_sp), m_impl_up(new Impl(core_file, this)) -{ -} +ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec &core_file) + : ProcessWindows(target_sp, listener_sp), + m_impl_up(new Impl(core_file, this)) {} -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(); +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(); +ConstString ProcessWinMiniDump::GetPluginName() { + return GetPluginNameStatic(); } -uint32_t -ProcessWinMiniDump::GetPluginVersion() -{ - return 1; -} +uint32_t ProcessWinMiniDump::GetPluginVersion() { return 1; } -Error -ProcessWinMiniDump::DoLoadCore() -{ - return m_impl_up->DoLoadCore(); -} +Error ProcessWinMiniDump::DoLoadCore() { return m_impl_up->DoLoadCore(); } -DynamicLoader * -ProcessWinMiniDump::GetDynamicLoader() -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset(DynamicLoader::FindPlugin(this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); - return m_dyld_ap.get(); +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) -{ - return m_impl_up->UpdateThreadList(old_thread_list, new_thread_list); +bool ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + return m_impl_up->UpdateThreadList(old_thread_list, new_thread_list); } -void -ProcessWinMiniDump::RefreshStateAfterStop() -{ - if (!m_impl_up) - return; - return m_impl_up->RefreshStateAfterStop(); +void ProcessWinMiniDump::RefreshStateAfterStop() { + if (!m_impl_up) + return; + return m_impl_up->RefreshStateAfterStop(); } -Error -ProcessWinMiniDump::DoDestroy() -{ - return Error(); -} +Error ProcessWinMiniDump::DoDestroy() { return Error(); } -bool -ProcessWinMiniDump::IsAlive() -{ - return true; -} +bool ProcessWinMiniDump::IsAlive() { return true; } -bool -ProcessWinMiniDump::WarnBeforeDetach() const -{ - // Since this is post-mortem debugging, there's no need to warn the user - // that quitting the debugger will terminate the process. - return false; +bool ProcessWinMiniDump::WarnBeforeDetach() const { + // Since this is post-mortem debugging, there's no need to warn the user + // that quitting the debugger will terminate the process. + return false; } -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 we have it all cached our our dump file anyway. - return DoReadMemory(addr, buf, size, error); +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 we have it all cached our our dump file anyway. + return DoReadMemory(addr, buf, size, error); } -size_t -ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - return m_impl_up->DoReadMemory(addr, buf, size, error); +size_t ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Error &error) { + return m_impl_up->DoReadMemory(addr, buf, size, error); } -Error -ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) -{ - return m_impl_up->GetMemoryRegionInfo(load_addr, info); +Error ProcessWinMiniDump::GetMemoryRegionInfo( + lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) { + return m_impl_up->GetMemoryRegionInfo(load_addr, info); } -void -ProcessWinMiniDump::Clear() -{ - m_thread_list.Clear(); -} +void ProcessWinMiniDump::Clear() { m_thread_list.Clear(); } -void -ProcessWinMiniDump::Initialize() -{ - static std::once_flag g_once_flag; +void ProcessWinMiniDump::Initialize() { + static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); - }); + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } -ArchSpec -ProcessWinMiniDump::GetArchitecture() -{ - // TODO - return ArchSpec(); +ArchSpec ProcessWinMiniDump::GetArchitecture() { + // TODO + return ArchSpec(); } diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h index 3e1ac4bffbe..c242c60d09b 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h @@ -21,84 +21,66 @@ struct ThreadData; -class ProcessWinMiniDump : public lldb_private::ProcessWindows -{ - public: - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); +class ProcessWinMiniDump : public lldb_private::ProcessWindows { +public: + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path); - static void - Initialize(); + static void Initialize(); - static void - Terminate(); + static void Terminate(); - static lldb_private::ConstString - GetPluginNameStatic(); + static lldb_private::ConstString GetPluginNameStatic(); - static const char * - GetPluginDescriptionStatic(); + static const char *GetPluginDescriptionStatic(); - ProcessWinMiniDump(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec &core_file); + ProcessWinMiniDump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec &core_file); - virtual - ~ProcessWinMiniDump(); + virtual ~ProcessWinMiniDump(); - bool - CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; - lldb_private::Error - DoLoadCore() override; + lldb_private::Error DoLoadCore() override; - lldb_private::DynamicLoader * - GetDynamicLoader() override; + lldb_private::DynamicLoader *GetDynamicLoader() override; - lldb_private::ConstString - GetPluginName() override; + lldb_private::ConstString GetPluginName() override; - uint32_t - GetPluginVersion() override; + uint32_t GetPluginVersion() override; - lldb_private::Error - DoDestroy() override; + lldb_private::Error DoDestroy() override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - bool - IsAlive() override; + bool IsAlive() override; - bool - WarnBeforeDetach () const override; + bool WarnBeforeDetach() const override; - size_t - ReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) 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; + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; - lldb_private::ArchSpec - GetArchitecture(); + lldb_private::ArchSpec GetArchitecture(); - lldb_private::Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &range_info) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo &range_info) override; - protected: - void - Clear(); +protected: + void Clear(); - bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; - private: - // Keep Windows-specific types out of this header. - class Impl; - std::unique_ptr<Impl> m_impl_up; +private: + // Keep Windows-specific types out of this header. + class Impl; + std::unique_ptr<Impl> m_impl_up; }; -#endif // liblldb_ProcessWinMiniDump_h_ +#endif // liblldb_ProcessWinMiniDump_h_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp index ddcd15b1ae1..a1d637767dc 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp @@ -27,78 +27,61 @@ using namespace lldb_private; // be fleshed out as more mini-dump functionality is added. class ThreadWinMiniDump::Data { - public: - Data() : m_context(nullptr) {} - const CONTEXT *m_context; +public: + Data() : m_context(nullptr) {} + const CONTEXT *m_context; }; -ThreadWinMiniDump::ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid) : - Thread(process, tid), - m_data(new Data) -{ -} +ThreadWinMiniDump::ThreadWinMiniDump(lldb_private::Process &process, + lldb::tid_t tid) + : Thread(process, tid), m_data(new Data) {} -ThreadWinMiniDump::~ThreadWinMiniDump() -{ -} +ThreadWinMiniDump::~ThreadWinMiniDump() {} -void -ThreadWinMiniDump::RefreshStateAfterStop() -{ -} +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::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; - ArchSpec arch = HostInfo::GetArchitecture(); - switch (arch.GetMachine()) - { - case llvm::Triple::x86: +lldb::RegisterContextSP ThreadWinMiniDump::CreateRegisterContextForFrame( + lldb_private::StackFrame *frame) { + const uint32_t concrete_frame_idx = + (frame) ? frame->GetConcreteFrameIndex() : 0; + RegisterContextSP reg_ctx_sp; + ArchSpec arch = HostInfo::GetArchitecture(); + switch (arch.GetMachine()) { + case llvm::Triple::x86: #if defined(_WIN64) - // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 +// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 #else - reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x86(*this, concrete_frame_idx, m_data->m_context)); + reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x86( + *this, concrete_frame_idx, m_data->m_context)); #endif - break; - case llvm::Triple::x86_64: + break; + case llvm::Triple::x86_64: #if defined(_WIN64) - reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x64(*this, concrete_frame_idx, m_data->m_context)); + reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x64( + *this, concrete_frame_idx, m_data->m_context)); #else - // LLDB is 32-bit, but the target process is 64-bit. We probably can't debug this. +// LLDB is 32-bit, but the target process is 64-bit. We probably can't debug +// this. #endif - default: - break; - } - return reg_ctx_sp; + default: + break; + } + return reg_ctx_sp; } -void -ThreadWinMiniDump::ClearStackFrames() -{ -} +void ThreadWinMiniDump::ClearStackFrames() {} -void -ThreadWinMiniDump::SetContext(const void *context) -{ - if (m_data) - { - m_data->m_context = static_cast<const CONTEXT *>(context); - } +void ThreadWinMiniDump::SetContext(const void *context) { + if (m_data) { + m_data->m_context = static_cast<const CONTEXT *>(context); + } } -bool -ThreadWinMiniDump::CalculateStopInfo() -{ - return false; -} +bool ThreadWinMiniDump::CalculateStopInfo() { return false; } diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h index c7892542210..bee5a6ab5f4 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h @@ -15,35 +15,29 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Target/Thread.h" -class ThreadWinMiniDump : public lldb_private::Thread -{ +class ThreadWinMiniDump : public lldb_private::Thread { public: - ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid); + ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid); - virtual - ~ThreadWinMiniDump(); + virtual ~ThreadWinMiniDump(); - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - lldb::RegisterContextSP - GetRegisterContext() override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - void - ClearStackFrames() override; + void ClearStackFrames() override; - void - SetContext(const void *context); + void SetContext(const void *context); protected: - lldb::RegisterContextSP m_reg_context_sp; - class Data; - std::unique_ptr<Data> m_data; // for WinAPI-specific data + lldb::RegisterContextSP m_reg_context_sp; + class Data; + std::unique_ptr<Data> m_data; // for WinAPI-specific data - bool CalculateStopInfo() override; + bool CalculateStopInfo() override; }; #endif diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp index 41d9195f1ee..7f523fd0eba 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp @@ -7,41 +7,36 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" #include "RegisterContextWindowsMiniDump_x64.h" using namespace lldb; -namespace lldb_private -{ - -RegisterContextWindowsMiniDump_x64::RegisterContextWindowsMiniDump_x64(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) - : RegisterContextWindows_x64(thread, concrete_frame_idx) -{ - if (context) - { - m_context = *context; - m_context_stale = false; - } -} +namespace lldb_private { -RegisterContextWindowsMiniDump_x64::~RegisterContextWindowsMiniDump_x64() -{ +RegisterContextWindowsMiniDump_x64::RegisterContextWindowsMiniDump_x64( + Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) + : RegisterContextWindows_x64(thread, concrete_frame_idx) { + if (context) { + m_context = *context; + m_context_stale = false; + } } -bool -RegisterContextWindowsMiniDump_x64::WriteRegister(const RegisterInfo * /* reg_info */, const RegisterValue & /* reg_value */) -{ - return false; +RegisterContextWindowsMiniDump_x64::~RegisterContextWindowsMiniDump_x64() {} + +bool RegisterContextWindowsMiniDump_x64::WriteRegister( + const RegisterInfo * /* reg_info */, + const RegisterValue & /* reg_value */) { + return false; } -bool -RegisterContextWindowsMiniDump_x64::CacheAllRegisterValues() -{ - // Since this is post-mortem debugging, we either have the context or we don't. - return !m_context_stale; +bool RegisterContextWindowsMiniDump_x64::CacheAllRegisterValues() { + // Since this is post-mortem debugging, we either have the context or we + // don't. + return !m_context_stale; } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h index 86d58046113..b4b29f7a679 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h @@ -10,27 +10,27 @@ #ifndef liblldb_RegisterContextWindowsMiniDump_x64_H_ #define liblldb_RegisterContextWindowsMiniDump_x64_H_ -#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsMiniDump_x64 : public RegisterContextWindows_x64 -{ - public: - RegisterContextWindowsMiniDump_x64(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context); +class RegisterContextWindowsMiniDump_x64 : public RegisterContextWindows_x64 { +public: + RegisterContextWindowsMiniDump_x64(Thread &thread, + uint32_t concrete_frame_idx, + const CONTEXT *context); - virtual ~RegisterContextWindowsMiniDump_x64(); + virtual ~RegisterContextWindowsMiniDump_x64(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - protected: - bool CacheAllRegisterValues() override; +protected: + bool CacheAllRegisterValues() override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsMiniDump_x64_H_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp index 2c8a069c537..c34a1335b36 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp @@ -7,41 +7,36 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" #include "RegisterContextWindowsMiniDump_x86.h" using namespace lldb; -namespace lldb_private -{ - -RegisterContextWindowsMiniDump_x86::RegisterContextWindowsMiniDump_x86(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) - : RegisterContextWindows_x86(thread, concrete_frame_idx) -{ - if (context) - { - m_context = *context; - m_context_stale = false; - } -} +namespace lldb_private { -RegisterContextWindowsMiniDump_x86::~RegisterContextWindowsMiniDump_x86() -{ +RegisterContextWindowsMiniDump_x86::RegisterContextWindowsMiniDump_x86( + Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) + : RegisterContextWindows_x86(thread, concrete_frame_idx) { + if (context) { + m_context = *context; + m_context_stale = false; + } } -bool -RegisterContextWindowsMiniDump_x86::WriteRegister(const RegisterInfo * /* reg_info */, const RegisterValue & /* reg_value */) -{ - return false; +RegisterContextWindowsMiniDump_x86::~RegisterContextWindowsMiniDump_x86() {} + +bool RegisterContextWindowsMiniDump_x86::WriteRegister( + const RegisterInfo * /* reg_info */, + const RegisterValue & /* reg_value */) { + return false; } -bool -RegisterContextWindowsMiniDump_x86::CacheAllRegisterValues() -{ - // Since this is post-mortem debugging, we either have the context or we don't. - return !m_context_stale; +bool RegisterContextWindowsMiniDump_x86::CacheAllRegisterValues() { + // Since this is post-mortem debugging, we either have the context or we + // don't. + return !m_context_stale; } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h index d36e0cfd9e7..2754dcfb03a 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h @@ -1,4 +1,5 @@ -//===-- RegisterContextWindowsMiniDump_x86.h ------------------------*- C++ -*-===// +//===-- RegisterContextWindowsMiniDump_x86.h ------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,27 +11,27 @@ #ifndef liblldb_RegisterContextWindowsMiniDump_x86_H_ #define liblldb_RegisterContextWindowsMiniDump_x86_H_ -#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsMiniDump_x86 : public RegisterContextWindows_x86 -{ - public: - RegisterContextWindowsMiniDump_x86(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context); +class RegisterContextWindowsMiniDump_x86 : public RegisterContextWindows_x86 { +public: + RegisterContextWindowsMiniDump_x86(Thread &thread, + uint32_t concrete_frame_idx, + const CONTEXT *context); - virtual ~RegisterContextWindowsMiniDump_x86(); + virtual ~RegisterContextWindowsMiniDump_x86(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - protected: - bool CacheAllRegisterValues() override; +protected: + bool CacheAllRegisterValues() override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsMiniDump_x86_H_ |