Closed by commit rL221807 (authored by @zturner).

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D6224

Files:
  lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
  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/ProcessWindows.cpp
  lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
Index: lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
@@ -13,14 +13,17 @@
 
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Predicate.h"
 #include "lldb/Host/ThisThread.h"
 #include "lldb/Host/ThreadLauncher.h"
 #include "lldb/Host/windows/HostProcessWindows.h"
 #include "lldb/Host/windows/HostThreadWindows.h"
 #include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Target/ProcessLaunchInfo.h"
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace lldb;
@@ -185,7 +188,8 @@
     ((HostThreadWindows &)m_main_thread.GetNativeThread()).SetOwnsHandle(false);
     m_image_file = info.hFile;
 
-    m_debug_delegate->OnDebuggerConnected();
+    lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
+    m_debug_delegate->OnDebuggerConnected(load_addr);
 
     return DBG_CONTINUE;
 }
@@ -211,14 +215,41 @@
 DWORD
 DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
 {
-    // Windows does not automatically close info.hFile when the DLL is unloaded.
+    if (info.hFile == nullptr)
+    {
+        // Not sure what this is, so just ignore it.
+        return DBG_CONTINUE;
+    }
+
+    std::vector<char> buffer(1);
+    DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
+    if (required_size > 0)
+    {
+        buffer.resize(required_size + 1);
+        required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
+        llvm::StringRef path_str(&buffer[0]);
+        const char *path = path_str.data();
+        if (path_str.startswith("\\\\?\\"))
+            path += 4;
+
+        FileSpec file_spec(path, false);
+        ModuleSpec module_spec(file_spec);
+        lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
+        m_debug_delegate->OnLoadDll(module_spec, load_addr);
+    }
+    else
+    {
+        // An unknown error occurred getting the path name.
+    }
+    // Windows does not automatically close info.hFile, so we need to do it.
     ::CloseHandle(info.hFile);
     return DBG_CONTINUE;
 }
 
 DWORD
 DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
 {
+    m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll));
     return DBG_CONTINUE;
 }
 
Index: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
@@ -25,9 +25,9 @@
 }
 
 void
-LocalDebugDelegate::OnDebuggerConnected()
+LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base)
 {
-    ((ProcessWindows &)*m_process).OnDebuggerConnected();
+    ((ProcessWindows &)*m_process).OnDebuggerConnected(image_base);
 }
 
 ExceptionResult
@@ -49,15 +49,15 @@
 }
 
 void
-LocalDebugDelegate::OnLoadDll()
+LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr)
 {
-    ((ProcessWindows &)*m_process).OnLoadDll();
+    ((ProcessWindows &)*m_process).OnLoadDll(module_spec, module_addr);
 }
 
 void
-LocalDebugDelegate::OnUnloadDll()
+LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr)
 {
-    ((ProcessWindows &)*m_process).OnUnloadDll();
+    ((ProcessWindows &)*m_process).OnUnloadDll(module_addr);
 }
 
 void
Index: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
@@ -20,15 +20,15 @@
 // Other libraries and framework includes
 #include "ForwardDecl.h"
 #include "IDebugDelegate.h"
+#include "lldb/lldb-forward.h"
 #include "lldb/Core/Error.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Target/Process.h"
 
 class ProcessMonitor;
 
 namespace lldb_private
 {
-class HostProcess;
 class ProcessWindowsData;
 }
 
@@ -116,20 +116,18 @@
 
     // IDebugDelegate overrides.
     virtual void OnExitProcess(uint32_t exit_code) override;
-    virtual void OnDebuggerConnected() override;
+    virtual void OnDebuggerConnected(lldb::addr_t image_base) override;
     virtual ExceptionResult OnDebugException(bool first_chance, const lldb_private::ExceptionRecord &record) override;
     virtual void OnCreateThread(const lldb_private::HostThread &thread) override;
     virtual void OnExitThread(const lldb_private::HostThread &thread) override;
-    virtual void OnLoadDll() override;
-    virtual void OnUnloadDll() override;
+    virtual void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override;
+    virtual void OnUnloadDll(lldb::addr_t module_addr) override;
     virtual void OnDebugString(const std::string &string) override;
     virtual void OnDebuggerError(const lldb_private::Error &error, uint32_t type) 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;
+    // Data for the active debugging session.
+    std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data;
 };
 
 #endif  // liblldb_Plugins_Process_Windows_ProcessWindows_H_
Index: lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
+++ lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
@@ -11,6 +11,8 @@
 #define liblldb_Plugins_Process_Windows_IDebugDelegate_H_
 
 #include "ForwardDecl.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
 #include <string>
 
 namespace lldb_private
@@ -30,12 +32,12 @@
     virtual ~IDebugDelegate() {}
 
     virtual void OnExitProcess(uint32_t exit_code) = 0;
