33#include "llvm/Support/ConvertUTF.h"
34#include "llvm/Support/Format.h"
35#include "llvm/Support/Threading.h"
36#include "llvm/Support/raw_ostream.h"
51std::string GetProcessExecutableName(HANDLE process_handle) {
52 std::vector<wchar_t> file_name;
53 DWORD file_name_size = MAX_PATH;
57 file_name.resize(file_name_size);
58 copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
60 }
while (copied >= file_name_size);
61 file_name.resize(copied);
63 llvm::convertWideToUTF8(file_name.data(), result);
67std::string GetProcessExecutableName(DWORD pid) {
68 std::string file_name;
69 HANDLE process_handle =
70 ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
71 if (process_handle != NULL) {
72 file_name = GetProcessExecutableName(process_handle);
73 ::CloseHandle(process_handle);
89 llvm::StringRef use_lldb_server = ::getenv(
"LLDB_USE_LLDB_SERVER");
90 return use_lldb_server.equals_insensitive(
"on") ||
91 use_lldb_server.equals_insensitive(
"yes") ||
92 use_lldb_server.equals_insensitive(
"1") ||
93 use_lldb_server.equals_insensitive(
"true");
98 static llvm::once_flag g_once_flag;
100 llvm::call_once(g_once_flag, []() {
111 return "Process plugin for Windows";
126 error.SetErrorString(
"GetSTDOUT unsupported on Windows");
131 error.SetErrorString(
"GetSTDERR unsupported on Windows");
137 error.SetErrorString(
"PutSTDIN unsupported on Windows");
143 return Status(
"Hardware breakpoints are not supported.");
146 LLDB_LOG(log,
"bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
150 if (!
error.Success())
157 LLDB_LOG(log,
"bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
162 if (!
error.Success())
178 error.SetErrorStringWithFormatv(
"error: process {0} in state = {1}, but "
179 "cannot detach it in this state.",
180 GetID(), private_state);
208 llvm::sys::ScopedLock lock(
m_mutex);
213 LLDB_LOG(log,
"process {0} is in state {1}. Resuming...",
221 auto thread = std::static_pointer_cast<TargetThreadWindows>(
223 Status result = thread->DoResume();
228 "Trying to resume thread at index {0}, but failed with error {1}.",
234 error.SetErrorString(
"ProcessWindows::DoResume failed");
241 if (active_exception) {
246 ExceptionResult::MaskException);
249 LLDB_LOG(log,
"error: process {0} is in state {1}. Returning...",
275 llvm::sys::ScopedLock lock(
m_mutex);
291 const int addr_min_width = 2 + 8;
293 const std::vector<ULONG_PTR> &args = exception->GetExceptionArguments();
294 switch (exception->GetExceptionCode()) {
295 case EXCEPTION_ACCESS_VIOLATION: {
300 const int access_violation_code = args[0];
302 switch (access_violation_code) {
304 stream <<
"Access violation reading";
307 stream <<
"Access violation writing";
310 stream <<
"User-mode data execution prevention (DEP) violation at";
313 stream <<
"Unknown access violation (code " << access_violation_code
317 stream <<
" location "
318 << llvm::format_hex(access_violation_address, addr_min_width);
321 case EXCEPTION_IN_PAGE_ERROR: {
326 const int page_load_error_code = args[0];
328 const DWORD underlying_code = args[2];
329 switch (page_load_error_code) {
331 stream <<
"In page error reading";
334 stream <<
"In page error writing";
337 stream <<
"User-mode data execution prevention (DEP) violation at";
340 stream <<
"Unknown page loading error (code " << page_load_error_code
344 stream <<
" location "
345 << llvm::format_hex(page_load_error_address, addr_min_width)
346 <<
" (status code " << llvm::format_hex(underlying_code, 8) <<
")";
354 llvm::sys::ScopedLock lock(
m_mutex);
357 LLDB_LOG(log,
"no active session. Returning...");
363 std::weak_ptr<ExceptionRecord> exception_record =
366 if (!active_exception) {
368 "there is no active exception in process {0}. Why is the "
380 switch (active_exception->GetExceptionCode()) {
381 case EXCEPTION_SINGLE_STEP: {
383 const uint64_t
pc = register_context->GetPC();
385 if (site && site->ValidForThisThread(*stop_thread)) {
387 "Single-stepped onto a breakpoint in process {0} at "
388 "address {1:x} with breakpoint site {2}",
393 stop_thread->SetStopInfo(stop_info);
399 stop_thread->GetRegisterContext().get());
404 "Single-stepped onto a watchpoint in process {0} at address "
405 "{1:x} with watchpoint {2}",
409 stop_thread->SetStopInfo(stop_info);
414 LLDB_LOG(log,
"single stepping thread {0}", stop_thread->GetID());
416 stop_thread->SetStopInfo(stop_info);
421 case EXCEPTION_BREAKPOINT: {
424 int breakpoint_size = 1;
425 switch (
GetTarget().GetArchitecture().GetMachine()) {
426 case llvm::Triple::aarch64:
430 case llvm::Triple::arm:
431 case llvm::Triple::thumb:
435 case llvm::Triple::x86:
436 case llvm::Triple::x86_64:
441 LLDB_LOG(log,
"Unknown breakpoint size for architecture");
446 uint64_t
pc = register_context->GetPC() - breakpoint_size;
451 "detected breakpoint in process {0} at address {1:x} with "
452 "breakpoint site {2}",
456 if (site->ValidForThisThread(*stop_thread)) {
458 "Breakpoint site {0} is valid for this thread ({1:x}), "
459 "creating stop info.",
460 site->GetID(), stop_thread->GetID());
463 *stop_thread, site->GetID());
464 register_context->SetPC(
pc);
467 "Breakpoint site {0} is not valid for this thread, "
468 "creating empty stop info.",
471 stop_thread->SetStopInfo(stop_info);
477 "No breakpoint site matches for this thread. __debugbreak()? "
478 "Creating stop info with the exception.");
487 llvm::raw_string_ostream desc_stream(desc);
488 desc_stream <<
"Exception "
489 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
490 <<
" encountered at address "
491 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
495 *stop_thread, desc_stream.str().c_str());
496 stop_thread->SetStopInfo(stop_info);
497 LLDB_LOG(log,
"{0}", desc_stream.str());
504 bool plugin_specified_by_name) {
505 if (plugin_specified_by_name)
509 ModuleSP exe_module_sp(target_sp->GetExecutableModule());
510 if (exe_module_sp.get())
523 int continued_threads = 0;
524 int exited_threads = 0;
529 auto exited_thread_iter =
531 if (exited_thread_iter ==
m_session_data->m_exited_threads.end()) {
535 LLDB_LOGV(log,
"Thread {0} was running and is still running.",
538 LLDB_LOGV(log,
"Thread {0} was running and has exited.", old_thread_id);
546 new_thread_list.
AddThread(thread_info.second);
549 LLDB_LOGV(log,
"Thread {0} is new since last update.", thread_info.first);
552 LLDB_LOG(log,
"{0} new threads, {1} old threads, {2} exited threads.",
553 new_threads, continued_threads, exited_threads);
576 return HostInfo::GetArchitecture();
581 size_t bytes_read = 0;
588 size_t bytes_written = 0;
590 return bytes_written;
629 LLDB_LOG(log,
"Process {0} exited with code {1}",
GetID(), exit_code);
633 ModuleSP executable_module = target->GetExecutableModule();
635 unloaded_modules.
Append(executable_module);
636 target->ModulesDidUnload(unloaded_modules,
true);
648 LLDB_LOG(log,
"Debugger connected to process {0}. Image base = {1:x}",
649 debugger->GetProcess().GetProcessId(), image_base);
653 const DWORD pid = debugger->GetProcess().GetProcessId();
654 const std::string file_name = GetProcessExecutableName(pid);
655 if (file_name.empty()) {
659 FileSpec executable_file(file_name);
672 dyld->OnLoadModule(module,
ModuleSpec(), image_base);
678 llvm::sys::ScopedLock lock(
m_mutex);
680 const HostThread &host_main_thread = debugger->GetMainThread();
682 std::make_shared<TargetThreadWindows>(*
this, host_main_thread);
685 main_thread->SetID(
id);
694 llvm::sys::ScopedLock lock(
m_mutex);
705 "Debugger thread reported exception {0:x} at address {1:x}, "
706 "but there is no session.",
708 return ExceptionResult::SendToApplication;
719 case EXCEPTION_BREAKPOINT:
721 result = ExceptionResult::BreakInDebugger;
726 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
731 LLDB_LOG(log,
"Hit non-loader breakpoint at address {0:x}.",
736 case EXCEPTION_SINGLE_STEP:
737 result = ExceptionResult::BreakInDebugger;
742 "Debugger thread reported exception {0:x} at address {1:x} "
743 "(first_chance={2})",
749 result = ExceptionResult::SendToApplication;
751 result = ExceptionResult::BreakInDebugger;
758 llvm::sys::ScopedLock lock(
m_mutex);
760 ThreadSP thread = std::make_shared<TargetThreadWindows>(*
this, new_thread);
763 tid_t id = native_new_thread.GetThreadId();
768 for (
const std::map<int, WatchpointInfo>::value_type &p :
m_watchpoints) {
770 thread->GetRegisterContext().get());
772 p.second.size, p.second.read,
778 llvm::sys::ScopedLock lock(
m_mutex);
798 dyld->OnLoadModule(
nullptr, module_spec, module_addr);
803 dyld->OnUnloadModule(module_addr);
809 llvm::sys::ScopedLock lock(
m_mutex);
816 "Error {0} occurred during debugging. Unexpected behavior "
827 "Error {0} occurred launching the process before the initial stop. {1}",
840 if (wp_sp->IsEnabled()) {
841 wp_sp->SetEnabled(
true, notify);
852 error.SetErrorStringWithFormat(
"Can't find free slot for watchpoint %i",
856 info.
address = wp_sp->GetLoadAddress();
857 info.
size = wp_sp->GetByteSize();
858 info.
read = wp_sp->WatchpointRead();
859 info.
write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify();
867 error.SetErrorStringWithFormat(
868 "Can't enable watchpoint %i on thread 0x%llx", wp_sp->GetID(),
886 wp_sp->SetEnabled(
true, notify);
894 if (!wp_sp->IsEnabled()) {
895 wp_sp->SetEnabled(
false, notify);
901 error.SetErrorStringWithFormat(
"Info about watchpoint %i is not found",
910 if (!reg_ctx->RemoveHardwareBreakpoint(it->second.slot_id)) {
911 error.SetErrorStringWithFormat(
912 "Can't disable watchpoint %i on thread 0x%llx", wp_sp->GetID(),
923 wp_sp->SetEnabled(
false, notify);
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGV(log,...)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
A section + offset based address class.
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
bool IsValid() const
Check if the object state is valid.
An architecture specification class.
Class that manages the actual breakpoint that will be inserted into the running program.
static llvm::StringRef GetPluginNameStatic()
static DynamicLoader * FindPlugin(Process *process, llvm::StringRef plugin_name)
Find a dynamic loader plugin for a given process.
DWORD GetExceptionCode() const
lldb::addr_t GetExceptionAddress() const
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
static FileSystem & Instance()
HostNativeThread & GetNativeThread()
A collection class for Module objects.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
A class that describes an executable image and its associated object and symbol files.
A plug-in interface definition class for object file parsers.
virtual lldb_private::Address GetImageInfoAddress(Target *target)
Similar to Process::GetImageInfoAddress().
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
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)
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)
Status HaltProcess(bool &caused_stop)
Status DeallocateMemory(lldb::addr_t addr)
lldb::pid_t GetProcessID() const
void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) override
void OnDebugString(const std::string &string) override
ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
bool DoUpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override
Update the thread list following process plug-in's specific logic.
size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override
Puts data into this process's STDIN.
void RefreshStateAfterStop() override
Currently called as part of ShouldStop.
void OnDebuggerConnected(lldb::addr_t image_base) override
Status DoDeallocateMemory(lldb::addr_t ptr) override
Actually deallocate memory in the process.
Status DoDestroy() override
Status EnableBreakpointSite(BreakpointSite *bp_site) override
void DidLaunch() override
Called after launching a process.
std::optional< uint32_t > GetWatchpointSlotCount() override
Get the number of watchpoints supported by this target.
void OnUnloadDll(lldb::addr_t module_addr) override
DynamicLoaderWindowsDYLD * GetDynamicLoader() override
Get the dynamic loader plug-in for this process.
Status DoResume() override
Resumes all of a process's threads as configured using the Thread run control functions.
size_t GetSTDOUT(char *buf, size_t buf_size, Status &error) override
Get any available STDOUT.
Status DisableWatchpoint(lldb::WatchpointSP wp_sp, bool notify=true) override
bool IsAlive() override
Check if a process is still alive.
Status DoGetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) override
DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has removed non address bits from loa...
void OnCreateThread(const HostThread &thread) override
static llvm::StringRef GetPluginDescriptionStatic()
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error) override
Actually do the writing of memory to a process.
Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override
Launch a new process.
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error) override
Actually do the reading of memory from a process.
bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override
Check if a plug-in instance can debug the file in module.
static llvm::StringRef GetPluginNameStatic()
void DidAttach(lldb_private::ArchSpec &arch_spec) override
Called after attaching a process.
void OnExitProcess(uint32_t exit_code) override
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *, bool can_connect)
void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override
Status DoAttachToProcessWithID(lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override
Attach to an existing process using a process ID.
lldb::addr_t GetImageInfoAddress() override
Get the image information address for the current process.
ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) override
std::map< lldb::break_id_t, WatchpointInfo > m_watchpoints
void OnDebuggerError(const Status &error, uint32_t type) override
ArchSpec GetSystemArchitecture() override
Get the system architecture for this process.
Status DoDetach(bool keep_stopped) override
Detaches from a running or stopped process.
std::vector< lldb::break_id_t > m_watchpoint_ids
size_t GetSTDERR(char *buf, size_t buf_size, Status &error) override
Get any available STDERR.
lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, Status &error) override
Actually allocate memory in the process.
Status DisableBreakpointSite(BreakpointSite *bp_site) override
Status DoHalt(bool &caused_stop) override
Halts a running process.
Status EnableWatchpoint(lldb::WatchpointSP wp_sp, bool notify=true) override
A plug-in interface definition class for debugging a process.
StopPointSiteList< lldb_private::BreakpointSite > & GetBreakpointSiteList()
virtual Status DisableSoftwareBreakpoint(BreakpointSite *bp_site)
lldb::pid_t GetID() const
Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is no known pid.
lldb::StateType GetPrivateState()
lldb::DynamicLoaderUP m_dyld_up
lldb::TargetSP CalculateTarget() override
static bool SetProcessExitStatus(lldb::pid_t pid, bool exited, int signo, int status)
Static function that can be used with the host function Host::StartMonitoringChildProcess ().
virtual Status EnableSoftwareBreakpoint(BreakpointSite *bp_site)
void SetID(lldb::pid_t new_pid)
Sets the stored pid.
void SetPrivateState(lldb::StateType state)
ThreadList m_thread_list
The threads for this process as the user will see them.
Target & GetTarget()
Get the target object pointer for this module.
static constexpr uint32_t GetNumHardwareBreakpointSlots()
uint32_t GetTriggeredHardwareBreakpointSlotId()
bool RemoveHardwareBreakpoint(uint32_t slot)
bool AddHardwareBreakpoint(uint32_t slot, lldb::addr_t address, uint32_t size, bool read, bool write)
bool Fail() const
Test for error condition.
static lldb::StopInfoSP CreateStopReasonToTrace(Thread &thread)
static lldb::StopInfoSP CreateStopReasonWithWatchpointID(Thread &thread, lldb::break_id_t watch_id, bool silently_continue=false)
static lldb::StopInfoSP CreateStopReasonWithException(Thread &thread, const char *description)
static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID(Thread &thread, lldb::break_id_t break_id)
lldb::break_id_t GetID() const
virtual lldb::addr_t GetLoadAddress() const
bool HardwareRequired() const
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, bool notify, Status *error_ptr=nullptr)
Find a binary on the system and return its Module, or return an existing Module that is already in th...
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
void AddThread(const lldb::ThreadSP &thread_sp)
virtual ThreadIterable Threads()
lldb::ThreadSP GetSelectedThread()
uint32_t GetSize(bool can_update=true)
bool SetSelectedThreadByID(lldb::tid_t tid, bool notify=false)
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
void RefreshStateAfterStop()
virtual lldb::RegisterContextSP GetRegisterContext()=0
#define LLDB_INVALID_BREAK_ID
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
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< ExceptionRecord > ExceptionRecordSP
std::shared_ptr< IDebugDelegate > DebugDelegateSP
std::shared_ptr< DebuggerThread > DebuggerThreadSP
static void DumpAdditionalExceptionInformation(llvm::raw_ostream &stream, const ExceptionRecordSP &exception)
static bool ShouldUseLLDBServer()
std::shared_ptr< lldb_private::BreakpointSite > BreakpointSiteSP
std::shared_ptr< lldb_private::Thread > ThreadSP
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.
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateExited
Process has exited and can't be examined.
@ eStateCrashed
Process or thread has crashed and can be examined.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Watchpoint > WatchpointSP
std::shared_ptr< lldb_private::Listener > ListenerSP
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
std::shared_ptr< lldb_private::Module > ModuleSP
lldb::user_id_t GetID() const
Get accessor for the user ID.