LLDB mainline
ProcessDebugger.cpp
Go to the documentation of this file.
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
13#include <psapi.h>
14
22#include "lldb/Target/Process.h"
24#include "llvm/Support/ConvertUTF.h"
25#include "llvm/Support/Error.h"
26
27#include "DebuggerThread.h"
28#include "ExceptionRecord.h"
29#include "ProcessWindowsLog.h"
30
31#include <string>
32#include <string_view>
33
34using namespace lldb;
35using namespace lldb_private;
36
37static void NormalizeWindowsPathSeparators(std::string &s) {
38 for (char &c : s)
39 if (c == '/')
40 c = '\\';
41}
42
43bool ProcessDebugger::IsSystemDLL(llvm::StringRef path) {
44 if (path.empty())
45 return false;
46
47 static const std::string windows_prefix = []() {
48 std::string prefix;
49 wchar_t buf[MAX_PATH];
50 UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
51 if (len == 0 || len >= MAX_PATH)
52 return prefix;
53 llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
55 if (!prefix.empty() && prefix.back() != '\\')
56 prefix += '\\';
57 return prefix;
58 }();
59
60 if (windows_prefix.empty())
61 return false;
62
63 // A module loaded through an extended-length path has the "\\?\" prefix,
64 // which would not match the Windows directory.
65 std::string normalized = StripExtendedLengthPrefix(path);
67 return llvm::StringRef(normalized).starts_with_insensitive(windows_prefix);
68}
69
71 if (!m_session_data || !m_session_data->m_debugger)
72 return false;
73 lldb::process_t handle = m_session_data->m_debugger->GetProcess()
74 .GetNativeProcess()
75 .GetSystemHandle();
76 if (handle == nullptr || handle == LLDB_INVALID_PROCESS)
77 return false;
78
79 MEMORY_BASIC_INFORMATION mbi = {};
80 if (::VirtualQueryEx(handle, reinterpret_cast<LPCVOID>(addr), &mbi,
81 sizeof(mbi)) != sizeof(mbi))
82 return false;
83 if (mbi.AllocationBase == nullptr)
84 return false;
85
86 // A truncated path still carries the leading directory, which is all
87 // IsSystemDLL() inspects. MAX_PATH is enough.
88 wchar_t module_path[MAX_PATH];
89 DWORD len = ::GetModuleFileNameExW(
90 handle, reinterpret_cast<HMODULE>(mbi.AllocationBase), module_path,
91 MAX_PATH);
92 if (len == 0)
93 return false;
94
95 std::string path_utf8;
96 llvm::convertWideToUTF8(std::wstring_view(module_path, len), path_utf8);
97 return IsSystemDLL(path_utf8);
98}
99
100static DWORD ConvertLldbToWinApiProtect(uint32_t protect) {
101 // We also can process a read / write permissions here, but if the debugger
102 // will make later a write into the allocated memory, it will fail. To get
103 // around it is possible inside DoWriteMemory to remember memory permissions,
104 // allow write, write and restore permissions, but for now we process only
105 // the executable permission.
106 //
107 // TODO: Process permissions other than executable
108 if (protect & ePermissionsExecutable)
109 return PAGE_EXECUTE_READWRITE;
110
111 return PAGE_READWRITE;
112}
113
114// The Windows page protection bits are NOT independent masks that can be
115// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE
116// | PAGE_READ). To test for an access type, it's necessary to test for any of
117// the bits that provide that access type.
118static bool IsPageReadable(uint32_t protect) {
119 return (protect & PAGE_NOACCESS) == 0;
120}
121
122static bool IsPageWritable(uint32_t protect) {
123 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
124 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
125}
126
127static bool IsPageExecutable(uint32_t protect) {
128 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
129 PAGE_EXECUTE_WRITECOPY)) != 0;
130}
131
132namespace lldb_private {
133
135
137 if (m_session_data)
138 return m_session_data->m_debugger->GetProcess().GetProcessId();
140}
141
144 DebuggerThreadSP debugger_thread;
145 {
146 // Acquire the lock only long enough to get the DebuggerThread.
147 // StopDebugging() will trigger a call back into ProcessDebugger which will
148 // also acquire the lock. Thus we have to release the lock before calling
149 // StopDebugging().
150 llvm::sys::ScopedLock lock(m_mutex);
151
152 if (!m_session_data) {
153 LLDB_LOG(log, "there is no active session.");
154 return Status();
155 }
156
157 debugger_thread = m_session_data->m_debugger;
158 }
159
161
162 LLDB_LOG(log, "detaching from process {0}.",
163 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
164 error = debugger_thread->StopDebugging(false);
165
166 // By the time StopDebugging returns, there is no more debugger thread, so
167 // we can be assured that no other thread will race for the session data.
168 m_session_data.reset();
169
170 return error;
171}
172
174 DebugDelegateSP delegate) {
175 // Even though m_session_data is accessed here, it is before a debugger
176 // thread has been kicked off. So there's no race conditions, and it
177 // shouldn't be necessary to acquire the mutex.
178
180 Status result;
181
182 FileSpec working_dir = launch_info.GetWorkingDirectory();
183 namespace fs = llvm::sys::fs;
184 if (working_dir) {
185 FileSystem::Instance().Resolve(working_dir);
186 if (!FileSystem::Instance().IsDirectory(working_dir)) {
188 "No such file or directory: %s", working_dir.GetPath().c_str());
189 return result;
190 }
191 }
192
193 if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
194 StreamString stream;
195 stream.Printf("ProcessDebugger unable to launch '%s'. ProcessDebugger can "
196 "only be used for debug launches.",
197 launch_info.GetExecutableFile().GetPath().c_str());
198 std::string message = stream.GetString().str();
199 result = Status::FromErrorString(message.c_str());
200
201 LLDB_LOG(log, "error: {0}", message);
202 return result;
203 }
204
205 bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
206 m_session_data.reset(new ProcessWindowsData(stop_at_entry));
207 m_session_data->m_debugger.reset(new DebuggerThread(delegate));
208 DebuggerThreadSP debugger = m_session_data->m_debugger;
209
210 // Kick off the DebugLaunch asynchronously and wait for it to complete.
211 result = debugger->DebugLaunch(launch_info);
212 if (result.Fail()) {
213 LLDB_LOG(log, "failed launching '{0}'. {1}",
214 launch_info.GetExecutableFile().GetPath(), result);
215 return result;
216 }
217
218 HostProcess process;
219 Status error = WaitForDebuggerConnection(debugger, process);
220 if (error.Fail()) {
221 LLDB_LOG(log, "failed launching '{0}'. {1}",
222 launch_info.GetExecutableFile().GetPath(), error);
223 return error;
224 }
225
226 LLDB_LOG(log, "successfully launched '{0}'",
227 launch_info.GetExecutableFile().GetPath());
228
229 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
230 // private state should already be set to eStateStopped as a result of
231 // hitting the initial breakpoint. If it was not set, the breakpoint should
232 // have already been resumed from and the private state should already be
233 // eStateRunning.
234 launch_info.SetProcessID(process.GetProcessId());
235
236 return result;
237}
238
240 const ProcessAttachInfo &attach_info,
241 DebugDelegateSP delegate) {
243 m_session_data.reset(
244 new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
245 DebuggerThreadSP debugger(new DebuggerThread(delegate));
246
247 m_session_data->m_debugger = debugger;
248
249 DWORD process_id = static_cast<DWORD>(pid);
250 Status error = debugger->DebugAttach(process_id, attach_info);
251 if (error.Fail()) {
252 LLDB_LOG(
253 log,
254 "encountered an error occurred initiating the asynchronous attach. {0}",
255 error);
256 return error;
257 }
258
259 HostProcess process;
260 error = WaitForDebuggerConnection(debugger, process);
261 if (error.Fail()) {
262 LLDB_LOG(log,
263 "encountered an error waiting for the debugger to connect. {0}",
264 error);
265 return error;
266 }
267
268 LLDB_LOG(log, "successfully attached to process with pid={0}", process_id);
269
270 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
271 // private state should already be set to eStateStopped as a result of
272 // hitting the initial breakpoint. If it was not set, the breakpoint should
273 // have already been resumed from and the private state should already be
274 // eStateRunning.
275
276 return error;
277}
278
281 DebuggerThreadSP debugger_thread;
282 {
283 // Acquire this lock inside an inner scope, only long enough to get the
284 // DebuggerThread. StopDebugging() will trigger a call back into
285 // ProcessDebugger which will acquire the lock again, so we need to not
286 // deadlock.
287 llvm::sys::ScopedLock lock(m_mutex);
288
289 if (!m_session_data) {
290 LLDB_LOG(log, "warning: state = {0}, but there is no active session.",
291 state);
292 return Status();
293 }
294
295 debugger_thread = m_session_data->m_debugger;
296 }
297
298 if (state == eStateExited || state == eStateDetached) {
299 LLDB_LOG(log, "warning: cannot destroy process {0} while state = {1}.",
300 GetDebuggedProcessId(), state);
301 return Status();
302 }
303
304 LLDB_LOG(log, "Shutting down process {0}.",
305 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
306 auto error = debugger_thread->StopDebugging(true);
307
308 // By the time StopDebugging returns, there is no more debugger thread, so
309 // we can be assured that no other thread will race for the session data.
310 m_session_data.reset();
311
312 return error;
313}
314
316 DebuggerThreadSP debugger_thread;
317 {
318 llvm::sys::ScopedLock lock(m_mutex);
319 if (!m_session_data)
320 return;
321 debugger_thread = m_session_data->m_debugger;
322 }
323 debugger_thread->StopDebugging(/*terminate=*/true);
324 m_session_data.reset();
325}
326
330 llvm::sys::ScopedLock lock(m_mutex);
331 if (!m_session_data) {
332 caused_stop = false;
333 LLDB_LOG(log, "HaltProcess called with no active session.");
335 "HaltProcess called with no active debugger session.");
336 }
337 caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
338 .GetNativeProcess()
339 .GetSystemHandle());
340 if (!caused_stop) {
341 error = Status(::GetLastError(), eErrorTypeWin32);
342 LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error);
343 }
344
345 return error;
346}
347
348Status ProcessDebugger::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
349 size_t &bytes_read) {
351 bytes_read = 0;
353 llvm::sys::ScopedLock lock(m_mutex);
354
355 if (!m_session_data) {
357 "cannot read, there is no active debugger connection.");
358 LLDB_LOG(log, "error: {0}", error);
359 return error;
360 }
361
362 LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size,
363 vm_addr);
364
365 lldb::process_t handle = m_session_data->m_debugger->GetProcess()
366 .GetNativeProcess()
367 .GetSystemHandle();
368 void *addr = reinterpret_cast<void *>(vm_addr);
369 SIZE_T num_of_bytes_read = 0;
370 if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
371 bytes_read = num_of_bytes_read;
372 return Status();
373 }
374 error = Status(GetLastError(), eErrorTypeWin32);
375 MemoryRegionInfo info;
376 if (GetMemoryRegionInfo(vm_addr, info).Fail() ||
377 info.GetMapped() != eLazyBoolYes)
378 return error;
379 size = info.GetRange().GetRangeEnd() - vm_addr;
380 LLDB_LOG(log, "retrying the read with size {0:x}", size);
381 if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
382 LLDB_LOG(log, "success: read {0:x} bytes", num_of_bytes_read);
383 bytes_read = num_of_bytes_read;
384 return Status();
385 }
386 error = Status(GetLastError(), eErrorTypeWin32);
387 LLDB_LOG(log, "error: {0}", error);
388 return error;
389}
390
392 size_t size, size_t &bytes_written) {
394 bytes_written = 0;
396 llvm::sys::ScopedLock lock(m_mutex);
397 LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size,
398 vm_addr);
399
400 if (!m_session_data) {
402 "cannot write, there is no active debugger connection.");
403 LLDB_LOG(log, "error: {0}", error);
404 return error;
405 }
406
407 HostProcess process = m_session_data->m_debugger->GetProcess();
408 void *addr = reinterpret_cast<void *>(vm_addr);
409 SIZE_T num_of_bytes_written = 0;
411 if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
412 FlushInstructionCache(handle, addr, num_of_bytes_written);
413 bytes_written = num_of_bytes_written;
414 } else {
415 error = Status(GetLastError(), eErrorTypeWin32);
416 LLDB_LOG(log, "writing failed with error: {0}", error);
417 }
418 return error;
419}
420
421Status ProcessDebugger::AllocateMemory(size_t size, uint32_t permissions,
422 lldb::addr_t &addr) {
426 llvm::sys::ScopedLock lock(m_mutex);
427 LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size,
428 permissions);
429
430 if (!m_session_data) {
432 "cannot allocate, there is no active debugger connection");
433 LLDB_LOG(log, "error: {0}", error);
434 return error;
435 }
436
437 HostProcess process = m_session_data->m_debugger->GetProcess();
439 auto protect = ConvertLldbToWinApiProtect(permissions);
440 auto result = ::VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect);
441 if (!result) {
442 error = Status(GetLastError(), eErrorTypeWin32);
443 LLDB_LOG(log, "allocating failed with error: {0}", error);
444 } else {
445 addr = reinterpret_cast<addr_t>(result);
446 }
447 return error;
448}
449
451 Status result;
452
454 llvm::sys::ScopedLock lock(m_mutex);
455 LLDB_LOG(log, "attempting to deallocate bytes at address {0:x}", vm_addr);
456
457 if (!m_session_data) {
459 "cannot deallocate, there is no active debugger connection");
460 LLDB_LOG(log, "error: {0}", result);
461 return result;
462 }
463
464 HostProcess process = m_session_data->m_debugger->GetProcess();
466 if (!::VirtualFreeEx(handle, reinterpret_cast<LPVOID>(vm_addr), 0,
467 MEM_RELEASE)) {
468 result = Status(GetLastError(), eErrorTypeWin32);
469 LLDB_LOG(log, "deallocating failed with error: {0}", result);
470 }
471
472 return result;
473}
474
476 MemoryRegionInfo &info) {
479 llvm::sys::ScopedLock lock(m_mutex);
480 info.Clear();
481
482 if (!m_session_data) {
484 "GetMemoryRegionInfo called with no debugging session.");
485 LLDB_LOG(log, "error: {0}", error);
486 return error;
487 }
488 HostProcess process = m_session_data->m_debugger->GetProcess();
490 if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
492 "GetMemoryRegionInfo called with an invalid target process.");
493 LLDB_LOG(log, "error: {0}", error);
494 return error;
495 }
496
497 LLDB_LOG(log, "getting info for address {0:x}", vm_addr);
498
499 void *addr = reinterpret_cast<void *>(vm_addr);
500 MEMORY_BASIC_INFORMATION mem_info = {};
501 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
502 if (result == 0) {
503 DWORD last_error = ::GetLastError();
504 if (last_error == ERROR_INVALID_PARAMETER) {
505 // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with
506 // an address past the highest accessible address. We should return a
507 // range from the vm_addr to LLDB_INVALID_ADDRESS
508 info.GetRange().SetRangeBase(vm_addr);
514 return error;
515 } else {
516 error = Status(last_error, eErrorTypeWin32);
517 LLDB_LOG(log,
518 "VirtualQueryEx returned error {0} while getting memory "
519 "region info for address {1:x}",
520 error, vm_addr);
521 return error;
522 }
523 }
524
525 // Protect bits are only valid for MEM_COMMIT regions.
526 if (mem_info.State == MEM_COMMIT) {
527 const bool readable = IsPageReadable(mem_info.Protect);
528 const bool executable = IsPageExecutable(mem_info.Protect);
529 const bool writable = IsPageWritable(mem_info.Protect);
530 info.SetReadable(readable ? eLazyBoolYes : eLazyBoolNo);
531 info.SetExecutable(executable ? eLazyBoolYes : eLazyBoolNo);
532 info.SetWritable(writable ? eLazyBoolYes : eLazyBoolNo);
533 } else {
537 }
538
539 // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
540 if (mem_info.State != MEM_FREE) {
541 info.GetRange().SetRangeBase(
542 reinterpret_cast<addr_t>(mem_info.BaseAddress));
543 info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
544 mem_info.RegionSize);
546 } else {
547 // In the unmapped case we need to return the distance to the next block of
548 // memory. VirtualQueryEx nearly does that except that it gives the
549 // distance from the start of the page containing vm_addr.
550 SYSTEM_INFO data;
551 ::GetSystemInfo(&data);
552 DWORD page_offset = vm_addr % data.dwPageSize;
553 info.GetRange().SetRangeBase(vm_addr);
554 info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
556 }
557
559 "Memory region info for address {0:x}: readable={1}, "
560 "executable={2}, writable={3}",
561 vm_addr, info.GetReadable(), info.GetExecutable(),
562 info.GetWritable());
563 return error;
564}
565
566void ProcessDebugger::OnExitProcess(uint32_t exit_code) {
567 // If the process exits before any initial stop then notify the debugger
568 // of the error otherwise WaitForDebuggerConnection() will be blocked.
569 // An example of this issue is when a process fails to load a dependent DLL.
570 if (m_session_data && !m_session_data->m_initial_stop_received) {
572 "Process prematurely exited with {0:x}", exit_code);
574 }
575}
576
578
581 const ExceptionRecord &record) {
583 llvm::sys::ScopedLock lock(m_mutex);
584 // FIXME: Without this check, occasionally when running the test suite
585 // there is an issue where m_session_data can be null. It's not clear how
586 // this could happen but it only surfaces while running the test suite. In
587 // order to properly diagnose this, we probably need to first figure allow the
588 // test suite to print out full lldb logs, and then add logging to the process
589 // plugin.
590 if (!m_session_data) {
591 LLDB_LOG(log,
592 "Debugger thread reported exception {0:x} at address {1:x}, but "
593 "there is no session.",
594 record.GetExceptionValue(), record.GetExceptionAddress());
596 }
597
599 if ((record.GetExceptionValue() == EXCEPTION_BREAKPOINT ||
600 record.GetExceptionValue() ==
601 0x4000001FL /*WOW64 STATUS_WX86_BREAKPOINT*/) &&
602 !m_session_data->m_initial_stop_received) {
603 // Handle breakpoints at the first chance.
605 LLDB_LOG(
606 log,
607 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
608 record.GetExceptionAddress());
609 m_session_data->m_initial_stop_received = true;
610 ::SetEvent(m_session_data->m_initial_stop_event);
611 }
612 return result;
613}
614
616 // Do nothing by default
617}
618
619void ProcessDebugger::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
620 // Do nothing by default
621}
622
624 lldb::addr_t module_addr,
625 lldb::tid_t thread_id) {
627}
628
633
635 bool is_unicode,
636 uint16_t length_lower_word) {
637 // Do nothing by default
638}
639
640llvm::Error
642 bool is_unicode, uint16_t length_lower_word,
644 if (is_unicode && length_lower_word % 2 != 0)
645 return llvm::createStringError(
646 "Utf16 string can't have uneven size in bytes");
647
648 const auto is_zero_terminated = [&] {
649 // The zero terminator is always at the end of the buffer.
650 if (is_unicode)
651 return output.size() >= 2 && output.back() == 0 &&
652 output[output.size() - 2] == 0;
653
654 return !output.empty() && output.back() == 0;
655 };
656
657 // Read at most 1 MiB ((1 << 16) * 16 - 1 Bytes) since we don't know the exact
658 // size of the string. We know that `strlen(string) & 0xffff ==
659 // length_lower_word`, so we read in chunks until we reach the terminator:
660 // - 0: `length_lower_word` Bytes
661 // - 1..16: 64 KiB (= 2^16 Bytes)
662 size_t start = length_lower_word == 0 ? 1 : 0;
663 for (size_t i = start; i < 16; ++i) {
664 output.resize_for_overwrite(length_lower_word + i * (1 << 16));
665 size_t chunk_size = i == 0 ? length_lower_word : (1 << 16);
666 lldb::addr_t addr = debug_string_addr + output.size_in_bytes() - chunk_size;
667
668 size_t bytes_read = 0;
669 Status error =
670 ReadMemory(addr, output.end() - chunk_size, chunk_size, bytes_read);
671 if (error.Fail())
672 return error.takeError();
673
674 if (bytes_read != chunk_size) {
675 return llvm::createStringErrorV(
676 "Expected to read {0} bytes, but read {1}", chunk_size, bytes_read);
677 }
678
679 if (is_zero_terminated())
680 break;
681 }
682
683 if (!is_zero_terminated())
684 return llvm::createStringError("String is 1 MiB or larger");
685
686 // Remove null terminator.
687 output.pop_back_n(is_unicode ? 2 : 1);
688 return llvm::Error::success();
689}
690
691void ProcessDebugger::OnDebuggerError(const Status &error, uint32_t type) {
692 llvm::sys::ScopedLock lock(m_mutex);
694
695 if (!m_session_data) {
696 LLDB_LOG(log,
697 "OnDebuggerError called with no active session: error {0}: {1}",
698 error.GetError(), error);
699 return;
700 }
701
702 if (m_session_data->m_initial_stop_received) {
703 // This happened while debugging. Do we shutdown the debugging session,
704 // try to continue, or do something else?
705 LLDB_LOG(log,
706 "Error {0} occurred during debugging. Unexpected behavior "
707 "may result. {1}",
708 error.GetError(), error);
709 } else {
710 // If we haven't actually launched the process yet, this was an error
711 // launching the process. Set the internal error and signal the initial
712 // stop event so that the DoLaunch method wakes up and returns a failure.
713 m_session_data->m_launch_error = error.Clone();
714 ::SetEvent(m_session_data->m_initial_stop_event);
715 LLDB_LOG(log,
716 "Error {0} occurred launching the process before the initial "
717 "stop. {1}",
718 error.GetError(), error);
719 return;
720 }
721}
722
724 HostProcess &process) {
725 Status result;
727 LLDB_LOG(log, "Waiting for loader breakpoint.");
728
729 // Block this function until we receive the initial stop from the process.
730 if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
731 WAIT_OBJECT_0) {
732 LLDB_LOG(log, "hit loader breakpoint, returning.");
733
734 process = debugger->GetProcess();
735 return m_session_data->m_launch_error.Clone();
736 } else
737 return Status(::GetLastError(), eErrorTypeWin32);
738}
739
740} // namespace lldb_private
static llvm::raw_ostream & error(Stream &strm)
DllEventAction
Definition ForwardDecl.h:29
static int ReadProcessMemory(uint8_t *buffer, size_t size, const pt_asid *, uint64_t pc, void *context)
Callback used by libipt for reading the process memory.
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:382
#define MAX_PATH
static bool IsPageExecutable(uint32_t protect)
static bool IsPageWritable(uint32_t protect)
static bool IsPageReadable(uint32_t protect)
static DWORD ConvertLldbToWinApiProtect(uint32_t protect)
static void NormalizeWindowsPathSeparators(std::string &s)
unsigned long GetExceptionValue() const
lldb::addr_t GetExceptionAddress() const
A file utility class.
Definition FileSpec.h:56
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
bool Test(ValueType bit) const
Test a single flag bit.
Definition Flags.h:96
HostNativeProcessBase & GetNativeProcess()
lldb::pid_t GetProcessId() const
bool GetContinueOnceAttached() const
Definition Process.h:164
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 WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process)
virtual DllEventAction OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr, lldb::tid_t thread_id)
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info)
virtual void OnCreateThread(const HostThread &thread)
virtual void OnDebuggerError(const Status &error, uint32_t type)
virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code)
virtual void OnDebuggerConnected(lldb::addr_t image_base)
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
virtual void OnDebugString(lldb::addr_t debug_string_addr, bool is_unicode, uint16_t length_lower_word)
void EndDebugSession()
End the debug session, terminating the inferior if it still runs, and wait for the debugger thread to...
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
bool IsSystemModuleAddress(lldb::addr_t addr)
virtual void OnExitProcess(uint32_t exit_code)
virtual DllEventAction OnUnloadDll(lldb::addr_t module_addr, lldb::tid_t thread_id)
static bool IsSystemDLL(llvm::StringRef path)
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
const FileSpec & GetWorkingDirectory() const
An error handling class.
Definition Status.h:118
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
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS
Definition lldb-types.h:68
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:338
std::string StripExtendedLengthPrefix(llvm::StringRef path)
Convert an extended-length path to a regular DOS path: "\\?\C:\a" becomes "C:\a" and "\\?...
Definition PathUtils.h:21
std::shared_ptr< DebuggerThread > DebuggerThreadSP
Definition ForwardDecl.h:46
std::shared_ptr< IDebugDelegate > DebugDelegateSP
Definition ForwardDecl.h:45
StateType
Process and Thread States.
@ eStateDetached
Process has been detached and can't be examined.
@ eStateExited
Process has exited and can't be examined.
@ eErrorTypeWin32
Standard Win32 error codes.
uint64_t pid_t
Definition lldb-types.h:84
uint64_t addr_t
Definition lldb-types.h:80
uint64_t tid_t
Definition lldb-types.h:85
uint64_t process_t
Definition lldb-types.h:57
void SetRangeEnd(BaseType end)
Definition RangeMap.h:80
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
Definition RangeMap.h:48
BaseType GetRangeEnd() const
Definition RangeMap.h:78
void SetByteSize(SizeType s)
Definition RangeMap.h:89