[Lldb-commits] [lldb] r237817 - Implement attach to process on Windows.

Zachary Turner zturner at google.com
Wed May 20 11:31:17 PDT 2015


Author: zturner
Date: Wed May 20 13:31:17 2015
New Revision: 237817

URL: http://llvm.org/viewvc/llvm-project?rev=237817&view=rev
Log:
Implement attach to process on Windows.

Differential Revision: http://reviews.llvm.org/D9801
Reviewed by: Adrian McCarthy

Modified:
    lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp
    lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.h
    lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
    lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h
    lldb/trunk/source/Plugins/Process/Windows/DynamicLoaderWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp?rev=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp Wed May 20 13:31:17 2015
@@ -526,51 +526,88 @@ PlatformWindows::LaunchProcess (ProcessL
     return error;
 }
 
+ProcessSP
+PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Error &error)
+{
+    // Windows has special considerations that must be followed when launching or attaching to a process.  The
+    // key requirement is that when launching or attaching to a process, you must do it from the same the thread
+    // that will go into a permanent loop which will then receive debug events from the process.  In particular,
+    // this means we can't use any of LLDB's generic mechanisms to do it for us, because it doesn't have the
+    // special knowledge required for setting up the background thread or passing the right flags.  
+    //
+    // Another problem is that that LLDB's standard model for debugging a process is to first launch it, have
+    // it stop at the entry point, and then attach to it.  In Windows this doesn't quite work, you have to 
+    // specify as an argument to CreateProcess() that you're going to debug the process.  So we override DebugProcess
+    // here to handle this.  Launch operations go directly to the process plugin, and attach operations almost go
+    // directly to the process plugin (but we hijack the events first).  In essence, we encapsulate all the logic
+    // of Launching and Attaching in the process plugin, and PlatformWindows::DebugProcess is just a pass-through
+    // to get to the process plugin.
+
+    if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+    {
+        // This is a process attach.  Don't need to launch anything.
+        ProcessAttachInfo attach_info(launch_info);
+        return Attach(attach_info, debugger, target, error);
+    }
+    else
+    {
+        ProcessSP process_sp = target->CreateProcess(launch_info.GetListenerForProcess(debugger),
+                                                     launch_info.GetProcessPluginName(),
+                                                     nullptr);
+
+        // We need to launch and attach to the process.
+        launch_info.GetFlags().Set(eLaunchFlagDebug);
+        if (process_sp)
+            error = process_sp->Launch(launch_info);
+
+        return process_sp;
+    }
+}
+
 lldb::ProcessSP
 PlatformWindows::Attach(ProcessAttachInfo &attach_info,
                         Debugger &debugger,
                         Target *target,
                         Error &error)
 {
+    error.Clear();
     lldb::ProcessSP process_sp;
-    if (IsHost())
-    {
-        if (target == NULL)
-        {
-            TargetSP new_target_sp;
-            FileSpec emptyFileSpec;
-            ArchSpec emptyArchSpec;
-
-            error = debugger.GetTargetList().CreateTarget (debugger,
-                                                           NULL,
-                                                           NULL,
-                                                           false,
-                                                           NULL,
-                                                           new_target_sp);
-            target = new_target_sp.get();
-        }
-        else
-            error.Clear();
-
-        if (target && error.Success())
-        {
-            debugger.GetTargetList().SetSelectedTarget(target);
-            // The Windows platform always currently uses the GDB remote debugger plug-in
-            // so even when debugging locally we are debugging remotely!
-            // Just like the darwin plugin.
-            process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
-
-            if (process_sp)
-                error = process_sp->Attach (attach_info);
-        }
-    }
-    else
+    if (!IsHost())
     {
         if (m_remote_platform_sp)
             process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
         else
             error.SetErrorString ("the platform is not currently connected");
+        return process_sp;
+    }
+
+    if (target == NULL)
+    {
+        TargetSP new_target_sp;
+        FileSpec emptyFileSpec;
+        ArchSpec emptyArchSpec;
+
+        error = debugger.GetTargetList().CreateTarget (debugger,
+                                                        NULL,
+                                                        NULL,
+                                                        false,
+                                                        NULL,
+                                                        new_target_sp);
+        target = new_target_sp.get();
     }
+
+    if (!target || error.Fail())
+        return process_sp;
+
+    debugger.GetTargetList().SetSelectedTarget(target);
+
+    const char *plugin_name = attach_info.GetProcessPluginName();
+    process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), plugin_name, NULL);
+
+    process_sp->HijackProcessEvents(attach_info.GetHijackListener().get());
+    if (process_sp)
+        error = process_sp->Attach (attach_info);
+
     return process_sp;
 }
 
@@ -687,3 +724,9 @@ PlatformWindows::GetStatus (Stream &strm
          << " Build: " << update << '\n';
 #endif
 }
+
+bool
+PlatformWindows::CanDebugProcess()
+{
+    return true;
+}