-    virtual void OnDebuggerConnected() = 0;
+    virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0;
     virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) = 0;
     virtual void OnCreateThread(const HostThread &thread) = 0;
     virtual void OnExitThread(const HostThread &thread) = 0;
-    virtual void OnLoadDll() = 0;
-    virtual void OnUnloadDll() = 0;
+    virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) = 0;
+    virtual void OnUnloadDll(lldb::addr_t module_addr) = 0;
     virtual void OnDebugString(const std::string &string) = 0;
     virtual void OnDebuggerError(const Error &error, uint32_t type) = 0;
 };
Index: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
+++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
@@ -43,12 +43,12 @@
     explicit LocalDebugDelegate::LocalDebugDelegate(lldb::ProcessSP process);
 
     virtual void OnExitProcess(uint32_t exit_code) override;
-    virtual void OnDebuggerConnected() override;
+    virtual void OnDebuggerConnected(lldb::addr_t image_base) override;
     virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) override;
     virtual void OnCreateThread(const HostThread &thread) override;
     virtual void OnExitThread(const HostThread &thread) override;
-    virtual void OnLoadDll() override;
-    virtual void OnUnloadDll() override;
+    virtual void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override;
+    virtual void OnUnloadDll(lldb::addr_t module_addr) override;
     virtual void OnDebugString(const std::string &message) override;
     virtual void OnDebuggerError(const Error &error, uint32_t type) override;
 
Index: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
@@ -42,15 +42,22 @@
 class ProcessWindowsData
 {
   public:
-    ProcessWindowsData()
-        : m_launched_event(nullptr)
+    ProcessWindowsData(const ProcessLaunchInfo &launch_info)
+        : m_initial_stop_event(nullptr)
+        , m_launch_info(launch_info)
+        , m_initial_stop_received(false)
     {
-        m_launched_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+        m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
     }
 
-    ~ProcessWindowsData() { ::CloseHandle(m_launched_event); }
+    ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }
 
-    HANDLE m_launched_event;
+    ProcessLaunchInfo m_launch_info;
+    std::shared_ptr<lldb_private::ExceptionRecord> m_active_exception;
+    lldb_private::Error m_launch_error;
+    lldb_private::DebuggerThreadSP m_debugger;
+    HANDLE m_initial_stop_event;
+    bool m_initial_stop_received;
 };
 }
 //------------------------------------------------------------------------------
@@ -81,7 +88,6 @@
 
 ProcessWindows::ProcessWindows(Target &target, Listener &listener)
     : lldb_private::Process(target, listener)
-    , m_data_up(new ProcessWindowsData())
 {
 }
 
@@ -120,28 +126,36 @@
                          ProcessLaunchInfo &launch_info)
 {
     Error result;
-    HostProcess process;
+    if (!launch_info.GetFlags().Test(eLaunchFlagDebug))
+    {
+        result.SetErrorString("ProcessWindows can only be used to launch processes for debugging.");
+        return result;
+    }
+
+    m_session_data.reset(new ProcessWindowsData(launch_info));
+
     SetPrivateState(eStateLaunching);
-    if (launch_info.GetFlags().Test(eLaunchFlagDebug))
+    DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
+    m_session_data->m_debugger.reset(new DebuggerThread(delegate));
+    DebuggerThreadSP debugger = m_session_data->m_debugger;
+
+    // Kick off the DebugLaunch asynchronously and wait for it to complete.
+    result = debugger->DebugLaunch(launch_info);
+
+    HostProcess process;
+    if (result.Success())
     {
-        DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
-        m_debugger.reset(new DebuggerThread(delegate));
-        // Kick off the DebugLaunch asynchronously and wait for it to complete.
-        result = m_debugger->DebugLaunch(launch_info);
-        if (result.Success())
-        {
-            if (::WaitForSingleObject(m_data_up->m_launched_event, INFINITE) == WAIT_OBJECT_0)
-                process = m_debugger->GetProcess();
-            else
-                result.SetError(::GetLastError(), eErrorTypeWin32);
-        }
+        if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0)
+            process = debugger->GetProcess();
+        else
+            result.SetError(::GetLastError(), eErrorTypeWin32);
     }
-    else
-        return Host::LaunchProcess(launch_info);
 
     if (!result.Success())
         return result;
 
+    // We've hit the initial stop.  The private state should already be set to stopped as a result
+    // of encountering the breakpoint exception.
     launch_info.SetProcessID(process.GetProcessId());
     SetID(process.GetProcessId());
 
