1 //===-- DebuggerThread.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DebuggerThread.h" 10 #include "ExceptionRecord.h" 11 #include "IDebugDelegate.h" 12 13 #include "lldb/Core/ModuleSpec.h" 14 #include "lldb/Host/ProcessLaunchInfo.h" 15 #include "lldb/Host/ThreadLauncher.h" 16 #include "lldb/Host/windows/AutoHandle.h" 17 #include "lldb/Host/windows/HostProcessWindows.h" 18 #include "lldb/Host/windows/HostThreadWindows.h" 19 #include "lldb/Host/windows/ProcessLauncherWindows.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Utility/FileSpec.h" 22 #include "lldb/Utility/Log.h" 23 #include "lldb/Utility/Predicate.h" 24 #include "lldb/Utility/Status.h" 25 26 #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" 27 28 #include "llvm/ADT/STLExtras.h" 29 #include "llvm/Support/ConvertUTF.h" 30 #include "llvm/Support/Threading.h" 31 #include "llvm/Support/raw_ostream.h" 32 33 #include <psapi.h> 34 35 #ifndef STATUS_WX86_BREAKPOINT 36 #define STATUS_WX86_BREAKPOINT 0x4000001FL // For WOW64 37 #endif 38 39 using namespace lldb; 40 using namespace lldb_private; 41 42 DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) 43 : m_debug_delegate(debug_delegate), m_pid_to_detach(0), 44 m_is_shutting_down(false) { 45 m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 46 } 47 48 DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } 49 50 Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { 51 Log *log = GetLog(WindowsLog::Process); 52 LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); 53 54 Status result; 55 llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread( 56 "lldb.plugin.process-windows.secondary[?]", 57 [this, launch_info] { return DebuggerThreadLaunchRoutine(launch_info); }); 58 if (!secondary_thread) { 59 result = Status(secondary_thread.takeError()); 60 LLDB_LOG(log, "couldn't launch debugger thread. {0}", result); 61 } 62 63 return result; 64 } 65 66 Status DebuggerThread::DebugAttach(lldb::pid_t pid, 67 const ProcessAttachInfo &attach_info) { 68 Log *log = GetLog(WindowsLog::Process); 69 LLDB_LOG(log, "attaching to '{0}'", pid); 70 71 Status result; 72 llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread( 73 "lldb.plugin.process-windows.secondary[?]", [this, pid, attach_info] { 74 return DebuggerThreadAttachRoutine(pid, attach_info); 75 }); 76 if (!secondary_thread) { 77 result = Status(secondary_thread.takeError()); 78 LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, result); 79 } 80 81 return result; 82 } 83 84 lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( 85 const ProcessLaunchInfo &launch_info) { 86 // Grab a shared_ptr reference to this so that we know it won't get deleted 87 // until after the thread routine has exited. 88 std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 89 90 Log *log = GetLog(WindowsLog::Process); 91 LLDB_LOG(log, "preparing to launch '{0}' on background thread.", 92 launch_info.GetExecutableFile().GetPath()); 93 94 Status error; 95 ProcessLauncherWindows launcher; 96 HostProcess process(launcher.LaunchProcess(launch_info, error)); 97 // If we couldn't create the process, notify waiters immediately. Otherwise 98 // enter the debug loop and wait until we get the create process debug 99 // notification. Note that if the process was created successfully, we can 100 // throw away the process handle we got from CreateProcess because Windows 101 // will give us another (potentially more useful?) handle when it sends us 102 // the CREATE_PROCESS_DEBUG_EVENT. 103 if (error.Success()) 104 DebugLoop(); 105 else 106 m_debug_delegate->OnDebuggerError(error, 0); 107 108 return {}; 109 } 110 111 lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( 112 lldb::pid_t pid, const ProcessAttachInfo &attach_info) { 113 // Grab a shared_ptr reference to this so that we know it won't get deleted 114 // until after the thread routine has exited. 115 std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 116 117 Log *log = GetLog(WindowsLog::Process); 118 LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.", 119 pid); 120 121 if (!DebugActiveProcess((DWORD)pid)) { 122 Status error(::GetLastError(), eErrorTypeWin32); 123 m_debug_delegate->OnDebuggerError(error, 0); 124 return {}; 125 } 126 127 // The attach was successful, enter the debug loop. From here on out, this 128 // is no different than a create process operation, so all the same comments 129 // in DebugLaunch should apply from this point out. 130 DebugLoop(); 131 132 return {}; 133 } 134 135 Status DebuggerThread::StopDebugging(bool terminate) { 136 Status error; 137 138 lldb::pid_t pid = m_process.GetProcessId(); 139 140 Log *log = GetLog(WindowsLog::Process); 141 LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid); 142 143 // Set m_is_shutting_down to true if it was false. Return if it was already 144 // true. 145 bool expected = false; 146 if (!m_is_shutting_down.compare_exchange_strong(expected, true)) 147 return error; 148 149 // Make a copy of the process, since the termination sequence will reset 150 // DebuggerThread's internal copy and it needs to remain open for the Wait 151 // operation. 152 HostProcess process_copy = m_process; 153 lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); 154 155 if (terminate) { 156 if (handle != nullptr && handle != LLDB_INVALID_PROCESS) { 157 // Initiate the termination before continuing the exception, so that the 158 // next debug event we get is the exit process event, and not some other 159 // event. 160 BOOL terminate_suceeded = TerminateProcess(handle, 0); 161 LLDB_LOG(log, 162 "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", 163 handle, pid, terminate_suceeded); 164 } else { 165 LLDB_LOG(log, 166 "NOT calling TerminateProcess because the inferior is not valid " 167 "({0}, 0) (inferior={1})", 168 handle, pid); 169 } 170 } 171 172 // If we're stuck waiting for an exception to continue (e.g. the user is at a 173 // breakpoint messing around in the debugger), continue it now. But only 174 // AFTER calling TerminateProcess to make sure that the very next call to 175 // WaitForDebugEvent is an exit process event. 176 if (m_active_exception.get()) { 177 LLDB_LOG(log, "masking active exception"); 178 ContinueAsyncException(ExceptionResult::MaskException); 179 } 180 181 if (!terminate) { 182 // Indicate that we want to detach. 183 m_pid_to_detach = GetProcess().GetProcessId(); 184 185 // Force a fresh break so that the detach can happen from the debugger 186 // thread. 187 if (!::DebugBreakProcess( 188 GetProcess().GetNativeProcess().GetSystemHandle())) { 189 error.SetError(::GetLastError(), eErrorTypeWin32); 190 } 191 } 192 193 LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid); 194 195 DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); 196 if (wait_result != WAIT_OBJECT_0) { 197 error.SetError(GetLastError(), eErrorTypeWin32); 198 LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}", 199 m_debugging_ended_event, wait_result); 200 } else 201 LLDB_LOG(log, "detach from process {0} completed successfully.", pid); 202 203 if (!error.Success()) { 204 LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}", 205 pid, error); 206 } 207 return error; 208 } 209 210 void DebuggerThread::ContinueAsyncException(ExceptionResult result) { 211 if (!m_active_exception.get()) 212 return; 213 214 Log *log = GetLog(WindowsLog::Process | WindowsLog::Exception); 215 LLDB_LOG(log, "broadcasting for inferior process {0}.", 216 m_process.GetProcessId()); 217 218 m_active_exception.reset(); 219 m_exception_pred.SetValue(result, eBroadcastAlways); 220 } 221 222 void DebuggerThread::FreeProcessHandles() { 223 m_process = HostProcess(); 224 m_main_thread = HostThread(); 225 if (m_image_file) { 226 ::CloseHandle(m_image_file); 227 m_image_file = nullptr; 228 } 229 } 230 231 void DebuggerThread::DebugLoop() { 232 Log *log = GetLog(WindowsLog::Event); 233 DEBUG_EVENT dbe = {}; 234 bool should_debug = true; 235 LLDB_LOGV(log, "Entering WaitForDebugEvent loop"); 236 while (should_debug) { 237 LLDB_LOGV(log, "Calling WaitForDebugEvent"); 238 BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); 239 if (wait_result) { 240 DWORD continue_status = DBG_CONTINUE; 241 switch (dbe.dwDebugEventCode) { 242 default: 243 llvm_unreachable("Unhandle debug event code!"); 244 case EXCEPTION_DEBUG_EVENT: { 245 ExceptionResult status = 246 HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); 247 248 if (status == ExceptionResult::MaskException) 249 continue_status = DBG_CONTINUE; 250 else if (status == ExceptionResult::SendToApplication) 251 continue_status = DBG_EXCEPTION_NOT_HANDLED; 252 253 break; 254 } 255 case CREATE_THREAD_DEBUG_EVENT: 256 continue_status = 257 HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); 258 break; 259 case CREATE_PROCESS_DEBUG_EVENT: 260 continue_status = 261 HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); 262 break; 263 case EXIT_THREAD_DEBUG_EVENT: 264 continue_status = 265 HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); 266 break; 267 case EXIT_PROCESS_DEBUG_EVENT: 268 continue_status = 269 HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); 270 should_debug = false; 271 break; 272 case LOAD_DLL_DEBUG_EVENT: 273 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); 274 break; 275 case UNLOAD_DLL_DEBUG_EVENT: 276 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); 277 break; 278 case OUTPUT_DEBUG_STRING_EVENT: 279 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); 280 break; 281 case RIP_EVENT: 282 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); 283 if (dbe.u.RipInfo.dwType == SLE_ERROR) 284 should_debug = false; 285 break; 286 } 287 288 LLDB_LOGV(log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.", 289 dbe.dwProcessId, dbe.dwThreadId, continue_status, 290 ::GetCurrentThreadId()); 291 292 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); 293 294 if (m_detached) { 295 should_debug = false; 296 } 297 } else { 298 LLDB_LOG(log, "returned FALSE from WaitForDebugEvent. Error = {0}", 299 ::GetLastError()); 300 301 should_debug = false; 302 } 303 } 304 FreeProcessHandles(); 305 306 LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting."); 307 ::SetEvent(m_debugging_ended_event); 308 } 309 310 ExceptionResult 311 DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, 312 DWORD thread_id) { 313 Log *log = GetLog(WindowsLog::Event | WindowsLog::Exception); 314 if (m_is_shutting_down) { 315 // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic 316 // exception that 317 // we use simply to wake up the DebuggerThread so that we can close out the 318 // debug loop. 319 if (m_pid_to_detach != 0 && 320 (info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT || 321 info.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) { 322 LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}", 323 m_pid_to_detach.load()); 324 ::DebugActiveProcessStop(m_pid_to_detach); 325 m_detached = true; 326 } 327 328 // Don't perform any blocking operations while we're shutting down. That 329 // will cause TerminateProcess -> WaitForSingleObject to time out. 330 return ExceptionResult::SendToApplication; 331 } 332 333 bool first_chance = (info.dwFirstChance != 0); 334 335 m_active_exception.reset( 336 new ExceptionRecord(info.ExceptionRecord, thread_id)); 337 LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}", 338 first_chance ? "first" : "second", 339 info.ExceptionRecord.ExceptionCode, thread_id); 340 341 ExceptionResult result = 342 m_debug_delegate->OnDebugException(first_chance, *m_active_exception); 343 m_exception_pred.SetValue(result, eBroadcastNever); 344 345 LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger"); 346 result = *m_exception_pred.WaitForValueNotEqualTo( 347 ExceptionResult::BreakInDebugger); 348 349 LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue()); 350 return result; 351 } 352 353 DWORD 354 DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, 355 DWORD thread_id) { 356 Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 357 LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id, 358 m_process.GetProcessId()); 359 HostThread thread(info.hThread); 360 thread.GetNativeThread().SetOwnsHandle(false); 361 m_debug_delegate->OnCreateThread(thread); 362 return DBG_CONTINUE; 363 } 364 365 DWORD 366 DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, 367 DWORD thread_id) { 368 Log *log = GetLog(WindowsLog::Event | WindowsLog::Process); 369 uint32_t process_id = ::GetProcessId(info.hProcess); 370 371 LLDB_LOG(log, "process {0} spawned", process_id); 372 373 std::string thread_name; 374 llvm::raw_string_ostream name_stream(thread_name); 375 name_stream << "lldb.plugin.process-windows.secondary[" << process_id << "]"; 376 name_stream.flush(); 377 llvm::set_thread_name(thread_name); 378 379 // info.hProcess and info.hThread are closed automatically by Windows when 380 // EXIT_PROCESS_DEBUG_EVENT is received. 381 m_process = HostProcess(info.hProcess); 382 ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); 383 m_main_thread = HostThread(info.hThread); 384 m_main_thread.GetNativeThread().SetOwnsHandle(false); 385 m_image_file = info.hFile; 386 387 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); 388 m_debug_delegate->OnDebuggerConnected(load_addr); 389 390 return DBG_CONTINUE; 391 } 392 393 DWORD 394 DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, 395 DWORD thread_id) { 396 Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 397 LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id, 398 info.dwExitCode, m_process.GetProcessId()); 399 m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); 400 return DBG_CONTINUE; 401 } 402 403 DWORD 404 DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, 405 DWORD thread_id) { 406 Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 407 LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(), 408 info.dwExitCode); 409 410 m_debug_delegate->OnExitProcess(info.dwExitCode); 411 412 return DBG_CONTINUE; 413 } 414 415 static llvm::Optional<std::string> GetFileNameFromHandleFallback(HANDLE hFile) { 416 // Check that file is not empty as we cannot map a file with zero length. 417 DWORD dwFileSizeHi = 0; 418 DWORD dwFileSizeLo = ::GetFileSize(hFile, &dwFileSizeHi); 419 if (dwFileSizeLo == 0 && dwFileSizeHi == 0) 420 return llvm::None; 421 422 AutoHandle filemap( 423 ::CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 1, NULL), nullptr); 424 if (!filemap.IsValid()) 425 return llvm::None; 426 427 auto view_deleter = [](void *pMem) { ::UnmapViewOfFile(pMem); }; 428 std::unique_ptr<void, decltype(view_deleter)> pMem( 429 ::MapViewOfFile(filemap.get(), FILE_MAP_READ, 0, 0, 1), view_deleter); 430 if (!pMem) 431 return llvm::None; 432 433 std::array<wchar_t, MAX_PATH + 1> mapped_filename; 434 if (!::GetMappedFileNameW(::GetCurrentProcess(), pMem.get(), 435 mapped_filename.data(), mapped_filename.size())) 436 return llvm::None; 437 438 // A series of null-terminated strings, plus an additional null character 439 std::array<wchar_t, 512> drive_strings; 440 drive_strings[0] = L'\0'; 441 if (!::GetLogicalDriveStringsW(drive_strings.size(), drive_strings.data())) 442 return llvm::None; 443 444 std::array<wchar_t, 3> drive = {L"_:"}; 445 for (const wchar_t *it = drive_strings.data(); *it != L'\0'; 446 it += wcslen(it) + 1) { 447 // Copy the drive letter to the template string 448 drive[0] = it[0]; 449 std::array<wchar_t, MAX_PATH> device_name; 450 if (::QueryDosDeviceW(drive.data(), device_name.data(), 451 device_name.size())) { 452 size_t device_name_len = wcslen(device_name.data()); 453 if (device_name_len < mapped_filename.size()) { 454 bool match = _wcsnicmp(mapped_filename.data(), device_name.data(), 455 device_name_len) == 0; 456 if (match && mapped_filename[device_name_len] == L'\\') { 457 // Replace device path with its drive letter 458 std::wstring rebuilt_path(drive.data()); 459 rebuilt_path.append(&mapped_filename[device_name_len]); 460 std::string path_utf8; 461 llvm::convertWideToUTF8(rebuilt_path, path_utf8); 462 return path_utf8; 463 } 464 } 465 } 466 } 467 return llvm::None; 468 } 469 470 DWORD 471 DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, 472 DWORD thread_id) { 473 Log *log = GetLog(WindowsLog::Event); 474 if (info.hFile == nullptr) { 475 // Not sure what this is, so just ignore it. 476 LLDB_LOG(log, "Warning: Inferior {0} has a NULL file handle, returning...", 477 m_process.GetProcessId()); 478 return DBG_CONTINUE; 479 } 480 481 auto on_load_dll = [&](llvm::StringRef path) { 482 FileSpec file_spec(path); 483 ModuleSpec module_spec(file_spec); 484 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); 485 486 LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", 487 m_process.GetProcessId(), path, info.lpBaseOfDll); 488 489 m_debug_delegate->OnLoadDll(module_spec, load_addr); 490 }; 491 492 std::vector<wchar_t> buffer(1); 493 DWORD required_size = 494 GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); 495 if (required_size > 0) { 496 buffer.resize(required_size + 1); 497 required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 498 required_size, VOLUME_NAME_DOS); 499 std::string path_str_utf8; 500 llvm::convertWideToUTF8(buffer.data(), path_str_utf8); 501 llvm::StringRef path_str = path_str_utf8; 502 const char *path = path_str.data(); 503 if (path_str.startswith("\\\\?\\")) 504 path += 4; 505 506 on_load_dll(path); 507 } else if (llvm::Optional<std::string> path = 508 GetFileNameFromHandleFallback(info.hFile)) { 509 on_load_dll(*path); 510 } else { 511 LLDB_LOG( 512 log, 513 "Inferior {0} - Error {1} occurred calling GetFinalPathNameByHandle", 514 m_process.GetProcessId(), ::GetLastError()); 515 } 516 // Windows does not automatically close info.hFile, so we need to do it. 517 ::CloseHandle(info.hFile); 518 return DBG_CONTINUE; 519 } 520 521 DWORD 522 DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, 523 DWORD thread_id) { 524 Log *log = GetLog(WindowsLog::Event); 525 LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.", 526 m_process.GetProcessId(), info.lpBaseOfDll); 527 528 m_debug_delegate->OnUnloadDll( 529 reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); 530 return DBG_CONTINUE; 531 } 532 533 DWORD 534 DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, 535 DWORD thread_id) { 536 return DBG_CONTINUE; 537 } 538 539 DWORD 540 DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { 541 Log *log = GetLog(WindowsLog::Event); 542 LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}", 543 info.dwError, info.dwType, m_process.GetProcessId(), thread_id); 544 545 Status error(info.dwError, eErrorTypeWin32); 546 m_debug_delegate->OnDebuggerError(error, info.dwType); 547 548 return DBG_CONTINUE; 549 } 550