[Lldb-commits] [lldb] r221642 - [ProcessWindows] Implement breakpoint stop / resume on Windows.

Zachary Turner zturner at google.com
Mon Nov 10 16:00:14 PST 2014


Author: zturner
Date: Mon Nov 10 18:00:14 2014
New Revision: 221642

URL: http://llvm.org/viewvc/llvm-project?rev=221642&view=rev
Log:
[ProcessWindows] Implement breakpoint stop / resume on Windows.

This patch implements basic support for stopping at breakpoints
and resuming later.  While a breakpoint is stopped at, LLDB will
cease to process events in the debug loop, effectively suspending
the process, and then resume later when ProcessWindows::DoResume
is called.

As a side effect, this also correctly handles the loader breakpoint
(i.e. the initial stop) so that LLDB goes through the correct state
sequence during the initial process launch.

Added:
    lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
Modified:
    lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
    lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h
    lldb/trunk/source/Plugins/Process/Windows/ForwardDecl.h
    lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
    lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
    lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
    lldb/trunk/source/Plugins/Process/Windows/ProcessMessages.h
    lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h

Modified: lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp Mon Nov 10 18:00:14 2014
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DebuggerThread.h"
+#include "ExceptionRecord.h"
 #include "IDebugDelegate.h"
 #include "ProcessMessages.h"
 
@@ -98,6 +99,12 @@ DebuggerThread::DebuggerThreadRoutine(co
 }
 
 void
+DebuggerThread::ContinueAsyncException(ExceptionResult result)
+{
+    m_exception.SetValue(result, eBroadcastAlways);
+}
+
+void
 DebuggerThread::DebugLoop()
 {
     DEBUG_EVENT dbe = {0};
@@ -108,8 +115,17 @@ DebuggerThread::DebugLoop()
         switch (dbe.dwDebugEventCode)
         {
             case EXCEPTION_DEBUG_EVENT:
-                continue_status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
+            {
+                ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
+                m_exception.SetValue(status, eBroadcastNever);
+                m_exception.WaitForValueNotEqualTo(ExceptionResult::WillHandle, status);
+
+                if (status == ExceptionResult::Handled)
+                    continue_status = DBG_CONTINUE;
+                else if (status == ExceptionResult::NotHandled)
+                    continue_status = DBG_EXCEPTION_NOT_HANDLED;
                 break;
+            }
             case CREATE_THREAD_DEBUG_EVENT:
                 continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
                 break;
@@ -143,10 +159,12 @@ DebuggerThread::DebugLoop()
     }
 }
 
-DWORD
+ExceptionResult
 DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
 {
-    return DBG_CONTINUE;
+    bool first_chance = (info.dwFirstChance != 0);
+    ProcessMessageException message(m_process, ExceptionRecord(info.ExceptionRecord), first_chance);
+    return m_debug_delegate->OnDebugException(message);
 }
 
 DWORD

Modified: lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h Mon Nov 10 18:00:14 2014
@@ -13,6 +13,7 @@
 #include "ForwardDecl.h"
 #include "lldb/Host/HostProcess.h"
 #include "lldb/Host/HostThread.h"
+#include "lldb/Host/Predicate.h"
 #include "lldb/Host/windows/windows.h"
 
 #include <memory>
@@ -45,9 +46,11 @@ class DebuggerThread : public std::enabl
         return m_main_thread;
     }
 
+    void ContinueAsyncException(ExceptionResult result);
+
   private:
     void DebugLoop();
-    DWORD HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id);
+    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);
@@ -63,6 +66,10 @@ class DebuggerThread : public std::enabl
     HostThread m_main_thread; // The main thread of the inferior.
     HANDLE m_image_file;      // The image file of the process being debugged.
 
+    Predicate<ExceptionResult> m_exception; // A predicate which gets signalled when an exception
+                                            // is finished processing and the debug loop can be
+                                            // continued.
+
     static lldb::thread_result_t DebuggerThreadRoutine(void *data);
     lldb::thread_result_t DebuggerThreadRoutine(const ProcessLaunchInfo &launch_info);
 };

