663 lines · cpp
1//===-- NativeProcessWindows.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/windows/windows.h"10#include <psapi.h>11 12#include "NativeProcessWindows.h"13#include "NativeThreadWindows.h"14#include "lldb/Host/FileSystem.h"15#include "lldb/Host/HostNativeProcessBase.h"16#include "lldb/Host/HostProcess.h"17#include "lldb/Host/ProcessLaunchInfo.h"18#include "lldb/Host/windows/AutoHandle.h"19#include "lldb/Host/windows/HostThreadWindows.h"20#include "lldb/Host/windows/ProcessLauncherWindows.h"21#include "lldb/Target/MemoryRegionInfo.h"22#include "lldb/Target/Process.h"23#include "lldb/Utility/State.h"24#include "llvm/Support/ConvertUTF.h"25#include "llvm/Support/Errc.h"26#include "llvm/Support/Error.h"27#include "llvm/Support/Format.h"28#include "llvm/Support/Threading.h"29#include "llvm/Support/raw_ostream.h"30 31#include "DebuggerThread.h"32#include "ExceptionRecord.h"33#include "ProcessWindowsLog.h"34 35#include <tlhelp32.h>36 37#pragma warning(disable : 4005)38#include "winternl.h"39#include <ntstatus.h>40 41using namespace lldb;42using namespace lldb_private;43using namespace llvm;44 45namespace lldb_private {46 47NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,48 NativeDelegate &delegate,49 llvm::Error &E)50 : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,51 launch_info.GetPTY().ReleasePrimaryFileDescriptor(),52 delegate),53 ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {54 ErrorAsOutParameter EOut(&E);55 DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));56 E = LaunchProcess(launch_info, delegate_sp).ToError();57 if (E)58 return;59 60 SetID(GetDebuggedProcessId());61}62 63NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd,64 NativeDelegate &delegate,65 llvm::Error &E)66 : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger() {67 ErrorAsOutParameter EOut(&E);68 DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));69 ProcessAttachInfo attach_info;70 attach_info.SetProcessID(pid);71 E = AttachProcess(pid, attach_info, delegate_sp).ToError();72 if (E)73 return;74 75 SetID(GetDebuggedProcessId());76 77 ProcessInstanceInfo info;78 if (!Host::GetProcessInfo(pid, info)) {79 E = createStringError(inconvertibleErrorCode(),80 "Cannot get process information");81 return;82 }83 m_arch = info.GetArchitecture();84}85 86Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {87 Log *log = GetLog(WindowsLog::Process);88 Status error;89 llvm::sys::ScopedLock lock(m_mutex);90 91 StateType state = GetState();92 if (state == eStateStopped || state == eStateCrashed) {93 LLDB_LOG(log, "process {0} is in state {1}. Resuming...",94 GetDebuggedProcessId(), state);95 LLDB_LOG(log, "resuming {0} threads.", m_threads.size());96 97 bool failed = false;98 for (uint32_t i = 0; i < m_threads.size(); ++i) {99 auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());100 const ResumeAction *const action =101 resume_actions.GetActionForThread(thread->GetID(), true);102 if (action == nullptr)103 continue;104 105 switch (action->state) {106 case eStateRunning:107 case eStateStepping: {108 Status result = thread->DoResume(action->state);109 if (result.Fail()) {110 failed = true;111 LLDB_LOG(log,112 "Trying to resume thread at index {0}, but failed with "113 "error {1}.",114 i, result);115 }116 break;117 }118 case eStateSuspended:119 case eStateStopped:120 break;121 122 default:123 return Status::FromErrorStringWithFormat(124 "NativeProcessWindows::%s (): unexpected state %s specified "125 "for pid %" PRIu64 ", tid %" PRIu64,126 __FUNCTION__, StateAsCString(action->state), GetID(),127 thread->GetID());128 }129 }130 131 if (failed) {132 error = Status::FromErrorString("NativeProcessWindows::DoResume failed");133 } else {134 SetState(eStateRunning);135 }136 137 // Resume the debug loop.138 ExceptionRecordSP active_exception =139 m_session_data->m_debugger->GetActiveException().lock();140 if (active_exception) {141 // Resume the process and continue processing debug events. Mask the142 // exception so that from the process's view, there is no indication that143 // anything happened.144 m_session_data->m_debugger->ContinueAsyncException(145 ExceptionResult::MaskException);146 }147 } else {148 LLDB_LOG(log, "error: process {0} is in state {1}. Returning...",149 GetDebuggedProcessId(), GetState());150 }151 152 return error;153}154 155NativeThreadWindows *156NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {157 return static_cast<NativeThreadWindows *>(158 NativeProcessProtocol::GetThreadByID(thread_id));159}160 161Status NativeProcessWindows::Halt() {162 bool caused_stop = false;163 StateType state = GetState();164 if (state != eStateStopped)165 return HaltProcess(caused_stop);166 return Status();167}168 169Status NativeProcessWindows::Detach() {170 Status error;171 Log *log = GetLog(WindowsLog::Process);172 StateType state = GetState();173 if (state != eStateExited && state != eStateDetached) {174 error = DetachProcess();175 if (error.Success())176 SetState(eStateDetached);177 else178 LLDB_LOG(log, "Detaching process error: {0}", error);179 } else {180 error = Status::FromErrorStringWithFormatv(181 "error: process {0} in state = {1}, but "182 "cannot detach it in this state.",183 GetID(), state);184 LLDB_LOG(log, "error: {0}", error);185 }186 return error;187}188 189Status NativeProcessWindows::Signal(int signo) {190 Status error;191 error = Status::FromErrorString(192 "Windows does not support sending signals to processes");193 return error;194}195 196Status NativeProcessWindows::Interrupt() { return Halt(); }197 198Status NativeProcessWindows::Kill() {199 StateType state = GetState();200 return DestroyProcess(state);201}202 203Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {204 return Status();205}206 207Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr,208 MemoryRegionInfo &range_info) {209 return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info);210}211 212Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf,213 size_t size, size_t &bytes_read) {214 return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);215}216 217Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf,218 size_t size, size_t &bytes_written) {219 return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);220}221 222llvm::Expected<lldb::addr_t>223NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) {224 lldb::addr_t addr;225 Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr);226 if (ST.Success())227 return addr;228 return ST.ToError();229}230 231llvm::Error NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) {232 return ProcessDebugger::DeallocateMemory(addr).ToError();233}234 235lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; }236 237bool NativeProcessWindows::IsAlive() const {238 StateType state = GetState();239 switch (state) {240 case eStateCrashed:241 case eStateDetached:242 case eStateExited:243 case eStateInvalid:244 case eStateUnloaded:245 return false;246 default:247 return true;248 }249}250 251void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread,252 lldb::StopReason reason,253 std::string description) {254 SetCurrentThreadID(thread.GetID());255 256 ThreadStopInfo stop_info;257 stop_info.reason = reason;258 // No signal support on Windows but required to provide a 'valid' signum.259 stop_info.signo = SIGTRAP;260 261 if (reason == StopReason::eStopReasonException) {262 stop_info.details.exception.type = 0;263 stop_info.details.exception.data_count = 0;264 }265 266 thread.SetStopReason(stop_info, description);267}268 269void NativeProcessWindows::StopThread(lldb::tid_t thread_id,270 lldb::StopReason reason,271 std::string description) {272 NativeThreadWindows *thread = GetThreadByID(thread_id);273 if (!thread)274 return;275 276 for (uint32_t i = 0; i < m_threads.size(); ++i) {277 auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());278 Status error = t->DoStop();279 if (error.Fail())280 exit(1);281 }282 SetStopReasonForThread(*thread, reason, description);283}284 285size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); }286 287llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>288NativeProcessWindows::GetAuxvData() const {289 // Not available on this target.290 return llvm::errc::not_supported;291}292 293llvm::Expected<llvm::ArrayRef<uint8_t>>294NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {295 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e,296 0xd4}; // brk #0xf000297 static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe298 299 switch (GetArchitecture().GetMachine()) {300 case llvm::Triple::aarch64:301 return llvm::ArrayRef(g_aarch64_opcode);302 303 case llvm::Triple::arm:304 case llvm::Triple::thumb:305 return llvm::ArrayRef(g_thumb_opcode);306 307 default:308 return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);309 }310}311 312size_t NativeProcessWindows::GetSoftwareBreakpointPCOffset() {313 // Windows always reports an incremented PC after a breakpoint is hit,314 // even on ARM.315 return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();316}317 318bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {319 auto it = m_software_breakpoints.find(addr);320 if (it == m_software_breakpoints.end())321 return false;322 return true;323}324 325Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size,326 bool hardware) {327 if (hardware)328 return SetHardwareBreakpoint(addr, size);329 return SetSoftwareBreakpoint(addr, size);330}331 332Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,333 bool hardware) {334 if (hardware)335 return RemoveHardwareBreakpoint(addr);336 return RemoveSoftwareBreakpoint(addr);337}338 339Status NativeProcessWindows::CacheLoadedModules() {340 Status error;341 if (!m_loaded_modules.empty())342 return Status();343 344 // Retrieve loaded modules by a Target/Module free implemenation.345 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));346 if (snapshot.IsValid()) {347 MODULEENTRY32W me;348 me.dwSize = sizeof(MODULEENTRY32W);349 if (Module32FirstW(snapshot.get(), &me)) {350 do {351 std::string path;352 if (!llvm::convertWideToUTF8(me.szExePath, path))353 continue;354 355 FileSpec file_spec(path);356 FileSystem::Instance().Resolve(file_spec);357 m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr;358 } while (Module32Next(snapshot.get(), &me));359 }360 361 if (!m_loaded_modules.empty())362 return Status();363 }364 365 error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);366 return error;367}368 369Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path,370 FileSpec &file_spec) {371 Status error = CacheLoadedModules();372 if (error.Fail())373 return error;374 375 FileSpec module_file_spec(module_path);376 FileSystem::Instance().Resolve(module_file_spec);377 for (auto &it : m_loaded_modules) {378 if (it.first == module_file_spec) {379 file_spec = it.first;380 return Status();381 }382 }383 return Status::FromErrorStringWithFormat(384 "Module (%s) not found in process %" PRIu64 "!",385 module_file_spec.GetPath().c_str(), GetID());386}387 388Status389NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,390 lldb::addr_t &load_addr) {391 Status error = CacheLoadedModules();392 if (error.Fail())393 return error;394 395 load_addr = LLDB_INVALID_ADDRESS;396 FileSpec file_spec(file_name);397 FileSystem::Instance().Resolve(file_spec);398 for (auto &it : m_loaded_modules) {399 if (it.first == file_spec) {400 load_addr = it.second;401 return Status();402 }403 }404 return Status::FromErrorStringWithFormat(405 "Can't get loaded address of file (%s) in process %" PRIu64 "!",406 file_spec.GetPath().c_str(), GetID());407}408 409void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {410 Log *log = GetLog(WindowsLog::Process);411 LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);412 413 ProcessDebugger::OnExitProcess(exit_code);414 415 // No signal involved. It is just an exit event.416 WaitStatus wait_status(WaitStatus::Exit, exit_code);417 SetExitStatus(wait_status, true);418 419 // Notify the native delegate.420 SetState(eStateExited, true);421}422 423void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {424 Log *log = GetLog(WindowsLog::Process);425 LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",426 GetDebuggedProcessId(), image_base);427 428 // This is the earliest chance we can resolve the process ID and429 // architecture if we don't know them yet.430 if (GetID() == LLDB_INVALID_PROCESS_ID)431 SetID(GetDebuggedProcessId());432 433 if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {434 ProcessInstanceInfo process_info;435 if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) {436 LLDB_LOG(log, "Cannot get process information during debugger connecting "437 "to process");438 return;439 }440 SetArchitecture(process_info.GetArchitecture());441 }442 443 // The very first one shall always be the main thread.444 assert(m_threads.empty());445 m_threads.push_back(std::make_unique<NativeThreadWindows>(446 *this, m_session_data->m_debugger->GetMainThread()));447}448 449ExceptionResult450NativeProcessWindows::OnDebugException(bool first_chance,451 const ExceptionRecord &record) {452 Log *log = GetLog(WindowsLog::Exception);453 llvm::sys::ScopedLock lock(m_mutex);454 455 // Let the debugger establish the internal status.456 ProcessDebugger::OnDebugException(first_chance, record);457 458 static bool initial_stop = false;459 if (!first_chance) {460 SetState(eStateStopped, false);461 }462 463 ExceptionResult result = ExceptionResult::SendToApplication;464 switch (record.GetExceptionCode()) {465 case DWORD(STATUS_SINGLE_STEP):466 case STATUS_WX86_SINGLE_STEP: {467#ifndef __aarch64__468 uint32_t wp_id = LLDB_INVALID_INDEX32;469 if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {470 NativeRegisterContextWindows ®_ctx = thread->GetRegisterContext();471 Status error =472 reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());473 if (error.Fail())474 LLDB_LOG(log,475 "received error while checking for watchpoint hits, pid = "476 "{0}, error = {1}",477 thread->GetID(), error);478 if (wp_id != LLDB_INVALID_INDEX32) {479 addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id);480 addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id);481 std::string desc =482 formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str();483 StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint,484 desc);485 }486 }487 if (wp_id == LLDB_INVALID_INDEX32)488#endif489 StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);490 491 SetState(eStateStopped, true);492 493 // Continue the debugger.494 return ExceptionResult::MaskException;495 }496 case DWORD(STATUS_BREAKPOINT):497 case STATUS_WX86_BREAKPOINT:498 499 if (NativeThreadWindows *stop_thread =500 GetThreadByID(record.GetThreadID())) {501 auto ®_ctx = stop_thread->GetRegisterContext();502 const auto exception_addr = record.GetExceptionAddress();503 const auto thread_id = record.GetThreadID();504 505 if (FindSoftwareBreakpoint(exception_addr)) {506 LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",507 exception_addr);508 // The current PC is AFTER the BP opcode, on all architectures.509 reg_ctx.SetPC(reg_ctx.GetPC() - GetSoftwareBreakpointPCOffset());510 StopThread(thread_id, StopReason::eStopReasonBreakpoint);511 SetState(eStateStopped, true);512 return ExceptionResult::MaskException;513 } else {514 // This block of code will only be entered in case of a hardware515 // watchpoint or breakpoint hit on AArch64. However, we only handle516 // hardware watchpoints below as breakpoints are not yet supported.517 const std::vector<ULONG_PTR> &args = record.GetExceptionArguments();518 // Check that the ExceptionInformation array of EXCEPTION_RECORD519 // contains at least two elements: the first is a read-write flag520 // indicating the type of data access operation (read or write) while521 // the second contains the virtual address of the accessed data.522 if (args.size() >= 2) {523 uint32_t hw_id = LLDB_INVALID_INDEX32;524 Status error = reg_ctx.GetWatchpointHitIndex(hw_id, args[1]);525 if (error.Fail())526 LLDB_LOG(log,527 "received error while checking for watchpoint hits, pid = "528 "{0}, error = {1}",529 thread_id, error);530 531 if (hw_id != LLDB_INVALID_INDEX32) {532 std::string desc =533 formatv("{0} {1} {2}", reg_ctx.GetWatchpointAddress(hw_id),534 hw_id, exception_addr)535 .str();536 StopThread(thread_id, StopReason::eStopReasonWatchpoint, desc);537 SetState(eStateStopped, true);538 return ExceptionResult::MaskException;539 }540 }541 }542 }543 544 if (!initial_stop) {545 initial_stop = true;546 LLDB_LOG(log,547 "Hit loader breakpoint at address {0:x}, setting initial stop "548 "event.",549 record.GetExceptionAddress());550 551 // We are required to report the reason for the first stop after552 // launching or being attached.553 if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID()))554 SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint);555 556 // Do not notify the native delegate (e.g. llgs) since at this moment557 // the program hasn't returned from Manager::Launch() and the delegate558 // might not have an valid native process to operate on.559 SetState(eStateStopped, false);560 561 // Hit the initial stop. Continue the application.562 return ExceptionResult::BreakInDebugger;563 }564 565 [[fallthrough]];566 default:567 LLDB_LOG(log,568 "Debugger thread reported exception {0:x} at address {1:x} "569 "(first_chance={2})",570 record.GetExceptionCode(), record.GetExceptionAddress(),571 first_chance);572 573 {574 std::string desc;575 llvm::raw_string_ostream desc_stream(desc);576 desc_stream << "Exception "577 << llvm::format_hex(record.GetExceptionCode(), 8)578 << " encountered at address "579 << llvm::format_hex(record.GetExceptionAddress(), 8);580 StopThread(record.GetThreadID(), StopReason::eStopReasonException,581 desc.c_str());582 583 SetState(eStateStopped, true);584 }585 586 // For non-breakpoints, give the application a chance to handle the587 // exception first.588 if (first_chance)589 result = ExceptionResult::SendToApplication;590 else591 result = ExceptionResult::BreakInDebugger;592 }593 594 return result;595}596 597void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) {598 llvm::sys::ScopedLock lock(m_mutex);599 600 auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread);601 thread->GetRegisterContext().ClearAllHardwareWatchpoints();602 for (const auto &pair : GetWatchpointMap()) {603 const NativeWatchpoint &wp = pair.second;604 thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags,605 wp.m_hardware);606 }607 608 m_threads.push_back(std::move(thread));609}610 611void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,612 uint32_t exit_code) {613 llvm::sys::ScopedLock lock(m_mutex);614 NativeThreadWindows *thread = GetThreadByID(thread_id);615 if (!thread)616 return;617 618 for (auto t = m_threads.begin(); t != m_threads.end();) {619 if ((*t)->GetID() == thread_id) {620 t = m_threads.erase(t);621 } else {622 ++t;623 }624 }625}626 627void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec,628 lldb::addr_t module_addr) {629 // Simply invalidate the cached loaded modules.630 if (!m_loaded_modules.empty())631 m_loaded_modules.clear();632}633 634void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {635 if (!m_loaded_modules.empty())636 m_loaded_modules.clear();637}638 639llvm::Expected<std::unique_ptr<NativeProcessProtocol>>640NativeProcessWindows::Manager::Launch(641 ProcessLaunchInfo &launch_info,642 NativeProcessProtocol::NativeDelegate &native_delegate) {643 Error E = Error::success();644 auto process_up = std::unique_ptr<NativeProcessWindows>(645 new NativeProcessWindows(launch_info, native_delegate, E));646 if (E)647 return std::move(E);648 return std::move(process_up);649}650 651llvm::Expected<std::unique_ptr<NativeProcessProtocol>>652NativeProcessWindows::Manager::Attach(653 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {654 Error E = Error::success();655 // Set pty primary fd invalid since it is not available.656 auto process_up = std::unique_ptr<NativeProcessWindows>(657 new NativeProcessWindows(pid, -1, native_delegate, E));658 if (E)659 return std::move(E);660 return std::move(process_up);661}662} // namespace lldb_private663