summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2015-01-15 22:54:08 +0000
committerZachary Turner <zturner@google.com>2015-01-15 22:54:08 +0000
commitf194c50fc3b3dc4d64b6b1cc14ec4790dec14e93 (patch)
treeea4847f5f8ec426e59ae91c44b5a102f6d9aae21
parent8f3f7beac4d73a0c4e33f085e6885d37a61efbf7 (diff)
downloadbcm5719-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
-rw-r--r--lldb/source/Plugins/Process/Windows/ProcessWindows.cpp50
-rw-r--r--lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp41
-rw-r--r--lldb/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp3
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;
}
OpenPOWER on IntegriCloud