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