22#include "llvm/Support/ConvertUTF.h"
23#include "llvm/Support/Error.h"
40 if (protect & ePermissionsExecutable)
41 return PAGE_EXECUTE_READWRITE;
43 return PAGE_READWRITE;
51 return (protect & PAGE_NOACCESS) == 0;
55 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
56 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
60 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
61 PAGE_EXECUTE_WRITECOPY)) != 0;
82 llvm::sys::ScopedLock lock(
m_mutex);
85 LLDB_LOG(log,
"there is no active session.");
94 LLDB_LOG(log,
"detaching from process {0}.",
95 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
96 error = debugger_thread->StopDebugging(
false);
115 namespace fs = llvm::sys::fs;
120 working_dir.
GetPath().c_str());
127 stream.
Printf(
"ProcessDebugger unable to launch '%s'. ProcessDebugger can "
128 "only be used for debug launches.",
130 std::string message = stream.
GetString().str();
133 LLDB_LOG(log,
"error: {0}", message);
137 bool stop_at_entry = launch_info.
GetFlags().
Test(eLaunchFlagStopAtEntry);
143 result = debugger->DebugLaunch(launch_info);
145 LLDB_LOG(log,
"failed launching '{0}'. {1}",
153 LLDB_LOG(log,
"failed launching '{0}'. {1}",
158 LLDB_LOG(log,
"successfully launched '{0}'",
181 DWORD process_id =
static_cast<DWORD
>(pid);
182 Status error = debugger->DebugAttach(process_id, attach_info);
186 "encountered an error occurred initiating the asynchronous attach. {0}",
195 "encountered an error waiting for the debugger to connect. {0}",
200 LLDB_LOG(log,
"successfully attached to process with pid={0}", process_id);
219 llvm::sys::ScopedLock lock(
m_mutex);
222 LLDB_LOG(log,
"warning: state = {0}, but there is no active session.",
231 LLDB_LOG(log,
"warning: cannot destroy process {0} while state = {1}.",
236 LLDB_LOG(log,
"Shutting down process {0}.",
237 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
238 auto error = debugger_thread->StopDebugging(
true);
250 llvm::sys::ScopedLock lock(
m_mutex);
251 caused_stop = ::DebugBreakProcess(
m_session_data->m_debugger->GetProcess()
256 LLDB_LOG(log,
"DebugBreakProcess failed with error {0}",
error);
263 size_t &bytes_read) {
267 llvm::sys::ScopedLock lock(
m_mutex);
270 error.SetErrorString(
271 "cannot read, there is no active debugger connection.");
276 LLDB_LOG(log,
"attempting to read {0} bytes from address {1:x}", size,
280 void *addr =
reinterpret_cast<void *
>(vm_addr);
281 SIZE_T num_of_bytes_read = 0;
283 buf, size, &num_of_bytes_read)) {
287 bytes_read = num_of_bytes_read;
293 size_t size,
size_t &bytes_written) {
297 llvm::sys::ScopedLock lock(
m_mutex);
298 LLDB_LOG(log,
"attempting to write {0} bytes into address {1:x}", size,
302 error.SetErrorString(
303 "cannot write, there is no active debugger connection.");
309 void *addr =
reinterpret_cast<void *
>(vm_addr);
310 SIZE_T num_of_bytes_written = 0;
312 if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
313 FlushInstructionCache(handle, addr, num_of_bytes_written);
314 bytes_written = num_of_bytes_written;
327 llvm::sys::ScopedLock lock(
m_mutex);
328 LLDB_LOG(log,
"attempting to allocate {0} bytes with permissions {1}", size,
332 error.SetErrorString(
333 "cannot allocate, there is no active debugger connection");
341 auto result = ::VirtualAllocEx(handle,
nullptr, size, MEM_COMMIT, protect);
346 addr =
reinterpret_cast<addr_t>(result);
355 llvm::sys::ScopedLock lock(
m_mutex);
356 LLDB_LOG(log,
"attempting to deallocate bytes at address {0}", vm_addr);
360 "cannot deallocate, there is no active debugger connection");
361 LLDB_LOG(log,
"error: {0}", result);
367 if (!::VirtualFreeEx(handle,
reinterpret_cast<LPVOID
>(vm_addr), 0,
370 LLDB_LOG(log,
"deallocating failed with error: {0}", result);
380 llvm::sys::ScopedLock lock(
m_mutex);
384 error.SetErrorString(
385 "GetMemoryRegionInfo called with no debugging session.");
392 error.SetErrorString(
393 "GetMemoryRegionInfo called with an invalid target process.");
398 LLDB_LOG(log,
"getting info for address {0:x}", vm_addr);
400 void *addr =
reinterpret_cast<void *
>(vm_addr);
401 MEMORY_BASIC_INFORMATION mem_info = {};
402 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info,
sizeof(mem_info));
404 DWORD last_error = ::GetLastError();
405 if (last_error == ERROR_INVALID_PARAMETER) {
419 "VirtualQueryEx returned error {0} while getting memory "
420 "region info for address {1:x}",
427 if (mem_info.State == MEM_COMMIT) {
442 if (mem_info.State != MEM_FREE) {
444 reinterpret_cast<addr_t>(mem_info.BaseAddress));
446 mem_info.RegionSize);
453 ::GetSystemInfo(&data);
454 DWORD page_offset = vm_addr % data.dwPageSize;
461 "Memory region info for address {0}: readable={1}, "
462 "executable={2}, writable={3}",
484 llvm::sys::ScopedLock lock(
m_mutex);
493 "Debugger thread reported exception {0:x} at address {1:x}, but "
494 "there is no session.",
496 return ExceptionResult::SendToApplication;
505 result = ExceptionResult::BreakInDebugger;
508 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
536 llvm::sys::ScopedLock lock(
m_mutex);
543 "Error {0} occurred during debugging. Unexpected behavior "
553 "Error {0} occurred launching the process before the initial "
564 LLDB_LOG(log,
"Waiting for loader breakpoint.");
567 if (::WaitForSingleObject(
m_session_data->m_initial_stop_event, INFINITE) ==
569 LLDB_LOG(log,
"hit loader breakpoint, returning.");
571 process = debugger->GetProcess();
static llvm::raw_ostream & error(Stream &strm)
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.
#define LLDB_LOGV(log,...)
static bool IsPageExecutable(uint32_t protect)
static bool IsPageWritable(uint32_t protect)
static bool IsPageReadable(uint32_t protect)
static DWORD ConvertLldbToWinApiProtect(uint32_t protect)
DWORD GetExceptionCode() const
lldb::addr_t GetExceptionAddress() const
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
bool Test(ValueType bit) const
Test a single flag bit.
lldb::process_t GetSystemHandle() const
HostNativeProcessBase & GetNativeProcess()
lldb::pid_t GetProcessId() const
OptionalBool GetWritable() const
void SetMapped(OptionalBool val)
void SetReadable(OptionalBool val)
void SetExecutable(OptionalBool val)
void SetWritable(OptionalBool val)
OptionalBool GetReadable() const
OptionalBool GetExecutable() const
bool GetContinueOnceAttached() const
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)
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 void OnDebugString(const std::string &string)
virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record)
Status AttachProcess(lldb::pid_t pid, const ProcessAttachInfo &attach_info, DebugDelegateSP delegate)
virtual void OnUnloadDll(lldb::addr_t module_addr)
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)
virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr)
Status HaltProcess(bool &caused_stop)
virtual ~ProcessDebugger()
Status DeallocateMemory(lldb::addr_t addr)
void SetProcessID(lldb::pid_t pid)
FileSpec & GetExecutableFile()
const FileSpec & GetWorkingDirectory() const
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
bool Fail() const
Test for error condition.
int void SetError(ValueType err, lldb::ErrorType type)
Set accessor with an error value and type.
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS
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.
std::shared_ptr< IDebugDelegate > DebugDelegateSP
std::shared_ptr< DebuggerThread > DebuggerThreadSP
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.
void SetRangeEnd(BaseType end)
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
void SetByteSize(SizeType s)