958 lines · cpp
1//===-- ProcessWindows.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 "ProcessWindows.h"10 11// Windows includes12#include "lldb/Host/windows/windows.h"13#include <psapi.h>14 15#include "lldb/Breakpoint/Watchpoint.h"16#include "lldb/Core/Module.h"17#include "lldb/Core/ModuleSpec.h"18#include "lldb/Core/PluginManager.h"19#include "lldb/Core/Section.h"20#include "lldb/Host/FileSystem.h"21#include "lldb/Host/HostInfo.h"22#include "lldb/Host/HostNativeProcessBase.h"23#include "lldb/Host/HostProcess.h"24#include "lldb/Host/windows/HostThreadWindows.h"25#include "lldb/Symbol/ObjectFile.h"26#include "lldb/Target/DynamicLoader.h"27#include "lldb/Target/MemoryRegionInfo.h"28#include "lldb/Target/StopInfo.h"29#include "lldb/Target/Target.h"30#include "lldb/Utility/State.h"31 32#include "llvm/Support/ConvertUTF.h"33#include "llvm/Support/Format.h"34#include "llvm/Support/Threading.h"35#include "llvm/Support/raw_ostream.h"36 37#include "DebuggerThread.h"38#include "ExceptionRecord.h"39#include "ForwardDecl.h"40#include "LocalDebugDelegate.h"41#include "ProcessWindowsLog.h"42#include "TargetThreadWindows.h"43 44using namespace lldb;45using namespace lldb_private;46 47LLDB_PLUGIN_DEFINE_ADV(ProcessWindows, ProcessWindowsCommon)48 49namespace {50std::string GetProcessExecutableName(HANDLE process_handle) {51 std::vector<wchar_t> file_name;52 DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit53 DWORD copied = 0;54 do {55 file_name_size *= 2;56 file_name.resize(file_name_size);57 copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),58 file_name_size);59 } while (copied >= file_name_size);60 file_name.resize(copied);61 std::string result;62 llvm::convertWideToUTF8(file_name.data(), result);63 return result;64}65 66std::string GetProcessExecutableName(DWORD pid) {67 std::string file_name;68 HANDLE process_handle =69 ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);70 if (process_handle != NULL) {71 file_name = GetProcessExecutableName(process_handle);72 ::CloseHandle(process_handle);73 }74 return file_name;75}76} // anonymous namespace77 78namespace lldb_private {79 80ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,81 lldb::ListenerSP listener_sp,82 const FileSpec *,83 bool can_connect) {84 return ProcessSP(new ProcessWindows(target_sp, listener_sp));85}86 87static bool ShouldUseLLDBServer() {88 llvm::StringRef use_lldb_server = ::getenv("LLDB_USE_LLDB_SERVER");89 return use_lldb_server.equals_insensitive("on") ||90 use_lldb_server.equals_insensitive("yes") ||91 use_lldb_server.equals_insensitive("1") ||92 use_lldb_server.equals_insensitive("true");93}94 95void ProcessWindows::Initialize() {96 if (!ShouldUseLLDBServer()) {97 static llvm::once_flag g_once_flag;98 99 llvm::call_once(g_once_flag, []() {100 PluginManager::RegisterPlugin(GetPluginNameStatic(),101 GetPluginDescriptionStatic(),102 CreateInstance);103 });104 }105}106 107void ProcessWindows::Terminate() {}108 109llvm::StringRef ProcessWindows::GetPluginDescriptionStatic() {110 return "Process plugin for Windows";111}112 113// Constructors and destructors.114 115ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,116 lldb::ListenerSP listener_sp)117 : lldb_private::Process(target_sp, listener_sp),118 m_watchpoint_ids(119 RegisterContextWindows::GetNumHardwareBreakpointSlots(),120 LLDB_INVALID_BREAK_ID) {}121 122ProcessWindows::~ProcessWindows() {}123 124size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) {125 error = Status::FromErrorString("GetSTDOUT unsupported on Windows");126 return 0;127}128 129size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) {130 error = Status::FromErrorString("GetSTDERR unsupported on Windows");131 return 0;132}133 134size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,135 Status &error) {136 error = Status::FromErrorString("PutSTDIN unsupported on Windows");137 return 0;138}139 140Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {141 if (bp_site->HardwareRequired())142 return Status::FromErrorString("Hardware breakpoints are not supported.");143 144 Log *log = GetLog(WindowsLog::Breakpoints);145 LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,146 bp_site->GetID(), bp_site->GetLoadAddress());147 148 Status error = EnableSoftwareBreakpoint(bp_site);149 if (!error.Success())150 LLDB_LOG(log, "error: {0}", error);151 return error;152}153 154Status ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {155 Log *log = GetLog(WindowsLog::Breakpoints);156 LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,157 bp_site->GetID(), bp_site->GetLoadAddress());158 159 Status error = DisableSoftwareBreakpoint(bp_site);160 161 if (!error.Success())162 LLDB_LOG(log, "error: {0}", error);163 return error;164}165 166Status ProcessWindows::DoDetach(bool keep_stopped) {167 Status error;168 Log *log = GetLog(WindowsLog::Process);169 StateType private_state = GetPrivateState();170 if (private_state != eStateExited && private_state != eStateDetached) {171 if (!keep_stopped) {172 // if the thread is suspended by lldb, we have to resume threads before173 // detaching process. When we do after DetachProcess(), thread handles174 // become invalid so we do before detach.175 if (private_state == eStateStopped || private_state == eStateCrashed) {176 LLDB_LOG(log, "process {0} is in state {1}. Resuming for detach...",177 m_session_data->m_debugger->GetProcess().GetProcessId(),178 GetPrivateState());179 180 LLDB_LOG(log, "resuming {0} threads for detach.",181 m_thread_list.GetSize());182 183 bool failed = false;184 for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {185 auto thread = std::static_pointer_cast<TargetThreadWindows>(186 m_thread_list.GetThreadAtIndex(i));187 Status result = thread->DoResume();188 if (result.Fail()) {189 failed = true;190 LLDB_LOG(log,191 "Trying to resume thread at index {0}, but failed with "192 "error {1}.",193 i, result);194 }195 }196 197 if (failed) {198 error = Status::FromErrorString("Resuming Threads for Detach failed");199 }200 }201 }202 203 error = DetachProcess();204 if (error.Success())205 SetPrivateState(eStateDetached);206 else207 LLDB_LOG(log, "Detaching process error: {0}", error);208 } else {209 error = Status::FromErrorStringWithFormatv(210 "error: process {0} in state = {1}, but "211 "cannot detach it in this state.",212 GetID(), private_state);213 LLDB_LOG(log, "error: {0}", error);214 }215 return error;216}217 218Status ProcessWindows::DoLaunch(Module *exe_module,219 ProcessLaunchInfo &launch_info) {220 Status error;221 DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));222 error = LaunchProcess(launch_info, delegate);223 if (error.Success())224 SetID(launch_info.GetProcessID());225 return error;226}227 228Status229ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,230 const ProcessAttachInfo &attach_info) {231 DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));232 Status error = AttachProcess(pid, attach_info, delegate);233 if (error.Success())234 SetID(GetDebuggedProcessId());235 return error;236}237 238Status ProcessWindows::DoResume(RunDirection direction) {239 Log *log = GetLog(WindowsLog::Process);240 llvm::sys::ScopedLock lock(m_mutex);241 242 if (direction == RunDirection::eRunReverse) {243 return Status::FromErrorStringWithFormatv(244 "{0} does not support reverse execution of processes", GetPluginName());245 }246 247 Status error;248 249 StateType private_state = GetPrivateState();250 if (private_state == eStateStopped || private_state == eStateCrashed) {251 LLDB_LOG(log, "process {0} is in state {1}. Resuming...",252 m_session_data->m_debugger->GetProcess().GetProcessId(),253 GetPrivateState());254 255 LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());256 257 bool failed = false;258 for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {259 auto thread = std::static_pointer_cast<TargetThreadWindows>(260 m_thread_list.GetThreadAtIndex(i));261 Status result = thread->DoResume();262 if (result.Fail()) {263 failed = true;264 LLDB_LOG(265 log,266 "Trying to resume thread at index {0}, but failed with error {1}.",267 i, result);268 }269 }270 271 if (failed) {272 error = Status::FromErrorString("ProcessWindows::DoResume failed");273 } else {274 SetPrivateState(eStateRunning);275 }276 277 ExceptionRecordSP active_exception =278 m_session_data->m_debugger->GetActiveException().lock();279 if (active_exception) {280 // Resume the process and continue processing debug events. Mask the281 // exception so that from the process's view, there is no indication that282 // anything happened.283 m_session_data->m_debugger->ContinueAsyncException(284 ExceptionResult::MaskException);285 }286 } else {287 LLDB_LOG(log, "error: process {0} is in state {1}. Returning...",288 m_session_data->m_debugger->GetProcess().GetProcessId(),289 GetPrivateState());290 }291 return error;292}293 294Status ProcessWindows::DoDestroy() {295 StateType private_state = GetPrivateState();296 return DestroyProcess(private_state);297}298 299Status ProcessWindows::DoHalt(bool &caused_stop) {300 StateType state = GetPrivateState();301 if (state != eStateStopped)302 return HaltProcess(caused_stop);303 caused_stop = false;304 return Status();305}306 307void ProcessWindows::DidLaunch() {308 ArchSpec arch_spec;309 DidAttach(arch_spec);310}311 312void ProcessWindows::DidAttach(ArchSpec &arch_spec) {313 llvm::sys::ScopedLock lock(m_mutex);314 315 // The initial stop won't broadcast the state change event, so account for316 // that here.317 if (m_session_data && GetPrivateState() == eStateStopped &&318 m_session_data->m_stop_at_entry)319 RefreshStateAfterStop();320}321 322static void323DumpAdditionalExceptionInformation(llvm::raw_ostream &stream,324 const ExceptionRecordSP &exception) {325 // Decode additional exception information for specific exception types based326 // on327 // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record328 329 const int addr_min_width = 2 + 8; // "0x" + 4 address bytes330 331 const std::vector<ULONG_PTR> &args = exception->GetExceptionArguments();332 switch (exception->GetExceptionCode()) {333 case EXCEPTION_ACCESS_VIOLATION: {334 if (args.size() < 2)335 break;336 337 stream << ": ";338 const int access_violation_code = args[0];339 const lldb::addr_t access_violation_address = args[1];340 switch (access_violation_code) {341 case 0:342 stream << "Access violation reading";343 break;344 case 1:345 stream << "Access violation writing";346 break;347 case 8:348 stream << "User-mode data execution prevention (DEP) violation at";349 break;350 default:351 stream << "Unknown access violation (code " << access_violation_code352 << ") at";353 break;354 }355 stream << " location "356 << llvm::format_hex(access_violation_address, addr_min_width);357 break;358 }359 case EXCEPTION_IN_PAGE_ERROR: {360 if (args.size() < 3)361 break;362 363 stream << ": ";364 const int page_load_error_code = args[0];365 const lldb::addr_t page_load_error_address = args[1];366 const DWORD underlying_code = args[2];367 switch (page_load_error_code) {368 case 0:369 stream << "In page error reading";370 break;371 case 1:372 stream << "In page error writing";373 break;374 case 8:375 stream << "User-mode data execution prevention (DEP) violation at";376 break;377 default:378 stream << "Unknown page loading error (code " << page_load_error_code379 << ") at";380 break;381 }382 stream << " location "383 << llvm::format_hex(page_load_error_address, addr_min_width)384 << " (status code " << llvm::format_hex(underlying_code, 8) << ")";385 break;386 }387 }388}389 390void ProcessWindows::RefreshStateAfterStop() {391 Log *log = GetLog(WindowsLog::Exception);392 llvm::sys::ScopedLock lock(m_mutex);393 394 if (!m_session_data) {395 LLDB_LOG(log, "no active session. Returning...");396 return;397 }398 399 m_thread_list.RefreshStateAfterStop();400 401 std::weak_ptr<ExceptionRecord> exception_record =402 m_session_data->m_debugger->GetActiveException();403 ExceptionRecordSP active_exception = exception_record.lock();404 if (!active_exception) {405 LLDB_LOG(log,406 "there is no active exception in process {0}. Why is the "407 "process stopped?",408 m_session_data->m_debugger->GetProcess().GetProcessId());409 return;410 }411 412 StopInfoSP stop_info;413 m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());414 ThreadSP stop_thread = m_thread_list.GetSelectedThread();415 if (!stop_thread)416 return;417 418 RegisterContextSP register_context = stop_thread->GetRegisterContext();419 uint64_t pc = register_context->GetPC();420 421 // If we're at a BreakpointSite, mark this as an Unexecuted Breakpoint.422 // We'll clear that state if we've actually executed the breakpoint.423 BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));424 if (site && site->IsEnabled())425 stop_thread->SetThreadStoppedAtUnexecutedBP(pc);426 427 switch (active_exception->GetExceptionCode()) {428 case EXCEPTION_SINGLE_STEP: {429 auto *reg_ctx = static_cast<RegisterContextWindows *>(430 stop_thread->GetRegisterContext().get());431 uint32_t slot_id = reg_ctx->GetTriggeredHardwareBreakpointSlotId();432 if (slot_id != LLDB_INVALID_INDEX32) {433 int id = m_watchpoint_ids[slot_id];434 LLDB_LOG(log,435 "Single-stepped onto a watchpoint in process {0} at address "436 "{1:x} with watchpoint {2}",437 m_session_data->m_debugger->GetProcess().GetProcessId(), pc, id);438 439 stop_info = StopInfo::CreateStopReasonWithWatchpointID(*stop_thread, id);440 stop_thread->SetStopInfo(stop_info);441 442 return;443 }444 445 LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());446 stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);447 stop_thread->SetStopInfo(stop_info);448 449 return;450 }451 452 case EXCEPTION_BREAKPOINT: {453 int breakpoint_size = 1;454 switch (GetTarget().GetArchitecture().GetMachine()) {455 case llvm::Triple::aarch64:456 breakpoint_size = 4;457 break;458 459 case llvm::Triple::arm:460 case llvm::Triple::thumb:461 breakpoint_size = 2;462 break;463 464 case llvm::Triple::x86:465 case llvm::Triple::x86_64:466 breakpoint_size = 1;467 break;468 469 default:470 LLDB_LOG(log, "Unknown breakpoint size for architecture");471 break;472 }473 474 // The current PC is AFTER the BP opcode, on all architectures.475 pc = register_context->GetPC() - breakpoint_size;476 477 site = GetBreakpointSiteList().FindByAddress(pc);478 if (site) {479 LLDB_LOG(log,480 "detected breakpoint in process {0} at address {1:x} with "481 "breakpoint site {2}",482 m_session_data->m_debugger->GetProcess().GetProcessId(), pc,483 site->GetID());484 485 stop_thread->SetThreadHitBreakpointSite();486 if (site->ValidForThisThread(*stop_thread)) {487 LLDB_LOG(log,488 "Breakpoint site {0} is valid for this thread ({1:x}), "489 "creating stop info.",490 site->GetID(), stop_thread->GetID());491 492 stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(493 *stop_thread, site->GetID());494 register_context->SetPC(pc);495 } else {496 LLDB_LOG(log,497 "Breakpoint site {0} is not valid for this thread, "498 "creating empty stop info.",499 site->GetID());500 }501 stop_thread->SetStopInfo(stop_info);502 return;503 } else {504 // The thread hit a hard-coded breakpoint like an `int 3` or505 // `__debugbreak()`.506 LLDB_LOG(log,507 "No breakpoint site matches for this thread. __debugbreak()? "508 "Creating stop info with the exception.");509 // FALLTHROUGH: We'll treat this as a generic exception record in the510 // default case.511 [[fallthrough]];512 }513 }514 515 default: {516 std::string desc;517 llvm::raw_string_ostream desc_stream(desc);518 desc_stream << "Exception "519 << llvm::format_hex(active_exception->GetExceptionCode(), 8)520 << " encountered at address "521 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);522 DumpAdditionalExceptionInformation(desc_stream, active_exception);523 524 stop_info =525 StopInfo::CreateStopReasonWithException(*stop_thread, desc.c_str());526 stop_thread->SetStopInfo(stop_info);527 LLDB_LOG(log, "{0}", desc);528 return;529 }530 }531}532 533bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,534 bool plugin_specified_by_name) {535 if (plugin_specified_by_name)536 return true;537 538 // For now we are just making sure the file exists for a given module539 ModuleSP exe_module_sp(target_sp->GetExecutableModule());540 if (exe_module_sp.get())541 return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());542 // However, if there is no executable module, we return true since we might543 // be preparing to attach.544 return true;545}546 547bool ProcessWindows::DoUpdateThreadList(ThreadList &old_thread_list,548 ThreadList &new_thread_list) {549 Log *log = GetLog(WindowsLog::Thread);550 // Add all the threads that were previously running and for which we did not551 // detect a thread exited event.552 int new_size = 0;553 int continued_threads = 0;554 int exited_threads = 0;555 int new_threads = 0;556 557 for (ThreadSP old_thread : old_thread_list.Threads()) {558 lldb::tid_t old_thread_id = old_thread->GetID();559 auto exited_thread_iter =560 m_session_data->m_exited_threads.find(old_thread_id);561 if (exited_thread_iter == m_session_data->m_exited_threads.end()) {562 new_thread_list.AddThread(old_thread);563 ++new_size;564 ++continued_threads;565 LLDB_LOGV(log, "Thread {0} was running and is still running.",566 old_thread_id);567 } else {568 LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id);569 ++exited_threads;570 }571 }572 573 // Also add all the threads that are new since the last time we broke into574 // the debugger.575 for (const auto &thread_info : m_session_data->m_new_threads) {576 new_thread_list.AddThread(thread_info.second);577 ++new_size;578 ++new_threads;579 LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first);580 }581 582 LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.",583 new_threads, continued_threads, exited_threads);584 585 m_session_data->m_new_threads.clear();586 m_session_data->m_exited_threads.clear();587 588 return new_size > 0;589}590 591bool ProcessWindows::IsAlive() {592 StateType state = GetPrivateState();593 switch (state) {594 case eStateCrashed:595 case eStateDetached:596 case eStateUnloaded:597 case eStateExited:598 case eStateInvalid:599 return false;600 default:601 return true;602 }603}604 605ArchSpec ProcessWindows::GetSystemArchitecture() {606 return HostInfo::GetArchitecture();607}608 609size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,610 size_t size, Status &error) {611 size_t bytes_read = 0;612 error = ProcessDebugger::ReadMemory(vm_addr, buf, size, bytes_read);613 return bytes_read;614}615 616size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,617 size_t size, Status &error) {618 size_t bytes_written = 0;619 error = ProcessDebugger::WriteMemory(vm_addr, buf, size, bytes_written);620 return bytes_written;621}622 623lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions,624 Status &error) {625 lldb::addr_t vm_addr = LLDB_INVALID_ADDRESS;626 error = ProcessDebugger::AllocateMemory(size, permissions, vm_addr);627 return vm_addr;628}629 630Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) {631 return ProcessDebugger::DeallocateMemory(ptr);632}633 634Status ProcessWindows::DoGetMemoryRegionInfo(lldb::addr_t vm_addr,635 MemoryRegionInfo &info) {636 return ProcessDebugger::GetMemoryRegionInfo(vm_addr, info);637}638 639lldb::addr_t ProcessWindows::GetImageInfoAddress() {640 Target &target = GetTarget();641 ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();642 Address addr = obj_file->GetImageInfoAddress(&target);643 if (addr.IsValid())644 return addr.GetLoadAddress(&target);645 else646 return LLDB_INVALID_ADDRESS;647}648 649DynamicLoaderWindowsDYLD *ProcessWindows::GetDynamicLoader() {650 if (m_dyld_up.get() == NULL)651 m_dyld_up.reset(DynamicLoader::FindPlugin(652 this, DynamicLoaderWindowsDYLD::GetPluginNameStatic()));653 return static_cast<DynamicLoaderWindowsDYLD *>(m_dyld_up.get());654}655 656void ProcessWindows::OnExitProcess(uint32_t exit_code) {657 // No need to acquire the lock since m_session_data isn't accessed.658 Log *log = GetLog(WindowsLog::Process);659 LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);660 661 TargetSP target = CalculateTarget();662 if (target) {663 ModuleSP executable_module = target->GetExecutableModule();664 ModuleList unloaded_modules;665 unloaded_modules.Append(executable_module);666 target->ModulesDidUnload(unloaded_modules, true);667 }668 669 SetExitStatus(exit_code, /*exit_string=*/"");670 SetPrivateState(eStateExited);671 672 ProcessDebugger::OnExitProcess(exit_code);673}674 675void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {676 DebuggerThreadSP debugger = m_session_data->m_debugger;677 Log *log = GetLog(WindowsLog::Process);678 LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",679 debugger->GetProcess().GetProcessId(), image_base);680 681 ModuleSP module;682 // During attach, we won't have the executable module, so find it now.683 const DWORD pid = debugger->GetProcess().GetProcessId();684 const std::string file_name = GetProcessExecutableName(pid);685 if (file_name.empty()) {686 return;687 }688 689 FileSpec executable_file(file_name);690 FileSystem::Instance().Resolve(executable_file);691 ModuleSpec module_spec(executable_file);692 Status error;693 module =694 GetTarget().GetOrCreateModule(module_spec, true /* notify */, &error);695 if (!module) {696 return;697 }698 699 GetTarget().SetExecutableModule(module, eLoadDependentsNo);700 701 if (auto dyld = GetDynamicLoader())702 dyld->OnLoadModule(module, ModuleSpec(), image_base);703 704 // Add the main executable module to the list of pending module loads. We705 // can't call GetTarget().ModulesDidLoad() here because we still haven't706 // returned from DoLaunch() / DoAttach() yet so the target may not have set707 // the process instance to `this` yet.708 llvm::sys::ScopedLock lock(m_mutex);709 710 const HostThread &host_main_thread = debugger->GetMainThread();711 ThreadSP main_thread =712 std::make_shared<TargetThreadWindows>(*this, host_main_thread);713 714 tid_t id = host_main_thread.GetNativeThread().GetThreadId();715 main_thread->SetID(id);716 717 m_session_data->m_new_threads[id] = main_thread;718}719 720ExceptionResult721ProcessWindows::OnDebugException(bool first_chance,722 const ExceptionRecord &record) {723 Log *log = GetLog(WindowsLog::Exception);724 llvm::sys::ScopedLock lock(m_mutex);725 726 // FIXME: Without this check, occasionally when running the test suite there727 // is728 // an issue where m_session_data can be null. It's not clear how this could729 // happen but it only surfaces while running the test suite. In order to730 // properly diagnose this, we probably need to first figure allow the test731 // suite to print out full lldb logs, and then add logging to the process732 // plugin.733 if (!m_session_data) {734 LLDB_LOG(log,735 "Debugger thread reported exception {0:x} at address {1:x}, "736 "but there is no session.",737 record.GetExceptionCode(), record.GetExceptionAddress());738 return ExceptionResult::SendToApplication;739 }740 741 if (!first_chance) {742 // Not any second chance exception is an application crash by definition.743 // It may be an expression evaluation crash.744 SetPrivateState(eStateStopped);745 }746 747 ExceptionResult result = ExceptionResult::SendToApplication;748 switch (record.GetExceptionCode()) {749 case EXCEPTION_BREAKPOINT:750 // Handle breakpoints at the first chance.751 result = ExceptionResult::BreakInDebugger;752 753 if (!m_session_data->m_initial_stop_received) {754 LLDB_LOG(755 log,756 "Hit loader breakpoint at address {0:x}, setting initial stop event.",757 record.GetExceptionAddress());758 m_session_data->m_initial_stop_received = true;759 ::SetEvent(m_session_data->m_initial_stop_event);760 } else {761 LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",762 record.GetExceptionAddress());763 }764 SetPrivateState(eStateStopped);765 break;766 case EXCEPTION_SINGLE_STEP:767 result = ExceptionResult::BreakInDebugger;768 SetPrivateState(eStateStopped);769 break;770 default:771 LLDB_LOG(log,772 "Debugger thread reported exception {0:x} at address {1:x} "773 "(first_chance={2})",774 record.GetExceptionCode(), record.GetExceptionAddress(),775 first_chance);776 // For non-breakpoints, give the application a chance to handle the777 // exception first.778 if (first_chance)779 result = ExceptionResult::SendToApplication;780 else781 result = ExceptionResult::BreakInDebugger;782 }783 784 return result;785}786 787void ProcessWindows::OnCreateThread(const HostThread &new_thread) {788 llvm::sys::ScopedLock lock(m_mutex);789 790 ThreadSP thread = std::make_shared<TargetThreadWindows>(*this, new_thread);791 792 const HostNativeThread &native_new_thread = new_thread.GetNativeThread();793 tid_t id = native_new_thread.GetThreadId();794 thread->SetID(id);795 796 m_session_data->m_new_threads[id] = thread;797 798 for (const std::map<int, WatchpointInfo>::value_type &p : m_watchpoints) {799 auto *reg_ctx = static_cast<RegisterContextWindows *>(800 thread->GetRegisterContext().get());801 reg_ctx->AddHardwareBreakpoint(p.second.slot_id, p.second.address,802 p.second.size, p.second.read,803 p.second.write);804 }805}806 807void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {808 llvm::sys::ScopedLock lock(m_mutex);809 810 // On a forced termination, we may get exit thread events after the session811 // data has been cleaned up.812 if (!m_session_data)813 return;814 815 // A thread may have started and exited before the debugger stopped allowing a816 // refresh.817 // Just remove it from the new threads list in that case.818 auto iter = m_session_data->m_new_threads.find(thread_id);819 if (iter != m_session_data->m_new_threads.end())820 m_session_data->m_new_threads.erase(iter);821 else822 m_session_data->m_exited_threads.insert(thread_id);823}824 825void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,826 lldb::addr_t module_addr) {827 if (auto dyld = GetDynamicLoader())828 dyld->OnLoadModule(nullptr, module_spec, module_addr);829}830 831void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {832 if (auto dyld = GetDynamicLoader())833 dyld->OnUnloadModule(module_addr);834}835 836void ProcessWindows::OnDebugString(const std::string &string) {}837 838void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {839 llvm::sys::ScopedLock lock(m_mutex);840 Log *log = GetLog(WindowsLog::Process);841 842 if (m_session_data->m_initial_stop_received) {843 // This happened while debugging. Do we shutdown the debugging session,844 // try to continue, or do something else?845 LLDB_LOG(log,846 "Error {0} occurred during debugging. Unexpected behavior "847 "may result. {1}",848 error.GetError(), error);849 } else {850 // If we haven't actually launched the process yet, this was an error851 // launching the process. Set the internal error and signal the initial852 // stop event so that the DoLaunch method wakes up and returns a failure.853 m_session_data->m_launch_error = error.Clone();854 ::SetEvent(m_session_data->m_initial_stop_event);855 LLDB_LOG(856 log,857 "Error {0} occurred launching the process before the initial stop. {1}",858 error.GetError(), error);859 return;860 }861}862 863std::optional<uint32_t> ProcessWindows::GetWatchpointSlotCount() {864 return RegisterContextWindows::GetNumHardwareBreakpointSlots();865}866 867Status ProcessWindows::EnableWatchpoint(WatchpointSP wp_sp, bool notify) {868 Status error;869 870 if (wp_sp->IsEnabled()) {871 wp_sp->SetEnabled(true, notify);872 return error;873 }874 875 WatchpointInfo info;876 for (info.slot_id = 0;877 info.slot_id < RegisterContextWindows::GetNumHardwareBreakpointSlots();878 info.slot_id++)879 if (m_watchpoint_ids[info.slot_id] == LLDB_INVALID_BREAK_ID)880 break;881 if (info.slot_id == RegisterContextWindows::GetNumHardwareBreakpointSlots()) {882 error = Status::FromErrorStringWithFormat(883 "Can't find free slot for watchpoint %i", wp_sp->GetID());884 return error;885 }886 info.address = wp_sp->GetLoadAddress();887 info.size = wp_sp->GetByteSize();888 info.read = wp_sp->WatchpointRead();889 info.write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify();890 891 for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {892 Thread *thread = m_thread_list.GetThreadAtIndex(i).get();893 auto *reg_ctx = static_cast<RegisterContextWindows *>(894 thread->GetRegisterContext().get());895 if (!reg_ctx->AddHardwareBreakpoint(info.slot_id, info.address, info.size,896 info.read, info.write)) {897 error = Status::FromErrorStringWithFormat(898 "Can't enable watchpoint %i on thread 0x%llx", wp_sp->GetID(),899 thread->GetID());900 break;901 }902 }903 if (error.Fail()) {904 for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {905 Thread *thread = m_thread_list.GetThreadAtIndex(i).get();906 auto *reg_ctx = static_cast<RegisterContextWindows *>(907 thread->GetRegisterContext().get());908 reg_ctx->RemoveHardwareBreakpoint(info.slot_id);909 }910 return error;911 }912 913 m_watchpoints[wp_sp->GetID()] = info;914 m_watchpoint_ids[info.slot_id] = wp_sp->GetID();915 916 wp_sp->SetEnabled(true, notify);917 918 return error;919}920 921Status ProcessWindows::DisableWatchpoint(WatchpointSP wp_sp, bool notify) {922 Status error;923 924 if (!wp_sp->IsEnabled()) {925 wp_sp->SetEnabled(false, notify);926 return error;927 }928 929 auto it = m_watchpoints.find(wp_sp->GetID());930 if (it == m_watchpoints.end()) {931 error = Status::FromErrorStringWithFormat(932 "Info about watchpoint %i is not found", wp_sp->GetID());933 return error;934 }935 936 for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {937 Thread *thread = m_thread_list.GetThreadAtIndex(i).get();938 auto *reg_ctx = static_cast<RegisterContextWindows *>(939 thread->GetRegisterContext().get());940 if (!reg_ctx->RemoveHardwareBreakpoint(it->second.slot_id)) {941 error = Status::FromErrorStringWithFormat(942 "Can't disable watchpoint %i on thread 0x%llx", wp_sp->GetID(),943 thread->GetID());944 break;945 }946 }947 if (error.Fail())948 return error;949 950 m_watchpoint_ids[it->second.slot_id] = LLDB_INVALID_BREAK_ID;951 m_watchpoints.erase(it);952 953 wp_sp->SetEnabled(false, notify);954 955 return error;956}957} // namespace lldb_private958