LLDB mainline
NativeProcessWindows.cpp
Go to the documentation of this file.
1//===-- NativeProcessWindows.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
10#include <dbghelp.h>
11#include <excpt.h>
12#include <psapi.h>
13
15#include "NativeThreadWindows.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Utility/State.h"
29#include "llvm/ADT/StringRef.h"
30#include "llvm/Support/ConvertUTF.h"
31#include "llvm/Support/Errc.h"
32#include "llvm/Support/Error.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/Threading.h"
35#include "llvm/Support/raw_ostream.h"
36
37#include "DebuggerThread.h"
38#include "ExceptionRecord.h"
39#include "ProcessWindowsLog.h"
40
41#include <tlhelp32.h>
42
43#pragma warning(disable : 4005)
44#include "winternl.h"
45#include <ntstatus.h>
46
47using namespace lldb;
48using namespace lldb_private;
49using namespace llvm;
50
51namespace lldb_private {
52
53namespace {
54
55void NormalizeWindowsPath(std::string &s) {
56 for (char &c : s) {
57 if (c == '/')
58 c = '\\';
59 else
60 c = std::tolower(static_cast<unsigned char>(c));
61 }
62}
63
64bool IsSystemDLL(const FileSpec &spec) {
65 if (!spec)
66 return false;
67
68 static const std::string windows_prefix = []() {
69 std::string prefix;
70 wchar_t buf[MAX_PATH];
71 UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
72 if (len == 0 || len >= MAX_PATH)
73 return prefix;
74 llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
75 NormalizeWindowsPath(prefix);
76 if (!prefix.empty() && prefix.back() != '\\')
77 prefix += '\\';
78 return prefix;
79 }();
80
81 if (windows_prefix.empty())
82 return false;
83
84 std::string path = spec.GetPath();
85 NormalizeWindowsPath(path);
86 return llvm::StringRef(path).starts_with(windows_prefix);
87}
88
89} // namespace
90
92 NativeDelegate &delegate,
93 llvm::Error &E)
96 PseudoTerminal::invalid_fd, // NativeProcessWindows owns the ConPTY.
97 delegate),
98 ProcessDebugger(), m_arch(launch_info.GetArchitecture()),
99 m_stdio_communication("lldb.NativeProcessWindows.stdio") {
100 ErrorAsOutParameter EOut(&E);
101 DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
102 E = LaunchProcess(launch_info, delegate_sp).ToError();
103 if (E)
104 return;
105
107
108 m_pty = launch_info.TakePTY();
110}
111
113 NativeDelegate &delegate,
114 llvm::Error &E)
115 : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger(),
116 m_stdio_communication("lldb.NativeProcessWindows.stdio") {
117 ErrorAsOutParameter EOut(&E);
118 DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
119 ProcessAttachInfo attach_info;
120 attach_info.SetProcessID(pid);
121 E = AttachProcess(pid, attach_info, delegate_sp).ToError();
122 if (E)
123 return;
124
126
128 if (!Host::GetProcessInfo(pid, info)) {
129 E = createStringError(inconvertibleErrorCode(),
130 "Cannot get process information");
131 return;
132 }
133 m_arch = info.GetArchitecture();
134}
135
139 llvm::sys::ScopedLock lock(m_mutex);
140
141 StateType state = GetState();
142 if (state == eStateStopped || state == eStateCrashed) {
143 LLDB_LOG(log, "process {0} is in state {1}. Resuming...",
144 GetDebuggedProcessId(), state);
145 LLDB_LOG(log, "resuming {0} threads.", m_threads.size());
146
148
149 bool failed = false;
150 for (uint32_t i = 0; i < m_threads.size(); ++i) {
151 auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());
152 const ResumeAction *const action =
153 resume_actions.GetActionForThread(thread->GetID(), true);
154 if (action == nullptr)
155 continue;
156
157 switch (action->state) {
158 case eStateRunning:
159 case eStateStepping: {
160 Status result = thread->DoResume(action->state);
161 if (result.Fail()) {
162 failed = true;
163 LLDB_LOG(log,
164 "Trying to resume thread at index {0}, but failed with "
165 "error {1}.",
166 i, result);
167 }
168 break;
169 }
170 case eStateSuspended:
171 case eStateStopped:
172 break;
173
174 default:
176 "NativeProcessWindows::%s (): unexpected state %s specified "
177 "for pid %" PRIu64 ", tid %" PRIu64,
178 __FUNCTION__, StateAsCString(action->state), GetID(),
179 thread->GetID());
180 }
181 }
182
183 if (failed) {
184 error = Status::FromErrorString("NativeProcessWindows::DoResume failed");
185 } else {
187 }
188
189 // Resume the debug loop.
190 ExceptionRecordSP active_exception =
191 m_session_data->m_debugger->GetActiveException().lock();
192 if (active_exception) {
193 // Resume the process and continue processing debug events. Mask the
194 // exception so that from the process's view, there is no indication that
195 // anything happened.
196 m_session_data->m_debugger->ContinueAsyncException(
198 } else {
199 m_session_data->m_debugger->ContinueAsyncDllEvent();
200 }
201 } else {
202 LLDB_LOG(log, "error: process {0} is in state {1}. Returning...",
204 }
205
206 return error;
207}
208
214
216 bool caused_stop = false;
217 StateType state = GetState();
218 if (state != eStateStopped) {
219 m_pending_halt = true;
220 Status err = HaltProcess(caused_stop);
221 if (err.Fail() || !caused_stop)
222 m_pending_halt = false;
223 return err;
224 }
225 return Status();
226}
227
231 StateType state = GetState();
232 if (state != eStateExited && state != eStateDetached) {
234 if (error.Success())
236 else
237 LLDB_LOG(log, "Detaching process error: {0}", error);
238 } else {
240 "error: process {0} in state = {1}, but "
241 "cannot detach it in this state.",
242 GetID(), state);
243 LLDB_LOG(log, "error: {0}", error);
244 }
245 return error;
246}
247
251 "Windows does not support sending signals to processes");
252 return error;
253}
254
256
258 StateType state = GetState();
259 return DestroyProcess(state);
260}
261
262Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {
263 return Status();
264}
265
270
272 size_t size, size_t &bytes_read) {
273 return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);
274}
275
277 size_t size, size_t &bytes_written) {
278 return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);
279}
280
281llvm::Expected<lldb::addr_t>
282NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) {
283 lldb::addr_t addr;
284 Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr);
285 if (ST.Success())
286 return addr;
287 return ST.ToError();
288}
289
293
295
297 StateType state = GetState();
298 switch (state) {
299 case eStateCrashed:
300 case eStateDetached:
301 case eStateExited:
302 case eStateInvalid:
303 case eStateUnloaded:
304 return false;
305 default:
306 return true;
307 }
308}
309
311 lldb::StopReason reason,
312 std::string description) {
313 SetCurrentThreadID(thread.GetID());
314
315 ThreadStopInfo stop_info;
316 stop_info.reason = reason;
317 // No signal support on Windows but required to provide a 'valid' signum.
318 stop_info.signo = SIGTRAP;
319
320 if (reason == StopReason::eStopReasonException) {
321 stop_info.details.exception.type = 0;
322 stop_info.details.exception.data_count = 0;
323 }
324
325 thread.SetStopReason(stop_info, description);
326}
327
329 lldb::StopReason reason,
330 std::string description) {
331 NativeThreadWindows *thread = GetThreadByID(thread_id);
332 if (!thread)
333 return;
334
336 for (uint32_t i = 0; i < m_threads.size(); ++i) {
337 auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
338 if (Status error = t->DoStop(); error.Fail())
339 LLDB_LOG(log, "failed to stop thread {0}: {1}", t->GetID(), error);
340 }
341 SetStopReasonForThread(*thread, reason, description);
342}
343
345
346llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
348 // Not available on this target.
349 return llvm::errc::not_supported;
350}
351
352llvm::Expected<llvm::ArrayRef<uint8_t>>
354 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e,
355 0xd4}; // brk #0xf000
356 static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
357
358 switch (GetArchitecture().GetMachine()) {
359 case llvm::Triple::aarch64:
360 return llvm::ArrayRef(g_aarch64_opcode);
361
362 case llvm::Triple::arm:
363 case llvm::Triple::thumb:
364 return llvm::ArrayRef(g_thumb_opcode);
365
366 default:
368 }
369}
370
372 // Windows always reports an incremented PC after a breakpoint is hit,
373 // even on ARM.
374 return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();
375}
376
380
382 bool hardware) {
383 if (hardware)
384 return SetHardwareBreakpoint(addr, size);
385 return SetSoftwareBreakpoint(addr, size);
386}
387
389 bool hardware) {
390 if (hardware)
391 return RemoveHardwareBreakpoint(addr);
392 return RemoveSoftwareBreakpoint(addr);
393}
394
397 if (!m_loaded_modules.empty())
398 return Status();
399
400 // Retrieve loaded modules by a Target/Module-free implementation.
401 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
402 if (snapshot.IsValid()) {
403 MODULEENTRY32W me;
404 me.dwSize = sizeof(MODULEENTRY32W);
405 if (Module32FirstW(snapshot.get(), &me)) {
406 do {
407 std::string path;
408 if (!llvm::convertWideToUTF8(me.szExePath, path))
409 continue;
410
411 FileSpec file_spec(path);
412 FileSystem::Instance().Resolve(file_spec);
413 m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr;
414 } while (Module32Next(snapshot.get(), &me));
415 }
416
417 if (!m_loaded_modules.empty())
418 return Status();
419 }
420
421 error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
422 return error;
423}
424
426 FileSpec &file_spec) {
428 if (error.Fail())
429 return error;
430
431 FileSpec module_file_spec(module_path);
432 FileSystem::Instance().Resolve(module_file_spec);
433 for (auto &it : m_loaded_modules) {
434 if (it.first == module_file_spec) {
435 file_spec = it.first;
436 return Status();
437 }
438 }
440 "Module (%s) not found in process %" PRIu64 "!",
441 module_file_spec.GetPath().c_str(), GetID());
442}
443
444Status
445NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,
446 lldb::addr_t &load_addr) {
448 if (error.Fail())
449 return error;
450
451 load_addr = LLDB_INVALID_ADDRESS;
452 FileSpec file_spec(file_name);
453 FileSystem::Instance().Resolve(file_spec);
454 for (auto &it : m_loaded_modules) {
455 if (it.first == file_spec) {
456 load_addr = it.second;
457 return Status();
458 }
459 }
461 "Can't get loaded address of file (%s) in process %" PRIu64 "!",
462 file_spec.GetPath().c_str(), GetID());
463}
464
465llvm::Expected<std::vector<LoadedLibraryInfo>>
467 if (Status error = CacheLoadedModules(); error.Fail())
468 return error.ToError();
469
470 std::vector<LoadedLibraryInfo> libs;
471 libs.reserve(m_loaded_modules.size());
472 for (const auto &[file_spec, base] : m_loaded_modules) {
474 info.name = file_spec.GetPath();
475 info.base_addr = base;
476 libs.push_back(std::move(info));
477 }
478 return libs;
479}
480
484
485void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
487 LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
488
489 // Closing the ConPTY signals EOF on the parent-side STDOUT pipe so the
490 // read thread can exit. Tear it down before the debuggee is destroyed.
492
494
495 // No signal involved. It is just an exit event.
496 WaitStatus wait_status(WaitStatus::Exit, exit_code);
497 SetExitStatus(wait_status, true);
498
499 // Notify the native delegate.
500 SetState(eStateExited, true);
501}
502
505 LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
506 GetDebuggedProcessId(), image_base);
507
508 // This is the earliest chance we can resolve the process ID and
509 // architecture if we don't know them yet.
512
514 bool got_info = Host::GetProcessInfo(GetDebuggedProcessId(), info);
515
516 if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {
517 if (!got_info) {
518 LLDB_LOG(log, "Cannot get process information during debugger connecting "
519 "to process");
520 return;
521 }
523 }
524
525 if (got_info) {
526 FileSpec exe = info.GetExecutableFile();
527 if (exe) {
529 m_loaded_modules[exe] = image_base;
530 }
531 }
532
533 // The very first one shall always be the main thread.
534 assert(m_threads.empty());
535 m_threads.push_back(std::make_unique<NativeThreadWindows>(
536 *this, m_session_data->m_debugger->GetMainThread()));
537}
538
542 uint32_t wp_id = LLDB_INVALID_INDEX32;
543#ifndef __aarch64__
544 if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {
545 NativeRegisterContextWindows &reg_ctx = thread->GetRegisterContext();
546 Status error =
547 reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());
548 if (error.Fail())
549 LLDB_LOG(log,
550 "received error while checking for watchpoint hits, pid = "
551 "{0}, error = {1}",
552 thread->GetID(), error);
553 if (wp_id != LLDB_INVALID_INDEX32) {
554 addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id);
555 addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id);
556 std::string desc =
557 formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str();
559 }
560 }
561#endif
562 if (wp_id == LLDB_INVALID_INDEX32)
564
565 SetState(eStateStopped, true);
567}
568
572 const auto exception_addr = record.GetExceptionAddress();
573 const auto thread_id = record.GetThreadID();
574
575 if (NativeThreadWindows *stop_thread = GetThreadByID(thread_id)) {
576 auto &reg_ctx = stop_thread->GetRegisterContext();
577
578 if (FindSoftwareBreakpoint(exception_addr)) {
579 LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
580 exception_addr);
582 // The current PC is AFTER the BP opcode, on all architectures.
583 reg_ctx.SetPC(reg_ctx.GetPC() - GetSoftwareBreakpointPCOffset());
584 SetState(eStateStopped, true);
586 }
587
588 // This block of code will only be entered in case of a hardware
589 // watchpoint or breakpoint hit on AArch64. However, we only handle
590 // hardware watchpoints below as breakpoints are not yet supported.
591 const ArrayRef<uint64_t> args = record.GetExceptionArguments();
592 // Check that the ExceptionInformation array of EXCEPTION_RECORD
593 // contains at least two elements: the first is a read-write flag
594 // indicating the type of data access operation (read or write) while
595 // the second contains the virtual address of the accessed data.
596 if (args.size() >= 2) {
597 uint32_t hw_id = LLDB_INVALID_INDEX32;
598 Status error = reg_ctx.GetWatchpointHitIndex(hw_id, args[1]);
599 if (error.Fail())
600 LLDB_LOG(log,
601 "received error while checking for watchpoint hits, pid = "
602 "{0}, error = {1}",
603 thread_id, error);
604
605 if (hw_id != LLDB_INVALID_INDEX32) {
606 std::string desc =
607 formatv("{0} {1} {2}", reg_ctx.GetWatchpointAddress(hw_id), hw_id,
608 exception_addr)
609 .str();
611 SetState(eStateStopped, true);
613 }
614 }
615 }
616
617 if (!m_initial_stop_seen) {
618 m_initial_stop_seen = true;
619 LLDB_LOG(log,
620 "Hit loader breakpoint at address {0:x}, setting initial stop "
621 "event.",
622 exception_addr);
623
624 // We are required to report the reason for the first stop after
625 // launching or being attached.
626 if (NativeThreadWindows *thread = GetThreadByID(thread_id))
628
629 // Do not notify the native delegate (e.g. llgs) since at this moment
630 // the program hasn't returned from Manager::Launch() and the delegate
631 // might not have an valid native process to operate on.
632 SetState(eStateStopped, false);
633
634 // Hit the initial stop. Continue the application.
636 }
637
638 // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
639 // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
640 // Stop the debugger and let the user decide what to do.
641 if (m_pending_halt) {
642 LLDB_LOG(log,
643 "DebugBreakProcess injection treated as Halt SIGSTOP for tid "
644 "{0:x}",
645 thread_id);
646 m_pending_halt = false;
647 ThreadStopInfo signal_info;
649 signal_info.signo = 19; // SIGSTOP on POSIX
650
651 // Halt all threads at the kernel level.
652 for (uint32_t i = 0; i < m_threads.size(); ++i) {
653 auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
654 if (Status err = t->DoStop(); err.Fail()) {
655 LLDB_LOG(log, "Failed to stop thread {1:x}: {0}", t->GetID(),
656 err.GetError());
657 exit(1);
658 }
659 }
660 SetCurrentThreadID(thread_id);
661 if (NativeThreadWindows *injected = GetThreadByID(thread_id))
662 injected->SetStopReason(signal_info, "interrupt");
663 SetState(eStateStopped, true);
665 }
666
667 std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
668 record.GetExceptionValue(), exception_addr)
669 .str();
670 StopThread(thread_id, StopReason::eStopReasonException, std::move(desc));
671 SetState(eStateStopped, true);
673}
674
677 const ExceptionRecord &record) {
679 LLDB_LOG(log,
680 "Debugger thread reported exception {0:x} at address {1:x} "
681 "(first_chance={2})",
682 record.GetExceptionValue(), record.GetExceptionAddress(),
683 first_chance);
684
685 if (first_chance)
687
688 std::string desc;
689 llvm::raw_string_ostream desc_stream(desc);
690 desc_stream << "Exception " << llvm::format_hex(record.GetExceptionValue(), 8)
691 << " encountered at address "
692 << llvm::format_hex(record.GetExceptionAddress(), 8);
693 record.Dump(desc_stream);
695 std::move(desc));
696
697 SetState(eStateStopped, true);
699}
700
703 const ExceptionRecord &record) {
704 llvm::sys::ScopedLock lock(m_mutex);
705
706 // Handle the exception first to keep track of the stop reason.
707 ExceptionResult result;
708 switch (record.GetExceptionValue()) {
709 case DWORD(STATUS_SINGLE_STEP):
710 case STATUS_WX86_SINGLE_STEP:
711 result = HandleSingleStepException(record);
712 break;
713 case DWORD(STATUS_BREAKPOINT):
715 result = HandleBreakpointException(record);
716 break;
717 default:
718 result = HandleGenericException(first_chance, record);
719 break;
720 }
721
722 // Let the debugger establish the internal status.
723 ProcessDebugger::OnDebugException(first_chance, record);
724
725 return result;
726}
727
729 llvm::sys::ScopedLock lock(m_mutex);
730
731 auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread);
732 thread->GetRegisterContext().ClearAllHardwareWatchpoints();
733 for (const auto &pair : GetWatchpointMap()) {
734 const NativeWatchpoint &wp = pair.second;
735 thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags,
736 wp.m_hardware);
737 }
738
739 if (StateType state = GetState();
740 state == eStateStopped || state == eStateCrashed) {
741 if (Status error = thread->DoStop(); error.Fail()) {
743 LLDB_LOG(log, "failed to suspend newly-created thread {0}: {1}",
744 thread->GetID(), error);
745 }
746 ThreadStopInfo stop_info;
747 stop_info.reason = lldb::eStopReasonNone;
748 thread->SetStopReason(stop_info, "");
749 }
750
751 m_threads.push_back(std::move(thread));
752}
753
755 uint32_t exit_code) {
756 std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
757 llvm::erase_if(m_threads, [thread_id](const auto &t) {
758 return t->GetID() == thread_id;
759 });
760}
761
763 lldb::addr_t module_addr,
764 lldb::tid_t thread_id) {
766 llvm::sys::ScopedLock lock(m_mutex);
767
768 FileSpec resolved = module_spec.GetFileSpec();
769 if (resolved) {
770 FileSystem::Instance().Resolve(resolved);
771 m_loaded_modules[resolved] = module_addr;
772 }
774
777
778 // Can't resolve a breakpoint in a system DLL.
779 if (!resolved || IsSystemDLL(resolved))
781
782 NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
783 if (!loader_thread && !m_threads.empty()) {
784 LLDB_LOG(log, "LOAD_DLL on unknown tid {0:x}. Falling back to main thread.",
785 thread_id);
786 loader_thread = static_cast<NativeThreadWindows *>(m_threads[0].get());
787 }
788 if (loader_thread) {
789 SetCurrentThreadID(loader_thread->GetID());
790 if (loader_thread->DoStop().Fail())
791 LLDB_LOG(log, "Failed to suspend thread {0} on LOAD_DLL.",
792 loader_thread->GetID());
793 ThreadStopInfo info;
795 info.signo = 0;
796 loader_thread->SetStopReason(info, "");
797 }
798 SetState(eStateStopped, true);
799
801}
802
804 lldb::tid_t thread_id) {
806 llvm::sys::ScopedLock lock(m_mutex);
807
808 FileSpec unloaded_spec;
809 for (auto it = m_loaded_modules.begin(); it != m_loaded_modules.end();) {
810 if (it->second == module_addr) {
811 unloaded_spec = it->first;
812 it = m_loaded_modules.erase(it);
813 } else {
814 ++it;
815 }
816 }
818
821
822 if (!unloaded_spec || IsSystemDLL(unloaded_spec))
824
825 NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
826 if (!unloader_thread && !m_threads.empty()) {
827 LLDB_LOG(log,
828 "UNLOAD_DLL on unknown tid {0:x}. Falling back to main thread.",
829 thread_id);
830 unloader_thread = static_cast<NativeThreadWindows *>(m_threads[0].get());
831 }
832 if (unloader_thread) {
833 SetCurrentThreadID(unloader_thread->GetID());
834 if (unloader_thread->DoStop().Fail())
835 LLDB_LOG(log, "Failed to suspend thread {0} on UNLOAD_DLL.",
836 unloader_thread->GetID());
837 ThreadStopInfo info;
839 info.signo = 0;
840 unloader_thread->SetStopReason(info, "");
841 }
842 SetState(eStateStopped, true);
844}
845
847 bool is_unicode,
848 uint16_t length_lower_word) {
850
851 llvm::SmallVector<char, 256> buffer;
852 if (llvm::Error err = ProcessDebugger::ReadDebugString(
853 debug_string_addr, is_unicode, length_lower_word, buffer)) {
854 std::string err_str = llvm::toString(std::move(err));
855 std::string msg =
856 llvm::formatv("Failed to read debug string at {0:x} "
857 "(size & 0xffff={1}, unicode={2}): {3}\n",
858 debug_string_addr, length_lower_word, is_unicode, err_str)
859 .str();
860 LLDB_LOG(log, "{0}", msg);
861 m_delegate.NewProcessOutput(this, llvm::StringRef(msg));
862 return;
863 }
864 if (buffer.empty())
865 return;
866
867 if (is_unicode) {
868 assert(buffer.size() % 2 == 0);
869 llvm::ArrayRef<unsigned short> utf16(
870 reinterpret_cast<const unsigned short *>(buffer.data()),
871 buffer.size() / 2);
872 std::string out;
873 if (!llvm::convertUTF16ToUTF8String(utf16, out)) {
874 LLDB_LOG(log, "Debug string is not valid Utf 16");
875 return;
876 }
877 m_delegate.NewProcessOutput(this, llvm::StringRef(out.data(), out.size()));
878 } else {
879 m_delegate.NewProcessOutput(this,
880 llvm::StringRef(buffer.data(), buffer.size()));
881 }
882}
883
884llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
886 ProcessLaunchInfo &launch_info,
887 NativeProcessProtocol::NativeDelegate &native_delegate) {
888 Error E = Error::success();
889 auto process_up = std::unique_ptr<NativeProcessWindows>(
890 new NativeProcessWindows(launch_info, native_delegate, E));
891 if (E)
892 return std::move(E);
893 return std::move(process_up);
894}
895
896llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
899 Error E = Error::success();
900 // Set pty primary fd invalid since it is not available.
901 auto process_up = std::unique_ptr<NativeProcessWindows>(
902 new NativeProcessWindows(pid, -1, native_delegate, E));
903 if (E)
904 return std::move(E);
905 return std::move(process_up);
906}
907
909
911 if (!m_pty || !m_pty->IsConnected())
912 return;
913
914 m_stdio_communication.SetConnection(
915 std::make_unique<ConnectionConPTY>(m_pty));
916 if (!m_stdio_communication.IsConnected())
917 return;
918 m_stdio_communication.SetReadThreadBytesReceivedCallback(
920 m_stdio_communication.StartReadThread();
921}
922
924 if (!m_stdio_communication.HasConnection())
925 return;
926
927 if (m_pty)
928 m_pty->Close();
929
930 if (m_stdio_communication.ReadThreadIsRunning())
931 m_stdio_communication.JoinReadThread();
932
933 if (m_stdio_communication.HasConnection())
934 m_stdio_communication.Disconnect();
935}
936
938 const void *src,
939 size_t src_len) {
940 auto *self = static_cast<NativeProcessWindows *>(baton);
941 if (src_len == 0)
942 return;
943 self->m_delegate.NewProcessOutput(
944 self, llvm::StringRef(static_cast<const char *>(src), src_len));
945}
946
947size_t NativeProcessWindows::WriteStdin(const void *buf, size_t len,
948 Status &error) {
949 if (!m_stdio_communication.HasConnection()) {
951 "no ConPTY connection on this NativeProcessWindows");
952 return 0;
953 }
954 ConnectionStatus status;
955 size_t written = m_stdio_communication.Write(buf, len, status, &error);
956 if (status != eConnectionStatusSuccess && error.Success())
958 "ConPTY stdin write returned status {0}", static_cast<int>(status));
959 return written;
960}
961} // namespace lldb_private
static llvm::raw_ostream & error(Stream &strm)
#define STATUS_WX86_BREAKPOINT
DllEventAction
Definition ForwardDecl.h:29
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:376
#define MAX_PATH
lldb::tid_t GetThreadID() const
void Dump(llvm::raw_ostream &stream) const
unsigned long GetExceptionValue() const
llvm::ArrayRef< uint64_t > GetExceptionArguments() const
lldb::addr_t GetExceptionAddress() const
A file utility class.
Definition FileSpec.h:57
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:376
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
Definition aix/Host.cpp:211
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, NativeDelegate &delegate)
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint)
virtual const NativeWatchpointList::WatchpointMap & GetWatchpointMap() const
void SetState(lldb::StateType state, bool notify_delegates=true)
NativeThreadProtocol * GetThreadByID(lldb::tid_t tid)
std::vector< std::unique_ptr< NativeThreadProtocol > > m_threads
virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange)
Status RemoveSoftwareBreakpoint(lldb::addr_t addr)
virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size)
virtual llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint)
virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr)
std::unordered_map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate) override
Launch a process for debugging.
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Attach(lldb::pid_t pid, NativeDelegate &native_delegate) override
Attach to an existing process.
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override
ExceptionResult HandleBreakpointException(const ExceptionRecord &record)
llvm::Error DeallocateMemory(lldb::addr_t addr) override
Status Resume(const ResumeActionList &resume_actions) override
void OnCreateThread(const HostThread &thread) override
void OnExitProcess(uint32_t exit_code) override
Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override
void StartStdioForwarding()
Wire up m_stdio_communication on m_pty's STDOUT HANDLE.
static void STDIOReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
Bridge between m_stdio_communication's read thread and NativeDelegate::NewProcessOutput.
llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint) override
void OnDebuggerConnected(lldb::addr_t image_base) override
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override
NativeProcessWindows(ProcessLaunchInfo &launch_info, NativeDelegate &delegate, llvm::Error &E)
Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override
void StopStdioForwarding()
Tear down the read thread and disconnect m_stdio_communication.
size_t WriteStdin(const void *buf, size_t len, Status &error) override
Forward bytes from the gdb-remote I packet into the inferior's ConPTY-backed stdin via m_stdio_commun...
bool m_pending_halt
Set when Halt() / Interrupt() schedules a DebugBreakProcess injection.
ExceptionResult HandleGenericException(bool first_chance, const ExceptionRecord &record)
void SetArchitecture(const ArchSpec &arch_spec)
ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) override
void OnDebugString(lldb::addr_t debug_string_addr, bool is_unicode, uint16_t length_lower_word) override
size_t GetSoftwareBreakpointPCOffset() override
Return the offset of the PC relative to the software breakpoint that was hit.
std::shared_ptr< PseudoConsole > m_pty
PseudoConsole for the lldb-server stdio-forwarding path.
ThreadedCommunication m_stdio_communication
Wraps a ConnectionConPTY around the PTY's parent-side STDOUT HANDLE.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > GetAuxvData() const override
DllEventAction OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr, lldb::tid_t thread_id) override
Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override
NativeThreadWindows * GetThreadByID(lldb::tid_t thread_id)
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override
llvm::Expected< lldb::addr_t > AllocateMemory(size_t size, uint32_t permissions) override
DllEventAction OnUnloadDll(lldb::addr_t module_addr, lldb::tid_t thread_id) override
Status Signal(int signo) override
Sends a process a UNIX signal signal.
Status RemoveBreakpoint(lldb::addr_t addr, bool hardware=false) override
const ArchSpec & GetArchitecture() const override
void SetStopReasonForThread(NativeThreadWindows &thread, lldb::StopReason reason, std::string description="")
Status Interrupt() override
Tells a process to interrupt all operations as if by a Ctrl-C.
void StopThread(lldb::tid_t thread_id, lldb::StopReason reason, std::string description="")
ExceptionResult HandleSingleStepException(const ExceptionRecord &record)
bool m_initial_stop_seen
Whether we've seen the loader breakpoint that fires once per process at launch / attach.
bool m_pending_library_events
Set whenever an OS DLL load/unload event has been seen since the last stop reply.
llvm::Expected< std::vector< LoadedLibraryInfo > > GetLoadedLibraries() override
Return the currently loaded libraries of the target in the qXfer:libraries:read form (generic name + ...
lldb::addr_t GetSharedLibraryInfoAddress() override
Status IgnoreSignals(llvm::ArrayRef< int > signals) override
std::map< lldb_private::FileSpec, lldb::addr_t > m_loaded_modules
virtual Status GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
virtual lldb::addr_t GetWatchpointAddress(uint32_t wp_index)
virtual lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index)
void SetStopReason(ThreadStopInfo stop_info, std::string description)
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
Status DestroyProcess(lldb::StateType process_state)
Status LaunchProcess(ProcessLaunchInfo &launch_info, DebugDelegateSP delegate)
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info)
std::unique_ptr< ProcessWindowsData > m_session_data
Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr)
virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record)
Status AttachProcess(lldb::pid_t pid, const ProcessAttachInfo &attach_info, DebugDelegateSP delegate)
lldb::pid_t GetDebuggedProcessId() const
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
virtual void OnExitProcess(uint32_t exit_code)
llvm::Error ReadDebugString(lldb::addr_t debug_string_addr, bool is_unicode, uint16_t length_lower_word, llvm::SmallVectorImpl< char > &output)
Read an OUTPUT_DEBUG_STRING_INFO payload from the inferior.
Status HaltProcess(bool &caused_stop)
Status DeallocateMemory(lldb::addr_t addr)
void SetProcessID(lldb::pid_t pid)
Definition ProcessInfo.h:68
FileSpec & GetExecutableFile()
Definition ProcessInfo.h:41
ArchSpec & GetArchitecture()
Definition ProcessInfo.h:60
std::shared_ptr< PTY > TakePTY()
A pseudo terminal helper class.
const ResumeAction * GetActionForThread(lldb::tid_t tid, bool default_ok) const
Definition Debug.h:74
An error handling class.
Definition Status.h:118
llvm::Error ToError() const
FIXME: Replace all uses with takeError() instead.
Definition Status.cpp:138
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition Status.h:151
bool Success() const
Test for success condition.
Definition Status.cpp:303
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:339
std::shared_ptr< IDebugDelegate > DebugDelegateSP
Definition ForwardDecl.h:45
std::shared_ptr< ExceptionRecord > ExceptionRecordSP
Definition ForwardDecl.h:47
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
Definition State.cpp:14
ConnectionStatus
Connection Status Types.
@ eConnectionStatusSuccess
Success.
StateType
Process and Thread States.
@ eStateUnloaded
Process is object is valid, but not currently loaded.
@ eStateDetached
Process has been detached and can't be examined.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateExited
Process has exited and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
@ eStateCrashed
Process or thread has crashed and can be examined.
@ eErrorTypeWin32
Standard Win32 error codes.
uint64_t pid_t
Definition lldb-types.h:83
uint64_t addr_t
Definition lldb-types.h:80
StopReason
Thread stop reasons.
@ eStopReasonBreakpoint
@ eStopReasonException
@ eStopReasonWatchpoint
uint64_t tid_t
Definition lldb-types.h:84
Generic loaded-library entry used by the non-SVR4 qXfer:libraries:read form of the GDB remote library...
lldb::StateType state
Definition Debug.h:23
struct lldb_private::ThreadStopInfo::@116236113001137253323017204263037302160273237376::@034237007264067231263360140073224264215170222231 exception
lldb::StopReason reason
Definition Debug.h:132
union lldb_private::ThreadStopInfo::@116236113001137253323017204263037302160273237376 details
#define SIGTRAP