[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