diff options
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_ |