180814287SRaphael Isemann //===-- NativeProcessWindows.cpp ------------------------------------------===// 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, 5164ec505dSJonas Devlieghere launch_info.GetPTY().ReleasePrimaryFileDescriptor(), 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) { 876730df47SPavel Labath Log *log = GetLog(WindowsLog::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: 120b4f2d7cdSMichał Górny break; 1215146a9eaSAaron Smith 1225146a9eaSAaron Smith default: 1236ae657b0SAdrian Prantl return Status::FromErrorStringWithFormat( 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) { 1320642cd76SAdrian Prantl error = Status::FromErrorString("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; 1716730df47SPavel Labath Log *log = GetLog(WindowsLog::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 { 1800642cd76SAdrian Prantl error = Status::FromErrorStringWithFormatv( 1810642cd76SAdrian Prantl "error: process {0} in state = {1}, but " 1825146a9eaSAaron Smith "cannot detach it in this state.", 1835146a9eaSAaron Smith GetID(), state); 1845146a9eaSAaron Smith LLDB_LOG(log, "error: {0}", error); 1855146a9eaSAaron Smith } 1865146a9eaSAaron Smith return error; 1875146a9eaSAaron Smith } 1885146a9eaSAaron Smith 1895146a9eaSAaron Smith Status NativeProcessWindows::Signal(int signo) { 1905146a9eaSAaron Smith Status error; 1910642cd76SAdrian Prantl error = Status::FromErrorString( 1920642cd76SAdrian Prantl "Windows does not support sending signals to processes"); 1935146a9eaSAaron Smith return error; 1945146a9eaSAaron Smith } 1955146a9eaSAaron Smith 1965146a9eaSAaron Smith Status NativeProcessWindows::Interrupt() { return Halt(); } 1975146a9eaSAaron Smith 1985146a9eaSAaron Smith Status NativeProcessWindows::Kill() { 1995146a9eaSAaron Smith StateType state = GetState(); 2005146a9eaSAaron Smith return DestroyProcess(state); 2015146a9eaSAaron Smith } 2025146a9eaSAaron Smith 2035146a9eaSAaron Smith Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) { 2045146a9eaSAaron Smith return Status(); 2055146a9eaSAaron Smith } 2065146a9eaSAaron Smith 2075146a9eaSAaron Smith Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr, 2085146a9eaSAaron Smith MemoryRegionInfo &range_info) { 2095146a9eaSAaron Smith return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info); 2105146a9eaSAaron Smith } 2115146a9eaSAaron Smith 2125146a9eaSAaron Smith Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf, 2135146a9eaSAaron Smith size_t size, size_t &bytes_read) { 2145146a9eaSAaron Smith return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read); 2155146a9eaSAaron Smith } 2165146a9eaSAaron Smith 2175146a9eaSAaron Smith Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf, 2185146a9eaSAaron Smith size_t size, size_t &bytes_written) { 2195146a9eaSAaron Smith return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written); 2205146a9eaSAaron Smith } 2215146a9eaSAaron Smith 2222c4226f8SPavel Labath llvm::Expected<lldb::addr_t> 2232c4226f8SPavel Labath NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) { 2242c4226f8SPavel Labath lldb::addr_t addr; 2252c4226f8SPavel Labath Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr); 2262c4226f8SPavel Labath if (ST.Success()) 2272c4226f8SPavel Labath return addr; 2282c4226f8SPavel Labath return ST.ToError(); 2295146a9eaSAaron Smith } 2305146a9eaSAaron Smith 2312c4226f8SPavel Labath llvm::Error NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) { 2322c4226f8SPavel Labath return ProcessDebugger::DeallocateMemory(addr).ToError(); 2335146a9eaSAaron Smith } 2345146a9eaSAaron Smith 2355146a9eaSAaron Smith lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; } 2365146a9eaSAaron Smith 2375146a9eaSAaron Smith bool NativeProcessWindows::IsAlive() const { 2385146a9eaSAaron Smith StateType state = GetState(); 2395146a9eaSAaron Smith switch (state) { 2405146a9eaSAaron Smith case eStateCrashed: 2415146a9eaSAaron Smith case eStateDetached: 2425146a9eaSAaron Smith case eStateExited: 2435146a9eaSAaron Smith case eStateInvalid: 2445146a9eaSAaron Smith case eStateUnloaded: 2455146a9eaSAaron Smith return false; 2465146a9eaSAaron Smith default: 2475146a9eaSAaron Smith return true; 2485146a9eaSAaron Smith } 2495146a9eaSAaron Smith } 2505146a9eaSAaron Smith 2515146a9eaSAaron Smith void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread, 2525146a9eaSAaron Smith lldb::StopReason reason, 2535146a9eaSAaron Smith std::string description) { 2545146a9eaSAaron Smith SetCurrentThreadID(thread.GetID()); 2555146a9eaSAaron Smith 2565146a9eaSAaron Smith ThreadStopInfo stop_info; 2575146a9eaSAaron Smith stop_info.reason = reason; 2585146a9eaSAaron Smith // No signal support on Windows but required to provide a 'valid' signum. 259d6b3de72SMichał Górny stop_info.signo = SIGTRAP; 260d6b3de72SMichał Górny 2615146a9eaSAaron Smith if (reason == StopReason::eStopReasonException) { 2625146a9eaSAaron Smith stop_info.details.exception.type = 0; 2635146a9eaSAaron Smith stop_info.details.exception.data_count = 0; 2645146a9eaSAaron Smith } 2655146a9eaSAaron Smith 2665146a9eaSAaron Smith thread.SetStopReason(stop_info, description); 2675146a9eaSAaron Smith } 2685146a9eaSAaron Smith 2695146a9eaSAaron Smith void NativeProcessWindows::StopThread(lldb::tid_t thread_id, 2705146a9eaSAaron Smith lldb::StopReason reason, 2715146a9eaSAaron Smith std::string description) { 2725146a9eaSAaron Smith NativeThreadWindows *thread = GetThreadByID(thread_id); 2735146a9eaSAaron Smith if (!thread) 2745146a9eaSAaron Smith return; 2755146a9eaSAaron Smith 2765146a9eaSAaron Smith for (uint32_t i = 0; i < m_threads.size(); ++i) { 2775146a9eaSAaron Smith auto t = static_cast<NativeThreadWindows *>(m_threads[i].get()); 2785146a9eaSAaron Smith Status error = t->DoStop(); 2795146a9eaSAaron Smith if (error.Fail()) 2805146a9eaSAaron Smith exit(1); 2815146a9eaSAaron Smith } 2825146a9eaSAaron Smith SetStopReasonForThread(*thread, reason, description); 2835146a9eaSAaron Smith } 2845146a9eaSAaron Smith 2855146a9eaSAaron Smith size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); } 2865146a9eaSAaron Smith 2875146a9eaSAaron Smith llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 2885146a9eaSAaron Smith NativeProcessWindows::GetAuxvData() const { 2895146a9eaSAaron Smith // Not available on this target. 2905146a9eaSAaron Smith return llvm::errc::not_supported; 2915146a9eaSAaron Smith } 2925146a9eaSAaron Smith 2939f34f75fSMartin Storsjö llvm::Expected<llvm::ArrayRef<uint8_t>> 2949f34f75fSMartin Storsjö NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { 2959f34f75fSMartin Storsjö static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000 2969f34f75fSMartin Storsjö static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe 2979f34f75fSMartin Storsjö 2989f34f75fSMartin Storsjö switch (GetArchitecture().GetMachine()) { 2999f34f75fSMartin Storsjö case llvm::Triple::aarch64: 300984b800aSserge-sans-paille return llvm::ArrayRef(g_aarch64_opcode); 3019f34f75fSMartin Storsjö 3029f34f75fSMartin Storsjö case llvm::Triple::arm: 3039f34f75fSMartin Storsjö case llvm::Triple::thumb: 304984b800aSserge-sans-paille return llvm::ArrayRef(g_thumb_opcode); 3059f34f75fSMartin Storsjö 3069f34f75fSMartin Storsjö default: 3079f34f75fSMartin Storsjö return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint); 3089f34f75fSMartin Storsjö } 3099f34f75fSMartin Storsjö } 3109f34f75fSMartin Storsjö 3119f34f75fSMartin Storsjö size_t NativeProcessWindows::GetSoftwareBreakpointPCOffset() { 3129f34f75fSMartin Storsjö // Windows always reports an incremented PC after a breakpoint is hit, 3139f34f75fSMartin Storsjö // even on ARM. 3149f34f75fSMartin Storsjö return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size(); 3159f34f75fSMartin Storsjö } 3169f34f75fSMartin Storsjö 3175146a9eaSAaron Smith bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) { 3185146a9eaSAaron Smith auto it = m_software_breakpoints.find(addr); 3195146a9eaSAaron Smith if (it == m_software_breakpoints.end()) 3205146a9eaSAaron Smith return false; 3215146a9eaSAaron Smith return true; 3225146a9eaSAaron Smith } 3235146a9eaSAaron Smith 3245146a9eaSAaron Smith Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size, 3255146a9eaSAaron Smith bool hardware) { 3265146a9eaSAaron Smith if (hardware) 3275146a9eaSAaron Smith return SetHardwareBreakpoint(addr, size); 3285146a9eaSAaron Smith return SetSoftwareBreakpoint(addr, size); 3295146a9eaSAaron Smith } 3305146a9eaSAaron Smith 3315146a9eaSAaron Smith Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr, 3325146a9eaSAaron Smith bool hardware) { 3335146a9eaSAaron Smith if (hardware) 3345146a9eaSAaron Smith return RemoveHardwareBreakpoint(addr); 3355146a9eaSAaron Smith return RemoveSoftwareBreakpoint(addr); 3365146a9eaSAaron Smith } 3375146a9eaSAaron Smith 3385146a9eaSAaron Smith Status NativeProcessWindows::CacheLoadedModules() { 3395146a9eaSAaron Smith Status error; 3405146a9eaSAaron Smith if (!m_loaded_modules.empty()) 3415146a9eaSAaron Smith return Status(); 3425146a9eaSAaron Smith 3435146a9eaSAaron Smith // Retrieve loaded modules by a Target/Module free implemenation. 3445146a9eaSAaron Smith AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID())); 3455146a9eaSAaron Smith if (snapshot.IsValid()) { 3465146a9eaSAaron Smith MODULEENTRY32W me; 3475146a9eaSAaron Smith me.dwSize = sizeof(MODULEENTRY32W); 3485146a9eaSAaron Smith if (Module32FirstW(snapshot.get(), &me)) { 3495146a9eaSAaron Smith do { 3505146a9eaSAaron Smith std::string path; 3515146a9eaSAaron Smith if (!llvm::convertWideToUTF8(me.szExePath, path)) 3525146a9eaSAaron Smith continue; 3535146a9eaSAaron Smith 3545146a9eaSAaron Smith FileSpec file_spec(path); 3555146a9eaSAaron Smith FileSystem::Instance().Resolve(file_spec); 3565146a9eaSAaron Smith m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr; 3575146a9eaSAaron Smith } while (Module32Next(snapshot.get(), &me)); 3585146a9eaSAaron Smith } 3595146a9eaSAaron Smith 3605146a9eaSAaron Smith if (!m_loaded_modules.empty()) 3615146a9eaSAaron Smith return Status(); 3625146a9eaSAaron Smith } 3635146a9eaSAaron Smith 3646ae657b0SAdrian Prantl error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32); 3655146a9eaSAaron Smith return error; 3665146a9eaSAaron Smith } 3675146a9eaSAaron Smith 3685146a9eaSAaron Smith Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path, 3695146a9eaSAaron Smith FileSpec &file_spec) { 3705146a9eaSAaron Smith Status error = CacheLoadedModules(); 3715146a9eaSAaron Smith if (error.Fail()) 3725146a9eaSAaron Smith return error; 3735146a9eaSAaron Smith 3745146a9eaSAaron Smith FileSpec module_file_spec(module_path); 3755146a9eaSAaron Smith FileSystem::Instance().Resolve(module_file_spec); 3765146a9eaSAaron Smith for (auto &it : m_loaded_modules) { 3775146a9eaSAaron Smith if (it.first == module_file_spec) { 3785146a9eaSAaron Smith file_spec = it.first; 3795146a9eaSAaron Smith return Status(); 3805146a9eaSAaron Smith } 3815146a9eaSAaron Smith } 3820642cd76SAdrian Prantl return Status::FromErrorStringWithFormat( 3830642cd76SAdrian Prantl "Module (%s) not found in process %" PRIu64 "!", 384529a3d87SGreg Clayton module_file_spec.GetPath().c_str(), GetID()); 3855146a9eaSAaron Smith } 3865146a9eaSAaron Smith 3875146a9eaSAaron Smith Status 3885146a9eaSAaron Smith NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name, 3895146a9eaSAaron Smith lldb::addr_t &load_addr) { 3905146a9eaSAaron Smith Status error = CacheLoadedModules(); 3915146a9eaSAaron Smith if (error.Fail()) 3925146a9eaSAaron Smith return error; 3935146a9eaSAaron Smith 3945146a9eaSAaron Smith load_addr = LLDB_INVALID_ADDRESS; 3955146a9eaSAaron Smith FileSpec file_spec(file_name); 3965146a9eaSAaron Smith FileSystem::Instance().Resolve(file_spec); 3975146a9eaSAaron Smith for (auto &it : m_loaded_modules) { 3985146a9eaSAaron Smith if (it.first == file_spec) { 3995146a9eaSAaron Smith load_addr = it.second; 4005146a9eaSAaron Smith return Status(); 4015146a9eaSAaron Smith } 4025146a9eaSAaron Smith } 4030642cd76SAdrian Prantl return Status::FromErrorStringWithFormat( 4040642cd76SAdrian Prantl "Can't get loaded address of file (%s) in process %" PRIu64 "!", 405529a3d87SGreg Clayton file_spec.GetPath().c_str(), GetID()); 4065146a9eaSAaron Smith } 4075146a9eaSAaron Smith 4085146a9eaSAaron Smith void NativeProcessWindows::OnExitProcess(uint32_t exit_code) { 4096730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 4105146a9eaSAaron Smith LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code); 4115146a9eaSAaron Smith 4125146a9eaSAaron Smith ProcessDebugger::OnExitProcess(exit_code); 4135146a9eaSAaron Smith 4145146a9eaSAaron Smith // No signal involved. It is just an exit event. 4155146a9eaSAaron Smith WaitStatus wait_status(WaitStatus::Exit, exit_code); 4165146a9eaSAaron Smith SetExitStatus(wait_status, true); 4175146a9eaSAaron Smith 4185146a9eaSAaron Smith // Notify the native delegate. 4195146a9eaSAaron Smith SetState(eStateExited, true); 4205146a9eaSAaron Smith } 4215146a9eaSAaron Smith 4225146a9eaSAaron Smith void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { 4236730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 4245146a9eaSAaron Smith LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}", 4255146a9eaSAaron Smith GetDebuggedProcessId(), image_base); 4265146a9eaSAaron Smith 4275146a9eaSAaron Smith // This is the earliest chance we can resolve the process ID and 428e9264b74SKazuaki Ishizaki // architecture if we don't know them yet. 4295146a9eaSAaron Smith if (GetID() == LLDB_INVALID_PROCESS_ID) 4305146a9eaSAaron Smith SetID(GetDebuggedProcessId()); 4315146a9eaSAaron Smith 4325146a9eaSAaron Smith if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) { 4335146a9eaSAaron Smith ProcessInstanceInfo process_info; 4345146a9eaSAaron Smith if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) { 4355146a9eaSAaron Smith LLDB_LOG(log, "Cannot get process information during debugger connecting " 4365146a9eaSAaron Smith "to process"); 4375146a9eaSAaron Smith return; 4385146a9eaSAaron Smith } 4395146a9eaSAaron Smith SetArchitecture(process_info.GetArchitecture()); 4405146a9eaSAaron Smith } 4415146a9eaSAaron Smith 4425146a9eaSAaron Smith // The very first one shall always be the main thread. 4435146a9eaSAaron Smith assert(m_threads.empty()); 444a8f3ae7cSJonas Devlieghere m_threads.push_back(std::make_unique<NativeThreadWindows>( 4455146a9eaSAaron Smith *this, m_session_data->m_debugger->GetMainThread())); 4465146a9eaSAaron Smith } 4475146a9eaSAaron Smith 4485146a9eaSAaron Smith ExceptionResult 4495146a9eaSAaron Smith NativeProcessWindows::OnDebugException(bool first_chance, 4505146a9eaSAaron Smith const ExceptionRecord &record) { 4516730df47SPavel Labath Log *log = GetLog(WindowsLog::Exception); 4525146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 4535146a9eaSAaron Smith 4545146a9eaSAaron Smith // Let the debugger establish the internal status. 4555146a9eaSAaron Smith ProcessDebugger::OnDebugException(first_chance, record); 4565146a9eaSAaron Smith 4575146a9eaSAaron Smith static bool initial_stop = false; 4585146a9eaSAaron Smith if (!first_chance) { 4595146a9eaSAaron Smith SetState(eStateStopped, false); 4605146a9eaSAaron Smith } 4615146a9eaSAaron Smith 4625146a9eaSAaron Smith ExceptionResult result = ExceptionResult::SendToApplication; 4635146a9eaSAaron Smith switch (record.GetExceptionCode()) { 464e7823a53SSaleem Abdulrasool case DWORD(STATUS_SINGLE_STEP): 4655b5274eaSAleksandr Urakov case STATUS_WX86_SINGLE_STEP: { 4665b5274eaSAleksandr Urakov uint32_t wp_id = LLDB_INVALID_INDEX32; 4675b5274eaSAleksandr Urakov if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) { 4685b5274eaSAleksandr Urakov NativeRegisterContextWindows ®_ctx = thread->GetRegisterContext(); 4695b5274eaSAleksandr Urakov Status error = 4705b5274eaSAleksandr Urakov reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress()); 4715b5274eaSAleksandr Urakov if (error.Fail()) 4725b5274eaSAleksandr Urakov LLDB_LOG(log, 4735b5274eaSAleksandr Urakov "received error while checking for watchpoint hits, pid = " 4745b5274eaSAleksandr Urakov "{0}, error = {1}", 4755b5274eaSAleksandr Urakov thread->GetID(), error); 4765b5274eaSAleksandr Urakov if (wp_id != LLDB_INVALID_INDEX32) { 4775b5274eaSAleksandr Urakov addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id); 4785b5274eaSAleksandr Urakov addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id); 4795b5274eaSAleksandr Urakov std::string desc = 4805b5274eaSAleksandr Urakov formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str(); 4815b5274eaSAleksandr Urakov StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint, 4825b5274eaSAleksandr Urakov desc); 4835b5274eaSAleksandr Urakov } 4845b5274eaSAleksandr Urakov } 4855b5274eaSAleksandr Urakov if (wp_id == LLDB_INVALID_INDEX32) 4865146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonTrace); 4875b5274eaSAleksandr Urakov 4885146a9eaSAaron Smith SetState(eStateStopped, true); 4895146a9eaSAaron Smith 4905146a9eaSAaron Smith // Continue the debugger. 4915146a9eaSAaron Smith return ExceptionResult::MaskException; 4925b5274eaSAleksandr Urakov } 493e7823a53SSaleem Abdulrasool case DWORD(STATUS_BREAKPOINT): 4945146a9eaSAaron Smith case STATUS_WX86_BREAKPOINT: 4955146a9eaSAaron Smith if (FindSoftwareBreakpoint(record.GetExceptionAddress())) { 4965146a9eaSAaron Smith LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", 4975146a9eaSAaron Smith record.GetExceptionAddress()); 4985146a9eaSAaron Smith 4995146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint); 5005146a9eaSAaron Smith 5015146a9eaSAaron Smith if (NativeThreadWindows *stop_thread = 5025146a9eaSAaron Smith GetThreadByID(record.GetThreadID())) { 5035146a9eaSAaron Smith auto ®ister_context = stop_thread->GetRegisterContext(); 5049f34f75fSMartin Storsjö uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset(); 5059f34f75fSMartin Storsjö // The current PC is AFTER the BP opcode, on all architectures. 5069f34f75fSMartin Storsjö uint64_t pc = register_context.GetPC() - breakpoint_size; 5075146a9eaSAaron Smith register_context.SetPC(pc); 5085146a9eaSAaron Smith } 5095146a9eaSAaron Smith 5105146a9eaSAaron Smith SetState(eStateStopped, true); 5115146a9eaSAaron Smith return ExceptionResult::MaskException; 5125146a9eaSAaron Smith } 5135146a9eaSAaron Smith 5145146a9eaSAaron Smith if (!initial_stop) { 5155146a9eaSAaron Smith initial_stop = true; 5165146a9eaSAaron Smith LLDB_LOG(log, 5175146a9eaSAaron Smith "Hit loader breakpoint at address {0:x}, setting initial stop " 5185146a9eaSAaron Smith "event.", 5195146a9eaSAaron Smith record.GetExceptionAddress()); 5205146a9eaSAaron Smith 5215146a9eaSAaron Smith // We are required to report the reason for the first stop after 5225146a9eaSAaron Smith // launching or being attached. 5235146a9eaSAaron Smith if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) 5245146a9eaSAaron Smith SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint); 5255146a9eaSAaron Smith 5265146a9eaSAaron Smith // Do not notify the native delegate (e.g. llgs) since at this moment 527e64cc756SPavel Labath // the program hasn't returned from Manager::Launch() and the delegate 5285146a9eaSAaron Smith // might not have an valid native process to operate on. 5295146a9eaSAaron Smith SetState(eStateStopped, false); 5305146a9eaSAaron Smith 5315146a9eaSAaron Smith // Hit the initial stop. Continue the application. 5325146a9eaSAaron Smith return ExceptionResult::BreakInDebugger; 5335146a9eaSAaron Smith } 5345146a9eaSAaron Smith 53559d2495fSFangrui Song [[fallthrough]]; 5365146a9eaSAaron Smith default: 5375146a9eaSAaron Smith LLDB_LOG(log, 5385146a9eaSAaron Smith "Debugger thread reported exception {0:x} at address {1:x} " 5395146a9eaSAaron Smith "(first_chance={2})", 5405146a9eaSAaron Smith record.GetExceptionCode(), record.GetExceptionAddress(), 5415146a9eaSAaron Smith first_chance); 5425146a9eaSAaron Smith 5435146a9eaSAaron Smith { 5445146a9eaSAaron Smith std::string desc; 5455146a9eaSAaron Smith llvm::raw_string_ostream desc_stream(desc); 5465146a9eaSAaron Smith desc_stream << "Exception " 5475146a9eaSAaron Smith << llvm::format_hex(record.GetExceptionCode(), 8) 5485146a9eaSAaron Smith << " encountered at address " 5495146a9eaSAaron Smith << llvm::format_hex(record.GetExceptionAddress(), 8); 5505146a9eaSAaron Smith StopThread(record.GetThreadID(), StopReason::eStopReasonException, 551*d7796855SYoungsuk Kim desc.c_str()); 5525146a9eaSAaron Smith 5535146a9eaSAaron Smith SetState(eStateStopped, true); 5545146a9eaSAaron Smith } 5555146a9eaSAaron Smith 5565146a9eaSAaron Smith // For non-breakpoints, give the application a chance to handle the 5575146a9eaSAaron Smith // exception first. 5585146a9eaSAaron Smith if (first_chance) 5595146a9eaSAaron Smith result = ExceptionResult::SendToApplication; 5605146a9eaSAaron Smith else 5615146a9eaSAaron Smith result = ExceptionResult::BreakInDebugger; 5625146a9eaSAaron Smith } 5635146a9eaSAaron Smith 5645146a9eaSAaron Smith return result; 5655146a9eaSAaron Smith } 5665146a9eaSAaron Smith 5675146a9eaSAaron Smith void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) { 5685146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 5695b5274eaSAleksandr Urakov 5705b5274eaSAleksandr Urakov auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread); 5715b5274eaSAleksandr Urakov thread->GetRegisterContext().ClearAllHardwareWatchpoints(); 5725b5274eaSAleksandr Urakov for (const auto &pair : GetWatchpointMap()) { 5735b5274eaSAleksandr Urakov const NativeWatchpoint &wp = pair.second; 5745b5274eaSAleksandr Urakov thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, 5755b5274eaSAleksandr Urakov wp.m_hardware); 5765b5274eaSAleksandr Urakov } 5775b5274eaSAleksandr Urakov 5785b5274eaSAleksandr Urakov m_threads.push_back(std::move(thread)); 5795146a9eaSAaron Smith } 5805146a9eaSAaron Smith 5815146a9eaSAaron Smith void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id, 5825146a9eaSAaron Smith uint32_t exit_code) { 5835146a9eaSAaron Smith llvm::sys::ScopedLock lock(m_mutex); 5845146a9eaSAaron Smith NativeThreadWindows *thread = GetThreadByID(thread_id); 5855146a9eaSAaron Smith if (!thread) 5865146a9eaSAaron Smith return; 5875146a9eaSAaron Smith 5885146a9eaSAaron Smith for (auto t = m_threads.begin(); t != m_threads.end();) { 5895146a9eaSAaron Smith if ((*t)->GetID() == thread_id) { 5905146a9eaSAaron Smith t = m_threads.erase(t); 5915146a9eaSAaron Smith } else { 5925146a9eaSAaron Smith ++t; 5935146a9eaSAaron Smith } 5945146a9eaSAaron Smith } 5955146a9eaSAaron Smith } 5965146a9eaSAaron Smith 5975146a9eaSAaron Smith void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec, 5985146a9eaSAaron Smith lldb::addr_t module_addr) { 5995146a9eaSAaron Smith // Simply invalidate the cached loaded modules. 6005146a9eaSAaron Smith if (!m_loaded_modules.empty()) 6015146a9eaSAaron Smith m_loaded_modules.clear(); 6025146a9eaSAaron Smith } 6035146a9eaSAaron Smith 6045146a9eaSAaron Smith void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { 6055146a9eaSAaron Smith if (!m_loaded_modules.empty()) 6065146a9eaSAaron Smith m_loaded_modules.clear(); 6075146a9eaSAaron Smith } 6085146a9eaSAaron Smith 6095146a9eaSAaron Smith llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 610e64cc756SPavel Labath NativeProcessWindows::Manager::Launch( 6115146a9eaSAaron Smith ProcessLaunchInfo &launch_info, 612e64cc756SPavel Labath NativeProcessProtocol::NativeDelegate &native_delegate) { 6135146a9eaSAaron Smith Error E = Error::success(); 6145146a9eaSAaron Smith auto process_up = std::unique_ptr<NativeProcessWindows>( 6155146a9eaSAaron Smith new NativeProcessWindows(launch_info, native_delegate, E)); 6165146a9eaSAaron Smith if (E) 6175146a9eaSAaron Smith return std::move(E); 6185146a9eaSAaron Smith return std::move(process_up); 6195146a9eaSAaron Smith } 6205146a9eaSAaron Smith 6215146a9eaSAaron Smith llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 622e64cc756SPavel Labath NativeProcessWindows::Manager::Attach( 623e64cc756SPavel Labath lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) { 6245146a9eaSAaron Smith Error E = Error::success(); 62552a3ed5bSQuinn Pham // Set pty primary fd invalid since it is not available. 6265146a9eaSAaron Smith auto process_up = std::unique_ptr<NativeProcessWindows>( 6275146a9eaSAaron Smith new NativeProcessWindows(pid, -1, native_delegate, E)); 6285146a9eaSAaron Smith if (E) 6295146a9eaSAaron Smith return std::move(E); 6305146a9eaSAaron Smith return std::move(process_up); 6315146a9eaSAaron Smith } 6325146a9eaSAaron Smith } // namespace lldb_private 633