blob: 50f787f78495a65c2a1b76676adb44ba8bd729d5 [file] [log] [blame]
Adrian McCarthy18a9135d2015-10-28 18:21:45 +00001//===-- ProcessWindows.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 "ProcessWindows.h"
11
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000012// Windows includes
13#include "lldb/Host/windows/windows.h"
14#include <psapi.h>
15
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000016// Other libraries and framework includes
17#include "lldb/Core/Module.h"
18#include "lldb/Core/ModuleSpec.h"
19#include "lldb/Core/PluginManager.h"
20#include "lldb/Core/Section.h"
21#include "lldb/Core/State.h"
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000022#include "lldb/Host/HostNativeProcessBase.h"
23#include "lldb/Host/HostProcess.h"
24#include "lldb/Host/windows/HostThreadWindows.h"
Adrian McCarthy0c35cde2015-12-04 22:22:15 +000025#include "lldb/Host/windows/windows.h"
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000026#include "lldb/Target/DynamicLoader.h"
27#include "lldb/Target/MemoryRegionInfo.h"
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000028#include "lldb/Target/StopInfo.h"
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000029#include "lldb/Target/Target.h"
30
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000031#include "llvm/Support/ConvertUTF.h"
32#include "llvm/Support/Format.h"
33#include "llvm/Support/raw_ostream.h"
34
35#include "DebuggerThread.h"
36#include "ExceptionRecord.h"
37#include "ForwardDecl.h"
38#include "LocalDebugDelegate.h"
39#include "ProcessWindowsLog.h"
40#include "TargetThreadWindows.h"
41
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000042using namespace lldb;
43using namespace lldb_private;
44
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000045namespace {
46std::string GetProcessExecutableName(HANDLE process_handle) {
47 std::vector<wchar_t> file_name;
48 DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
49 DWORD copied = 0;
50 do {
51 file_name_size *= 2;
52 file_name.resize(file_name_size);
53 copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
54 file_name_size);
55 } while (copied >= file_name_size);
56 file_name.resize(copied);
57 std::string result;
58 llvm::convertWideToUTF8(file_name.data(), result);
59 return result;
60}
61
62std::string GetProcessExecutableName(DWORD pid) {
63 std::string file_name;
64 HANDLE process_handle =
65 ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
66 if (process_handle != NULL) {
67 file_name = GetProcessExecutableName(process_handle);
68 ::CloseHandle(process_handle);
69 }
70 return file_name;
71}
72
73} // anonymous namespace
74
Kate Stoneb9c1b512016-09-06 20:57:50 +000075namespace lldb_private {
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000076
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000077// We store a pointer to this class in the ProcessWindows, so that we don't
78// expose Windows-specific types and implementation details from a public header
79// file.
80class ProcessWindowsData {
81public:
82 ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) {
83 m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
84 }
85
86 ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }
87
88 Error m_launch_error;
89 DebuggerThreadSP m_debugger;
90 StopInfoSP m_pending_stop_info;
91 HANDLE m_initial_stop_event = nullptr;
92 bool m_initial_stop_received = false;
93 bool m_stop_at_entry;
94 std::map<lldb::tid_t, HostThread> m_new_threads;
95 std::set<lldb::tid_t> m_exited_threads;
96};
97
98ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,
99 lldb::ListenerSP listener_sp,
100 const FileSpec *) {
101 return ProcessSP(new ProcessWindows(target_sp, listener_sp));
102}
103
104void ProcessWindows::Initialize() {
105 static std::once_flag g_once_flag;
106
107 std::call_once(g_once_flag, []() {
108 PluginManager::RegisterPlugin(GetPluginNameStatic(),
109 GetPluginDescriptionStatic(), CreateInstance);
110 });
111}
112
113void ProcessWindows::Terminate() {}
114
115lldb_private::ConstString ProcessWindows::GetPluginNameStatic() {
116 static ConstString g_name("windows");
117 return g_name;
118}
119
120const char *ProcessWindows::GetPluginDescriptionStatic() {
121 return "Process plugin for Windows";
122}
123
Adrian McCarthy18a9135d2015-10-28 18:21:45 +0000124//------------------------------------------------------------------------------
125// Constructors and destructors.
126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
128 lldb::ListenerSP listener_sp)
129 : lldb_private::Process(target_sp, listener_sp) {}
130
131ProcessWindows::~ProcessWindows() {}
132
133size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) {
134 error.SetErrorString("GetSTDOUT unsupported on Windows");
135 return 0;
Adrian McCarthy18a9135d2015-10-28 18:21:45 +0000136}
137
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) {
139 error.SetErrorString("GetSTDERR unsupported on Windows");
140 return 0;
Adrian McCarthy18a9135d2015-10-28 18:21:45 +0000141}
142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
144 Error &error) {
145 error.SetErrorString("PutSTDIN unsupported on Windows");
146 return 0;
Adrian McCarthy18a9135d2015-10-28 18:21:45 +0000147}
148
149//------------------------------------------------------------------------------
150// ProcessInterface protocol.
151
Adrian McCarthy4ad5def2016-11-23 16:26:37 +0000152lldb_private::ConstString ProcessWindows::GetPluginName() {
153 return GetPluginNameStatic();
154}
155
156uint32_t ProcessWindows::GetPluginVersion() { return 1; }
157
158Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
159 WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
160 "EnableBreakpointSite called with bp_site 0x%p "
161 "(id=%d, addr=0x%llx)",
162 bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
163
164 Error error = EnableSoftwareBreakpoint(bp_site);
165 if (!error.Success()) {
166 WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s",
167 error.AsCString());
168 }
169 return error;
170}
171
172Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {
173 WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
174 "DisableBreakpointSite called with bp_site 0x%p "
175 "(id=%d, addr=0x%llx)",
176 bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
177
178 Error error = DisableSoftwareBreakpoint(bp_site);
179
180 if (!error.Success()) {
181 WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s",
182 error.AsCString());
183 }
184 return error;
185}
186
187Error ProcessWindows::DoDetach(bool keep_stopped) {
188 DebuggerThreadSP debugger_thread;
189 StateType private_state;
190 {
191 // Acquire the lock only long enough to get the DebuggerThread.
192 // StopDebugging() will trigger a call back into ProcessWindows which
193 // will also acquire the lock. Thus we have to release the lock before
194 // calling StopDebugging().
195 llvm::sys::ScopedLock lock(m_mutex);
196
197 private_state = GetPrivateState();
198
199 if (!m_session_data) {
200 WINWARN_IFALL(
201 WINDOWS_LOG_PROCESS,
202 "DoDetach called while state = %u, but there is no active session.",
203 private_state);
204 return Error();
205 }
206
207 debugger_thread = m_session_data->m_debugger;
208 }
209
210 Error error;
211 if (private_state != eStateExited && private_state != eStateDetached) {
212 WINLOG_IFALL(
213 WINDOWS_LOG_PROCESS,
214 "DoDetach called for process %p while state = %d. Detaching...",
215 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
216 private_state);
217 error = debugger_thread->StopDebugging(false);
218 if (error.Success()) {
219 SetPrivateState(eStateDetached);
220 }
221
222 // By the time StopDebugging returns, there is no more debugger thread, so
223 // we can be assured that no other thread will race for the session data.
224 m_session_data.reset();
225 } else {
226 WINERR_IFALL(
227 WINDOWS_LOG_PROCESS, "DoDetach called for process %p while state = "
228 "%d, but cannot destroy in this state.",
229 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
230 private_state);
231 }
232
233 return error;
234}
235
236Error ProcessWindows::DoLaunch(Module *exe_module,
237 ProcessLaunchInfo &launch_info) {
238 // Even though m_session_data is accessed here, it is before a debugger thread
239 // has been
240 // kicked off. So there's no race conditions, and it shouldn't be necessary
241 // to acquire
242 // the mutex.
243
244 Error result;
245 if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
246 StreamString stream;
247 stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can "
248 "only be used for debug launches.",
249 launch_info.GetExecutableFile().GetPath().c_str());
250 std::string message = stream.GetString();
251 result.SetErrorString(message.c_str());
252
253 WINERR_IFALL(WINDOWS_LOG_PROCESS, "%s", message.c_str());
254 return result;
255 }
256
257 bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
258 m_session_data.reset(new ProcessWindowsData(stop_at_entry));
259
260 SetPrivateState(eStateLaunching);
261 DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
262 m_session_data->m_debugger.reset(new DebuggerThread(delegate));
263 DebuggerThreadSP debugger = m_session_data->m_debugger;
264
265 // Kick off the DebugLaunch asynchronously and wait for it to complete.
266 result = debugger->DebugLaunch(launch_info);
267 if (result.Fail()) {
268 WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s",
269 launch_info.GetExecutableFile().GetPath().c_str(),
270 result.AsCString());
271 return result;
272 }
273
274 HostProcess process;
275 Error error = WaitForDebuggerConnection(debugger, process);
276 if (error.Fail()) {
277 WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s",
278 launch_info.GetExecutableFile().GetPath().c_str(),
279 error.AsCString());
280 return error;
281 }
282
283 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'",
284 launch_info.GetExecutableFile().GetPath().c_str());
285
286 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
287 // private state
288 // should already be set to eStateStopped as a result of hitting the initial
289 // breakpoint. If
290 // it was not set, the breakpoint should have already been resumed from and
291 // the private state
292 // should already be eStateRunning.
293 launch_info.SetProcessID(process.GetProcessId());
294 SetID(process.GetProcessId());
295
296 return result;
297}
298
299Error ProcessWindows::DoAttachToProcessWithID(
300 lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
301 m_session_data.reset(
302 new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
303
304 DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
305 DebuggerThreadSP debugger(new DebuggerThread(delegate));
306
307 m_session_data->m_debugger = debugger;
308
309 DWORD process_id = static_cast<DWORD>(pid);
310 Error error = debugger->DebugAttach(process_id, attach_info);
311 if (error.Fail()) {
312 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
313 "error occurred initiating the "
314 "asynchronous attach. %s",
315 error.AsCString());
316 return error;
317 }
318
319 HostProcess process;
320 error = WaitForDebuggerConnection(debugger, process);
321 if (error.Fail()) {
322 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
323 "error waiting for the debugger to "
324 "connect. %s",
325 error.AsCString());
326 return error;
327 }
328
329 WINLOG_IFALL(
330 WINDOWS_LOG_PROCESS,
331 "DoAttachToProcessWithID successfully attached to process with pid=%lu",
332 process_id);
333
334 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
335 // private state
336 // should already be set to eStateStopped as a result of hitting the initial
337 // breakpoint. If
338 // it was not set, the breakpoint should have already been resumed from and
339 // the private state
340 // should already be eStateRunning.
341 SetID(process.GetProcessId());
342 return error;
343}
344
345Error ProcessWindows::DoResume() {
346 llvm::sys::ScopedLock lock(m_mutex);
347 Error error;
348
349 StateType private_state = GetPrivateState();
350 if (private_state == eStateStopped || private_state == eStateCrashed) {
351 WINLOG_IFALL(
352 WINDOWS_LOG_PROCESS,
353 "DoResume called for process %I64u while state is %u. Resuming...",
354 m_session_data->m_debugger->GetProcess().GetProcessId(),
355 GetPrivateState());
356
357 ExceptionRecordSP active_exception =
358 m_session_data->m_debugger->GetActiveException().lock();
359 if (active_exception) {
360 // Resume the process and continue processing debug events. Mask
361 // the exception so that from the process's view, there is no
362 // indication that anything happened.
363 m_session_data->m_debugger->ContinueAsyncException(
364 ExceptionResult::MaskException);
365 }
366
367 WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD,
368 "DoResume resuming %u threads.", m_thread_list.GetSize());
369
370 for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
371 auto thread = std::static_pointer_cast<TargetThreadWindows>(
372 m_thread_list.GetThreadAtIndex(i));
373 thread->DoResume();
374 }
375
376 SetPrivateState(eStateRunning);
377 } else {
378 WINERR_IFALL(
379 WINDOWS_LOG_PROCESS,
380 "DoResume called for process %I64u but state is %u. Returning...",
381 m_session_data->m_debugger->GetProcess().GetProcessId(),
382 GetPrivateState());
383 }
384 return error;
385}
386
387Error ProcessWindows::DoDestroy() {
388 DebuggerThreadSP debugger_thread;
389 StateType private_state;
390 {
391 // Acquire this lock inside an inner scope, only long enough to get the
392 // DebuggerThread.
393 // StopDebugging() will trigger a call back into ProcessWindows which will
394 // acquire the lock
395 // again, so we need to not deadlock.
396 llvm::sys::ScopedLock lock(m_mutex);
397
398 private_state = GetPrivateState();
399
400 if (!m_session_data) {
401 WINWARN_IFALL(
402 WINDOWS_LOG_PROCESS,
403 "DoDestroy called while state = %u, but there is no active session.",
404 private_state);
405 return Error();
406 }
407
408 debugger_thread = m_session_data->m_debugger;
409 }
410
411 Error error;
412 if (private_state != eStateExited && private_state != eStateDetached) {
413 WINLOG_IFALL(
414 WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
415 "%u. Shutting down...",
416 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
417 private_state);
418 error = debugger_thread->StopDebugging(true);
419
420 // By the time StopDebugging returns, there is no more debugger thread, so
421 // we can be assured that no other thread will race for the session data.
422 m_session_data.reset();
423 } else {
424 WINERR_IFALL(
425 WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
426 "%d, but cannot destroy in this state.",
427 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
428 private_state);
429 }
430
431 return error;
432}
433
434Error ProcessWindows::DoHalt(bool &caused_stop) {
435 Error error;
436 StateType state = GetPrivateState();
437 if (state == eStateStopped)
438 caused_stop = false;
439 else {
440 llvm::sys::ScopedLock lock(m_mutex);
441 caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
442 .GetNativeProcess()
443 .GetSystemHandle());
444 if (!caused_stop) {
445 error.SetError(::GetLastError(), eErrorTypeWin32);
446 WINERR_IFALL(
447 WINDOWS_LOG_PROCESS,
448 "DoHalt called DebugBreakProcess, but it failed with error %u",
449 error.GetError());
450 }
451 }
452 return error;
453}
454
455void ProcessWindows::DidLaunch() {
456 ArchSpec arch_spec;
457 DidAttach(arch_spec);
458}
459
460void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
461 llvm::sys::ScopedLock lock(m_mutex);
462
463 // The initial stop won't broadcast the state change event, so account for
464 // that here.
465 if (m_session_data && GetPrivateState() == eStateStopped &&
466 m_session_data->m_stop_at_entry)
467 RefreshStateAfterStop();
468}
469
470void ProcessWindows::RefreshStateAfterStop() {
471 llvm::sys::ScopedLock lock(m_mutex);
472
473 if (!m_session_data) {
474 WINWARN_IFALL(
475 WINDOWS_LOG_PROCESS,
476 "RefreshStateAfterStop called with no active session. Returning...");
477 return;
478 }
479
480 m_thread_list.RefreshStateAfterStop();
481
482 std::weak_ptr<ExceptionRecord> exception_record =
483 m_session_data->m_debugger->GetActiveException();
484 ExceptionRecordSP active_exception = exception_record.lock();
485 if (!active_exception) {
486 WINERR_IFALL(
487 WINDOWS_LOG_PROCESS,
488 "RefreshStateAfterStop called for process %I64u but there is no "
489 "active exception. Why is the process stopped?",
490 m_session_data->m_debugger->GetProcess().GetProcessId());
491 return;
492 }
493
494 StopInfoSP stop_info;
495 m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
496 ThreadSP stop_thread = m_thread_list.GetSelectedThread();
497 if (!stop_thread)
498 return;
499
500 switch (active_exception->GetExceptionCode()) {
501 case EXCEPTION_SINGLE_STEP: {
502 RegisterContextSP register_context = stop_thread->GetRegisterContext();
503 const uint64_t pc = register_context->GetPC();
504 BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
505 if (site && site->ValidForThisThread(stop_thread.get())) {
506 WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION |
507 WINDOWS_LOG_STEP,
508 "Single-stepped onto a breakpoint in process %I64u at "
509 "address 0x%I64x with breakpoint site %d",
510 m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
511 site->GetID());
512 stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
513 site->GetID());
514 stop_thread->SetStopInfo(stop_info);
515 } else {
516 WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP,
517 "RefreshStateAfterStop single stepping thread %llu",
518 stop_thread->GetID());
519 stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
520 stop_thread->SetStopInfo(stop_info);
521 }
522 return;
523 }
524
525 case EXCEPTION_BREAKPOINT: {
526 RegisterContextSP register_context = stop_thread->GetRegisterContext();
527
528 // The current EIP is AFTER the BP opcode, which is one byte.
529 uint64_t pc = register_context->GetPC() - 1;
530
531 BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
532 if (site) {
533 WINLOG_IFANY(
534 WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
535 "RefreshStateAfterStop detected breakpoint in process %I64u at "
536 "address 0x%I64x with breakpoint site %d",
537 m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
538 site->GetID());
539
540 if (site->ValidForThisThread(stop_thread.get())) {
541 WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
542 "Breakpoint site %d is valid for this thread (0x%I64x), "
543 "creating stop info.",
544 site->GetID(), stop_thread->GetID());
545
546 stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
547 *stop_thread, site->GetID());
548 register_context->SetPC(pc);
549 } else {
550 WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
551 "Breakpoint site %d is not valid for this thread, "
552 "creating empty stop info.",
553 site->GetID());
554 }
555 stop_thread->SetStopInfo(stop_info);
556 return;
557 } else {
558 // The thread hit a hard-coded breakpoint like an `int 3` or
559 // `__debugbreak()`.
560 WINLOG_IFALL(
561 WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
562 "No breakpoint site matches for this thread. __debugbreak()? "
563 "Creating stop info with the exception.");
564 // FALLTHROUGH: We'll treat this as a generic exception record in the
565 // default case.
566 }
567 }
568
569 default: {
570 std::string desc;
571 llvm::raw_string_ostream desc_stream(desc);
572 desc_stream << "Exception "
573 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
574 << " encountered at address "
575 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
576 stop_info = StopInfo::CreateStopReasonWithException(
577 *stop_thread, desc_stream.str().c_str());
578 stop_thread->SetStopInfo(stop_info);
579 WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, "%s", desc_stream.str().c_str());
580 return;
581 }
582 }
583}
584
585bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
586 bool plugin_specified_by_name) {
587 if (plugin_specified_by_name)
588 return true;
589
590 // For now we are just making sure the file exists for a given module
591 ModuleSP exe_module_sp(target_sp->GetExecutableModule());
592 if (exe_module_sp.get())
593 return exe_module_sp->GetFileSpec().Exists();
594 // However, if there is no executable module, we return true since we might be
595 // preparing to attach.
596 return true;
597}
598
599bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
600 ThreadList &new_thread_list) {
601 // Add all the threads that were previously running and for which we did not
602 // detect a thread exited event.
603 int new_size = 0;
604 int continued_threads = 0;
605 int exited_threads = 0;
606 int new_threads = 0;
607
608 for (ThreadSP old_thread : old_thread_list.Threads()) {
609 lldb::tid_t old_thread_id = old_thread->GetID();
610 auto exited_thread_iter =
611 m_session_data->m_exited_threads.find(old_thread_id);
612 if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
613 new_thread_list.AddThread(old_thread);
614 ++new_size;
615 ++continued_threads;
616 WINLOGV_IFALL(
617 WINDOWS_LOG_THREAD,
618 "UpdateThreadList - Thread %llu was running and is still running.",
619 old_thread_id);
620 } else {
621 WINLOGV_IFALL(
622 WINDOWS_LOG_THREAD,
623 "UpdateThreadList - Thread %llu was running and has exited.",
624 old_thread_id);
625 ++exited_threads;
626 }
627 }
628
629 // Also add all the threads that are new since the last time we broke into the
630 // debugger.
631 for (const auto &thread_info : m_session_data->m_new_threads) {
632 ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
633 thread->SetID(thread_info.first);
634 new_thread_list.AddThread(thread);
635 ++new_size;
636 ++new_threads;
637 WINLOGV_IFALL(WINDOWS_LOG_THREAD,
638 "UpdateThreadList - Thread %llu is new since last update.",
639 thread_info.first);
640 }
641
642 WINLOG_IFALL(
643 WINDOWS_LOG_THREAD,
644 "UpdateThreadList - %d new threads, %d old threads, %d exited threads.",
645 new_threads, continued_threads, exited_threads);
646
647 m_session_data->m_new_threads.clear();
648 m_session_data->m_exited_threads.clear();
649
650 return new_size > 0;
651}
652
653bool ProcessWindows::IsAlive() {
654 StateType state = GetPrivateState();
655 switch (state) {
656 case eStateCrashed:
657 case eStateDetached:
658 case eStateUnloaded:
659 case eStateExited:
660 case eStateInvalid:
661 return false;
662 default:
663 return true;
664 }
665}
666
667size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
668 size_t size, Error &error) {
669 llvm::sys::ScopedLock lock(m_mutex);
670
671 if (!m_session_data)
672 return 0;
673
674 WINLOG_IFALL(WINDOWS_LOG_MEMORY,
675 "DoReadMemory attempting to read %u bytes from address 0x%I64x",
676 size, vm_addr);
677
678 HostProcess process = m_session_data->m_debugger->GetProcess();
679 void *addr = reinterpret_cast<void *>(vm_addr);
680 SIZE_T bytes_read = 0;
681 if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr,
682 buf, size, &bytes_read)) {
683 error.SetError(GetLastError(), eErrorTypeWin32);
684 WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u",
685 error.GetError());
686 }
687 return bytes_read;
688}
689
690size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
691 size_t size, Error &error) {
692 llvm::sys::ScopedLock lock(m_mutex);
693 WINLOG_IFALL(
694 WINDOWS_LOG_MEMORY,
695 "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size,
696 vm_addr);
697
698 if (!m_session_data) {
699 WINERR_IFANY(
700 WINDOWS_LOG_MEMORY,
701 "DoWriteMemory cannot write, there is no active debugger connection.");
702 return 0;
703 }
704
705 HostProcess process = m_session_data->m_debugger->GetProcess();
706 void *addr = reinterpret_cast<void *>(vm_addr);
707 SIZE_T bytes_written = 0;
708 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
709 if (WriteProcessMemory(handle, addr, buf, size, &bytes_written))
710 FlushInstructionCache(handle, addr, bytes_written);
711 else {
712 error.SetError(GetLastError(), eErrorTypeWin32);
713 WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u",
714 error.GetError());
715 }
716 return bytes_written;
717}
718
719#define BOOL_STR(b) ((b) ? "true" : "false")
720
721Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
722 MemoryRegionInfo &info) {
723 Error error;
724 llvm::sys::ScopedLock lock(m_mutex);
725 info.Clear();
726
727 if (!m_session_data) {
728 error.SetErrorString(
729 "GetMemoryRegionInfo called with no debugging session.");
730 WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
731 return error;
732 }
733 HostProcess process = m_session_data->m_debugger->GetProcess();
734 lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
735 if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
736 error.SetErrorString(
737 "GetMemoryRegionInfo called with an invalid target process.");
738 WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
739 return error;
740 }
741
742 WINLOG_IFALL(WINDOWS_LOG_MEMORY,
743 "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr);
744
745 void *addr = reinterpret_cast<void *>(vm_addr);
746 MEMORY_BASIC_INFORMATION mem_info = {};
747 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
748 if (result == 0) {
749 if (::GetLastError() == ERROR_INVALID_PARAMETER) {
750 // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an
751 // address
752 // past the highest accessible address. We should return a range from the
753 // vm_addr
754 // to LLDB_INVALID_ADDRESS
755 info.GetRange().SetRangeBase(vm_addr);
756 info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
757 info.SetReadable(MemoryRegionInfo::eNo);
758 info.SetExecutable(MemoryRegionInfo::eNo);
759 info.SetWritable(MemoryRegionInfo::eNo);
760 info.SetMapped(MemoryRegionInfo::eNo);
761 return error;
762 } else {
763 error.SetError(::GetLastError(), eErrorTypeWin32);
764 WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while "
765 "getting memory region info for address "
766 "0x%I64x",
767 error.GetError(), vm_addr);
768 return error;
769 }
770 }
771
772 // Protect bits are only valid for MEM_COMMIT regions.
773 if (mem_info.State == MEM_COMMIT) {
774 const bool readable = IsPageReadable(mem_info.Protect);
775 const bool executable = IsPageExecutable(mem_info.Protect);
776 const bool writable = IsPageWritable(mem_info.Protect);
777 info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
778 info.SetExecutable(executable ? MemoryRegionInfo::eYes
779 : MemoryRegionInfo::eNo);
780 info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
781 } else {
782 info.SetReadable(MemoryRegionInfo::eNo);
783 info.SetExecutable(MemoryRegionInfo::eNo);
784 info.SetWritable(MemoryRegionInfo::eNo);
785 }
786
787 // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
788 if (mem_info.State != MEM_FREE) {
789 info.GetRange().SetRangeBase(
790 reinterpret_cast<addr_t>(mem_info.AllocationBase));
791 info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
792 mem_info.RegionSize);
793 info.SetMapped(MemoryRegionInfo::eYes);
794 } else {
795 // In the unmapped case we need to return the distance to the next block of
796 // memory.
797 // VirtualQueryEx nearly does that except that it gives the distance from
798 // the start
799 // of the page containing vm_addr.
800 SYSTEM_INFO data;
801 GetSystemInfo(&data);
802 DWORD page_offset = vm_addr % data.dwPageSize;
803 info.GetRange().SetRangeBase(vm_addr);
804 info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
805 info.SetMapped(MemoryRegionInfo::eNo);
806 }
807
808 error.SetError(::GetLastError(), eErrorTypeWin32);
809 WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address %llu: "
810 "readable=%s, executable=%s, writable=%s",
811 vm_addr, BOOL_STR(info.GetReadable()),
812 BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable()));
813 return error;
814}
815
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816lldb::addr_t ProcessWindows::GetImageInfoAddress() {
817 Target &target = GetTarget();
818 ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
819 Address addr = obj_file->GetImageInfoAddress(&target);
820 if (addr.IsValid())
821 return addr.GetLoadAddress(&target);
822 else
823 return LLDB_INVALID_ADDRESS;
Adrian McCarthy18a9135d2015-10-28 18:21:45 +0000824}
825
Adrian McCarthy4ad5def2016-11-23 16:26:37 +0000826void ProcessWindows::OnExitProcess(uint32_t exit_code) {
827 // No need to acquire the lock since m_session_data isn't accessed.
828 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %llu exited with code %u", GetID(),
829 exit_code);
830
831 TargetSP target = m_target_sp.lock();
832 if (target) {
833 ModuleSP executable_module = target->GetExecutableModule();
834 ModuleList unloaded_modules;
835 unloaded_modules.Append(executable_module);
836 target->ModulesDidUnload(unloaded_modules, true);
837 }
838
839 SetProcessExitStatus(GetID(), true, 0, exit_code);
840 SetPrivateState(eStateExited);
841}
842
843void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
844 DebuggerThreadSP debugger = m_session_data->m_debugger;
845
846 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
847 "Debugger connected to process %I64u. Image base = 0x%I64x",
848 debugger->GetProcess().GetProcessId(), image_base);
849
850 ModuleSP module = GetTarget().GetExecutableModule();
851 if (!module) {
852 // During attach, we won't have the executable module, so find it now.
853 const DWORD pid = debugger->GetProcess().GetProcessId();
854 const std::string file_name = GetProcessExecutableName(pid);
855 if (file_name.empty()) {
856 return;
857 }
858
859 FileSpec executable_file(file_name, true);
860 ModuleSpec module_spec(executable_file);
861 Error error;
862 module = GetTarget().GetSharedModule(module_spec, &error);
863 if (!module) {
864 return;
865 }
866
867 GetTarget().SetExecutableModule(module, false);
868 }
869
870 bool load_addr_changed;
871 module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);
872
873 ModuleList loaded_modules;
874 loaded_modules.Append(module);
875 GetTarget().ModulesDidLoad(loaded_modules);
876
877 // Add the main executable module to the list of pending module loads. We
878 // can't call
879 // GetTarget().ModulesDidLoad() here because we still haven't returned from
880 // DoLaunch() / DoAttach() yet
881 // so the target may not have set the process instance to `this` yet.
882 llvm::sys::ScopedLock lock(m_mutex);
883 const HostThreadWindows &wmain_thread =
884 debugger->GetMainThread().GetNativeThread();
885 m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
886 debugger->GetMainThread();
887}
888
889ExceptionResult
890ProcessWindows::OnDebugException(bool first_chance,
891 const ExceptionRecord &record) {
892 llvm::sys::ScopedLock lock(m_mutex);
893
894 // FIXME: Without this check, occasionally when running the test suite there
895 // is
896 // an issue where m_session_data can be null. It's not clear how this could
897 // happen
898 // but it only surfaces while running the test suite. In order to properly
899 // diagnose
900 // this, we probably need to first figure allow the test suite to print out
901 // full
902 // lldb logs, and then add logging to the process plugin.
903 if (!m_session_data) {
904 WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
905 "0x%lx at address 0x%llu, but there is "
906 "no session.",
907 record.GetExceptionCode(), record.GetExceptionAddress());
908 return ExceptionResult::SendToApplication;
909 }
910
911 if (!first_chance) {
912 // Any second chance exception is an application crash by definition.
913 SetPrivateState(eStateCrashed);
914 }
915
916 ExceptionResult result = ExceptionResult::SendToApplication;
917 switch (record.GetExceptionCode()) {
918 case EXCEPTION_BREAKPOINT:
919 // Handle breakpoints at the first chance.
920 result = ExceptionResult::BreakInDebugger;
921
922 if (!m_session_data->m_initial_stop_received) {
923 WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address "
924 "0x%I64x, setting initial stop "
925 "event.",
926 record.GetExceptionAddress());
927 m_session_data->m_initial_stop_received = true;
928 ::SetEvent(m_session_data->m_initial_stop_event);
929 } else {
930 WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS,
931 "Hit non-loader breakpoint at address 0x%I64x.",
932 record.GetExceptionAddress());
933 }
934 SetPrivateState(eStateStopped);
935 break;
936 case EXCEPTION_SINGLE_STEP:
937 result = ExceptionResult::BreakInDebugger;
938 SetPrivateState(eStateStopped);
939 break;
940 default:
941 WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
942 "0x%lx at address 0x%llx "
943 "(first_chance=%s)",
944 record.GetExceptionCode(), record.GetExceptionAddress(),
945 BOOL_STR(first_chance));
946 // For non-breakpoints, give the application a chance to handle the
947 // exception first.
948 if (first_chance)
949 result = ExceptionResult::SendToApplication;
950 else
951 result = ExceptionResult::BreakInDebugger;
952 }
953
954 return result;
955}
956
957void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
958 llvm::sys::ScopedLock lock(m_mutex);
959 const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
960 m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
961}
962
963void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
964 llvm::sys::ScopedLock lock(m_mutex);
965
966 // On a forced termination, we may get exit thread events after the session
967 // data has been cleaned up.
968 if (!m_session_data)
969 return;
970
971 // A thread may have started and exited before the debugger stopped allowing a
972 // refresh.
973 // Just remove it from the new threads list in that case.
974 auto iter = m_session_data->m_new_threads.find(thread_id);
975 if (iter != m_session_data->m_new_threads.end())
976 m_session_data->m_new_threads.erase(iter);
977 else
978 m_session_data->m_exited_threads.insert(thread_id);
979}
980
981void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
982 lldb::addr_t module_addr) {
983 // Confusingly, there is no Target::AddSharedModule. Instead, calling
984 // GetSharedModule() with
985 // a new module will add it to the module list and return a corresponding
986 // ModuleSP.
987 Error error;
988 ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
989 bool load_addr_changed = false;
990 module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed);
991
992 ModuleList loaded_modules;
993 loaded_modules.Append(module);
994 GetTarget().ModulesDidLoad(loaded_modules);
995}
996
997void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
998 Address resolved_addr;
999 if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) {
1000 ModuleSP module = resolved_addr.GetModule();
1001 if (module) {
1002 ModuleList unloaded_modules;
1003 unloaded_modules.Append(module);
1004 GetTarget().ModulesDidUnload(unloaded_modules, false);
1005 }
1006 }
1007}
1008
1009void ProcessWindows::OnDebugString(const std::string &string) {}
1010
1011void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) {
1012 llvm::sys::ScopedLock lock(m_mutex);
1013
1014 if (m_session_data->m_initial_stop_received) {
1015 // This happened while debugging. Do we shutdown the debugging session, try
1016 // to continue,
1017 // or do something else?
1018 WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. "
1019 "Unexpected behavior may result. %s",
1020 error.GetError(), error.AsCString());
1021 } else {
1022 // If we haven't actually launched the process yet, this was an error
1023 // launching the
1024 // process. Set the internal error and signal the initial stop event so
1025 // that the DoLaunch
1026 // method wakes up and returns a failure.
1027 m_session_data->m_launch_error = error;
1028 ::SetEvent(m_session_data->m_initial_stop_event);
1029 WINERR_IFALL(
1030 WINDOWS_LOG_PROCESS,
1031 "Error %u occurred launching the process before the initial stop. %s",
1032 error.GetError(), error.AsCString());
1033 return;
1034 }
1035}
1036
1037Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger,
1038 HostProcess &process) {
1039 Error result;
1040 WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
1041 "WaitForDebuggerConnection Waiting for loader breakpoint.");
1042
1043 // Block this function until we receive the initial stop from the process.
1044 if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
1045 WAIT_OBJECT_0) {
1046 WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
1047 "WaitForDebuggerConnection hit loader breakpoint, returning.");
1048
1049 process = debugger->GetProcess();
1050 return m_session_data->m_launch_error;
1051 } else
1052 return Error(::GetLastError(), eErrorTypeWin32);
1053}
1054
Kate Stoneb9c1b512016-09-06 20:57:50 +00001055// The Windows page protection bits are NOT independent masks that can be
Adrian McCarthy4ad5def2016-11-23 16:26:37 +00001056// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not
1057// (PAGE_EXECUTE | PAGE_READ). To test for an access type, it's necessary to
1058// test for any of the bits that provide that access type.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001059bool ProcessWindows::IsPageReadable(uint32_t protect) {
1060 return (protect & PAGE_NOACCESS) == 0;
Adrian McCarthy0c35cde2015-12-04 22:22:15 +00001061}
1062
Kate Stoneb9c1b512016-09-06 20:57:50 +00001063bool ProcessWindows::IsPageWritable(uint32_t protect) {
1064 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
1065 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
Adrian McCarthy0c35cde2015-12-04 22:22:15 +00001066}
1067
Kate Stoneb9c1b512016-09-06 20:57:50 +00001068bool ProcessWindows::IsPageExecutable(uint32_t protect) {
1069 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
1070 PAGE_EXECUTE_WRITECOPY)) != 0;
Adrian McCarthy0c35cde2015-12-04 22:22:15 +00001071}
Adrian McCarthy4ad5def2016-11-23 16:26:37 +00001072
1073} // namespace lldb_private