1 //===-- ProcessDebugger.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 "ProcessDebugger.h"
10
11 // Windows includes
12 #include "lldb/Host/windows/windows.h"
13 #include <psapi.h>
14
15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/HostNativeProcessBase.h"
17 #include "lldb/Host/HostProcess.h"
18 #include "lldb/Host/HostThread.h"
19 #include "lldb/Host/ProcessLaunchInfo.h"
20 #include "lldb/Target/MemoryRegionInfo.h"
21 #include "lldb/Target/Process.h"
22 #include "llvm/Support/ConvertUTF.h"
23 #include "llvm/Support/Error.h"
24
25 #include "DebuggerThread.h"
26 #include "ExceptionRecord.h"
27 #include "ProcessWindowsLog.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
ConvertLldbToWinApiProtect(uint32_t protect)32 static DWORD ConvertLldbToWinApiProtect(uint32_t protect) {
33 // We also can process a read / write permissions here, but if the debugger
34 // will make later a write into the allocated memory, it will fail. To get
35 // around it is possible inside DoWriteMemory to remember memory permissions,
36 // allow write, write and restore permissions, but for now we process only
37 // the executable permission.
38 //
39 // TODO: Process permissions other than executable
40 if (protect & ePermissionsExecutable)
41 return PAGE_EXECUTE_READWRITE;
42
43 return PAGE_READWRITE;
44 }
45
46 // The Windows page protection bits are NOT independent masks that can be
47 // bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE
48 // | PAGE_READ). To test for an access type, it's necessary to test for any of
49 // the bits that provide that access type.
IsPageReadable(uint32_t protect)50 static bool IsPageReadable(uint32_t protect) {
51 return (protect & PAGE_NOACCESS) == 0;
52 }
53
IsPageWritable(uint32_t protect)54 static bool IsPageWritable(uint32_t protect) {
55 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
56 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
57 }
58
IsPageExecutable(uint32_t protect)59 static bool IsPageExecutable(uint32_t protect) {
60 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
61 PAGE_EXECUTE_WRITECOPY)) != 0;
62 }
63
64 namespace lldb_private {
65
~ProcessDebugger()66 ProcessDebugger::~ProcessDebugger() {}
67
GetDebuggedProcessId() const68 lldb::pid_t ProcessDebugger::GetDebuggedProcessId() const {
69 if (m_session_data)
70 return m_session_data->m_debugger->GetProcess().GetProcessId();
71 return LLDB_INVALID_PROCESS_ID;
72 }
73
DetachProcess()74 Status ProcessDebugger::DetachProcess() {
75 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
76 DebuggerThreadSP debugger_thread;
77 {
78 // Acquire the lock only long enough to get the DebuggerThread.
79 // StopDebugging() will trigger a call back into ProcessDebugger which will
80 // also acquire the lock. Thus we have to release the lock before calling
81 // StopDebugging().
82 llvm::sys::ScopedLock lock(m_mutex);
83
84 if (!m_session_data) {
85 LLDB_LOG(log, "there is no active session.");
86 return Status();
87 }
88
89 debugger_thread = m_session_data->m_debugger;
90 }
91
92 Status error;
93
94 LLDB_LOG(log, "detaching from process {0}.",
95 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
96 error = debugger_thread->StopDebugging(false);
97
98 // By the time StopDebugging returns, there is no more debugger thread, so
99 // we can be assured that no other thread will race for the session data.
100 m_session_data.reset();
101
102 return error;
103 }
104
LaunchProcess(ProcessLaunchInfo & launch_info,DebugDelegateSP delegate)105 Status ProcessDebugger::LaunchProcess(ProcessLaunchInfo &launch_info,
106 DebugDelegateSP delegate) {
107 // Even though m_session_data is accessed here, it is before a debugger
108 // thread has been kicked off. So there's no race conditions, and it
109 // shouldn't be necessary to acquire the mutex.
110
111 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
112 Status result;
113
114 FileSpec working_dir = launch_info.GetWorkingDirectory();
115 namespace fs = llvm::sys::fs;
116 if (working_dir) {
117 FileSystem::Instance().Resolve(working_dir);
118 if (!FileSystem::Instance().IsDirectory(working_dir)) {
119 result.SetErrorStringWithFormat("No such file or directory: %s",
120 working_dir.GetCString());
121 return result;
122 }
123 }
124
125 if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
126 StreamString stream;
127 stream.Printf("ProcessDebugger unable to launch '%s'. ProcessDebugger can "
128 "only be used for debug launches.",
129 launch_info.GetExecutableFile().GetPath().c_str());
130 std::string message = stream.GetString().str();
131 result.SetErrorString(message.c_str());
132
133 LLDB_LOG(log, "error: {0}", message);
134 return result;
135 }
136
137 bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
138 m_session_data.reset(new ProcessWindowsData(stop_at_entry));
139 m_session_data->m_debugger.reset(new DebuggerThread(delegate));
140 DebuggerThreadSP debugger = m_session_data->m_debugger;
141
142 // Kick off the DebugLaunch asynchronously and wait for it to complete.
143 result = debugger->DebugLaunch(launch_info);
144 if (result.Fail()) {
145 LLDB_LOG(log, "failed launching '{0}'. {1}",
146 launch_info.GetExecutableFile().GetPath(), result);
147 return result;
148 }
149
150 HostProcess process;
151 Status error = WaitForDebuggerConnection(debugger, process);
152 if (error.Fail()) {
153 LLDB_LOG(log, "failed launching '{0}'. {1}",
154 launch_info.GetExecutableFile().GetPath(), error);
155 return error;
156 }
157
158 LLDB_LOG(log, "successfully launched '{0}'",
159 launch_info.GetExecutableFile().GetPath());
160
161 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
162 // private state should already be set to eStateStopped as a result of
163 // hitting the initial breakpoint. If it was not set, the breakpoint should
164 // have already been resumed from and the private state should already be
165 // eStateRunning.
166 launch_info.SetProcessID(process.GetProcessId());
167
168 return result;
169 }
170
AttachProcess(lldb::pid_t pid,const ProcessAttachInfo & attach_info,DebugDelegateSP delegate)171 Status ProcessDebugger::AttachProcess(lldb::pid_t pid,
172 const ProcessAttachInfo &attach_info,
173 DebugDelegateSP delegate) {
174 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
175 m_session_data.reset(
176 new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
177 DebuggerThreadSP debugger(new DebuggerThread(delegate));
178
179 m_session_data->m_debugger = debugger;
180
181 DWORD process_id = static_cast<DWORD>(pid);
182 Status error = debugger->DebugAttach(process_id, attach_info);
183 if (error.Fail()) {
184 LLDB_LOG(
185 log,
186 "encountered an error occurred initiating the asynchronous attach. {0}",
187 error);
188 return error;
189 }
190
191 HostProcess process;
192 error = WaitForDebuggerConnection(debugger, process);
193 if (error.Fail()) {
194 LLDB_LOG(log,
195 "encountered an error waiting for the debugger to connect. {0}",
196 error);
197 return error;
198 }
199
200 LLDB_LOG(log, "successfully attached to process with pid={0}", process_id);
201
202 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
203 // private state should already be set to eStateStopped as a result of
204 // hitting the initial breakpoint. If it was not set, the breakpoint should
205 // have already been resumed from and the private state should already be
206 // eStateRunning.
207
208 return error;
209 }
210
DestroyProcess(const lldb::StateType state)211 Status ProcessDebugger::DestroyProcess(const lldb::StateType state) {
212 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
213 DebuggerThreadSP debugger_thread;
214 {
215 // Acquire this lock inside an inner scope, only long enough to get the
216 // DebuggerThread. StopDebugging() will trigger a call back into
217 // ProcessDebugger which will acquire the lock again, so we need to not
218 // deadlock.
219 llvm::sys::ScopedLock lock(m_mutex);
220
221 if (!m_session_data) {
222 LLDB_LOG(log, "warning: state = {0}, but there is no active session.",
223 state);
224 return Status();
225 }
226
227 debugger_thread = m_session_data->m_debugger;
228 }
229
230 if (state == eStateExited || state == eStateDetached) {
231 LLDB_LOG(log, "warning: cannot destroy process {0} while state = {1}.",
232 GetDebuggedProcessId(), state);
233 return Status();
234 }
235
236 LLDB_LOG(log, "Shutting down process {0}.",
237 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
238 auto error = debugger_thread->StopDebugging(true);
239
240 // By the time StopDebugging returns, there is no more debugger thread, so
241 // we can be assured that no other thread will race for the session data.
242 m_session_data.reset();
243
244 return error;
245 }
246
HaltProcess(bool & caused_stop)247 Status ProcessDebugger::HaltProcess(bool &caused_stop) {
248 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
249 Status error;
250 llvm::sys::ScopedLock lock(m_mutex);
251 caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
252 .GetNativeProcess()
253 .GetSystemHandle());
254 if (!caused_stop) {
255 error.SetError(::GetLastError(), eErrorTypeWin32);
256 LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error);
257 }
258
259 return error;
260 }
261
ReadMemory(lldb::addr_t vm_addr,void * buf,size_t size,size_t & bytes_read)262 Status ProcessDebugger::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
263 size_t &bytes_read) {
264 Status error;
265 bytes_read = 0;
266 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
267 llvm::sys::ScopedLock lock(m_mutex);
268
269 if (!m_session_data) {
270 error.SetErrorString(
271 "cannot read, there is no active debugger connection.");
272 LLDB_LOG(log, "error: {0}", error);
273 return error;
274 }
275
276 LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size,
277 vm_addr);
278
279 HostProcess process = m_session_data->m_debugger->GetProcess();
280 void *addr = reinterpret_cast<void *>(vm_addr);
281 SIZE_T num_of_bytes_read = 0;
282 if (!::ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr,
283 buf, size, &num_of_bytes_read)) {
284 // Reading from the process can fail for a number of reasons - set the
285 // error code and make sure that the number of bytes read is set back to 0
286 // because in some scenarios the value of bytes_read returned from the API
287 // is garbage.
288 error.SetError(GetLastError(), eErrorTypeWin32);
289 LLDB_LOG(log, "reading failed with error: {0}", error);
290 } else {
291 bytes_read = num_of_bytes_read;
292 }
293 return error;
294 }
295
WriteMemory(lldb::addr_t vm_addr,const void * buf,size_t size,size_t & bytes_written)296 Status ProcessDebugger::WriteMemory(lldb::addr_t vm_addr, const void *buf,
297 size_t size, size_t &bytes_written) {
298 Status error;
299 bytes_written = 0;
300 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
301 llvm::sys::ScopedLock lock(m_mutex);
302 LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size,
303 vm_addr);
304
305 if (!m_session_data) {
306 error.SetErrorString(
307 "cannot write, there is no active debugger connection.");
308 LLDB_LOG(log, "error: {0}", error);
309 return error;
310 }
311
312 HostProcess process = m_session_data->m_debugger->GetProcess();
313 void *addr = reinterpret_cast<void *>(vm_addr);
314 SIZE_T num_of_bytes_written = 0;
315 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
316 if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
317 FlushInstructionCache(handle, addr, num_of_bytes_written);
318 bytes_written = num_of_bytes_written;
319 } else {
320 error.SetError(GetLastError(), eErrorTypeWin32);
321 LLDB_LOG(log, "writing failed with error: {0}", error);
322 }
323 return error;
324 }
325
AllocateMemory(size_t size,uint32_t permissions,lldb::addr_t & addr)326 Status ProcessDebugger::AllocateMemory(size_t size, uint32_t permissions,
327 lldb::addr_t &addr) {
328 Status error;
329 addr = LLDB_INVALID_ADDRESS;
330 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
331 llvm::sys::ScopedLock lock(m_mutex);
332 LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size,
333 permissions);
334
335 if (!m_session_data) {
336 error.SetErrorString(
337 "cannot allocate, there is no active debugger connection");
338 LLDB_LOG(log, "error: {0}", error);
339 return error;
340 }
341
342 HostProcess process = m_session_data->m_debugger->GetProcess();
343 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
344 auto protect = ConvertLldbToWinApiProtect(permissions);
345 auto result = ::VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect);
346 if (!result) {
347 error.SetError(GetLastError(), eErrorTypeWin32);
348 LLDB_LOG(log, "allocating failed with error: {0}", error);
349 } else {
350 addr = reinterpret_cast<addr_t>(result);
351 }
352 return error;
353 }
354
DeallocateMemory(lldb::addr_t vm_addr)355 Status ProcessDebugger::DeallocateMemory(lldb::addr_t vm_addr) {
356 Status result;
357
358 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
359 llvm::sys::ScopedLock lock(m_mutex);
360 LLDB_LOG(log, "attempting to deallocate bytes at address {0}", vm_addr);
361
362 if (!m_session_data) {
363 result.SetErrorString(
364 "cannot deallocate, there is no active debugger connection");
365 LLDB_LOG(log, "error: {0}", result);
366 return result;
367 }
368
369 HostProcess process = m_session_data->m_debugger->GetProcess();
370 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
371 if (!::VirtualFreeEx(handle, reinterpret_cast<LPVOID>(vm_addr), 0,
372 MEM_RELEASE)) {
373 result.SetError(GetLastError(), eErrorTypeWin32);
374 LLDB_LOG(log, "deallocating failed with error: {0}", result);
375 }
376
377 return result;
378 }
379
GetMemoryRegionInfo(lldb::addr_t vm_addr,MemoryRegionInfo & info)380 Status ProcessDebugger::GetMemoryRegionInfo(lldb::addr_t vm_addr,
381 MemoryRegionInfo &info) {
382 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
383 Status error;
384 llvm::sys::ScopedLock lock(m_mutex);
385 info.Clear();
386
387 if (!m_session_data) {
388 error.SetErrorString(
389 "GetMemoryRegionInfo called with no debugging session.");
390 LLDB_LOG(log, "error: {0}", error);
391 return error;
392 }
393 HostProcess process = m_session_data->m_debugger->GetProcess();
394 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
395 if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
396 error.SetErrorString(
397 "GetMemoryRegionInfo called with an invalid target process.");
398 LLDB_LOG(log, "error: {0}", error);
399 return error;
400 }
401
402 LLDB_LOG(log, "getting info for address {0:x}", vm_addr);
403
404 void *addr = reinterpret_cast<void *>(vm_addr);
405 MEMORY_BASIC_INFORMATION mem_info = {};
406 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
407 if (result == 0) {
408 DWORD last_error = ::GetLastError();
409 if (last_error == ERROR_INVALID_PARAMETER) {
410 // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with
411 // an address past the highest accessible address. We should return a
412 // range from the vm_addr to LLDB_INVALID_ADDRESS
413 info.GetRange().SetRangeBase(vm_addr);
414 info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
415 info.SetReadable(MemoryRegionInfo::eNo);
416 info.SetExecutable(MemoryRegionInfo::eNo);
417 info.SetWritable(MemoryRegionInfo::eNo);
418 info.SetMapped(MemoryRegionInfo::eNo);
419 return error;
420 } else {
421 error.SetError(last_error, eErrorTypeWin32);
422 LLDB_LOG(log,
423 "VirtualQueryEx returned error {0} while getting memory "
424 "region info for address {1:x}",
425 error, vm_addr);
426 return error;
427 }
428 }
429
430 // Protect bits are only valid for MEM_COMMIT regions.
431 if (mem_info.State == MEM_COMMIT) {
432 const bool readable = IsPageReadable(mem_info.Protect);
433 const bool executable = IsPageExecutable(mem_info.Protect);
434 const bool writable = IsPageWritable(mem_info.Protect);
435 info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
436 info.SetExecutable(executable ? MemoryRegionInfo::eYes
437 : MemoryRegionInfo::eNo);
438 info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
439 } else {
440 info.SetReadable(MemoryRegionInfo::eNo);
441 info.SetExecutable(MemoryRegionInfo::eNo);
442 info.SetWritable(MemoryRegionInfo::eNo);
443 }
444
445 // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
446 if (mem_info.State != MEM_FREE) {
447 info.GetRange().SetRangeBase(
448 reinterpret_cast<addr_t>(mem_info.AllocationBase));
449 info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
450 mem_info.RegionSize);
451 info.SetMapped(MemoryRegionInfo::eYes);
452 } else {
453 // In the unmapped case we need to return the distance to the next block of
454 // memory. VirtualQueryEx nearly does that except that it gives the
455 // distance from the start of the page containing vm_addr.
456 SYSTEM_INFO data;
457 ::GetSystemInfo(&data);
458 DWORD page_offset = vm_addr % data.dwPageSize;
459 info.GetRange().SetRangeBase(vm_addr);
460 info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
461 info.SetMapped(MemoryRegionInfo::eNo);
462 }
463
464 LLDB_LOGV(log,
465 "Memory region info for address {0}: readable={1}, "
466 "executable={2}, writable={3}",
467 vm_addr, info.GetReadable(), info.GetExecutable(),
468 info.GetWritable());
469 return error;
470 }
471
OnExitProcess(uint32_t exit_code)472 void ProcessDebugger::OnExitProcess(uint32_t exit_code) {
473 // If the process exits before any initial stop then notify the debugger
474 // of the error otherwise WaitForDebuggerConnection() will be blocked.
475 // An example of this issue is when a process fails to load a dependent DLL.
476 if (m_session_data && !m_session_data->m_initial_stop_received) {
477 Status error(exit_code, eErrorTypeWin32);
478 OnDebuggerError(error, 0);
479 }
480 }
481
OnDebuggerConnected(lldb::addr_t image_base)482 void ProcessDebugger::OnDebuggerConnected(lldb::addr_t image_base) {}
483
484 ExceptionResult
OnDebugException(bool first_chance,const ExceptionRecord & record)485 ProcessDebugger::OnDebugException(bool first_chance,
486 const ExceptionRecord &record) {
487 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
488 llvm::sys::ScopedLock lock(m_mutex);
489 // FIXME: Without this check, occasionally when running the test suite
490 // there is an issue where m_session_data can be null. It's not clear how
491 // this could happen but it only surfaces while running the test suite. In
492 // order to properly diagnose this, we probably need to first figure allow the
493 // test suite to print out full lldb logs, and then add logging to the process
494 // plugin.
495 if (!m_session_data) {
496 LLDB_LOG(log,
497 "Debugger thread reported exception {0:x} at address {1:x}, but "
498 "there is no session.",
499 record.GetExceptionCode(), record.GetExceptionAddress());
500 return ExceptionResult::SendToApplication;
501 }
502
503 ExceptionResult result = ExceptionResult::SendToApplication;
504 if ((record.GetExceptionCode() == EXCEPTION_BREAKPOINT ||
505 record.GetExceptionCode() ==
506 0x4000001FL /*WOW64 STATUS_WX86_BREAKPOINT*/) &&
507 !m_session_data->m_initial_stop_received) {
508 // Handle breakpoints at the first chance.
509 result = ExceptionResult::BreakInDebugger;
510 LLDB_LOG(
511 log,
512 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
513 record.GetExceptionAddress());
514 m_session_data->m_initial_stop_received = true;
515 ::SetEvent(m_session_data->m_initial_stop_event);
516 }
517 return result;
518 }
519
OnCreateThread(const HostThread & thread)520 void ProcessDebugger::OnCreateThread(const HostThread &thread) {
521 // Do nothing by default
522 }
523
OnExitThread(lldb::tid_t thread_id,uint32_t exit_code)524 void ProcessDebugger::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
525 // Do nothing by default
526 }
527
OnLoadDll(const ModuleSpec & module_spec,lldb::addr_t module_addr)528 void ProcessDebugger::OnLoadDll(const ModuleSpec &module_spec,
529 lldb::addr_t module_addr) {
530 // Do nothing by default
531 }
532
OnUnloadDll(lldb::addr_t module_addr)533 void ProcessDebugger::OnUnloadDll(lldb::addr_t module_addr) {
534 // Do nothing by default
535 }
536
OnDebugString(const std::string & string)537 void ProcessDebugger::OnDebugString(const std::string &string) {}
538
OnDebuggerError(const Status & error,uint32_t type)539 void ProcessDebugger::OnDebuggerError(const Status &error, uint32_t type) {
540 llvm::sys::ScopedLock lock(m_mutex);
541 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
542
543 if (m_session_data->m_initial_stop_received) {
544 // This happened while debugging. Do we shutdown the debugging session,
545 // try to continue, or do something else?
546 LLDB_LOG(log,
547 "Error {0} occurred during debugging. Unexpected behavior "
548 "may result. {1}",
549 error.GetError(), error);
550 } else {
551 // If we haven't actually launched the process yet, this was an error
552 // launching the process. Set the internal error and signal the initial
553 // stop event so that the DoLaunch method wakes up and returns a failure.
554 m_session_data->m_launch_error = error;
555 ::SetEvent(m_session_data->m_initial_stop_event);
556 LLDB_LOG(log,
557 "Error {0} occurred launching the process before the initial "
558 "stop. {1}",
559 error.GetError(), error);
560 return;
561 }
562 }
563
WaitForDebuggerConnection(DebuggerThreadSP debugger,HostProcess & process)564 Status ProcessDebugger::WaitForDebuggerConnection(DebuggerThreadSP debugger,
565 HostProcess &process) {
566 Status result;
567 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS |
568 WINDOWS_LOG_BREAKPOINTS);
569 LLDB_LOG(log, "Waiting for loader breakpoint.");
570
571 // Block this function until we receive the initial stop from the process.
572 if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
573 WAIT_OBJECT_0) {
574 LLDB_LOG(log, "hit loader breakpoint, returning.");
575
576 process = debugger->GetProcess();
577 return m_session_data->m_launch_error;
578 } else
579 return Status(::GetLastError(), eErrorTypeWin32);
580 }
581
582 } // namespace lldb_private
583