15146a9eaSAaron Smith //===-- NativeProcessWindows.cpp --------------------------------*- C++ -*-===// 25146a9eaSAaron Smith // 35146a9eaSAaron Smith // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45146a9eaSAaron Smith // See https://llvm.org/LICENSE.txt for license information. 55146a9eaSAaron Smith // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65146a9eaSAaron Smith // 75146a9eaSAaron Smith //===----------------------------------------------------------------------===// 85146a9eaSAaron Smith 95146a9eaSAaron Smith #include "lldb/Host/windows/windows.h" 105146a9eaSAaron Smith #include <psapi.h> 115146a9eaSAaron Smith 125146a9eaSAaron Smith #include "NativeProcessWindows.h" 135146a9eaSAaron Smith #include "NativeThreadWindows.h" 145146a9eaSAaron Smith #include "lldb/Host/FileSystem.h" 155146a9eaSAaron Smith #include "lldb/Host/HostNativeProcessBase.h" 165146a9eaSAaron Smith #include "lldb/Host/HostProcess.h" 175146a9eaSAaron Smith #include "lldb/Host/ProcessLaunchInfo.h" 185146a9eaSAaron Smith #include "lldb/Host/windows/AutoHandle.h" 195146a9eaSAaron Smith #include "lldb/Host/windows/HostThreadWindows.h" 205146a9eaSAaron Smith #include "lldb/Host/windows/ProcessLauncherWindows.h" 215146a9eaSAaron Smith #include "lldb/Target/MemoryRegionInfo.h" 225146a9eaSAaron Smith #include "lldb/Target/Process.h" 235146a9eaSAaron Smith #include "lldb/Utility/State.h" 245146a9eaSAaron Smith #include "llvm/Support/ConvertUTF.h" 255146a9eaSAaron Smith #include "llvm/Support/Errc.h" 265146a9eaSAaron Smith #include "llvm/Support/Error.h" 275146a9eaSAaron Smith #include "llvm/Support/Format.h" 285146a9eaSAaron Smith #include "llvm/Support/Threading.h" 295146a9eaSAaron Smith #include "llvm/Support/raw_ostream.h" 305146a9eaSAaron Smith 315146a9eaSAaron Smith #include "DebuggerThread.h" 325146a9eaSAaron Smith #include "ExceptionRecord.h" 335146a9eaSAaron Smith #include "ProcessWindowsLog.h" 345146a9eaSAaron Smith 355146a9eaSAaron Smith #include <tlhelp32.h> 365146a9eaSAaron Smith 375146a9eaSAaron Smith #pragma warning(disable : 4005) 385146a9eaSAaron Smith #include "winternl.h" 395146a9eaSAaron Smith #include <ntstatus.h> 405146a9eaSAaron Smith 415146a9eaSAaron Smith using namespace lldb; 425146a9eaSAaron Smith using namespace lldb_private; 435146a9eaSAaron Smith using namespace llvm; 445146a9eaSAaron Smith 455146a9eaSAaron Smith namespace lldb_private { 465146a9eaSAaron Smith 475146a9eaSAaron Smith NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info, 485146a9eaSAaron Smith NativeDelegate &delegate, 495146a9eaSAaron Smith llvm::Error &E) 505146a9eaSAaron Smith : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID, 515146a9eaSAaron Smith launch_info.GetPTY().ReleaseMasterFileDescriptor(), 525146a9eaSAaron Smith delegate), 535146a9eaSAaron Smith ProcessDebugger(), m_arch(launch_info.GetArchitecture()) { 545146a9eaSAaron Smith ErrorAsOutParameter EOut(&E); 555146a9eaSAaron Smith DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this)); 565146a9eaSAaron Smith E = LaunchProcess(launch_info, delegate_sp).ToError(); 575146a9eaSAaron Smith if (E) 585146a9eaSAaron Smith return; 595146a9eaSAaron Smith 605146a9eaSAaron Smith SetID(GetDebuggedProcessId()); 615146a9eaSAaron Smith } 625146a9eaSAaron Smith 635146a9eaSAaron Smith NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd, 645146a9eaSAaron Smith NativeDelegate &delegate, 655146a9eaSAaron Smith llvm::Error &E) 665146a9eaSAaron Smith : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger() { 675146a9eaSAaron Smith ErrorAsOutParameter EOut(&E); 685146a9eaSAaron Smith DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this)); 695146a9eaSAaron Smith ProcessAttachInfo attach_info; 705146a9eaSAaron Smith attach_info.SetProcessID(pid); 715146a9eaSAaron Smith E = AttachProcess(pid, attach_info, delegate_sp).ToError(); 725146a9eaSAaron Smith if (E) 735146a9eaSAaron Smith return; 745146a9eaSAaron Smith 755146a9eaSAaron Smith SetID(GetDebuggedProcessId()); 765146a9eaSAaron Smith 775146a9eaSAaron Smith ProcessInstanceInfo info; 785146a9eaSAaron Smith if (!Host::GetProcessInfo(pid, info)) { 795146a9eaSAaron Smith E = createStringError(inconvertibleErrorCode(), 805146a9eaSAaron Smith "Cannot get process information"); 815146a9eaSAaron Smith return; 825146a9eaSAaron Smith } 835146a9eaSAaron Smith m_arch = info.GetArchitecture(); 845146a9eaSAaron Smith } 855146a9eaSAaron Smith 865146a9eaSAaron Smith Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) { 875146a9eaSAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 885146a9eaSAaron Smith Status error; 895146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 905146a9eaSAaron Smith 915146a9eaSAaron Smith StateType state = GetState(); 925146a9eaSAaron Smith if (state == eStateStopped || state == eStateCrashed) { 935146a9eaSAaron Smith LLDB_LOG(log, "process {0} is in state {1}. Resuming...", 945146a9eaSAaron Smith GetDebuggedProcessId(), state); 955146a9eaSAaron Smith LLDB_LOG(log, "resuming {0} threads.", m_threads.size()); 965146a9eaSAaron Smith 975146a9eaSAaron Smith bool failed = false; 985146a9eaSAaron Smith for (uint32_t i = 0; i < m_threads.size(); ++i) { 995146a9eaSAaron Smith auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get()); 1005146a9eaSAaron Smith const ResumeAction *const action = 1015146a9eaSAaron Smith resume_actions.GetActionForThread(thread->GetID(), true); 1025146a9eaSAaron Smith if (action == nullptr) 1035146a9eaSAaron Smith continue; 1045146a9eaSAaron Smith 1055146a9eaSAaron Smith switch (action->state) { 1065146a9eaSAaron Smith case eStateRunning: 1075146a9eaSAaron Smith case eStateStepping: { 1085146a9eaSAaron Smith Status result = thread->DoResume(action->state); 1095146a9eaSAaron Smith if (result.Fail()) { 1105146a9eaSAaron Smith failed = true; 1115146a9eaSAaron Smith LLDB_LOG(log, 1125146a9eaSAaron Smith "Trying to resume thread at index {0}, but failed with " 1135146a9eaSAaron Smith "error {1}.", 1145146a9eaSAaron Smith i, result); 1155146a9eaSAaron Smith } 1165146a9eaSAaron Smith break; 1175146a9eaSAaron Smith } 1185146a9eaSAaron Smith case eStateSuspended: 1195146a9eaSAaron Smith case eStateStopped: 1205146a9eaSAaron Smith llvm_unreachable("Unexpected state"); 1215146a9eaSAaron Smith 1225146a9eaSAaron Smith default: 1235146a9eaSAaron Smith return Status( 1245146a9eaSAaron Smith "NativeProcessWindows::%s (): unexpected state %s specified " 1255146a9eaSAaron Smith "for pid %" PRIu64 ", tid %" PRIu64, 1265146a9eaSAaron Smith __FUNCTION__, StateAsCString(action->state), GetID(), 1275146a9eaSAaron Smith thread->GetID()); 1285146a9eaSAaron Smith } 1295146a9eaSAaron Smith } 1305146a9eaSAaron Smith 1315146a9eaSAaron Smith if (failed) { 1325146a9eaSAaron Smith error.SetErrorString("NativeProcessWindows::DoResume failed"); 1335146a9eaSAaron Smith } else { 1345146a9eaSAaron Smith SetState(eStateRunning); 1355146a9eaSAaron Smith } 1365146a9eaSAaron Smith 1375146a9eaSAaron Smith // Resume the debug loop. 1385146a9eaSAaron Smith ExceptionRecordSP active_exception = 1395146a9eaSAaron Smith m_session_data->m_debugger->GetActiveException().lock(); 1405146a9eaSAaron Smith if (active_exception) { 1415146a9eaSAaron Smith // Resume the process and continue processing debug events. Mask the 1425146a9eaSAaron Smith // exception so that from the process's view, there is no indication that 1435146a9eaSAaron Smith // anything happened. 1445146a9eaSAaron Smith m_session_data->m_debugger->ContinueAsyncException( 1455146a9eaSAaron Smith ExceptionResult::MaskException); 1465146a9eaSAaron Smith } 1475146a9eaSAaron Smith } else { 1485146a9eaSAaron Smith LLDB_LOG(log, "error: process {0} is in state {1}. Returning...", 1495146a9eaSAaron Smith GetDebuggedProcessId(), GetState()); 1505146a9eaSAaron Smith } 1515146a9eaSAaron Smith 1525146a9eaSAaron Smith return error; 1535146a9eaSAaron Smith } 1545146a9eaSAaron Smith 1555146a9eaSAaron Smith NativeThreadWindows * 1565146a9eaSAaron Smith NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) { 1575146a9eaSAaron Smith return static_cast<NativeThreadWindows *>( 1585146a9eaSAaron Smith NativeProcessProtocol::GetThreadByID(thread_id)); 1595146a9eaSAaron Smith } 1605146a9eaSAaron Smith 1615146a9eaSAaron Smith Status NativeProcessWindows::Halt() { 1625146a9eaSAaron Smith bool caused_stop = false; 1635146a9eaSAaron Smith StateType state = GetState(); 1645146a9eaSAaron Smith if (state != eStateStopped) 1655146a9eaSAaron Smith return HaltProcess(caused_stop); 1665146a9eaSAaron Smith return Status(); 1675146a9eaSAaron Smith } 1685146a9eaSAaron Smith 1695146a9eaSAaron Smith Status NativeProcessWindows::Detach() { 1705146a9eaSAaron Smith Status error; 1715146a9eaSAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 1725146a9eaSAaron Smith StateType state = GetState(); 1735146a9eaSAaron Smith if (state != eStateExited && state != eStateDetached) { 1745146a9eaSAaron Smith error = DetachProcess(); 1755146a9eaSAaron Smith if (error.Success()) 1765146a9eaSAaron Smith SetState(eStateDetached); 1775146a9eaSAaron Smith else 1785146a9eaSAaron Smith LLDB_LOG(log, "Detaching process error: {0}", error); 1795146a9eaSAaron Smith } else { 180ed78dc8eSMartin Storsjo error.SetErrorStringWithFormatv("error: process {0} in state = {1}, but " 1815146a9eaSAaron Smith "cannot detach it in this state.", 1825146a9eaSAaron Smith GetID(), state); 1835146a9eaSAaron Smith LLDB_LOG(log, "error: {0}", error); 1845146a9eaSAaron Smith } 1855146a9eaSAaron Smith return error; 1865146a9eaSAaron Smith } 1875146a9eaSAaron Smith 1885146a9eaSAaron Smith Status NativeProcessWindows::Signal(int signo) { 1895146a9eaSAaron Smith Status error; 1905146a9eaSAaron Smith error.SetErrorString("Windows does not support sending signals to processes"); 1915146a9eaSAaron Smith return error; 1925146a9eaSAaron Smith } 1935146a9eaSAaron Smith 1945146a9eaSAaron Smith Status NativeProcessWindows::Interrupt() { return Halt(); } 1955146a9eaSAaron Smith 1965146a9eaSAaron Smith Status NativeProcessWindows::Kill() { 1975146a9eaSAaron Smith StateType state = GetState(); 1985146a9eaSAaron Smith return DestroyProcess(state); 1995146a9eaSAaron Smith } 2005146a9eaSAaron Smith 2015146a9eaSAaron Smith Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) { 2025146a9eaSAaron Smith return Status(); 2035146a9eaSAaron Smith } 2045146a9eaSAaron Smith 2055146a9eaSAaron Smith Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr, 2065146a9eaSAaron Smith MemoryRegionInfo &range_info) { 2075146a9eaSAaron Smith return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info); 2085146a9eaSAaron Smith } 2095146a9eaSAaron Smith 2105146a9eaSAaron Smith Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf, 2115146a9eaSAaron Smith size_t size, size_t &bytes_read) { 2125146a9eaSAaron Smith return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read); 2135146a9eaSAaron Smith } 2145146a9eaSAaron Smith 2155146a9eaSAaron Smith Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf, 2165146a9eaSAaron Smith size_t size, size_t &bytes_written) { 2175146a9eaSAaron Smith return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written); 2185146a9eaSAaron Smith } 2195146a9eaSAaron Smith 2205146a9eaSAaron Smith Status NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions, 2215146a9eaSAaron Smith lldb::addr_t &addr) { 2225146a9eaSAaron Smith return ProcessDebugger::AllocateMemory(size, permissions, addr); 2235146a9eaSAaron Smith } 2245146a9eaSAaron Smith 2255146a9eaSAaron Smith Status NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) { 2265146a9eaSAaron Smith return ProcessDebugger::DeallocateMemory(addr); 2275146a9eaSAaron Smith } 2285146a9eaSAaron Smith 2295146a9eaSAaron Smith lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; } 2305146a9eaSAaron Smith 2315146a9eaSAaron Smith bool NativeProcessWindows::IsAlive() const { 2325146a9eaSAaron Smith StateType state = GetState(); 2335146a9eaSAaron Smith switch (state) { 2345146a9eaSAaron Smith case eStateCrashed: 2355146a9eaSAaron Smith case eStateDetached: 2365146a9eaSAaron Smith case eStateExited: 2375146a9eaSAaron Smith case eStateInvalid: 2385146a9eaSAaron Smith case eStateUnloaded: 2395146a9eaSAaron Smith return false; 2405146a9eaSAaron Smith default: 2415146a9eaSAaron Smith return true; 2425146a9eaSAaron Smith } 2435146a9eaSAaron Smith } 2445146a9eaSAaron Smith 2455146a9eaSAaron Smith void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread, 2465146a9eaSAaron Smith lldb::StopReason reason, 2475146a9eaSAaron Smith std::string description) { 2485146a9eaSAaron Smith SetCurrentThreadID(thread.GetID()); 2495146a9eaSAaron Smith 2505146a9eaSAaron Smith ThreadStopInfo stop_info; 2515146a9eaSAaron Smith stop_info.reason = reason; 2525146a9eaSAaron Smith 2535146a9eaSAaron Smith // No signal support on Windows but required to provide a 'valid' signum. 2545146a9eaSAaron Smith if (reason == StopReason::eStopReasonException) { 2555146a9eaSAaron Smith stop_info.details.exception.type = 0; 2565146a9eaSAaron Smith stop_info.details.exception.data_count = 0; 2575146a9eaSAaron Smith } else { 2585146a9eaSAaron Smith stop_info.details.signal.signo = SIGTRAP; 2595146a9eaSAaron Smith } 2605146a9eaSAaron Smith 2615146a9eaSAaron Smith thread.SetStopReason(stop_info, description); 2625146a9eaSAaron Smith } 2635146a9eaSAaron Smith 2645146a9eaSAaron Smith void NativeProcessWindows::StopThread(lldb::tid_t thread_id, 2655146a9eaSAaron Smith lldb::StopReason reason, 2665146a9eaSAaron Smith std::string description) { 2675146a9eaSAaron Smith NativeThreadWindows *thread = GetThreadByID(thread_id); 2685146a9eaSAaron Smith if (!thread) 2695146a9eaSAaron Smith return; 2705146a9eaSAaron Smith 2715146a9eaSAaron Smith for (uint32_t i = 0; i < m_threads.size(); ++i) { 2725146a9eaSAaron Smith auto t = static_cast<NativeThreadWindows *>(m_threads[i].get()); 2735146a9eaSAaron Smith Status error = t->DoStop(); 2745146a9eaSAaron Smith if (error.Fail()) 2755146a9eaSAaron Smith exit(1); 2765146a9eaSAaron Smith } 2775146a9eaSAaron Smith SetStopReasonForThread(*thread, reason, description); 2785146a9eaSAaron Smith } 2795146a9eaSAaron Smith 2805146a9eaSAaron Smith size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); } 2815146a9eaSAaron Smith 2825146a9eaSAaron Smith llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 2835146a9eaSAaron Smith NativeProcessWindows::GetAuxvData() const { 2845146a9eaSAaron Smith // Not available on this target. 2855146a9eaSAaron Smith return llvm::errc::not_supported; 2865146a9eaSAaron Smith } 2875146a9eaSAaron Smith 2885146a9eaSAaron Smith bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) { 2895146a9eaSAaron Smith auto it = m_software_breakpoints.find(addr); 2905146a9eaSAaron Smith if (it == m_software_breakpoints.end()) 2915146a9eaSAaron Smith return false; 2925146a9eaSAaron Smith return true; 2935146a9eaSAaron Smith } 2945146a9eaSAaron Smith 2955146a9eaSAaron Smith Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size, 2965146a9eaSAaron Smith bool hardware) { 2975146a9eaSAaron Smith if (hardware) 2985146a9eaSAaron Smith return SetHardwareBreakpoint(addr, size); 2995146a9eaSAaron Smith return SetSoftwareBreakpoint(addr, size); 3005146a9eaSAaron Smith } 3015146a9eaSAaron Smith 3025146a9eaSAaron Smith Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr, 3035146a9eaSAaron Smith bool hardware) { 3045146a9eaSAaron Smith if (hardware) 3055146a9eaSAaron Smith return RemoveHardwareBreakpoint(addr); 3065146a9eaSAaron Smith return RemoveSoftwareBreakpoint(addr); 3075146a9eaSAaron Smith } 3085146a9eaSAaron Smith 3095146a9eaSAaron Smith Status NativeProcessWindows::CacheLoadedModules() { 3105146a9eaSAaron Smith Status error; 3115146a9eaSAaron Smith if (!m_loaded_modules.empty()) 3125146a9eaSAaron Smith return Status(); 3135146a9eaSAaron Smith 3145146a9eaSAaron Smith // Retrieve loaded modules by a Target/Module free implemenation. 3155146a9eaSAaron Smith AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID())); 3165146a9eaSAaron Smith if (snapshot.IsValid()) { 3175146a9eaSAaron Smith MODULEENTRY32W me; 3185146a9eaSAaron Smith me.dwSize = sizeof(MODULEENTRY32W); 3195146a9eaSAaron Smith if (Module32FirstW(snapshot.get(), &me)) { 3205146a9eaSAaron Smith do { 3215146a9eaSAaron Smith std::string path; 3225146a9eaSAaron Smith if (!llvm::convertWideToUTF8(me.szExePath, path)) 3235146a9eaSAaron Smith continue; 3245146a9eaSAaron Smith 3255146a9eaSAaron Smith FileSpec file_spec(path); 3265146a9eaSAaron Smith FileSystem::Instance().Resolve(file_spec); 3275146a9eaSAaron Smith m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr; 3285146a9eaSAaron Smith } while (Module32Next(snapshot.get(), &me)); 3295146a9eaSAaron Smith } 3305146a9eaSAaron Smith 3315146a9eaSAaron Smith if (!m_loaded_modules.empty()) 3325146a9eaSAaron Smith return Status(); 3335146a9eaSAaron Smith } 3345146a9eaSAaron Smith 3355146a9eaSAaron Smith error.SetError(::GetLastError(), lldb::ErrorType::eErrorTypeWin32); 3365146a9eaSAaron Smith return error; 3375146a9eaSAaron Smith } 3385146a9eaSAaron Smith 3395146a9eaSAaron Smith Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path, 3405146a9eaSAaron Smith FileSpec &file_spec) { 3415146a9eaSAaron Smith Status error = CacheLoadedModules(); 3425146a9eaSAaron Smith if (error.Fail()) 3435146a9eaSAaron Smith return error; 3445146a9eaSAaron Smith 3455146a9eaSAaron Smith FileSpec module_file_spec(module_path); 3465146a9eaSAaron Smith FileSystem::Instance().Resolve(module_file_spec); 3475146a9eaSAaron Smith for (auto &it : m_loaded_modules) { 3485146a9eaSAaron Smith if (it.first == module_file_spec) { 3495146a9eaSAaron Smith file_spec = it.first; 3505146a9eaSAaron Smith return Status(); 3515146a9eaSAaron Smith } 3525146a9eaSAaron Smith } 3535146a9eaSAaron Smith return Status("Module (%s) not found in process %" PRIu64 "!", 3545146a9eaSAaron Smith module_file_spec.GetCString(), GetID()); 3555146a9eaSAaron Smith } 3565146a9eaSAaron Smith 3575146a9eaSAaron Smith Status 3585146a9eaSAaron Smith NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name, 3595146a9eaSAaron Smith lldb::addr_t &load_addr) { 3605146a9eaSAaron Smith Status error = CacheLoadedModules(); 3615146a9eaSAaron Smith if (error.Fail()) 3625146a9eaSAaron Smith return error; 3635146a9eaSAaron Smith 3645146a9eaSAaron Smith load_addr = LLDB_INVALID_ADDRESS; 3655146a9eaSAaron Smith FileSpec file_spec(file_name); 3665146a9eaSAaron Smith FileSystem::Instance().Resolve(file_spec); 3675146a9eaSAaron Smith for (auto &it : m_loaded_modules) { 3685146a9eaSAaron Smith if (it.first == file_spec) { 3695146a9eaSAaron Smith load_addr = it.second; 3705146a9eaSAaron Smith return Status(); 3715146a9eaSAaron Smith } 3725146a9eaSAaron Smith } 3735146a9eaSAaron Smith return Status("Can't get loaded address of file (%s) in process %" PRIu64 "!", 3745146a9eaSAaron Smith file_spec.GetCString(), GetID()); 3755146a9eaSAaron Smith } 3765146a9eaSAaron Smith 3775146a9eaSAaron Smith void NativeProcessWindows::OnExitProcess(uint32_t exit_code) { 3785146a9eaSAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 3795146a9eaSAaron Smith LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code); 3805146a9eaSAaron Smith 3815146a9eaSAaron Smith ProcessDebugger::OnExitProcess(exit_code); 3825146a9eaSAaron Smith 3835146a9eaSAaron Smith // No signal involved. It is just an exit event. 3845146a9eaSAaron Smith WaitStatus wait_status(WaitStatus::Exit, exit_code); 3855146a9eaSAaron Smith SetExitStatus(wait_status, true); 3865146a9eaSAaron Smith 3875146a9eaSAaron Smith // Notify the native delegate. 3885146a9eaSAaron Smith SetState(eStateExited, true); 3895146a9eaSAaron Smith } 3905146a9eaSAaron Smith 3915146a9eaSAaron Smith void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { 3925146a9eaSAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 3935146a9eaSAaron Smith LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}", 3945146a9eaSAaron Smith GetDebuggedProcessId(), image_base); 3955146a9eaSAaron Smith 3965146a9eaSAaron Smith // This is the earliest chance we can resolve the process ID and 3975146a9eaSAaron Smith // architecutre if we don't know them yet. 3985146a9eaSAaron Smith if (GetID() == LLDB_INVALID_PROCESS_ID) 3995146a9eaSAaron Smith SetID(GetDebuggedProcessId()); 4005146a9eaSAaron Smith 4015146a9eaSAaron Smith if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) { 4025146a9eaSAaron Smith ProcessInstanceInfo process_info; 4035146a9eaSAaron Smith if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) { 4045146a9eaSAaron Smith LLDB_LOG(log, "Cannot get process information during debugger connecting " 4055146a9eaSAaron Smith "to process"); 4065146a9eaSAaron Smith return; 4075146a9eaSAaron Smith } 4085146a9eaSAaron Smith SetArchitecture(process_info.GetArchitecture()); 4095146a9eaSAaron Smith } 4105146a9eaSAaron Smith 4115146a9eaSAaron Smith // The very first one shall always be the main thread. 4125146a9eaSAaron Smith assert(m_threads.empty()); 413a8f3ae7cSJonas Devlieghere m_threads.push_back(std::make_unique<NativeThreadWindows>( 4145146a9eaSAaron Smith *this, m_session_data->m_debugger->GetMainThread())); 4155146a9eaSAaron Smith } 4165146a9eaSAaron Smith 4175146a9eaSAaron Smith ExceptionResult 4185146a9eaSAaron Smith NativeProcessWindows::OnDebugException(bool first_chance, 4195146a9eaSAaron Smith const ExceptionRecord &record) { 4205146a9eaSAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); 4215146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 4225146a9eaSAaron Smith 4235146a9eaSAaron Smith // Let the debugger establish the internal status. 4245146a9eaSAaron Smith ProcessDebugger::OnDebugException(first_chance, record); 4255146a9eaSAaron Smith 4265146a9eaSAaron Smith static bool initial_stop = false; 4275146a9eaSAaron Smith if (!first_chance) { 4285146a9eaSAaron Smith SetState(eStateStopped, false); 4295146a9eaSAaron Smith } 4305146a9eaSAaron Smith 4315146a9eaSAaron Smith ExceptionResult result = ExceptionResult::SendToApplication; 4325146a9eaSAaron Smith switch (record.GetExceptionCode()) { 433e7823a53SSaleem Abdulrasool case DWORD(STATUS_SINGLE_STEP): 434*5b5274eaSAleksandr Urakov case STATUS_WX86_SINGLE_STEP: { 435*5b5274eaSAleksandr Urakov uint32_t wp_id = LLDB_INVALID_INDEX32; 436*5b5274eaSAleksandr Urakov if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) { 437*5b5274eaSAleksandr Urakov NativeRegisterContextWindows ®_ctx = thread->GetRegisterContext(); 438*5b5274eaSAleksandr Urakov Status error = 439*5b5274eaSAleksandr Urakov reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress()); 440*5b5274eaSAleksandr Urakov if (error.Fail()) 441*5b5274eaSAleksandr Urakov LLDB_LOG(log, 442*5b5274eaSAleksandr Urakov "received error while checking for watchpoint hits, pid = " 443*5b5274eaSAleksandr Urakov "{0}, error = {1}", 444*5b5274eaSAleksandr Urakov thread->GetID(), error); 445*5b5274eaSAleksandr Urakov if (wp_id != LLDB_INVALID_INDEX32) { 446*5b5274eaSAleksandr Urakov addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id); 447*5b5274eaSAleksandr Urakov addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id); 448*5b5274eaSAleksandr Urakov std::string desc = 449*5b5274eaSAleksandr Urakov formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str(); 450*5b5274eaSAleksandr Urakov StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint, 451*5b5274eaSAleksandr Urakov desc); 452*5b5274eaSAleksandr Urakov } 453*5b5274eaSAleksandr Urakov } 454*5b5274eaSAleksandr Urakov if (wp_id == LLDB_INVALID_INDEX32) 4555146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonTrace); 456*5b5274eaSAleksandr Urakov 4575146a9eaSAaron Smith SetState(eStateStopped, true); 4585146a9eaSAaron Smith 4595146a9eaSAaron Smith // Continue the debugger. 4605146a9eaSAaron Smith return ExceptionResult::MaskException; 461*5b5274eaSAleksandr Urakov } 462e7823a53SSaleem Abdulrasool case DWORD(STATUS_BREAKPOINT): 4635146a9eaSAaron Smith case STATUS_WX86_BREAKPOINT: 4645146a9eaSAaron Smith if (FindSoftwareBreakpoint(record.GetExceptionAddress())) { 4655146a9eaSAaron Smith LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", 4665146a9eaSAaron Smith record.GetExceptionAddress()); 4675146a9eaSAaron Smith 4685146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint); 4695146a9eaSAaron Smith 4705146a9eaSAaron Smith if (NativeThreadWindows *stop_thread = 4715146a9eaSAaron Smith GetThreadByID(record.GetThreadID())) { 4725146a9eaSAaron Smith auto ®ister_context = stop_thread->GetRegisterContext(); 4735146a9eaSAaron Smith // The current EIP is AFTER the BP opcode, which is one byte '0xCC' 4745146a9eaSAaron Smith uint64_t pc = register_context.GetPC() - 1; 4755146a9eaSAaron Smith register_context.SetPC(pc); 4765146a9eaSAaron Smith } 4775146a9eaSAaron Smith 4785146a9eaSAaron Smith SetState(eStateStopped, true); 4795146a9eaSAaron Smith return ExceptionResult::MaskException; 4805146a9eaSAaron Smith } 4815146a9eaSAaron Smith 4825146a9eaSAaron Smith if (!initial_stop) { 4835146a9eaSAaron Smith initial_stop = true; 4845146a9eaSAaron Smith LLDB_LOG(log, 4855146a9eaSAaron Smith "Hit loader breakpoint at address {0:x}, setting initial stop " 4865146a9eaSAaron Smith "event.", 4875146a9eaSAaron Smith record.GetExceptionAddress()); 4885146a9eaSAaron Smith 4895146a9eaSAaron Smith // We are required to report the reason for the first stop after 4905146a9eaSAaron Smith // launching or being attached. 4915146a9eaSAaron Smith if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) 4925146a9eaSAaron Smith SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint); 4935146a9eaSAaron Smith 4945146a9eaSAaron Smith // Do not notify the native delegate (e.g. llgs) since at this moment 4955146a9eaSAaron Smith // the program hasn't returned from Factory::Launch() and the delegate 4965146a9eaSAaron Smith // might not have an valid native process to operate on. 4975146a9eaSAaron Smith SetState(eStateStopped, false); 4985146a9eaSAaron Smith 4995146a9eaSAaron Smith // Hit the initial stop. Continue the application. 5005146a9eaSAaron Smith return ExceptionResult::BreakInDebugger; 5015146a9eaSAaron Smith } 5025146a9eaSAaron Smith 5035c38730dSMartin Storsjo LLVM_FALLTHROUGH; 5045146a9eaSAaron Smith default: 5055146a9eaSAaron Smith LLDB_LOG(log, 5065146a9eaSAaron Smith "Debugger thread reported exception {0:x} at address {1:x} " 5075146a9eaSAaron Smith "(first_chance={2})", 5085146a9eaSAaron Smith record.GetExceptionCode(), record.GetExceptionAddress(), 5095146a9eaSAaron Smith first_chance); 5105146a9eaSAaron Smith 5115146a9eaSAaron Smith { 5125146a9eaSAaron Smith std::string desc; 5135146a9eaSAaron Smith llvm::raw_string_ostream desc_stream(desc); 5145146a9eaSAaron Smith desc_stream << "Exception " 5155146a9eaSAaron Smith << llvm::format_hex(record.GetExceptionCode(), 8) 5165146a9eaSAaron Smith << " encountered at address " 5175146a9eaSAaron Smith << llvm::format_hex(record.GetExceptionAddress(), 8); 5185146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonException, 5195146a9eaSAaron Smith desc_stream.str().c_str()); 5205146a9eaSAaron Smith 5215146a9eaSAaron Smith SetState(eStateStopped, true); 5225146a9eaSAaron Smith } 5235146a9eaSAaron Smith 5245146a9eaSAaron Smith // For non-breakpoints, give the application a chance to handle the 5255146a9eaSAaron Smith // exception first. 5265146a9eaSAaron Smith if (first_chance) 5275146a9eaSAaron Smith result = ExceptionResult::SendToApplication; 5285146a9eaSAaron Smith else 5295146a9eaSAaron Smith result = ExceptionResult::BreakInDebugger; 5305146a9eaSAaron Smith } 5315146a9eaSAaron Smith 5325146a9eaSAaron Smith return result; 5335146a9eaSAaron Smith } 5345146a9eaSAaron Smith 5355146a9eaSAaron Smith void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) { 5365146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 537*5b5274eaSAleksandr Urakov 538*5b5274eaSAleksandr Urakov auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread); 539*5b5274eaSAleksandr Urakov thread->GetRegisterContext().ClearAllHardwareWatchpoints(); 540*5b5274eaSAleksandr Urakov for (const auto &pair : GetWatchpointMap()) { 541*5b5274eaSAleksandr Urakov const NativeWatchpoint &wp = pair.second; 542*5b5274eaSAleksandr Urakov thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, 543*5b5274eaSAleksandr Urakov wp.m_hardware); 544*5b5274eaSAleksandr Urakov } 545*5b5274eaSAleksandr Urakov 546*5b5274eaSAleksandr Urakov m_threads.push_back(std::move(thread)); 5475146a9eaSAaron Smith } 5485146a9eaSAaron Smith 5495146a9eaSAaron Smith void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id, 5505146a9eaSAaron Smith uint32_t exit_code) { 5515146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 5525146a9eaSAaron Smith NativeThreadWindows *thread = GetThreadByID(thread_id); 5535146a9eaSAaron Smith if (!thread) 5545146a9eaSAaron Smith return; 5555146a9eaSAaron Smith 5565146a9eaSAaron Smith for (auto t = m_threads.begin(); t != m_threads.end();) { 5575146a9eaSAaron Smith if ((*t)->GetID() == thread_id) { 5585146a9eaSAaron Smith t = m_threads.erase(t); 5595146a9eaSAaron Smith } else { 5605146a9eaSAaron Smith ++t; 5615146a9eaSAaron Smith } 5625146a9eaSAaron Smith } 5635146a9eaSAaron Smith } 5645146a9eaSAaron Smith 5655146a9eaSAaron Smith void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec, 5665146a9eaSAaron Smith lldb::addr_t module_addr) { 5675146a9eaSAaron Smith // Simply invalidate the cached loaded modules. 5685146a9eaSAaron Smith if (!m_loaded_modules.empty()) 5695146a9eaSAaron Smith m_loaded_modules.clear(); 5705146a9eaSAaron Smith } 5715146a9eaSAaron Smith 5725146a9eaSAaron Smith void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { 5735146a9eaSAaron Smith if (!m_loaded_modules.empty()) 5745146a9eaSAaron Smith m_loaded_modules.clear(); 5755146a9eaSAaron Smith } 5765146a9eaSAaron Smith 5775146a9eaSAaron Smith llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 5785146a9eaSAaron Smith NativeProcessWindows::Factory::Launch( 5795146a9eaSAaron Smith ProcessLaunchInfo &launch_info, 5805146a9eaSAaron Smith NativeProcessProtocol::NativeDelegate &native_delegate, 5815146a9eaSAaron Smith MainLoop &mainloop) const { 5825146a9eaSAaron Smith Error E = Error::success(); 5835146a9eaSAaron Smith auto process_up = std::unique_ptr<NativeProcessWindows>( 5845146a9eaSAaron Smith new NativeProcessWindows(launch_info, native_delegate, E)); 5855146a9eaSAaron Smith if (E) 5865146a9eaSAaron Smith return std::move(E); 5875146a9eaSAaron Smith return std::move(process_up); 5885146a9eaSAaron Smith } 5895146a9eaSAaron Smith 5905146a9eaSAaron Smith llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 5915146a9eaSAaron Smith NativeProcessWindows::Factory::Attach( 5925146a9eaSAaron Smith lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, 5935146a9eaSAaron Smith MainLoop &mainloop) const { 5945146a9eaSAaron Smith Error E = Error::success(); 5955146a9eaSAaron Smith // Set pty master fd invalid since it is not available. 5965146a9eaSAaron Smith auto process_up = std::unique_ptr<NativeProcessWindows>( 5975146a9eaSAaron Smith new NativeProcessWindows(pid, -1, native_delegate, E)); 5985146a9eaSAaron Smith if (E) 5995146a9eaSAaron Smith return std::move(E); 6005146a9eaSAaron Smith return std::move(process_up); 6015146a9eaSAaron Smith } 6025146a9eaSAaron Smith } // namespace lldb_private 603