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