Modified: lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.h?rev=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.h (original)
+++ lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.h Wed May 20 13:31:17 2015
@@ -122,10 +122,12 @@ public:
     LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
 
     lldb::ProcessSP
-    Attach(lldb_private::ProcessAttachInfo &attach_info,
-           lldb_private::Debugger &debugger,
-           lldb_private::Target *target,
-           lldb_private::Error &error) override;
+    DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger,
+                 lldb_private::Target *target, lldb_private::Error &error) override;
+
+    lldb::ProcessSP
+    Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger,
+           lldb_private::Target *target, lldb_private::Error &error) override;
 
     lldb_private::Error
     GetFileWithUUID(const lldb_private::FileSpec &platform_file,
@@ -145,12 +147,7 @@ public:
     void
     GetStatus(lldb_private::Stream &strm) override;
 
-    // Local debugging not yet supported
-    bool
-    CanDebugProcess(void) override
-    {
-        return false;
-    }
+    bool CanDebugProcess() override;
 
     // FIXME not sure what the _sigtramp equivalent would be on this platform
     void

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=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp Wed May 20 13:31:17 2015
@@ -22,6 +22,7 @@
 #include "lldb/Host/windows/HostThreadWindows.h"
 #include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Target/ProcessLaunchInfo.h"
+#include "lldb/Target/Process.h"
 
 #include "Plugins/Process/Windows/ProcessWindowsLog.h"
 
@@ -43,6 +44,19 @@ struct DebugLaunchContext
     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;
+};
 }
 
 DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
@@ -64,7 +78,7 @@ DebuggerThread::DebugLaunch(const Proces
     Error error;
     DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
     HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
-                            DebuggerThreadRoutine, context, &error));
+                                                         DebuggerThreadLaunchRoutine, context, &error));
 
     if (!error.Success())
     {
@@ -75,25 +89,53 @@ DebuggerThread::DebugLaunch(const Proces
     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));
+
+    if (!error.Success())
+    {
+        WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'.  %s", (DWORD)pid,
+                     error.AsCString());
+    }
+
+    return error;
+}
+
 lldb::thread_result_t
-DebuggerThread::DebuggerThreadRoutine(void *data)
+DebuggerThread::DebuggerThreadLaunchRoutine(void *data)
 {
     DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
-    lldb::thread_result_t result = context->m_thread->DebuggerThreadRoutine(context->m_launch_info);
+    lldb::thread_result_t result = context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info);
+    delete context;
+    return result;
+}
+
+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::DebuggerThreadRoutine(const ProcessLaunchInfo &launch_info)
+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'.",
-        launch_info.GetExecutableFile().GetPath().c_str());
+    WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to launch '%s' on background thread.",
+                 launch_info.GetExecutableFile().GetPath().c_str());
 
     Error error;
     ProcessLauncherWindows launcher;
@@ -110,6 +152,31 @@ DebuggerThread::DebuggerThreadRoutine(co
 
     return 0;
 }
+
+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.
+    DebugLoop();
+
+    return 0;
+}
 
 Error
 DebuggerThread::StopDebugging(bool terminate)

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=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.h Wed May 20 13:31:17 2015
@@ -34,6 +34,7 @@ class DebuggerThread : public std::enabl
     virtual ~DebuggerThread();
 
     Error DebugLaunch(const ProcessLaunchInfo &launch_info);
+    Error DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info);
 
     HostProcess
     GetProcess() const
@@ -80,8 +81,10 @@ class DebuggerThread : public std::enabl
                                                  // 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);
+    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);
 };
 }
 

Modified: lldb/trunk/source/Plugins/Process/Windows/DynamicLoaderWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/DynamicLoaderWindows.cpp?rev=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DynamicLoaderWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/DynamicLoaderWindows.cpp Wed May 20 13:31:17 2015
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DynamicLoaderWindows.h"
+#include "ProcessWindowsLog.h"
 
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Target/Process.h"
@@ -65,6 +66,7 @@ DynamicLoader *DynamicLoaderWindows::Cre
 
     if (should_create)
         return new DynamicLoaderWindows (process);
