[Lldb-commits] [lldb] r226221 - Some fixes for thread stepping on Windows.

Zachary Turner zturner at google.com
Thu Jan 15 14:54:08 PST 2015


Author: zturner
Date: Thu Jan 15 16:54:08 2015
New Revision: 226221

URL: http://llvm.org/viewvc/llvm-project?rev=226221&view=rev
Log:
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.

Modified:
    lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/TargetThreadWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp

Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp?rev=226221&r1=226220&r2=226221&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp Thu Jan 15 16:54:08 2015
@@ -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 fi
     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 fi
                 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 fi
                 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;
 }
 

Modified: lldb/trunk/source/Plugins/Process/Windows/TargetThreadWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/TargetThreadWindows.cpp?rev=226221&r1=226220&r2=226221&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/TargetThreadWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/TargetThreadWindows.cpp Thu Jan 15 16:54:08 2015
@@ -38,12 +38,15 @@ TargetThreadWindows::~TargetThreadWindow
 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;
 }

Modified: lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp?rev=226221&r1=226220&r2=226221&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp Thu Jan 15 16:54:08 2015
@@ -343,12 +343,13 @@ RegisterContextWindows_x86::CacheAllRegi
 {
     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;
 }





More information about the lldb-commits mailing list