diff options
| author | Zachary Turner <zturner@google.com> | 2015-01-15 22:54:08 +0000 |
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2015-01-15 22:54:08 +0000 |
| commit | f194c50fc3b3dc4d64b6b1cc14ec4790dec14e93 (patch) | |
| tree | ea4847f5f8ec426e59ae91c44b5a102f6d9aae21 | |
| parent | 8f3f7beac4d73a0c4e33f085e6885d37a61efbf7 (diff) | |
| download | bcm5719-llvm-f194c50fc3b3dc4d64b6b1cc14ec4790dec14e93.tar.gz bcm5719-llvm-f194c50fc3b3dc4d64b6b1cc14ec4790dec14e93.zip | |
Some fixes for thread stepping on Windows.
This hooks up the changes necessary to set the trap flag on the
CPU and properly manage the process and thread's resume state
and private state so that the ThreadPlan does its thing.
Stepping still doesn't work as of this change, because there are
some issues with stack frames where it doesn't update the thread's
frame list correctly when it breaks inside of a function, but
I will try to fix that separately.
llvm-svn: 226221
3 files changed, 48 insertions, 46 deletions
diff --git a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp index 890aa8f7fd9..b02fa6c8ade 100644 --- a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp @@ -254,6 +254,13 @@ ProcessWindows::DoResume() m_session_data->m_debugger->ContinueAsyncException(ExceptionResult::MaskException); } + for (int i = 0; i < m_thread_list.GetSize(); ++i) + { + typedef std::shared_ptr<TargetThreadWindows> TargetThreadWindowsSP; + TargetThreadWindowsSP thread = std::static_pointer_cast<TargetThreadWindows>(m_thread_list.GetThreadAtIndex(i)); + thread->DoResume(); + } + SetPrivateState(eStateRunning); } return error; @@ -319,18 +326,21 @@ ProcessWindows::RefreshStateAfterStop() uint64_t pc = register_context->GetPC(); if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT) { - // TODO(zturner): The current EIP is AFTER the BP opcode, which is one byte. So - // to find the breakpoint, move the PC back. A better way to do this is probably - // to ask the Platform how big a breakpoint opcode is. - --pc; - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + // TODO(zturner): The current EIP is AFTER the BP opcode, which is one byte. + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc - 1)); if (site && site->ValidForThisThread(stop_thread.get())) { lldb::break_id_t break_id = LLDB_INVALID_BREAK_ID; stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); + register_context->SetPC(pc - 1); } stop_thread->SetStopInfo(stop_info); } + else if (active_exception->GetExceptionCode() == EXCEPTION_SINGLE_STEP) + { + stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); + stop_thread->SetStopInfo(stop_info); + } else { std::string desc; @@ -498,7 +508,14 @@ ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &recor if (!m_session_data) return ExceptionResult::SendToApplication; + if (!first_chance) + { + // Any second chance exception is an application crash by definition. + SetPrivateState(eStateCrashed); + } + ExceptionResult result = ExceptionResult::SendToApplication; + lldb::StateType state = GetPrivateState(); switch (record.GetExceptionCode()) { case EXCEPTION_BREAKPOINT: @@ -510,7 +527,11 @@ ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &recor m_session_data->m_initial_stop_received = true; ::SetEvent(m_session_data->m_initial_stop_event); } - + SetPrivateState(eStateStopped); + break; + case EXCEPTION_SINGLE_STEP: + result = ExceptionResult::BreakInDebugger; + SetPrivateState(eStateStopped); break; default: // For non-breakpoints, give the application a chance to handle the exception first. @@ -520,23 +541,6 @@ ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &recor result = ExceptionResult::BreakInDebugger; } - if (!first_chance) - { - // Any second chance exception is an application crash by definition. - SetPrivateState(eStateCrashed); - } - else if (result == ExceptionResult::BreakInDebugger) - { - // For first chance exceptions that we can handle, the process is stopped so the user - // can interact with the debugger. - SetPrivateState(eStateStopped); - } - else - { - // For first chance exceptions that we either eat or send back to the application, don't - // modify the state of the application. - } - return result; } diff --git a/lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp index 2f5ddc93056..b57f33f0dd5 100644 --- a/lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp @@ -38,12 +38,15 @@ TargetThreadWindows::~TargetThreadWindows() void TargetThreadWindows::RefreshStateAfterStop() { + DWORD old_suspend_count = ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); + GetRegisterContext()->InvalidateIfNeeded(false); } void TargetThreadWindows::WillResume(lldb::StateType resume_state) { + SetResumeState(resume_state); } void @@ -118,28 +121,22 @@ TargetThreadWindows::DoResume() if (resume_state == current_state) return true; - bool success = false; - DWORD suspend_count = 0; - switch (resume_state) + 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) { - case eStateRunning: - SetState(resume_state); - do - { - suspend_count = ::ResumeThread(m_host_thread.GetNativeThread().GetSystemHandle()); - } while (suspend_count > 1 && suspend_count != (DWORD)-1); - success = (suspend_count != (DWORD)-1); - break; - case eStateStopped: - case eStateSuspended: - if (current_state != eStateStopped && current_state != eStateSuspended) - { - suspend_count = SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - success = (suspend_count != (DWORD)-1); - } - break; - default: - success = false; + 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 success; + return true; } diff --git a/lldb/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp b/lldb/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp index f4bef83557b..7d49e0bcf85 100644 --- a/lldb/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp @@ -343,12 +343,13 @@ RegisterContextWindows_x86::CacheAllRegisterValues() { if (!m_context_stale) return true; + if (!m_cached_context && !InitializeContextDataBuffer(m_cached_context, &m_context_ptr)) return false; TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), m_context_ptr)) return false; - m_context_stale = true; + m_context_stale = false; return true; } |