+
     return nullptr;
 }
 

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=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp Wed May 20 13:31:17 2015
@@ -62,8 +62,8 @@ namespace lldb_private
 class ProcessWindowsData
 {
   public:
-    ProcessWindowsData(const ProcessLaunchInfo &launch_info)
-        : m_launch_info(launch_info)
+    ProcessWindowsData(bool stop_at_entry)
+        : m_stop_at_entry(stop_at_entry)
         , m_initial_stop_event(nullptr)
         , m_initial_stop_received(false)
     {
@@ -72,11 +72,11 @@ class ProcessWindowsData
 
     ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }
 
-    ProcessLaunchInfo m_launch_info;
     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;
@@ -257,7 +257,8 @@ ProcessWindows::DoLaunch(Module *exe_mod
         return result;
     }
 
-    m_session_data.reset(new ProcessWindowsData(launch_info));
+    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()));
@@ -266,42 +267,92 @@ ProcessWindows::DoLaunch(Module *exe_mod
 
     // 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;
-    if (result.Success())
+    Error error = WaitForDebuggerConnection(debugger, process);
+    if (error.Fail())
     {
-        WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch started asynchronous launch of '%s'.  Waiting for initial stop.",
-                     launch_info.GetExecutableFile().GetPath().c_str());
-
-        // 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)
-        {
-            process = debugger->GetProcess();
-            if (m_session_data->m_launch_error.Fail())
-                result = m_session_data->m_launch_error;
-        }
-        else
-            result.SetError(::GetLastError(), eErrorTypeWin32);
+        WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
+                     launch_info.GetExecutableFile().GetPath().c_str(), error.AsCString());
+        return error;
     }
 
-    if (result.Success())
+    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
+ProcessWindows::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;
+
+    DWORD process_id = static_cast<DWORD>(pid);
+    Error error = debugger->DebugAttach(process_id, attach_info);
+    if (error.Fail())
     {
-        WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'",
-                     launch_info.GetExecutableFile().GetPath().c_str());
+        WINLOG_IFALL(WINDOWS_LOG_PROCESS,
+                     "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach.  %s",
+                     error.AsCString());
+        return error;
     }
-    else
+
+    HostProcess process;
+    error = WaitForDebuggerConnection(debugger, process);
+    if (error.Fail())
     {
-        WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
-                     launch_info.GetExecutableFile().GetPath().c_str(), result.AsCString());
-        return result;
+        WINLOG_IFALL(WINDOWS_LOG_PROCESS,
+                     "DoAttachToProcessWithID encountered an error waiting for the debugger to connect.  %s",
+                     error.AsCString());
+        return error;
     }
 
-    // We've hit the initial stop.  The private state should already be set to stopped as a result
-    // of encountering the breakpoint exception in ProcessWindows::OnDebugException.
-    launch_info.SetProcessID(process.GetProcessId());
+    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;
+}
 
-    return result;
+Error
+ProcessWindows::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);
 }
 
 Error
@@ -521,11 +572,16 @@ ProcessWindows::DoHalt(bool &caused_stop
 
 void ProcessWindows::DidLaunch()
 {
+    DidAttach(ArchSpec());
+}
+
+void
+ProcessWindows::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_launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
+    if (m_session_data && GetPrivateState() == eStateStopped && m_session_data->m_stop_at_entry)
         RefreshStateAfterStop();
 }
 
@@ -557,11 +613,13 @@ size_t
 ProcessWindows::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;
-
-    WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, vm_addr);
+    }
 
     HostProcess process = m_session_data->m_debugger->GetProcess();
     void *addr = reinterpret_cast<void *>(vm_addr);
@@ -672,20 +730,18 @@ ProcessWindows::OnDebuggerConnected(lldb
     WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Debugger established connected to process %I64u.  Image base = 0x%I64x",
                  debugger->GetProcess().GetProcessId(), image_base);
 
-    // Either we successfully attached to an existing process, or we successfully launched a new
-    // process under the debugger.
     ModuleSP module = GetTarget().GetExecutableModule();
     bool load_addr_changed;
     module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);
 
-    // Notify the target that the executable module has loaded.  This will cause any pending
-    // breakpoints to be resolved to explicit brekapoint sites.
     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();
 }
@@ -723,9 +779,18 @@ ProcessWindows::OnDebugException(bool fi
 
             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:

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=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h Wed May 20 13:31:17 2015
@@ -30,6 +30,7 @@ class ProcessMonitor;
 
 namespace lldb_private
 {
+class HostProcess;
 class ProcessWindowsData;
 }
 
@@ -77,11 +78,14 @@ public:
 
     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;
     lldb::addr_t GetImageInfoAddress() override;
@@ -116,6 +120,9 @@ public:
     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.

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=237817&r1=237816&r2=237817&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed May 20 13:31:17 2015
@@ -3336,6 +3336,9 @@ Process::AttachCompletionHandler::Perfor
 
     switch (state)
     {
+        case eStateAttaching:
+            return eEventActionSuccess;
+
         case eStateRunning:
         case eStateConnected:
             return eEventActionRetry;
@@ -4457,7 +4460,8 @@ Process::HandlePrivateEvent (EventSP &ev
             // Only push the input handler if we aren't fowarding events,
             // as this means the curses GUI is in use...
             // Or don't push it if we are launching since it will come up stopped.
-            if (!GetTarget().GetDebugger().IsForwardingEvents() && new_state != eStateLaunching)
+            if (!GetTarget().GetDebugger().IsForwardingEvents() && new_state != eStateLaunching &&
+                new_state != eStateAttaching)
                 PushProcessIOHandler ();
             m_iohandler_sync.SetValue(true, eBroadcastAlways);
         }





More information about the lldb-commits mailing list