Added: lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h?rev=221642&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h Mon Nov 10 18:00:14 2014
@@ -0,0 +1,74 @@
+//===-- ExceptionRecord.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_ExceptionRecord_H_
+#define liblldb_Plugins_Process_Windows_ExceptionRecord_H_
+
+#include "ForwardDecl.h"
+
+#include "lldb/lldb-forward.h"
+#include "lldb/Host/windows/windows.h"
+
+#include <memory>
+#include <vector>
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+// ExceptionRecord
+//
+// ExceptionRecord defines an interface which allows implementors to receive
+// notification of events that happen in a debugged process.
+//----------------------------------------------------------------------
+class ExceptionRecord
+{
+  public:
+    explicit ExceptionRecord(const EXCEPTION_RECORD &record)
+    {
+        m_code = record.ExceptionCode;
+        m_continuable = (record.ExceptionFlags == 0);
+        if (record.ExceptionRecord)
+            m_next_exception.reset(new ExceptionRecord(*record.ExceptionRecord));
+        m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress);
+        m_arguments.assign(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters);
+    }
+    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;
+    }
+
+  private:
+    DWORD m_code;
+    bool m_continuable;
+    std::shared_ptr<ExceptionRecord> m_next_exception;
+    lldb::addr_t m_exception_addr;
+    std::vector<ULONG_PTR> m_arguments;
+};
+}
+
+#endif

Modified: lldb/trunk/source/Plugins/Process/Windows/ForwardDecl.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ForwardDecl.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ForwardDecl.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ForwardDecl.h Mon Nov 10 18:00:14 2014
@@ -14,12 +14,25 @@ class ProcessWindows;
 
 #include <memory>
 
+// ExceptionResult is returned by the debug delegate to specify how it processed
+// the exception.
+enum class ExceptionResult
+{
+    Handled,    // The delegate handled the exception.  Continue.
+    NotHandled, // The delegate did not handle the exception.  Keep
+                // searching.
+    WillHandle  // The delegate will handle the exception.  Do not
+                // process further debug events until it finishes.
+};
+
 namespace lldb_private
 {
-class IDebugDelegate;
 
+class IDebugDelegate;
 class DebuggerThread;
 
+class ExceptionRecord;
+
 // Process message forward declarations.
 class ProcessMessageBase;
 class ProcessMessageExitProcess;

Modified: lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h Mon Nov 10 18:00:14 2014
@@ -28,7 +28,7 @@ class IDebugDelegate
 
     virtual void OnExitProcess(const ProcessMessageExitProcess &message) = 0;
     virtual void OnDebuggerConnected(const ProcessMessageDebuggerConnected &message) = 0;
-    virtual void OnDebugException(const ProcessMessageException &message) = 0;
+    virtual ExceptionResult OnDebugException(const ProcessMessageException &message) = 0;
     virtual void OnCreateThread(const ProcessMessageCreateThread &message) = 0;
     virtual void OnExitThread(const ProcessMessageExitThread &message) = 0;
     virtual void OnLoadDll(const ProcessMessageLoadDll &message) = 0;

Modified: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp Mon Nov 10 18:00:14 2014
@@ -30,10 +30,10 @@ LocalDebugDelegate::OnDebuggerConnected(
     ((ProcessWindows &)*m_process).OnDebuggerConnected(message);
 }
 
-void
+ExceptionResult
 LocalDebugDelegate::OnDebugException(const ProcessMessageException &message)
 {
-    ((ProcessWindows &)*m_process).OnDebugException(message);
+    return ((ProcessWindows &)*m_process).OnDebugException(message);
 }
 
 void

Modified: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h Mon Nov 10 18:00:14 2014
@@ -44,7 +44,7 @@ class LocalDebugDelegate : public IDebug
 
     void OnExitProcess(const ProcessMessageExitProcess &message) override;
     void OnDebuggerConnected(const ProcessMessageDebuggerConnected &message) override;
-    void OnDebugException(const ProcessMessageException &message) override;
+    ExceptionResult OnDebugException(const ProcessMessageException &message) override;
     void OnCreateThread(const ProcessMessageCreateThread &message) override;
     void OnExitThread(const ProcessMessageExitThread &message) override;
     void OnLoadDll(const ProcessMessageLoadDll &message) override;

Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessMessages.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessMessages.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessMessages.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessMessages.h Mon Nov 10 18:00:14 2014
@@ -10,9 +10,13 @@
 #ifndef liblldb_Plugins_Process_Windows_ProcessMessages_H_
 #define liblldb_Plugins_Process_Windows_ProcessMessages_H_
 
+#include "ExceptionRecord.h"
+
 #include "lldb/Core/Error.h"
 #include "lldb/Host/HostProcess.h"
 
+#include <memory>
+
 namespace lldb_private
 {
 
@@ -51,6 +55,32 @@ class ProcessMessageDebuggerConnected :
     }
 };
 