@@ -152,11 +166,17 @@
 ProcessWindows::DoResume()
 {
     Error error;
-    if (!m_active_exception)
-        return error;
+    if (GetPrivateState() == eStateStopped)
+    {
+        if (m_session_data->m_active_exception)
+        {
+            // Resume the process and continue processing debug events.
+            m_session_data->m_active_exception.reset();
+            m_session_data->m_debugger->ContinueAsyncException(ExceptionResult::Handled);
+        }
 
-    m_debugger->ContinueAsyncException(ExceptionResult::Handled);
-    SetPrivateState(eStateRunning);
+        SetPrivateState(eStateRunning);
+    }
     return error;
 }
 
@@ -197,15 +217,18 @@
 ProcessWindows::DoDetach(bool keep_stopped)
 {
     Error error;
-    error.SetErrorString("Detaching from processes is not currently supported on Windows.");
     return error;
 }
 
 Error
 ProcessWindows::DoDestroy()
 {
     Error error;
-    error.SetErrorString("Destroying processes is not currently supported on Windows.");
+    if (GetPrivateState() != eStateExited && GetPrivateState() != eStateDetached)
+    {
+        DebugActiveProcessStop(m_session_data->m_debugger->GetProcess().GetProcessId());
+        SetPrivateState(eStateExited);
+    }
     return error;
 }
 
@@ -217,7 +240,18 @@
 bool
 ProcessWindows::IsAlive()
 {
-    return false;
+    StateType state = GetPrivateState();
+    switch (state)
+    {
+        case eStateCrashed:
+        case eStateDetached:
+        case eStateUnloaded:
+        case eStateExited:
+        case eStateInvalid:
+            return false;
+        default:
+            return true;
+    }
 }
 
 size_t
@@ -250,23 +284,55 @@
 }
 
 void
-ProcessWindows::OnDebuggerConnected()
+ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base)
 {
-    ::SetEvent(m_data_up->m_launched_event);
+    ModuleSP module = GetTarget().GetExecutableModule();
+    bool load_addr_changed;
+    module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);
 }
 
 ExceptionResult
 ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &record)
 {
-    ExceptionResult result = ExceptionResult::Handled;
-    m_active_exception.reset(new ExceptionRecord(record));
+    ExceptionResult result = ExceptionResult::NotHandled;
+    m_session_data->m_active_exception.reset(new ExceptionRecord(record));
     switch (record.GetExceptionCode())
     {
         case EXCEPTION_BREAKPOINT:
-            SetPrivateState(eStateStopped);
+            // Handle breakpoints at the first chance.
             result = ExceptionResult::WillHandle;
+
+            if (!m_session_data->m_initial_stop_received)
+            {
+                m_session_data->m_initial_stop_received = true;
+                ::SetEvent(m_session_data->m_initial_stop_event);
+            }
             break;
+        default:
+            // For non-breakpoints, give the application a chance to handle the exception first.
+            if (first_chance)
+                result = ExceptionResult::NotHandled;
+            else
+                result = ExceptionResult::WillHandle;
     }
+
+    if (!first_chance)
+    {
+        // Any second chance exception is an application crash by definition.
+        SetPrivateState(eStateCrashed);
+    }
+    else if (result == ExceptionResult::WillHandle)
+    {
+        // For first chance exceptions that we can handle, the process is stopped so the user
+        // can inspect / manipulate the state of the process in 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;
 }
 
@@ -281,13 +347,21 @@
 }
 
 void
-ProcessWindows::OnLoadDll()
+ProcessWindows::OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr)
 {
+    // Confusingly, there is no Target::AddSharedModule.  Instead, calling GetSharedModule() with
+    // a new module will add it to the module list and return a corresponding ModuleSP.
+    Error error;
+    ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
+    bool load_addr_changed = false;
+    module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed);
 }
 
 void
-ProcessWindows::OnUnloadDll()
+ProcessWindows::OnUnloadDll(lldb::addr_t module_addr)
 {
+    // TODO: Figure out how to get the ModuleSP loaded at the specified address and remove
+    // it from the target's module list.
 }
 
 void
@@ -298,16 +372,15 @@
 void
 ProcessWindows::OnDebuggerError(const Error &error, uint32_t type)
 {
-    DWORD result = ::WaitForSingleObject(m_data_up->m_launched_event, 0);
-    if (result == WAIT_TIMEOUT)
+    if (!m_session_data->m_initial_stop_received)
     {
         // If we haven't actually launched the process yet, this was an error
         // launching the process.  Set the internal error and signal.
-        m_launch_error = error;
-        ::SetEvent(m_data_up->m_launched_event);
+        m_session_data->m_launch_error = error;
+        ::SetEvent(m_session_data->m_initial_stop_event);
         return;
     }
 
-    // This happened while debugging.
-    // TODO: Implement this.
+    // This happened while debugging.  Do we shutdown the debugging session, try to continue,
+    // or do something else?
 }
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to