118a9135dSAdrian McCarthy //===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===//
218a9135dSAdrian McCarthy //
318a9135dSAdrian McCarthy //                     The LLVM Compiler Infrastructure
418a9135dSAdrian McCarthy //
518a9135dSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
618a9135dSAdrian McCarthy // License. See LICENSE.TXT for details.
718a9135dSAdrian McCarthy //
818a9135dSAdrian McCarthy //===----------------------------------------------------------------------===//
918a9135dSAdrian McCarthy 
1018a9135dSAdrian McCarthy #include "ProcessWindows.h"
1118a9135dSAdrian McCarthy 
124ad5def9SAdrian McCarthy // Windows includes
134ad5def9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
144ad5def9SAdrian McCarthy #include <psapi.h>
154ad5def9SAdrian McCarthy 
1618a9135dSAdrian McCarthy // Other libraries and framework includes
1718a9135dSAdrian McCarthy #include "lldb/Core/Module.h"
1818a9135dSAdrian McCarthy #include "lldb/Core/ModuleSpec.h"
1918a9135dSAdrian McCarthy #include "lldb/Core/PluginManager.h"
2018a9135dSAdrian McCarthy #include "lldb/Core/Section.h"
2118a9135dSAdrian McCarthy #include "lldb/Core/State.h"
224ad5def9SAdrian McCarthy #include "lldb/Host/HostNativeProcessBase.h"
234ad5def9SAdrian McCarthy #include "lldb/Host/HostProcess.h"
244ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h"
250c35cde9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
2618a9135dSAdrian McCarthy #include "lldb/Target/DynamicLoader.h"
2718a9135dSAdrian McCarthy #include "lldb/Target/MemoryRegionInfo.h"
284ad5def9SAdrian McCarthy #include "lldb/Target/StopInfo.h"
2918a9135dSAdrian McCarthy #include "lldb/Target/Target.h"
3018a9135dSAdrian McCarthy 
314ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h"
324ad5def9SAdrian McCarthy #include "llvm/Support/Format.h"
33*c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h"
344ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h"
354ad5def9SAdrian McCarthy 
364ad5def9SAdrian McCarthy #include "DebuggerThread.h"
374ad5def9SAdrian McCarthy #include "ExceptionRecord.h"
384ad5def9SAdrian McCarthy #include "ForwardDecl.h"
394ad5def9SAdrian McCarthy #include "LocalDebugDelegate.h"
404ad5def9SAdrian McCarthy #include "ProcessWindowsLog.h"
414ad5def9SAdrian McCarthy #include "TargetThreadWindows.h"
424ad5def9SAdrian McCarthy 
4318a9135dSAdrian McCarthy using namespace lldb;
4418a9135dSAdrian McCarthy using namespace lldb_private;
4518a9135dSAdrian McCarthy 
464ad5def9SAdrian McCarthy namespace {
474ad5def9SAdrian McCarthy std::string GetProcessExecutableName(HANDLE process_handle) {
484ad5def9SAdrian McCarthy   std::vector<wchar_t> file_name;
494ad5def9SAdrian McCarthy   DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
504ad5def9SAdrian McCarthy   DWORD copied = 0;
514ad5def9SAdrian McCarthy   do {
524ad5def9SAdrian McCarthy     file_name_size *= 2;
534ad5def9SAdrian McCarthy     file_name.resize(file_name_size);
544ad5def9SAdrian McCarthy     copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
554ad5def9SAdrian McCarthy                                     file_name_size);
564ad5def9SAdrian McCarthy   } while (copied >= file_name_size);
574ad5def9SAdrian McCarthy   file_name.resize(copied);
584ad5def9SAdrian McCarthy   std::string result;
594ad5def9SAdrian McCarthy   llvm::convertWideToUTF8(file_name.data(), result);
604ad5def9SAdrian McCarthy   return result;
614ad5def9SAdrian McCarthy }
624ad5def9SAdrian McCarthy 
634ad5def9SAdrian McCarthy std::string GetProcessExecutableName(DWORD pid) {
644ad5def9SAdrian McCarthy   std::string file_name;
654ad5def9SAdrian McCarthy   HANDLE process_handle =
664ad5def9SAdrian McCarthy       ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
674ad5def9SAdrian McCarthy   if (process_handle != NULL) {
684ad5def9SAdrian McCarthy     file_name = GetProcessExecutableName(process_handle);
694ad5def9SAdrian McCarthy     ::CloseHandle(process_handle);
704ad5def9SAdrian McCarthy   }
714ad5def9SAdrian McCarthy   return file_name;
724ad5def9SAdrian McCarthy }
734ad5def9SAdrian McCarthy 
744ad5def9SAdrian McCarthy } // anonymous namespace
754ad5def9SAdrian McCarthy 
76b9c1b51eSKate Stone namespace lldb_private {
7718a9135dSAdrian McCarthy 
784ad5def9SAdrian McCarthy // We store a pointer to this class in the ProcessWindows, so that we don't
794ad5def9SAdrian McCarthy // expose Windows-specific types and implementation details from a public header
804ad5def9SAdrian McCarthy // file.
814ad5def9SAdrian McCarthy class ProcessWindowsData {
824ad5def9SAdrian McCarthy public:
834ad5def9SAdrian McCarthy   ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) {
844ad5def9SAdrian McCarthy     m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
854ad5def9SAdrian McCarthy   }
864ad5def9SAdrian McCarthy 
874ad5def9SAdrian McCarthy   ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }
884ad5def9SAdrian McCarthy 
894ad5def9SAdrian McCarthy   Error m_launch_error;
904ad5def9SAdrian McCarthy   DebuggerThreadSP m_debugger;
914ad5def9SAdrian McCarthy   StopInfoSP m_pending_stop_info;
924ad5def9SAdrian McCarthy   HANDLE m_initial_stop_event = nullptr;
934ad5def9SAdrian McCarthy   bool m_initial_stop_received = false;
944ad5def9SAdrian McCarthy   bool m_stop_at_entry;
954ad5def9SAdrian McCarthy   std::map<lldb::tid_t, HostThread> m_new_threads;
964ad5def9SAdrian McCarthy   std::set<lldb::tid_t> m_exited_threads;
974ad5def9SAdrian McCarthy };
984ad5def9SAdrian McCarthy 
994ad5def9SAdrian McCarthy ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,
1004ad5def9SAdrian McCarthy                                          lldb::ListenerSP listener_sp,
1014ad5def9SAdrian McCarthy                                          const FileSpec *) {
1024ad5def9SAdrian McCarthy   return ProcessSP(new ProcessWindows(target_sp, listener_sp));
1034ad5def9SAdrian McCarthy }
1044ad5def9SAdrian McCarthy 
1054ad5def9SAdrian McCarthy void ProcessWindows::Initialize() {
106*c5f28e2aSKamil Rytarowski   static llvm::once_flag g_once_flag;
1074ad5def9SAdrian McCarthy 
108*c5f28e2aSKamil Rytarowski   llvm::call_once(g_once_flag, []() {
1094ad5def9SAdrian McCarthy     PluginManager::RegisterPlugin(GetPluginNameStatic(),
1104ad5def9SAdrian McCarthy                                   GetPluginDescriptionStatic(), CreateInstance);
1114ad5def9SAdrian McCarthy   });
1124ad5def9SAdrian McCarthy }
1134ad5def9SAdrian McCarthy 
1144ad5def9SAdrian McCarthy void ProcessWindows::Terminate() {}
1154ad5def9SAdrian McCarthy 
1164ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginNameStatic() {
1174ad5def9SAdrian McCarthy   static ConstString g_name("windows");
1184ad5def9SAdrian McCarthy   return g_name;
1194ad5def9SAdrian McCarthy }
1204ad5def9SAdrian McCarthy 
1214ad5def9SAdrian McCarthy const char *ProcessWindows::GetPluginDescriptionStatic() {
1224ad5def9SAdrian McCarthy   return "Process plugin for Windows";
1234ad5def9SAdrian McCarthy }
1244ad5def9SAdrian McCarthy 
12518a9135dSAdrian McCarthy //------------------------------------------------------------------------------
12618a9135dSAdrian McCarthy // Constructors and destructors.
12718a9135dSAdrian McCarthy 
128b9c1b51eSKate Stone ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
129b9c1b51eSKate Stone                                lldb::ListenerSP listener_sp)
130b9c1b51eSKate Stone     : lldb_private::Process(target_sp, listener_sp) {}
13118a9135dSAdrian McCarthy 
132b9c1b51eSKate Stone ProcessWindows::~ProcessWindows() {}
13318a9135dSAdrian McCarthy 
134b9c1b51eSKate Stone size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) {
13518a9135dSAdrian McCarthy   error.SetErrorString("GetSTDOUT unsupported on Windows");
13618a9135dSAdrian McCarthy   return 0;
13718a9135dSAdrian McCarthy }
13818a9135dSAdrian McCarthy 
139b9c1b51eSKate Stone size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) {
14018a9135dSAdrian McCarthy   error.SetErrorString("GetSTDERR unsupported on Windows");
14118a9135dSAdrian McCarthy   return 0;
14218a9135dSAdrian McCarthy }
14318a9135dSAdrian McCarthy 
144b9c1b51eSKate Stone size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
145b9c1b51eSKate Stone                                 Error &error) {
14618a9135dSAdrian McCarthy   error.SetErrorString("PutSTDIN unsupported on Windows");
14718a9135dSAdrian McCarthy   return 0;
14818a9135dSAdrian McCarthy }
14918a9135dSAdrian McCarthy 
15018a9135dSAdrian McCarthy //------------------------------------------------------------------------------
15118a9135dSAdrian McCarthy // ProcessInterface protocol.
15218a9135dSAdrian McCarthy 
1534ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginName() {
1544ad5def9SAdrian McCarthy   return GetPluginNameStatic();
1554ad5def9SAdrian McCarthy }
1564ad5def9SAdrian McCarthy 
1574ad5def9SAdrian McCarthy uint32_t ProcessWindows::GetPluginVersion() { return 1; }
1584ad5def9SAdrian McCarthy 
1594ad5def9SAdrian McCarthy Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
1604ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
1614ad5def9SAdrian McCarthy                "EnableBreakpointSite called with bp_site 0x%p "
1624ad5def9SAdrian McCarthy                "(id=%d, addr=0x%llx)",
1634ad5def9SAdrian McCarthy                bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
1644ad5def9SAdrian McCarthy 
1654ad5def9SAdrian McCarthy   Error error = EnableSoftwareBreakpoint(bp_site);
1664ad5def9SAdrian McCarthy   if (!error.Success()) {
1674ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed.  %s",
1684ad5def9SAdrian McCarthy                  error.AsCString());
1694ad5def9SAdrian McCarthy   }
1704ad5def9SAdrian McCarthy   return error;
1714ad5def9SAdrian McCarthy }
1724ad5def9SAdrian McCarthy 
1734ad5def9SAdrian McCarthy Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {
1744ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
1754ad5def9SAdrian McCarthy                "DisableBreakpointSite called with bp_site 0x%p "
1764ad5def9SAdrian McCarthy                "(id=%d, addr=0x%llx)",
1774ad5def9SAdrian McCarthy                bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
1784ad5def9SAdrian McCarthy 
1794ad5def9SAdrian McCarthy   Error error = DisableSoftwareBreakpoint(bp_site);
1804ad5def9SAdrian McCarthy 
1814ad5def9SAdrian McCarthy   if (!error.Success()) {
1824ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed.  %s",
1834ad5def9SAdrian McCarthy                  error.AsCString());
1844ad5def9SAdrian McCarthy   }
1854ad5def9SAdrian McCarthy   return error;
1864ad5def9SAdrian McCarthy }
1874ad5def9SAdrian McCarthy 
1884ad5def9SAdrian McCarthy Error ProcessWindows::DoDetach(bool keep_stopped) {
1894ad5def9SAdrian McCarthy   DebuggerThreadSP debugger_thread;
1904ad5def9SAdrian McCarthy   StateType private_state;
1914ad5def9SAdrian McCarthy   {
1924ad5def9SAdrian McCarthy     // Acquire the lock only long enough to get the DebuggerThread.
1934ad5def9SAdrian McCarthy     // StopDebugging() will trigger a call back into ProcessWindows which
1944ad5def9SAdrian McCarthy     // will also acquire the lock.  Thus we have to release the lock before
1954ad5def9SAdrian McCarthy     // calling StopDebugging().
1964ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
1974ad5def9SAdrian McCarthy 
1984ad5def9SAdrian McCarthy     private_state = GetPrivateState();
1994ad5def9SAdrian McCarthy 
2004ad5def9SAdrian McCarthy     if (!m_session_data) {
2014ad5def9SAdrian McCarthy       WINWARN_IFALL(
2024ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
2034ad5def9SAdrian McCarthy           "DoDetach called while state = %u, but there is no active session.",
2044ad5def9SAdrian McCarthy           private_state);
2054ad5def9SAdrian McCarthy       return Error();
2064ad5def9SAdrian McCarthy     }
2074ad5def9SAdrian McCarthy 
2084ad5def9SAdrian McCarthy     debugger_thread = m_session_data->m_debugger;
2094ad5def9SAdrian McCarthy   }
2104ad5def9SAdrian McCarthy 
2114ad5def9SAdrian McCarthy   Error error;
2124ad5def9SAdrian McCarthy   if (private_state != eStateExited && private_state != eStateDetached) {
2134ad5def9SAdrian McCarthy     WINLOG_IFALL(
2144ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
2154ad5def9SAdrian McCarthy         "DoDetach called for process %p while state = %d.  Detaching...",
2164ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
2174ad5def9SAdrian McCarthy         private_state);
2184ad5def9SAdrian McCarthy     error = debugger_thread->StopDebugging(false);
2194ad5def9SAdrian McCarthy     if (error.Success()) {
2204ad5def9SAdrian McCarthy       SetPrivateState(eStateDetached);
2214ad5def9SAdrian McCarthy     }
2224ad5def9SAdrian McCarthy 
2234ad5def9SAdrian McCarthy     // By the time StopDebugging returns, there is no more debugger thread, so
2244ad5def9SAdrian McCarthy     // we can be assured that no other thread will race for the session data.
2254ad5def9SAdrian McCarthy     m_session_data.reset();
2264ad5def9SAdrian McCarthy   } else {
2274ad5def9SAdrian McCarthy     WINERR_IFALL(
2284ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDetach called for process %p while state = "
2294ad5def9SAdrian McCarthy                              "%d, but cannot destroy in this state.",
2304ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
2314ad5def9SAdrian McCarthy         private_state);
2324ad5def9SAdrian McCarthy   }
2334ad5def9SAdrian McCarthy 
2344ad5def9SAdrian McCarthy   return error;
2354ad5def9SAdrian McCarthy }
2364ad5def9SAdrian McCarthy 
2374ad5def9SAdrian McCarthy Error ProcessWindows::DoLaunch(Module *exe_module,
2384ad5def9SAdrian McCarthy                                ProcessLaunchInfo &launch_info) {
2394ad5def9SAdrian McCarthy   // Even though m_session_data is accessed here, it is before a debugger thread
2404ad5def9SAdrian McCarthy   // has been
2414ad5def9SAdrian McCarthy   // kicked off.  So there's no race conditions, and it shouldn't be necessary
2424ad5def9SAdrian McCarthy   // to acquire
2434ad5def9SAdrian McCarthy   // the mutex.
2444ad5def9SAdrian McCarthy 
2454ad5def9SAdrian McCarthy   Error result;
2464ad5def9SAdrian McCarthy   if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
2474ad5def9SAdrian McCarthy     StreamString stream;
2484ad5def9SAdrian McCarthy     stream.Printf("ProcessWindows unable to launch '%s'.  ProcessWindows can "
2494ad5def9SAdrian McCarthy                   "only be used for debug launches.",
2504ad5def9SAdrian McCarthy                   launch_info.GetExecutableFile().GetPath().c_str());
2514ad5def9SAdrian McCarthy     std::string message = stream.GetString();
2524ad5def9SAdrian McCarthy     result.SetErrorString(message.c_str());
2534ad5def9SAdrian McCarthy 
2544ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "%s", message.c_str());
2554ad5def9SAdrian McCarthy     return result;
2564ad5def9SAdrian McCarthy   }
2574ad5def9SAdrian McCarthy 
2584ad5def9SAdrian McCarthy   bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
2594ad5def9SAdrian McCarthy   m_session_data.reset(new ProcessWindowsData(stop_at_entry));
2604ad5def9SAdrian McCarthy 
2614ad5def9SAdrian McCarthy   SetPrivateState(eStateLaunching);
2624ad5def9SAdrian McCarthy   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
2634ad5def9SAdrian McCarthy   m_session_data->m_debugger.reset(new DebuggerThread(delegate));
2644ad5def9SAdrian McCarthy   DebuggerThreadSP debugger = m_session_data->m_debugger;
2654ad5def9SAdrian McCarthy 
2664ad5def9SAdrian McCarthy   // Kick off the DebugLaunch asynchronously and wait for it to complete.
2674ad5def9SAdrian McCarthy   result = debugger->DebugLaunch(launch_info);
2684ad5def9SAdrian McCarthy   if (result.Fail()) {
2694ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
2704ad5def9SAdrian McCarthy                  launch_info.GetExecutableFile().GetPath().c_str(),
2714ad5def9SAdrian McCarthy                  result.AsCString());
2724ad5def9SAdrian McCarthy     return result;
2734ad5def9SAdrian McCarthy   }
2744ad5def9SAdrian McCarthy 
2754ad5def9SAdrian McCarthy   HostProcess process;
2764ad5def9SAdrian McCarthy   Error error = WaitForDebuggerConnection(debugger, process);
2774ad5def9SAdrian McCarthy   if (error.Fail()) {
2784ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
2794ad5def9SAdrian McCarthy                  launch_info.GetExecutableFile().GetPath().c_str(),
2804ad5def9SAdrian McCarthy                  error.AsCString());
2814ad5def9SAdrian McCarthy     return error;
2824ad5def9SAdrian McCarthy   }
2834ad5def9SAdrian McCarthy 
2844ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'",
2854ad5def9SAdrian McCarthy                launch_info.GetExecutableFile().GetPath().c_str());
2864ad5def9SAdrian McCarthy 
2874ad5def9SAdrian McCarthy   // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
2884ad5def9SAdrian McCarthy   // private state
2894ad5def9SAdrian McCarthy   // should already be set to eStateStopped as a result of hitting the initial
2904ad5def9SAdrian McCarthy   // breakpoint.  If
2914ad5def9SAdrian McCarthy   // it was not set, the breakpoint should have already been resumed from and
2924ad5def9SAdrian McCarthy   // the private state
2934ad5def9SAdrian McCarthy   // should already be eStateRunning.
2944ad5def9SAdrian McCarthy   launch_info.SetProcessID(process.GetProcessId());
2954ad5def9SAdrian McCarthy   SetID(process.GetProcessId());
2964ad5def9SAdrian McCarthy 
2974ad5def9SAdrian McCarthy   return result;
2984ad5def9SAdrian McCarthy }
2994ad5def9SAdrian McCarthy 
3004ad5def9SAdrian McCarthy Error ProcessWindows::DoAttachToProcessWithID(
3014ad5def9SAdrian McCarthy     lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
3024ad5def9SAdrian McCarthy   m_session_data.reset(
3034ad5def9SAdrian McCarthy       new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
3044ad5def9SAdrian McCarthy 
3054ad5def9SAdrian McCarthy   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
3064ad5def9SAdrian McCarthy   DebuggerThreadSP debugger(new DebuggerThread(delegate));
3074ad5def9SAdrian McCarthy 
3084ad5def9SAdrian McCarthy   m_session_data->m_debugger = debugger;
3094ad5def9SAdrian McCarthy 
3104ad5def9SAdrian McCarthy   DWORD process_id = static_cast<DWORD>(pid);
3114ad5def9SAdrian McCarthy   Error error = debugger->DebugAttach(process_id, attach_info);
3124ad5def9SAdrian McCarthy   if (error.Fail()) {
3134ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
3144ad5def9SAdrian McCarthy                                       "error occurred initiating the "
3154ad5def9SAdrian McCarthy                                       "asynchronous attach.  %s",
3164ad5def9SAdrian McCarthy                  error.AsCString());
3174ad5def9SAdrian McCarthy     return error;
3184ad5def9SAdrian McCarthy   }
3194ad5def9SAdrian McCarthy 
3204ad5def9SAdrian McCarthy   HostProcess process;
3214ad5def9SAdrian McCarthy   error = WaitForDebuggerConnection(debugger, process);
3224ad5def9SAdrian McCarthy   if (error.Fail()) {
3234ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
3244ad5def9SAdrian McCarthy                                       "error waiting for the debugger to "
3254ad5def9SAdrian McCarthy                                       "connect.  %s",
3264ad5def9SAdrian McCarthy                  error.AsCString());
3274ad5def9SAdrian McCarthy     return error;
3284ad5def9SAdrian McCarthy   }
3294ad5def9SAdrian McCarthy 
3304ad5def9SAdrian McCarthy   WINLOG_IFALL(
3314ad5def9SAdrian McCarthy       WINDOWS_LOG_PROCESS,
3324ad5def9SAdrian McCarthy       "DoAttachToProcessWithID successfully attached to process with pid=%lu",
3334ad5def9SAdrian McCarthy       process_id);
3344ad5def9SAdrian McCarthy 
3354ad5def9SAdrian McCarthy   // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
3364ad5def9SAdrian McCarthy   // private state
3374ad5def9SAdrian McCarthy   // should already be set to eStateStopped as a result of hitting the initial
3384ad5def9SAdrian McCarthy   // breakpoint.  If
3394ad5def9SAdrian McCarthy   // it was not set, the breakpoint should have already been resumed from and
3404ad5def9SAdrian McCarthy   // the private state
3414ad5def9SAdrian McCarthy   // should already be eStateRunning.
3424ad5def9SAdrian McCarthy   SetID(process.GetProcessId());
3434ad5def9SAdrian McCarthy   return error;
3444ad5def9SAdrian McCarthy }
3454ad5def9SAdrian McCarthy 
3464ad5def9SAdrian McCarthy Error ProcessWindows::DoResume() {
3474ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
3484ad5def9SAdrian McCarthy   Error error;
3494ad5def9SAdrian McCarthy 
3504ad5def9SAdrian McCarthy   StateType private_state = GetPrivateState();
3514ad5def9SAdrian McCarthy   if (private_state == eStateStopped || private_state == eStateCrashed) {
3524ad5def9SAdrian McCarthy     WINLOG_IFALL(
3534ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
3544ad5def9SAdrian McCarthy         "DoResume called for process %I64u while state is %u.  Resuming...",
3554ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId(),
3564ad5def9SAdrian McCarthy         GetPrivateState());
3574ad5def9SAdrian McCarthy 
3584ad5def9SAdrian McCarthy     ExceptionRecordSP active_exception =
3594ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetActiveException().lock();
3604ad5def9SAdrian McCarthy     if (active_exception) {
3614ad5def9SAdrian McCarthy       // Resume the process and continue processing debug events.  Mask
3624ad5def9SAdrian McCarthy       // the exception so that from the process's view, there is no
3634ad5def9SAdrian McCarthy       // indication that anything happened.
3644ad5def9SAdrian McCarthy       m_session_data->m_debugger->ContinueAsyncException(
3654ad5def9SAdrian McCarthy           ExceptionResult::MaskException);
3664ad5def9SAdrian McCarthy     }
3674ad5def9SAdrian McCarthy 
3684ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD,
3694ad5def9SAdrian McCarthy                  "DoResume resuming %u threads.", m_thread_list.GetSize());
3704ad5def9SAdrian McCarthy 
3714ad5def9SAdrian McCarthy     for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
3724ad5def9SAdrian McCarthy       auto thread = std::static_pointer_cast<TargetThreadWindows>(
3734ad5def9SAdrian McCarthy           m_thread_list.GetThreadAtIndex(i));
3744ad5def9SAdrian McCarthy       thread->DoResume();
3754ad5def9SAdrian McCarthy     }
3764ad5def9SAdrian McCarthy 
3774ad5def9SAdrian McCarthy     SetPrivateState(eStateRunning);
3784ad5def9SAdrian McCarthy   } else {
3794ad5def9SAdrian McCarthy     WINERR_IFALL(
3804ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
3814ad5def9SAdrian McCarthy         "DoResume called for process %I64u but state is %u.  Returning...",
3824ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId(),
3834ad5def9SAdrian McCarthy         GetPrivateState());
3844ad5def9SAdrian McCarthy   }
3854ad5def9SAdrian McCarthy   return error;
3864ad5def9SAdrian McCarthy }
3874ad5def9SAdrian McCarthy 
3884ad5def9SAdrian McCarthy Error ProcessWindows::DoDestroy() {
3894ad5def9SAdrian McCarthy   DebuggerThreadSP debugger_thread;
3904ad5def9SAdrian McCarthy   StateType private_state;
3914ad5def9SAdrian McCarthy   {
3924ad5def9SAdrian McCarthy     // Acquire this lock inside an inner scope, only long enough to get the
3934ad5def9SAdrian McCarthy     // DebuggerThread.
3944ad5def9SAdrian McCarthy     // StopDebugging() will trigger a call back into ProcessWindows which will
3954ad5def9SAdrian McCarthy     // acquire the lock
3964ad5def9SAdrian McCarthy     // again, so we need to not deadlock.
3974ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
3984ad5def9SAdrian McCarthy 
3994ad5def9SAdrian McCarthy     private_state = GetPrivateState();
4004ad5def9SAdrian McCarthy 
4014ad5def9SAdrian McCarthy     if (!m_session_data) {
4024ad5def9SAdrian McCarthy       WINWARN_IFALL(
4034ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
4044ad5def9SAdrian McCarthy           "DoDestroy called while state = %u, but there is no active session.",
4054ad5def9SAdrian McCarthy           private_state);
4064ad5def9SAdrian McCarthy       return Error();
4074ad5def9SAdrian McCarthy     }
4084ad5def9SAdrian McCarthy 
4094ad5def9SAdrian McCarthy     debugger_thread = m_session_data->m_debugger;
4104ad5def9SAdrian McCarthy   }
4114ad5def9SAdrian McCarthy 
4124ad5def9SAdrian McCarthy   Error error;
4134ad5def9SAdrian McCarthy   if (private_state != eStateExited && private_state != eStateDetached) {
4144ad5def9SAdrian McCarthy     WINLOG_IFALL(
4154ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
4164ad5def9SAdrian McCarthy                              "%u.  Shutting down...",
4174ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
4184ad5def9SAdrian McCarthy         private_state);
4194ad5def9SAdrian McCarthy     error = debugger_thread->StopDebugging(true);
4204ad5def9SAdrian McCarthy 
4214ad5def9SAdrian McCarthy     // By the time StopDebugging returns, there is no more debugger thread, so
4224ad5def9SAdrian McCarthy     // we can be assured that no other thread will race for the session data.
4234ad5def9SAdrian McCarthy     m_session_data.reset();
4244ad5def9SAdrian McCarthy   } else {
4254ad5def9SAdrian McCarthy     WINERR_IFALL(
4264ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
4274ad5def9SAdrian McCarthy                              "%d, but cannot destroy in this state.",
4284ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
4294ad5def9SAdrian McCarthy         private_state);
4304ad5def9SAdrian McCarthy   }
4314ad5def9SAdrian McCarthy 
4324ad5def9SAdrian McCarthy   return error;
4334ad5def9SAdrian McCarthy }
4344ad5def9SAdrian McCarthy 
4354ad5def9SAdrian McCarthy Error ProcessWindows::DoHalt(bool &caused_stop) {
4364ad5def9SAdrian McCarthy   Error error;
4374ad5def9SAdrian McCarthy   StateType state = GetPrivateState();
4384ad5def9SAdrian McCarthy   if (state == eStateStopped)
4394ad5def9SAdrian McCarthy     caused_stop = false;
4404ad5def9SAdrian McCarthy   else {
4414ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
4424ad5def9SAdrian McCarthy     caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
4434ad5def9SAdrian McCarthy                                           .GetNativeProcess()
4444ad5def9SAdrian McCarthy                                           .GetSystemHandle());
4454ad5def9SAdrian McCarthy     if (!caused_stop) {
4464ad5def9SAdrian McCarthy       error.SetError(::GetLastError(), eErrorTypeWin32);
4474ad5def9SAdrian McCarthy       WINERR_IFALL(
4484ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
4494ad5def9SAdrian McCarthy           "DoHalt called DebugBreakProcess, but it failed with error %u",
4504ad5def9SAdrian McCarthy           error.GetError());
4514ad5def9SAdrian McCarthy     }
4524ad5def9SAdrian McCarthy   }
4534ad5def9SAdrian McCarthy   return error;
4544ad5def9SAdrian McCarthy }
4554ad5def9SAdrian McCarthy 
4564ad5def9SAdrian McCarthy void ProcessWindows::DidLaunch() {
4574ad5def9SAdrian McCarthy   ArchSpec arch_spec;
4584ad5def9SAdrian McCarthy   DidAttach(arch_spec);
4594ad5def9SAdrian McCarthy }
4604ad5def9SAdrian McCarthy 
4614ad5def9SAdrian McCarthy void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
4624ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
4634ad5def9SAdrian McCarthy 
4644ad5def9SAdrian McCarthy   // The initial stop won't broadcast the state change event, so account for
4654ad5def9SAdrian McCarthy   // that here.
4664ad5def9SAdrian McCarthy   if (m_session_data && GetPrivateState() == eStateStopped &&
4674ad5def9SAdrian McCarthy       m_session_data->m_stop_at_entry)
4684ad5def9SAdrian McCarthy     RefreshStateAfterStop();
4694ad5def9SAdrian McCarthy }
4704ad5def9SAdrian McCarthy 
4714ad5def9SAdrian McCarthy void ProcessWindows::RefreshStateAfterStop() {
4724ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
4734ad5def9SAdrian McCarthy 
4744ad5def9SAdrian McCarthy   if (!m_session_data) {
4754ad5def9SAdrian McCarthy     WINWARN_IFALL(
4764ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
4774ad5def9SAdrian McCarthy         "RefreshStateAfterStop called with no active session.  Returning...");
4784ad5def9SAdrian McCarthy     return;
4794ad5def9SAdrian McCarthy   }
4804ad5def9SAdrian McCarthy 
4814ad5def9SAdrian McCarthy   m_thread_list.RefreshStateAfterStop();
4824ad5def9SAdrian McCarthy 
4834ad5def9SAdrian McCarthy   std::weak_ptr<ExceptionRecord> exception_record =
4844ad5def9SAdrian McCarthy       m_session_data->m_debugger->GetActiveException();
4854ad5def9SAdrian McCarthy   ExceptionRecordSP active_exception = exception_record.lock();
4864ad5def9SAdrian McCarthy   if (!active_exception) {
4874ad5def9SAdrian McCarthy     WINERR_IFALL(
4884ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
4894ad5def9SAdrian McCarthy         "RefreshStateAfterStop called for process %I64u but there is no "
4904ad5def9SAdrian McCarthy         "active exception.  Why is the process stopped?",
4914ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId());
4924ad5def9SAdrian McCarthy     return;
4934ad5def9SAdrian McCarthy   }
4944ad5def9SAdrian McCarthy 
4954ad5def9SAdrian McCarthy   StopInfoSP stop_info;
4964ad5def9SAdrian McCarthy   m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
4974ad5def9SAdrian McCarthy   ThreadSP stop_thread = m_thread_list.GetSelectedThread();
4984ad5def9SAdrian McCarthy   if (!stop_thread)
4994ad5def9SAdrian McCarthy     return;
5004ad5def9SAdrian McCarthy 
5014ad5def9SAdrian McCarthy   switch (active_exception->GetExceptionCode()) {
5024ad5def9SAdrian McCarthy   case EXCEPTION_SINGLE_STEP: {
5034ad5def9SAdrian McCarthy     RegisterContextSP register_context = stop_thread->GetRegisterContext();
5044ad5def9SAdrian McCarthy     const uint64_t pc = register_context->GetPC();
5054ad5def9SAdrian McCarthy     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
5064ad5def9SAdrian McCarthy     if (site && site->ValidForThisThread(stop_thread.get())) {
5074ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION |
5084ad5def9SAdrian McCarthy                        WINDOWS_LOG_STEP,
5094ad5def9SAdrian McCarthy                    "Single-stepped onto a breakpoint in process %I64u at "
5104ad5def9SAdrian McCarthy                    "address 0x%I64x with breakpoint site %d",
5114ad5def9SAdrian McCarthy                    m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
5124ad5def9SAdrian McCarthy                    site->GetID());
5134ad5def9SAdrian McCarthy       stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
5144ad5def9SAdrian McCarthy                                                                  site->GetID());
5154ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
5164ad5def9SAdrian McCarthy     } else {
5174ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP,
5184ad5def9SAdrian McCarthy                    "RefreshStateAfterStop single stepping thread %llu",
5194ad5def9SAdrian McCarthy                    stop_thread->GetID());
5204ad5def9SAdrian McCarthy       stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
5214ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
5224ad5def9SAdrian McCarthy     }
5234ad5def9SAdrian McCarthy     return;
5244ad5def9SAdrian McCarthy   }
5254ad5def9SAdrian McCarthy 
5264ad5def9SAdrian McCarthy   case EXCEPTION_BREAKPOINT: {
5274ad5def9SAdrian McCarthy     RegisterContextSP register_context = stop_thread->GetRegisterContext();
5284ad5def9SAdrian McCarthy 
5294ad5def9SAdrian McCarthy     // The current EIP is AFTER the BP opcode, which is one byte.
5304ad5def9SAdrian McCarthy     uint64_t pc = register_context->GetPC() - 1;
5314ad5def9SAdrian McCarthy 
5324ad5def9SAdrian McCarthy     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
5334ad5def9SAdrian McCarthy     if (site) {
5344ad5def9SAdrian McCarthy       WINLOG_IFANY(
5354ad5def9SAdrian McCarthy           WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
5364ad5def9SAdrian McCarthy           "RefreshStateAfterStop detected breakpoint in process %I64u at "
5374ad5def9SAdrian McCarthy           "address 0x%I64x with breakpoint site %d",
5384ad5def9SAdrian McCarthy           m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
5394ad5def9SAdrian McCarthy           site->GetID());
5404ad5def9SAdrian McCarthy 
5414ad5def9SAdrian McCarthy       if (site->ValidForThisThread(stop_thread.get())) {
5424ad5def9SAdrian McCarthy         WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
5434ad5def9SAdrian McCarthy                      "Breakpoint site %d is valid for this thread (0x%I64x), "
5444ad5def9SAdrian McCarthy                      "creating stop info.",
5454ad5def9SAdrian McCarthy                      site->GetID(), stop_thread->GetID());
5464ad5def9SAdrian McCarthy 
5474ad5def9SAdrian McCarthy         stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
5484ad5def9SAdrian McCarthy             *stop_thread, site->GetID());
5494ad5def9SAdrian McCarthy         register_context->SetPC(pc);
5504ad5def9SAdrian McCarthy       } else {
5514ad5def9SAdrian McCarthy         WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
5524ad5def9SAdrian McCarthy                      "Breakpoint site %d is not valid for this thread, "
5534ad5def9SAdrian McCarthy                      "creating empty stop info.",
5544ad5def9SAdrian McCarthy                      site->GetID());
5554ad5def9SAdrian McCarthy       }
5564ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
5574ad5def9SAdrian McCarthy       return;
5584ad5def9SAdrian McCarthy     } else {
5594ad5def9SAdrian McCarthy       // The thread hit a hard-coded breakpoint like an `int 3` or
5604ad5def9SAdrian McCarthy       // `__debugbreak()`.
5614ad5def9SAdrian McCarthy       WINLOG_IFALL(
5624ad5def9SAdrian McCarthy           WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
5634ad5def9SAdrian McCarthy           "No breakpoint site matches for this thread. __debugbreak()?  "
5644ad5def9SAdrian McCarthy           "Creating stop info with the exception.");
5654ad5def9SAdrian McCarthy       // FALLTHROUGH:  We'll treat this as a generic exception record in the
5664ad5def9SAdrian McCarthy       // default case.
5674ad5def9SAdrian McCarthy     }
5684ad5def9SAdrian McCarthy   }
5694ad5def9SAdrian McCarthy 
5704ad5def9SAdrian McCarthy   default: {
5714ad5def9SAdrian McCarthy     std::string desc;
5724ad5def9SAdrian McCarthy     llvm::raw_string_ostream desc_stream(desc);
5734ad5def9SAdrian McCarthy     desc_stream << "Exception "
5744ad5def9SAdrian McCarthy                 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
5754ad5def9SAdrian McCarthy                 << " encountered at address "
5764ad5def9SAdrian McCarthy                 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
5774ad5def9SAdrian McCarthy     stop_info = StopInfo::CreateStopReasonWithException(
5784ad5def9SAdrian McCarthy         *stop_thread, desc_stream.str().c_str());
5794ad5def9SAdrian McCarthy     stop_thread->SetStopInfo(stop_info);
5804ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, "%s", desc_stream.str().c_str());
5814ad5def9SAdrian McCarthy     return;
5824ad5def9SAdrian McCarthy   }
5834ad5def9SAdrian McCarthy   }
5844ad5def9SAdrian McCarthy }
5854ad5def9SAdrian McCarthy 
5864ad5def9SAdrian McCarthy bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
5874ad5def9SAdrian McCarthy                               bool plugin_specified_by_name) {
5884ad5def9SAdrian McCarthy   if (plugin_specified_by_name)
5894ad5def9SAdrian McCarthy     return true;
5904ad5def9SAdrian McCarthy 
5914ad5def9SAdrian McCarthy   // For now we are just making sure the file exists for a given module
5924ad5def9SAdrian McCarthy   ModuleSP exe_module_sp(target_sp->GetExecutableModule());
5934ad5def9SAdrian McCarthy   if (exe_module_sp.get())
5944ad5def9SAdrian McCarthy     return exe_module_sp->GetFileSpec().Exists();
5954ad5def9SAdrian McCarthy   // However, if there is no executable module, we return true since we might be
5964ad5def9SAdrian McCarthy   // preparing to attach.
5974ad5def9SAdrian McCarthy   return true;
5984ad5def9SAdrian McCarthy }
5994ad5def9SAdrian McCarthy 
6004ad5def9SAdrian McCarthy bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
6014ad5def9SAdrian McCarthy                                       ThreadList &new_thread_list) {
6024ad5def9SAdrian McCarthy   // Add all the threads that were previously running and for which we did not
6034ad5def9SAdrian McCarthy   // detect a thread exited event.
6044ad5def9SAdrian McCarthy   int new_size = 0;
6054ad5def9SAdrian McCarthy   int continued_threads = 0;
6064ad5def9SAdrian McCarthy   int exited_threads = 0;
6074ad5def9SAdrian McCarthy   int new_threads = 0;
6084ad5def9SAdrian McCarthy 
6094ad5def9SAdrian McCarthy   for (ThreadSP old_thread : old_thread_list.Threads()) {
6104ad5def9SAdrian McCarthy     lldb::tid_t old_thread_id = old_thread->GetID();
6114ad5def9SAdrian McCarthy     auto exited_thread_iter =
6124ad5def9SAdrian McCarthy         m_session_data->m_exited_threads.find(old_thread_id);
6134ad5def9SAdrian McCarthy     if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
6144ad5def9SAdrian McCarthy       new_thread_list.AddThread(old_thread);
6154ad5def9SAdrian McCarthy       ++new_size;
6164ad5def9SAdrian McCarthy       ++continued_threads;
6174ad5def9SAdrian McCarthy       WINLOGV_IFALL(
6184ad5def9SAdrian McCarthy           WINDOWS_LOG_THREAD,
6194ad5def9SAdrian McCarthy           "UpdateThreadList - Thread %llu was running and is still running.",
6204ad5def9SAdrian McCarthy           old_thread_id);
6214ad5def9SAdrian McCarthy     } else {
6224ad5def9SAdrian McCarthy       WINLOGV_IFALL(
6234ad5def9SAdrian McCarthy           WINDOWS_LOG_THREAD,
6244ad5def9SAdrian McCarthy           "UpdateThreadList - Thread %llu was running and has exited.",
6254ad5def9SAdrian McCarthy           old_thread_id);
6264ad5def9SAdrian McCarthy       ++exited_threads;
6274ad5def9SAdrian McCarthy     }
6284ad5def9SAdrian McCarthy   }
6294ad5def9SAdrian McCarthy 
6304ad5def9SAdrian McCarthy   // Also add all the threads that are new since the last time we broke into the
6314ad5def9SAdrian McCarthy   // debugger.
6324ad5def9SAdrian McCarthy   for (const auto &thread_info : m_session_data->m_new_threads) {
6334ad5def9SAdrian McCarthy     ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
6344ad5def9SAdrian McCarthy     thread->SetID(thread_info.first);
6354ad5def9SAdrian McCarthy     new_thread_list.AddThread(thread);
6364ad5def9SAdrian McCarthy     ++new_size;
6374ad5def9SAdrian McCarthy     ++new_threads;
6384ad5def9SAdrian McCarthy     WINLOGV_IFALL(WINDOWS_LOG_THREAD,
6394ad5def9SAdrian McCarthy                   "UpdateThreadList - Thread %llu is new since last update.",
6404ad5def9SAdrian McCarthy                   thread_info.first);
6414ad5def9SAdrian McCarthy   }
6424ad5def9SAdrian McCarthy 
6434ad5def9SAdrian McCarthy   WINLOG_IFALL(
6444ad5def9SAdrian McCarthy       WINDOWS_LOG_THREAD,
6454ad5def9SAdrian McCarthy       "UpdateThreadList - %d new threads, %d old threads, %d exited threads.",
6464ad5def9SAdrian McCarthy       new_threads, continued_threads, exited_threads);
6474ad5def9SAdrian McCarthy 
6484ad5def9SAdrian McCarthy   m_session_data->m_new_threads.clear();
6494ad5def9SAdrian McCarthy   m_session_data->m_exited_threads.clear();
6504ad5def9SAdrian McCarthy 
6514ad5def9SAdrian McCarthy   return new_size > 0;
6524ad5def9SAdrian McCarthy }
6534ad5def9SAdrian McCarthy 
6544ad5def9SAdrian McCarthy bool ProcessWindows::IsAlive() {
6554ad5def9SAdrian McCarthy   StateType state = GetPrivateState();
6564ad5def9SAdrian McCarthy   switch (state) {
6574ad5def9SAdrian McCarthy   case eStateCrashed:
6584ad5def9SAdrian McCarthy   case eStateDetached:
6594ad5def9SAdrian McCarthy   case eStateUnloaded:
6604ad5def9SAdrian McCarthy   case eStateExited:
6614ad5def9SAdrian McCarthy   case eStateInvalid:
6624ad5def9SAdrian McCarthy     return false;
6634ad5def9SAdrian McCarthy   default:
6644ad5def9SAdrian McCarthy     return true;
6654ad5def9SAdrian McCarthy   }
6664ad5def9SAdrian McCarthy }
6674ad5def9SAdrian McCarthy 
6684ad5def9SAdrian McCarthy size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
6694ad5def9SAdrian McCarthy                                     size_t size, Error &error) {
6704ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
6714ad5def9SAdrian McCarthy 
6724ad5def9SAdrian McCarthy   if (!m_session_data)
6734ad5def9SAdrian McCarthy     return 0;
6744ad5def9SAdrian McCarthy 
6754ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_MEMORY,
6764ad5def9SAdrian McCarthy                "DoReadMemory attempting to read %u bytes from address 0x%I64x",
6774ad5def9SAdrian McCarthy                size, vm_addr);
6784ad5def9SAdrian McCarthy 
6794ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
6804ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
6814ad5def9SAdrian McCarthy   SIZE_T bytes_read = 0;
6824ad5def9SAdrian McCarthy   if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr,
6834ad5def9SAdrian McCarthy                          buf, size, &bytes_read)) {
6844ad5def9SAdrian McCarthy     error.SetError(GetLastError(), eErrorTypeWin32);
6854ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u",
6864ad5def9SAdrian McCarthy                  error.GetError());
6874ad5def9SAdrian McCarthy   }
6884ad5def9SAdrian McCarthy   return bytes_read;
6894ad5def9SAdrian McCarthy }
6904ad5def9SAdrian McCarthy 
6914ad5def9SAdrian McCarthy size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
6924ad5def9SAdrian McCarthy                                      size_t size, Error &error) {
6934ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
6944ad5def9SAdrian McCarthy   WINLOG_IFALL(
6954ad5def9SAdrian McCarthy       WINDOWS_LOG_MEMORY,
6964ad5def9SAdrian McCarthy       "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size,
6974ad5def9SAdrian McCarthy       vm_addr);
6984ad5def9SAdrian McCarthy 
6994ad5def9SAdrian McCarthy   if (!m_session_data) {
7004ad5def9SAdrian McCarthy     WINERR_IFANY(
7014ad5def9SAdrian McCarthy         WINDOWS_LOG_MEMORY,
7024ad5def9SAdrian McCarthy         "DoWriteMemory cannot write, there is no active debugger connection.");
7034ad5def9SAdrian McCarthy     return 0;
7044ad5def9SAdrian McCarthy   }
7054ad5def9SAdrian McCarthy 
7064ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
7074ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
7084ad5def9SAdrian McCarthy   SIZE_T bytes_written = 0;
7094ad5def9SAdrian McCarthy   lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
7104ad5def9SAdrian McCarthy   if (WriteProcessMemory(handle, addr, buf, size, &bytes_written))
7114ad5def9SAdrian McCarthy     FlushInstructionCache(handle, addr, bytes_written);
7124ad5def9SAdrian McCarthy   else {
7134ad5def9SAdrian McCarthy     error.SetError(GetLastError(), eErrorTypeWin32);
7144ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u",
7154ad5def9SAdrian McCarthy                  error.GetError());
7164ad5def9SAdrian McCarthy   }
7174ad5def9SAdrian McCarthy   return bytes_written;
7184ad5def9SAdrian McCarthy }
7194ad5def9SAdrian McCarthy 
7204ad5def9SAdrian McCarthy #define BOOL_STR(b) ((b) ? "true" : "false")
7214ad5def9SAdrian McCarthy 
7224ad5def9SAdrian McCarthy Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
7234ad5def9SAdrian McCarthy                                           MemoryRegionInfo &info) {
7244ad5def9SAdrian McCarthy   Error error;
7254ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
7264ad5def9SAdrian McCarthy   info.Clear();
7274ad5def9SAdrian McCarthy 
7284ad5def9SAdrian McCarthy   if (!m_session_data) {
7294ad5def9SAdrian McCarthy     error.SetErrorString(
7304ad5def9SAdrian McCarthy         "GetMemoryRegionInfo called with no debugging session.");
7314ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
7324ad5def9SAdrian McCarthy     return error;
7334ad5def9SAdrian McCarthy   }
7344ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
7354ad5def9SAdrian McCarthy   lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
7364ad5def9SAdrian McCarthy   if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
7374ad5def9SAdrian McCarthy     error.SetErrorString(
7384ad5def9SAdrian McCarthy         "GetMemoryRegionInfo called with an invalid target process.");
7394ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
7404ad5def9SAdrian McCarthy     return error;
7414ad5def9SAdrian McCarthy   }
7424ad5def9SAdrian McCarthy 
7434ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_MEMORY,
7444ad5def9SAdrian McCarthy                "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr);
7454ad5def9SAdrian McCarthy 
7464ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
7474ad5def9SAdrian McCarthy   MEMORY_BASIC_INFORMATION mem_info = {};
7484ad5def9SAdrian McCarthy   SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
7494ad5def9SAdrian McCarthy   if (result == 0) {
7504ad5def9SAdrian McCarthy     if (::GetLastError() == ERROR_INVALID_PARAMETER) {
7514ad5def9SAdrian McCarthy       // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an
7524ad5def9SAdrian McCarthy       // address
7534ad5def9SAdrian McCarthy       // past the highest accessible address. We should return a range from the
7544ad5def9SAdrian McCarthy       // vm_addr
7554ad5def9SAdrian McCarthy       // to LLDB_INVALID_ADDRESS
7564ad5def9SAdrian McCarthy       info.GetRange().SetRangeBase(vm_addr);
7574ad5def9SAdrian McCarthy       info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
7584ad5def9SAdrian McCarthy       info.SetReadable(MemoryRegionInfo::eNo);
7594ad5def9SAdrian McCarthy       info.SetExecutable(MemoryRegionInfo::eNo);
7604ad5def9SAdrian McCarthy       info.SetWritable(MemoryRegionInfo::eNo);
7614ad5def9SAdrian McCarthy       info.SetMapped(MemoryRegionInfo::eNo);
7624ad5def9SAdrian McCarthy       return error;
7634ad5def9SAdrian McCarthy     } else {
7644ad5def9SAdrian McCarthy       error.SetError(::GetLastError(), eErrorTypeWin32);
7654ad5def9SAdrian McCarthy       WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while "
7664ad5def9SAdrian McCarthy                                        "getting memory region info for address "
7674ad5def9SAdrian McCarthy                                        "0x%I64x",
7684ad5def9SAdrian McCarthy                    error.GetError(), vm_addr);
7694ad5def9SAdrian McCarthy       return error;
7704ad5def9SAdrian McCarthy     }
7714ad5def9SAdrian McCarthy   }
7724ad5def9SAdrian McCarthy 
7734ad5def9SAdrian McCarthy   // Protect bits are only valid for MEM_COMMIT regions.
7744ad5def9SAdrian McCarthy   if (mem_info.State == MEM_COMMIT) {
7754ad5def9SAdrian McCarthy     const bool readable = IsPageReadable(mem_info.Protect);
7764ad5def9SAdrian McCarthy     const bool executable = IsPageExecutable(mem_info.Protect);
7774ad5def9SAdrian McCarthy     const bool writable = IsPageWritable(mem_info.Protect);
7784ad5def9SAdrian McCarthy     info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
7794ad5def9SAdrian McCarthy     info.SetExecutable(executable ? MemoryRegionInfo::eYes
7804ad5def9SAdrian McCarthy                                   : MemoryRegionInfo::eNo);
7814ad5def9SAdrian McCarthy     info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
7824ad5def9SAdrian McCarthy   } else {
7834ad5def9SAdrian McCarthy     info.SetReadable(MemoryRegionInfo::eNo);
7844ad5def9SAdrian McCarthy     info.SetExecutable(MemoryRegionInfo::eNo);
7854ad5def9SAdrian McCarthy     info.SetWritable(MemoryRegionInfo::eNo);
7864ad5def9SAdrian McCarthy   }
7874ad5def9SAdrian McCarthy 
7884ad5def9SAdrian McCarthy   // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
7894ad5def9SAdrian McCarthy   if (mem_info.State != MEM_FREE) {
7904ad5def9SAdrian McCarthy     info.GetRange().SetRangeBase(
7914ad5def9SAdrian McCarthy         reinterpret_cast<addr_t>(mem_info.AllocationBase));
7924ad5def9SAdrian McCarthy     info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
7934ad5def9SAdrian McCarthy                                 mem_info.RegionSize);
7944ad5def9SAdrian McCarthy     info.SetMapped(MemoryRegionInfo::eYes);
7954ad5def9SAdrian McCarthy   } else {
7964ad5def9SAdrian McCarthy     // In the unmapped case we need to return the distance to the next block of
7974ad5def9SAdrian McCarthy     // memory.
7984ad5def9SAdrian McCarthy     // VirtualQueryEx nearly does that except that it gives the distance from
7994ad5def9SAdrian McCarthy     // the start
8004ad5def9SAdrian McCarthy     // of the page containing vm_addr.
8014ad5def9SAdrian McCarthy     SYSTEM_INFO data;
8024ad5def9SAdrian McCarthy     GetSystemInfo(&data);
8034ad5def9SAdrian McCarthy     DWORD page_offset = vm_addr % data.dwPageSize;
8044ad5def9SAdrian McCarthy     info.GetRange().SetRangeBase(vm_addr);
8054ad5def9SAdrian McCarthy     info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
8064ad5def9SAdrian McCarthy     info.SetMapped(MemoryRegionInfo::eNo);
8074ad5def9SAdrian McCarthy   }
8084ad5def9SAdrian McCarthy 
8094ad5def9SAdrian McCarthy   error.SetError(::GetLastError(), eErrorTypeWin32);
8104ad5def9SAdrian McCarthy   WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address %llu: "
8114ad5def9SAdrian McCarthy                                     "readable=%s, executable=%s, writable=%s",
8124ad5def9SAdrian McCarthy                 vm_addr, BOOL_STR(info.GetReadable()),
8134ad5def9SAdrian McCarthy                 BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable()));
8144ad5def9SAdrian McCarthy   return error;
8154ad5def9SAdrian McCarthy }
8164ad5def9SAdrian McCarthy 
817b9c1b51eSKate Stone lldb::addr_t ProcessWindows::GetImageInfoAddress() {
81818a9135dSAdrian McCarthy   Target &target = GetTarget();
81918a9135dSAdrian McCarthy   ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
82018a9135dSAdrian McCarthy   Address addr = obj_file->GetImageInfoAddress(&target);
82118a9135dSAdrian McCarthy   if (addr.IsValid())
82218a9135dSAdrian McCarthy     return addr.GetLoadAddress(&target);
82318a9135dSAdrian McCarthy   else
82418a9135dSAdrian McCarthy     return LLDB_INVALID_ADDRESS;
82518a9135dSAdrian McCarthy }
82618a9135dSAdrian McCarthy 
8274ad5def9SAdrian McCarthy void ProcessWindows::OnExitProcess(uint32_t exit_code) {
8284ad5def9SAdrian McCarthy   // No need to acquire the lock since m_session_data isn't accessed.
8294ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %llu exited with code %u", GetID(),
8304ad5def9SAdrian McCarthy                exit_code);
8314ad5def9SAdrian McCarthy 
8324ad5def9SAdrian McCarthy   TargetSP target = m_target_sp.lock();
8334ad5def9SAdrian McCarthy   if (target) {
8344ad5def9SAdrian McCarthy     ModuleSP executable_module = target->GetExecutableModule();
8354ad5def9SAdrian McCarthy     ModuleList unloaded_modules;
8364ad5def9SAdrian McCarthy     unloaded_modules.Append(executable_module);
8374ad5def9SAdrian McCarthy     target->ModulesDidUnload(unloaded_modules, true);
8384ad5def9SAdrian McCarthy   }
8394ad5def9SAdrian McCarthy 
8404ad5def9SAdrian McCarthy   SetProcessExitStatus(GetID(), true, 0, exit_code);
8414ad5def9SAdrian McCarthy   SetPrivateState(eStateExited);
8424ad5def9SAdrian McCarthy }
8434ad5def9SAdrian McCarthy 
8444ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
8454ad5def9SAdrian McCarthy   DebuggerThreadSP debugger = m_session_data->m_debugger;
8464ad5def9SAdrian McCarthy 
8474ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS,
8484ad5def9SAdrian McCarthy                "Debugger connected to process %I64u.  Image base = 0x%I64x",
8494ad5def9SAdrian McCarthy                debugger->GetProcess().GetProcessId(), image_base);
8504ad5def9SAdrian McCarthy 
8514ad5def9SAdrian McCarthy   ModuleSP module = GetTarget().GetExecutableModule();
8524ad5def9SAdrian McCarthy   if (!module) {
8534ad5def9SAdrian McCarthy     // During attach, we won't have the executable module, so find it now.
8544ad5def9SAdrian McCarthy     const DWORD pid = debugger->GetProcess().GetProcessId();
8554ad5def9SAdrian McCarthy     const std::string file_name = GetProcessExecutableName(pid);
8564ad5def9SAdrian McCarthy     if (file_name.empty()) {
8574ad5def9SAdrian McCarthy       return;
8584ad5def9SAdrian McCarthy     }
8594ad5def9SAdrian McCarthy 
8604ad5def9SAdrian McCarthy     FileSpec executable_file(file_name, true);
8614ad5def9SAdrian McCarthy     ModuleSpec module_spec(executable_file);
8624ad5def9SAdrian McCarthy     Error error;
8634ad5def9SAdrian McCarthy     module = GetTarget().GetSharedModule(module_spec, &error);
8644ad5def9SAdrian McCarthy     if (!module) {
8654ad5def9SAdrian McCarthy       return;
8664ad5def9SAdrian McCarthy     }
8674ad5def9SAdrian McCarthy 
8684ad5def9SAdrian McCarthy     GetTarget().SetExecutableModule(module, false);
8694ad5def9SAdrian McCarthy   }
8704ad5def9SAdrian McCarthy 
8714ad5def9SAdrian McCarthy   bool load_addr_changed;
8724ad5def9SAdrian McCarthy   module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);
8734ad5def9SAdrian McCarthy 
8744ad5def9SAdrian McCarthy   ModuleList loaded_modules;
8754ad5def9SAdrian McCarthy   loaded_modules.Append(module);
8764ad5def9SAdrian McCarthy   GetTarget().ModulesDidLoad(loaded_modules);
8774ad5def9SAdrian McCarthy 
8784ad5def9SAdrian McCarthy   // Add the main executable module to the list of pending module loads.  We
8794ad5def9SAdrian McCarthy   // can't call
8804ad5def9SAdrian McCarthy   // GetTarget().ModulesDidLoad() here because we still haven't returned from
8814ad5def9SAdrian McCarthy   // DoLaunch() / DoAttach() yet
8824ad5def9SAdrian McCarthy   // so the target may not have set the process instance to `this` yet.
8834ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
8844ad5def9SAdrian McCarthy   const HostThreadWindows &wmain_thread =
8854ad5def9SAdrian McCarthy       debugger->GetMainThread().GetNativeThread();
8864ad5def9SAdrian McCarthy   m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
8874ad5def9SAdrian McCarthy       debugger->GetMainThread();
8884ad5def9SAdrian McCarthy }
8894ad5def9SAdrian McCarthy 
8904ad5def9SAdrian McCarthy ExceptionResult
8914ad5def9SAdrian McCarthy ProcessWindows::OnDebugException(bool first_chance,
8924ad5def9SAdrian McCarthy                                  const ExceptionRecord &record) {
8934ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
8944ad5def9SAdrian McCarthy 
8954ad5def9SAdrian McCarthy   // FIXME: Without this check, occasionally when running the test suite there
8964ad5def9SAdrian McCarthy   // is
8974ad5def9SAdrian McCarthy   // an issue where m_session_data can be null.  It's not clear how this could
8984ad5def9SAdrian McCarthy   // happen
8994ad5def9SAdrian McCarthy   // but it only surfaces while running the test suite.  In order to properly
9004ad5def9SAdrian McCarthy   // diagnose
9014ad5def9SAdrian McCarthy   // this, we probably need to first figure allow the test suite to print out
9024ad5def9SAdrian McCarthy   // full
9034ad5def9SAdrian McCarthy   // lldb logs, and then add logging to the process plugin.
9044ad5def9SAdrian McCarthy   if (!m_session_data) {
9054ad5def9SAdrian McCarthy     WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
9064ad5def9SAdrian McCarthy                                         "0x%lx at address 0x%llu, but there is "
9074ad5def9SAdrian McCarthy                                         "no session.",
9084ad5def9SAdrian McCarthy                  record.GetExceptionCode(), record.GetExceptionAddress());
9094ad5def9SAdrian McCarthy     return ExceptionResult::SendToApplication;
9104ad5def9SAdrian McCarthy   }
9114ad5def9SAdrian McCarthy 
9124ad5def9SAdrian McCarthy   if (!first_chance) {
9134ad5def9SAdrian McCarthy     // Any second chance exception is an application crash by definition.
9144ad5def9SAdrian McCarthy     SetPrivateState(eStateCrashed);
9154ad5def9SAdrian McCarthy   }
9164ad5def9SAdrian McCarthy 
9174ad5def9SAdrian McCarthy   ExceptionResult result = ExceptionResult::SendToApplication;
9184ad5def9SAdrian McCarthy   switch (record.GetExceptionCode()) {
9194ad5def9SAdrian McCarthy   case EXCEPTION_BREAKPOINT:
9204ad5def9SAdrian McCarthy     // Handle breakpoints at the first chance.
9214ad5def9SAdrian McCarthy     result = ExceptionResult::BreakInDebugger;
9224ad5def9SAdrian McCarthy 
9234ad5def9SAdrian McCarthy     if (!m_session_data->m_initial_stop_received) {
9244ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address "
9254ad5def9SAdrian McCarthy                                             "0x%I64x, setting initial stop "
9264ad5def9SAdrian McCarthy                                             "event.",
9274ad5def9SAdrian McCarthy                    record.GetExceptionAddress());
9284ad5def9SAdrian McCarthy       m_session_data->m_initial_stop_received = true;
9294ad5def9SAdrian McCarthy       ::SetEvent(m_session_data->m_initial_stop_event);
9304ad5def9SAdrian McCarthy     } else {
9314ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS,
9324ad5def9SAdrian McCarthy                    "Hit non-loader breakpoint at address 0x%I64x.",
9334ad5def9SAdrian McCarthy                    record.GetExceptionAddress());
9344ad5def9SAdrian McCarthy     }
9354ad5def9SAdrian McCarthy     SetPrivateState(eStateStopped);
9364ad5def9SAdrian McCarthy     break;
9374ad5def9SAdrian McCarthy   case EXCEPTION_SINGLE_STEP:
9384ad5def9SAdrian McCarthy     result = ExceptionResult::BreakInDebugger;
9394ad5def9SAdrian McCarthy     SetPrivateState(eStateStopped);
9404ad5def9SAdrian McCarthy     break;
9414ad5def9SAdrian McCarthy   default:
9424ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
9434ad5def9SAdrian McCarthy                                         "0x%lx at address 0x%llx "
9444ad5def9SAdrian McCarthy                                         "(first_chance=%s)",
9454ad5def9SAdrian McCarthy                  record.GetExceptionCode(), record.GetExceptionAddress(),
9464ad5def9SAdrian McCarthy                  BOOL_STR(first_chance));
9474ad5def9SAdrian McCarthy     // For non-breakpoints, give the application a chance to handle the
9484ad5def9SAdrian McCarthy     // exception first.
9494ad5def9SAdrian McCarthy     if (first_chance)
9504ad5def9SAdrian McCarthy       result = ExceptionResult::SendToApplication;
9514ad5def9SAdrian McCarthy     else
9524ad5def9SAdrian McCarthy       result = ExceptionResult::BreakInDebugger;
9534ad5def9SAdrian McCarthy   }
9544ad5def9SAdrian McCarthy 
9554ad5def9SAdrian McCarthy   return result;
9564ad5def9SAdrian McCarthy }
9574ad5def9SAdrian McCarthy 
9584ad5def9SAdrian McCarthy void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
9594ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
9604ad5def9SAdrian McCarthy   const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
9614ad5def9SAdrian McCarthy   m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
9624ad5def9SAdrian McCarthy }
9634ad5def9SAdrian McCarthy 
9644ad5def9SAdrian McCarthy void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
9654ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
9664ad5def9SAdrian McCarthy 
9674ad5def9SAdrian McCarthy   // On a forced termination, we may get exit thread events after the session
9684ad5def9SAdrian McCarthy   // data has been cleaned up.
9694ad5def9SAdrian McCarthy   if (!m_session_data)
9704ad5def9SAdrian McCarthy     return;
9714ad5def9SAdrian McCarthy 
9724ad5def9SAdrian McCarthy   // A thread may have started and exited before the debugger stopped allowing a
9734ad5def9SAdrian McCarthy   // refresh.
9744ad5def9SAdrian McCarthy   // Just remove it from the new threads list in that case.
9754ad5def9SAdrian McCarthy   auto iter = m_session_data->m_new_threads.find(thread_id);
9764ad5def9SAdrian McCarthy   if (iter != m_session_data->m_new_threads.end())
9774ad5def9SAdrian McCarthy     m_session_data->m_new_threads.erase(iter);
9784ad5def9SAdrian McCarthy   else
9794ad5def9SAdrian McCarthy     m_session_data->m_exited_threads.insert(thread_id);
9804ad5def9SAdrian McCarthy }
9814ad5def9SAdrian McCarthy 
9824ad5def9SAdrian McCarthy void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
9834ad5def9SAdrian McCarthy                                lldb::addr_t module_addr) {
9844ad5def9SAdrian McCarthy   // Confusingly, there is no Target::AddSharedModule.  Instead, calling
9854ad5def9SAdrian McCarthy   // GetSharedModule() with
9864ad5def9SAdrian McCarthy   // a new module will add it to the module list and return a corresponding
9874ad5def9SAdrian McCarthy   // ModuleSP.
9884ad5def9SAdrian McCarthy   Error error;
9894ad5def9SAdrian McCarthy   ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
9904ad5def9SAdrian McCarthy   bool load_addr_changed = false;
9914ad5def9SAdrian McCarthy   module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed);
9924ad5def9SAdrian McCarthy 
9934ad5def9SAdrian McCarthy   ModuleList loaded_modules;
9944ad5def9SAdrian McCarthy   loaded_modules.Append(module);
9954ad5def9SAdrian McCarthy   GetTarget().ModulesDidLoad(loaded_modules);
9964ad5def9SAdrian McCarthy }
9974ad5def9SAdrian McCarthy 
9984ad5def9SAdrian McCarthy void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
9994ad5def9SAdrian McCarthy   Address resolved_addr;
10004ad5def9SAdrian McCarthy   if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) {
10014ad5def9SAdrian McCarthy     ModuleSP module = resolved_addr.GetModule();
10024ad5def9SAdrian McCarthy     if (module) {
10034ad5def9SAdrian McCarthy       ModuleList unloaded_modules;
10044ad5def9SAdrian McCarthy       unloaded_modules.Append(module);
10054ad5def9SAdrian McCarthy       GetTarget().ModulesDidUnload(unloaded_modules, false);
10064ad5def9SAdrian McCarthy     }
10074ad5def9SAdrian McCarthy   }
10084ad5def9SAdrian McCarthy }
10094ad5def9SAdrian McCarthy 
10104ad5def9SAdrian McCarthy void ProcessWindows::OnDebugString(const std::string &string) {}
10114ad5def9SAdrian McCarthy 
10124ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) {
10134ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
10144ad5def9SAdrian McCarthy 
10154ad5def9SAdrian McCarthy   if (m_session_data->m_initial_stop_received) {
10164ad5def9SAdrian McCarthy     // This happened while debugging.  Do we shutdown the debugging session, try
10174ad5def9SAdrian McCarthy     // to continue,
10184ad5def9SAdrian McCarthy     // or do something else?
10194ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging.  "
10204ad5def9SAdrian McCarthy                                       "Unexpected behavior may result.  %s",
10214ad5def9SAdrian McCarthy                  error.GetError(), error.AsCString());
10224ad5def9SAdrian McCarthy   } else {
10234ad5def9SAdrian McCarthy     // If we haven't actually launched the process yet, this was an error
10244ad5def9SAdrian McCarthy     // launching the
10254ad5def9SAdrian McCarthy     // process.  Set the internal error and signal the initial stop event so
10264ad5def9SAdrian McCarthy     // that the DoLaunch
10274ad5def9SAdrian McCarthy     // method wakes up and returns a failure.
10284ad5def9SAdrian McCarthy     m_session_data->m_launch_error = error;
10294ad5def9SAdrian McCarthy     ::SetEvent(m_session_data->m_initial_stop_event);
10304ad5def9SAdrian McCarthy     WINERR_IFALL(
10314ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
10324ad5def9SAdrian McCarthy         "Error %u occurred launching the process before the initial stop.  %s",
10334ad5def9SAdrian McCarthy         error.GetError(), error.AsCString());
10344ad5def9SAdrian McCarthy     return;
10354ad5def9SAdrian McCarthy   }
10364ad5def9SAdrian McCarthy }
10374ad5def9SAdrian McCarthy 
10384ad5def9SAdrian McCarthy Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger,
10394ad5def9SAdrian McCarthy                                                 HostProcess &process) {
10404ad5def9SAdrian McCarthy   Error result;
10414ad5def9SAdrian McCarthy   WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
10424ad5def9SAdrian McCarthy                "WaitForDebuggerConnection Waiting for loader breakpoint.");
10434ad5def9SAdrian McCarthy 
10444ad5def9SAdrian McCarthy   // Block this function until we receive the initial stop from the process.
10454ad5def9SAdrian McCarthy   if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
10464ad5def9SAdrian McCarthy       WAIT_OBJECT_0) {
10474ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
10484ad5def9SAdrian McCarthy                  "WaitForDebuggerConnection hit loader breakpoint, returning.");
10494ad5def9SAdrian McCarthy 
10504ad5def9SAdrian McCarthy     process = debugger->GetProcess();
10514ad5def9SAdrian McCarthy     return m_session_data->m_launch_error;
10524ad5def9SAdrian McCarthy   } else
10534ad5def9SAdrian McCarthy     return Error(::GetLastError(), eErrorTypeWin32);
10544ad5def9SAdrian McCarthy }
10554ad5def9SAdrian McCarthy 
1056b9c1b51eSKate Stone // The Windows page protection bits are NOT independent masks that can be
10574ad5def9SAdrian McCarthy // bitwise-ORed together.  For example, PAGE_EXECUTE_READ is not
10584ad5def9SAdrian McCarthy // (PAGE_EXECUTE | PAGE_READ).  To test for an access type, it's necessary to
10594ad5def9SAdrian McCarthy // test for any of the bits that provide that access type.
1060b9c1b51eSKate Stone bool ProcessWindows::IsPageReadable(uint32_t protect) {
10610c35cde9SAdrian McCarthy   return (protect & PAGE_NOACCESS) == 0;
10620c35cde9SAdrian McCarthy }
10630c35cde9SAdrian McCarthy 
1064b9c1b51eSKate Stone bool ProcessWindows::IsPageWritable(uint32_t protect) {
1065b9c1b51eSKate Stone   return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
1066b9c1b51eSKate Stone                      PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
10670c35cde9SAdrian McCarthy }
10680c35cde9SAdrian McCarthy 
1069b9c1b51eSKate Stone bool ProcessWindows::IsPageExecutable(uint32_t protect) {
1070b9c1b51eSKate Stone   return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
1071b9c1b51eSKate Stone                      PAGE_EXECUTE_WRITECOPY)) != 0;
10720c35cde9SAdrian McCarthy }
10734ad5def9SAdrian McCarthy 
10744ad5def9SAdrian McCarthy } // namespace lldb_private
1075