summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Windows')
-rw-r--r--lldb/source/Plugins/Process/Windows/DebuggerThread.cpp35
-rw-r--r--lldb/source/Plugins/Process/Windows/IDebugDelegate.h8
-rw-r--r--lldb/source/Plugins/Process/Windows/LocalDebugDelegate.cpp12
-rw-r--r--lldb/source/Plugins/Process/Windows/LocalDebugDelegate.h6
-rw-r--r--lldb/source/Plugins/Process/Windows/ProcessWindows.cpp155
-rw-r--r--lldb/source/Plugins/Process/Windows/ProcessWindows.h14
6 files changed, 167 insertions, 63 deletions
diff --git a/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp
index f67438c3127..ac191c40e06 100644
--- a/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp
+++ b/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp
@@ -13,6 +13,8 @@
#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"
@@ -21,6 +23,7 @@
#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 @@ DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info,
((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,7 +215,33 @@ DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWOR
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;
}
@@ -219,6 +249,7 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread
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;
}
diff --git a/lldb/source/Plugins/Process/Windows/IDebugDelegate.h b/lldb/source/Plugins/Process/Windows/IDebugDelegate.h
index 3e7b2167cb6..4efe1932919 100644
--- a/lldb/source/Plugins/Process/Windows/IDebugDelegate.h
+++ b/lldb/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 @@ class IDebugDelegate
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;
};
diff --git a/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.cpp b/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
index 51335ebd181..09bacf05ae9 100644
--- a/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
+++ b/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
@@ -25,9 +25,9 @@ LocalDebugDelegate::OnExitProcess(uint32_t exit_code)
}
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 @@ LocalDebugDelegate::OnExitThread(const HostThread &thread)
}
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
diff --git a/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.h b/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.h
index d5a15006d00..11fa1a82904 100644
--- a/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.h
+++ b/lldb/source/Plugins/Process/Windows/LocalDebugDelegate.h
@@ -43,12 +43,12 @@ class LocalDebugDelegate : public IDebugDelegate
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;
diff --git a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
index 829329a17b9..3c8e4a60010 100644
--- a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
@@ -42,15 +42,22 @@ namespace lldb_private
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::Initialize()
ProcessWindows::ProcessWindows(Target &target, Listener &listener)
: lldb_private::Process(target, listener)
- , m_data_up(new ProcessWindowsData())
{
}
@@ -120,28 +126,36 @@ ProcessWindows::DoLaunch(Module *exe_module,
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 @@ Error
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,7 +217,6 @@ Error
ProcessWindows::DoDetach(bool keep_stopped)
{
Error error;
- error.SetErrorString("Detaching from processes is not currently supported on Windows.");
return error;
}
@@ -205,7 +224,11 @@ 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 @@ ProcessWindows::RefreshStateAfterStop()
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 @@ ProcessWindows::OnExitProcess(uint32_t exit_code)
}
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 @@ ProcessWindows::OnExitThread(const HostThread &thread)
}
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 @@ ProcessWindows::OnDebugString(const std::string &string)
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?
}
diff --git a/lldb/source/Plugins/Process/Windows/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/ProcessWindows.h
index 7faf3a5d5ff..050539331df 100644
--- a/lldb/source/Plugins/Process/Windows/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/ProcessWindows.h
@@ -20,6 +20,7 @@
// 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"
@@ -28,7 +29,6 @@ class ProcessMonitor;
namespace lldb_private
{
-class HostProcess;
class ProcessWindowsData;
}
@@ -116,20 +116,18 @@ public:
// 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_
OpenPOWER on IntegriCloud