+class ProcessMessageException : public ProcessMessageBase
+{
+  public:
+    ProcessMessageException(const HostProcess &process, const ExceptionRecord &exception, bool first_chance)
+        : ProcessMessageBase(process)
+        , m_exception(exception)
+        , m_first_chance(first_chance)
+    {
+    }
+
+    bool
+    IsFirstChance() const
+    {
+        return m_first_chance;
+    }
+    const ExceptionRecord &
+    GetExceptionRecord() const
+    {
+        return m_exception;
+    }
+
+  private:
+    bool m_first_chance;
+    ExceptionRecord m_exception;
+};
+
 class ProcessMessageExitProcess : public ProcessMessageBase
 {
   public:

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=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp Mon Nov 10 18:00:14 2014
@@ -28,6 +28,7 @@
 #include "lldb/Target/Target.h"
 
 #include "DebuggerThread.h"
+#include "ExceptionRecord.h"
 #include "LocalDebugDelegate.h"
 #include "ProcessMessages.h"
 #include "ProcessWindows.h"
@@ -144,6 +145,7 @@ ProcessWindows::DoLaunch(Module *exe_mod
 
     launch_info.SetProcessID(process.GetProcessId());
     SetID(process.GetProcessId());
+
     return result;
 }
 
@@ -151,6 +153,11 @@ Error
 ProcessWindows::DoResume()
 {
     Error error;
+    if (!m_active_exception)
+        return error;
+
+    m_debugger->ContinueAsyncException(ExceptionResult::Handled);
+    SetPrivateState(eStateRunning);
     return error;
 }
 
@@ -240,6 +247,7 @@ void
 ProcessWindows::OnExitProcess(const ProcessMessageExitProcess &message)
 {
     SetProcessExitStatus(nullptr, GetID(), true, 0, message.GetExitCode());
+    SetPrivateState(eStateExited);
 }
 
 void
@@ -248,9 +256,20 @@ ProcessWindows::OnDebuggerConnected(cons
     ::SetEvent(m_data_up->m_launched_event);
 }
 
-void
+ExceptionResult
 ProcessWindows::OnDebugException(const ProcessMessageException &message)
 {
+    ExceptionResult result = ExceptionResult::Handled;
+    const ExceptionRecord &record = message.GetExceptionRecord();
+    m_active_exception.reset(new ExceptionRecord(record));
+    switch (record.GetExceptionCode())
+    {
+        case EXCEPTION_BREAKPOINT:
+            SetPrivateState(eStateStopped);
+            result = ExceptionResult::WillHandle;
+            break;
+    }
+    return result;
 }
 
 void

Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h?rev=221642&r1=221641&r2=221642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h Mon Nov 10 18:00:14 2014
@@ -117,7 +117,7 @@ public:
     // IDebugDelegate overrides.
     virtual void OnExitProcess(const lldb_private::ProcessMessageExitProcess &message) override;
     virtual void OnDebuggerConnected(const lldb_private::ProcessMessageDebuggerConnected &message) override;
-    virtual void OnDebugException(const lldb_private::ProcessMessageException &message) override;
+    virtual ExceptionResult OnDebugException(const lldb_private::ProcessMessageException &message) override;
     virtual void OnCreateThread(const lldb_private::ProcessMessageCreateThread &message) override;
     virtual void OnExitThread(const lldb_private::ProcessMessageExitThread &message) override;
     virtual void OnLoadDll(const lldb_private::ProcessMessageLoadDll &message) override;
@@ -126,6 +126,7 @@ public:
     virtual void OnDebuggerError(const lldb_private::ProcessMessageDebuggerError &message) override;
 
   private:
+    std::shared_ptr<lldb_private::ExceptionRecord> m_active_exception;
     std::unique_ptr<lldb_private::ProcessWindowsData> m_data_up;
     lldb_private::Error m_launch_error;
     lldb_private::DebuggerThreadSP m_debugger;





More information about the lldb-commits mailing list