1af245d11STodd Fiala //===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===// 2af245d11STodd Fiala // 3af245d11STodd Fiala // The LLVM Compiler Infrastructure 4af245d11STodd Fiala // 5af245d11STodd Fiala // This file is distributed under the University of Illinois Open Source 6af245d11STodd Fiala // License. See LICENSE.TXT for details. 7af245d11STodd Fiala // 8af245d11STodd Fiala //===----------------------------------------------------------------------===// 9af245d11STodd Fiala 102fe1d0abSChaoren Lin #include "lldb/Host/common/NativeProcessProtocol.h" 11af245d11STodd Fiala 12af245d11STodd Fiala #include "lldb/Core/ArchSpec.h" 13e77fce0aSTodd Fiala #include "lldb/Core/ModuleSpec.h" 14af245d11STodd Fiala #include "lldb/Core/State.h" 15511e5cdcSTodd Fiala #include "lldb/Host/Host.h" 162fe1d0abSChaoren Lin #include "lldb/Host/common/NativeRegisterContext.h" 172fe1d0abSChaoren Lin #include "lldb/Host/common/NativeThreadProtocol.h" 182fe1d0abSChaoren Lin #include "lldb/Host/common/SoftwareBreakpoint.h" 19e77fce0aSTodd Fiala #include "lldb/Symbol/ObjectFile.h" 20e77fce0aSTodd Fiala #include "lldb/Target/Process.h" 21e77fce0aSTodd Fiala #include "lldb/Utility/LLDBAssert.h" 226f9e6901SZachary Turner #include "lldb/Utility/Log.h" 23b9c1b51eSKate Stone #include "lldb/lldb-enumerations.h" 24af245d11STodd Fiala 25af245d11STodd Fiala using namespace lldb; 26af245d11STodd Fiala using namespace lldb_private; 27af245d11STodd Fiala 28af245d11STodd Fiala // ----------------------------------------------------------------------------- 29af245d11STodd Fiala // NativeProcessProtocol Members 30af245d11STodd Fiala // ----------------------------------------------------------------------------- 31af245d11STodd Fiala 32*96e600fcSPavel Labath NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, 33*96e600fcSPavel Labath NativeDelegate &delegate) 34*96e600fcSPavel Labath : m_pid(pid), m_terminal_fd(terminal_fd) { 35*96e600fcSPavel Labath bool registered = RegisterNativeDelegate(delegate); 36*96e600fcSPavel Labath assert(registered); 37*96e600fcSPavel Labath (void)registered; 38*96e600fcSPavel Labath } 39af245d11STodd Fiala 4097206d57SZachary Turner lldb_private::Status NativeProcessProtocol::Interrupt() { 4197206d57SZachary Turner Status error; 42511e5cdcSTodd Fiala #if !defined(SIGSTOP) 43511e5cdcSTodd Fiala error.SetErrorString("local host does not support signaling"); 44511e5cdcSTodd Fiala return error; 45511e5cdcSTodd Fiala #else 46511e5cdcSTodd Fiala return Signal(SIGSTOP); 47511e5cdcSTodd Fiala #endif 48511e5cdcSTodd Fiala } 49511e5cdcSTodd Fiala 5097206d57SZachary Turner Status NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef<int> signals) { 514a705e7eSPavel Labath m_signals_to_ignore.clear(); 524a705e7eSPavel Labath m_signals_to_ignore.insert(signals.begin(), signals.end()); 5397206d57SZachary Turner return Status(); 544a705e7eSPavel Labath } 554a705e7eSPavel Labath 5697206d57SZachary Turner lldb_private::Status 57b9c1b51eSKate Stone NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, 58b9c1b51eSKate Stone MemoryRegionInfo &range_info) { 59af245d11STodd Fiala // Default: not implemented. 6097206d57SZachary Turner return Status("not implemented"); 61af245d11STodd Fiala } 62af245d11STodd Fiala 633508fc8cSPavel Labath llvm::Optional<WaitStatus> NativeProcessProtocol::GetExitStatus() { 643508fc8cSPavel Labath if (m_state == lldb::eStateExited) 653508fc8cSPavel Labath return m_exit_status; 663508fc8cSPavel Labath 673508fc8cSPavel Labath return llvm::None; 68af245d11STodd Fiala } 69af245d11STodd Fiala 703508fc8cSPavel Labath bool NativeProcessProtocol::SetExitStatus(WaitStatus status, 71b9c1b51eSKate Stone bool bNotifyStateChange) { 72af245d11STodd Fiala Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 733508fc8cSPavel Labath LLDB_LOG(log, "status = {0}, notify = {1}", status, bNotifyStateChange); 74af245d11STodd Fiala 75af245d11STodd Fiala // Exit status already set 76b9c1b51eSKate Stone if (m_state == lldb::eStateExited) { 773508fc8cSPavel Labath if (m_exit_status) 783508fc8cSPavel Labath LLDB_LOG(log, "exit status already set to {0}", *m_exit_status); 793508fc8cSPavel Labath else 803508fc8cSPavel Labath LLDB_LOG(log, "state is exited, but status not set"); 81af245d11STodd Fiala return false; 82af245d11STodd Fiala } 83af245d11STodd Fiala 84af245d11STodd Fiala m_state = lldb::eStateExited; 85af245d11STodd Fiala m_exit_status = status; 86af245d11STodd Fiala 87af245d11STodd Fiala if (bNotifyStateChange) 88af245d11STodd Fiala SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); 89af245d11STodd Fiala 90af245d11STodd Fiala return true; 91af245d11STodd Fiala } 92af245d11STodd Fiala 93b9c1b51eSKate Stone NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { 9416ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 95af245d11STodd Fiala if (idx < m_threads.size()) 96af245d11STodd Fiala return m_threads[idx]; 97af245d11STodd Fiala return NativeThreadProtocolSP(); 98af245d11STodd Fiala } 99af245d11STodd Fiala 100af245d11STodd Fiala NativeThreadProtocolSP 101b9c1b51eSKate Stone NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { 102b9c1b51eSKate Stone for (auto thread_sp : m_threads) { 103af245d11STodd Fiala if (thread_sp->GetID() == tid) 104af245d11STodd Fiala return thread_sp; 105af245d11STodd Fiala } 106af245d11STodd Fiala return NativeThreadProtocolSP(); 107af245d11STodd Fiala } 108af245d11STodd Fiala 109b9c1b51eSKate Stone NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { 11016ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 111511e5cdcSTodd Fiala return GetThreadByIDUnlocked(tid); 112511e5cdcSTodd Fiala } 113511e5cdcSTodd Fiala 114b9c1b51eSKate Stone bool NativeProcessProtocol::IsAlive() const { 115b9c1b51eSKate Stone return m_state != eStateDetached && m_state != eStateExited && 116b9c1b51eSKate Stone m_state != eStateInvalid && m_state != eStateUnloaded; 117af245d11STodd Fiala } 118af245d11STodd Fiala 119b9c1b51eSKate Stone bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { 120af245d11STodd Fiala ArchSpec process_arch; 121af245d11STodd Fiala if (!GetArchitecture(process_arch)) 122af245d11STodd Fiala return false; 123af245d11STodd Fiala byte_order = process_arch.GetByteOrder(); 124af245d11STodd Fiala return true; 125af245d11STodd Fiala } 126af245d11STodd Fiala 12718fe6404SChaoren Lin const NativeWatchpointList::WatchpointMap & 128b9c1b51eSKate Stone NativeProcessProtocol::GetWatchpointMap() const { 12918fe6404SChaoren Lin return m_watchpoint_list.GetWatchpointMap(); 13018fe6404SChaoren Lin } 13118fe6404SChaoren Lin 132d5ffbad2SOmair Javaid llvm::Optional<std::pair<uint32_t, uint32_t>> 133d5ffbad2SOmair Javaid NativeProcessProtocol::GetHardwareDebugSupportInfo() const { 134af245d11STodd Fiala Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 135af245d11STodd Fiala 136af245d11STodd Fiala // get any thread 137b9c1b51eSKate Stone NativeThreadProtocolSP thread_sp( 138b9c1b51eSKate Stone const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); 139b9c1b51eSKate Stone if (!thread_sp) { 140af245d11STodd Fiala if (log) 141b9c1b51eSKate Stone log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " 142b9c1b51eSKate Stone "grab a NativeRegisterContext!", 143b9c1b51eSKate Stone __FUNCTION__); 144d5ffbad2SOmair Javaid return llvm::None; 145af245d11STodd Fiala } 146af245d11STodd Fiala 147af245d11STodd Fiala NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 148b9c1b51eSKate Stone if (!reg_ctx_sp) { 149af245d11STodd Fiala if (log) 150b9c1b51eSKate Stone log->Warning("NativeProcessProtocol::%s (): failed to get a " 151b9c1b51eSKate Stone "RegisterContextNativeProcess from the first thread!", 152b9c1b51eSKate Stone __FUNCTION__); 153d5ffbad2SOmair Javaid return llvm::None; 154af245d11STodd Fiala } 155af245d11STodd Fiala 156d5ffbad2SOmair Javaid return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), 157d5ffbad2SOmair Javaid reg_ctx_sp->NumSupportedHardwareWatchpoints()); 158af245d11STodd Fiala } 159af245d11STodd Fiala 16097206d57SZachary Turner Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, 161b9c1b51eSKate Stone uint32_t watch_flags, 162b9c1b51eSKate Stone bool hardware) { 163af245d11STodd Fiala // This default implementation assumes setting the watchpoint for 164af245d11STodd Fiala // the process will require setting the watchpoint for each of the 165af245d11STodd Fiala // threads. Furthermore, it will track watchpoints set for the 166af245d11STodd Fiala // process and will add them to each thread that is attached to 167af245d11STodd Fiala // via the (FIXME implement) OnThreadAttached () method. 168af245d11STodd Fiala 169af245d11STodd Fiala Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 170af245d11STodd Fiala 171af245d11STodd Fiala // Update the thread list 172af245d11STodd Fiala UpdateThreads(); 173af245d11STodd Fiala 174af245d11STodd Fiala // Keep track of the threads we successfully set the watchpoint 175af245d11STodd Fiala // for. If one of the thread watchpoint setting operations fails, 176af245d11STodd Fiala // back off and remove the watchpoint for all the threads that 177af245d11STodd Fiala // were successfully set so we get back to a consistent state. 178af245d11STodd Fiala std::vector<NativeThreadProtocolSP> watchpoint_established_threads; 179af245d11STodd Fiala 180af245d11STodd Fiala // Tell each thread to set a watchpoint. In the event that 181af245d11STodd Fiala // hardware watchpoints are requested but the SetWatchpoint fails, 182af245d11STodd Fiala // try to set a software watchpoint as a fallback. It's 183af245d11STodd Fiala // conceivable that if there are more threads than hardware 184af245d11STodd Fiala // watchpoints available, some of the threads will fail to set 185af245d11STodd Fiala // hardware watchpoints while software ones may be available. 18616ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 187b9c1b51eSKate Stone for (auto thread_sp : m_threads) { 188af245d11STodd Fiala assert(thread_sp && "thread list should not have a NULL thread!"); 189af245d11STodd Fiala if (!thread_sp) 190af245d11STodd Fiala continue; 191af245d11STodd Fiala 19297206d57SZachary Turner Status thread_error = 193b9c1b51eSKate Stone thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); 194b9c1b51eSKate Stone if (thread_error.Fail() && hardware) { 195af245d11STodd Fiala // Try software watchpoints since we failed on hardware watchpoint setting 196af245d11STodd Fiala // and we may have just run out of hardware watchpoints. 197af245d11STodd Fiala thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); 198b9c1b51eSKate Stone if (thread_error.Success()) { 199af245d11STodd Fiala if (log) 200b9c1b51eSKate Stone log->Warning( 201b9c1b51eSKate Stone "hardware watchpoint requested but software watchpoint set"); 202af245d11STodd Fiala } 203af245d11STodd Fiala } 204af245d11STodd Fiala 205b9c1b51eSKate Stone if (thread_error.Success()) { 206af245d11STodd Fiala // Remember that we set this watchpoint successfully in 207af245d11STodd Fiala // case we need to clear it later. 208af245d11STodd Fiala watchpoint_established_threads.push_back(thread_sp); 209b9c1b51eSKate Stone } else { 210af245d11STodd Fiala // Unset the watchpoint for each thread we successfully 211af245d11STodd Fiala // set so that we get back to a consistent state of "not 212af245d11STodd Fiala // set" for the watchpoint. 213b9c1b51eSKate Stone for (auto unwatch_thread_sp : watchpoint_established_threads) { 21497206d57SZachary Turner Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); 215b9c1b51eSKate Stone if (remove_error.Fail() && log) { 216b9c1b51eSKate Stone log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " 217b9c1b51eSKate Stone "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", 218b9c1b51eSKate Stone __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), 219b9c1b51eSKate Stone remove_error.AsCString()); 220af245d11STodd Fiala } 221af245d11STodd Fiala } 222af245d11STodd Fiala 223af245d11STodd Fiala return thread_error; 224af245d11STodd Fiala } 225af245d11STodd Fiala } 22618fe6404SChaoren Lin return m_watchpoint_list.Add(addr, size, watch_flags, hardware); 227af245d11STodd Fiala } 228af245d11STodd Fiala 22997206d57SZachary Turner Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { 230af245d11STodd Fiala // Update the thread list 231af245d11STodd Fiala UpdateThreads(); 232af245d11STodd Fiala 23397206d57SZachary Turner Status overall_error; 234af245d11STodd Fiala 23516ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 236b9c1b51eSKate Stone for (auto thread_sp : m_threads) { 237af245d11STodd Fiala assert(thread_sp && "thread list should not have a NULL thread!"); 238af245d11STodd Fiala if (!thread_sp) 239af245d11STodd Fiala continue; 240af245d11STodd Fiala 24197206d57SZachary Turner const Status thread_error = thread_sp->RemoveWatchpoint(addr); 242b9c1b51eSKate Stone if (thread_error.Fail()) { 243af245d11STodd Fiala // Keep track of the first thread error if any threads 244af245d11STodd Fiala // fail. We want to try to remove the watchpoint from 245af245d11STodd Fiala // every thread, though, even if one or more have errors. 246af245d11STodd Fiala if (!overall_error.Fail()) 247af245d11STodd Fiala overall_error = thread_error; 248af245d11STodd Fiala } 249af245d11STodd Fiala } 25097206d57SZachary Turner const Status error = m_watchpoint_list.Remove(addr); 25118fe6404SChaoren Lin return overall_error.Fail() ? overall_error : error; 252af245d11STodd Fiala } 253af245d11STodd Fiala 254d5ffbad2SOmair Javaid const HardwareBreakpointMap & 255d5ffbad2SOmair Javaid NativeProcessProtocol::GetHardwareBreakpointMap() const { 256d5ffbad2SOmair Javaid return m_hw_breakpoints_map; 257d5ffbad2SOmair Javaid } 258d5ffbad2SOmair Javaid 25997206d57SZachary Turner Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, 260d5ffbad2SOmair Javaid size_t size) { 261d5ffbad2SOmair Javaid // This default implementation assumes setting a hardware breakpoint for 262d5ffbad2SOmair Javaid // this process will require setting same hardware breakpoint for each 263d5ffbad2SOmair Javaid // of its existing threads. New thread will do the same once created. 264d5ffbad2SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 265d5ffbad2SOmair Javaid 266d5ffbad2SOmair Javaid // Update the thread list 267d5ffbad2SOmair Javaid UpdateThreads(); 268d5ffbad2SOmair Javaid 269d5ffbad2SOmair Javaid // Exit here if target does not have required hardware breakpoint capability. 270d5ffbad2SOmair Javaid auto hw_debug_cap = GetHardwareDebugSupportInfo(); 271d5ffbad2SOmair Javaid 272d5ffbad2SOmair Javaid if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || 273d5ffbad2SOmair Javaid hw_debug_cap->first <= m_hw_breakpoints_map.size()) 27497206d57SZachary Turner return Status("Target does not have required no of hardware breakpoints"); 275d5ffbad2SOmair Javaid 276d5ffbad2SOmair Javaid // Vector below stores all thread pointer for which we have we successfully 277d5ffbad2SOmair Javaid // set this hardware breakpoint. If any of the current process threads fails 278d5ffbad2SOmair Javaid // to set this hardware breakpoint then roll back and remove this breakpoint 279d5ffbad2SOmair Javaid // for all the threads that had already set it successfully. 280d5ffbad2SOmair Javaid std::vector<NativeThreadProtocolSP> breakpoint_established_threads; 281d5ffbad2SOmair Javaid 282d5ffbad2SOmair Javaid // Request to set a hardware breakpoint for each of current process threads. 283d5ffbad2SOmair Javaid std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 284d5ffbad2SOmair Javaid for (auto thread_sp : m_threads) { 285d5ffbad2SOmair Javaid assert(thread_sp && "thread list should not have a NULL thread!"); 286d5ffbad2SOmair Javaid if (!thread_sp) 287d5ffbad2SOmair Javaid continue; 288d5ffbad2SOmair Javaid 28997206d57SZachary Turner Status thread_error = thread_sp->SetHardwareBreakpoint(addr, size); 290d5ffbad2SOmair Javaid if (thread_error.Success()) { 291d5ffbad2SOmair Javaid // Remember that we set this breakpoint successfully in 292d5ffbad2SOmair Javaid // case we need to clear it later. 293d5ffbad2SOmair Javaid breakpoint_established_threads.push_back(thread_sp); 294d5ffbad2SOmair Javaid } else { 295d5ffbad2SOmair Javaid // Unset the breakpoint for each thread we successfully 296d5ffbad2SOmair Javaid // set so that we get back to a consistent state of "not 297d5ffbad2SOmair Javaid // set" for this hardware breakpoint. 298d5ffbad2SOmair Javaid for (auto rollback_thread_sp : breakpoint_established_threads) { 29997206d57SZachary Turner Status remove_error = 30097206d57SZachary Turner rollback_thread_sp->RemoveHardwareBreakpoint(addr); 301d5ffbad2SOmair Javaid if (remove_error.Fail() && log) { 302d5ffbad2SOmair Javaid log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" 303d5ffbad2SOmair Javaid " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", 304d5ffbad2SOmair Javaid __FUNCTION__, GetID(), rollback_thread_sp->GetID(), 305d5ffbad2SOmair Javaid remove_error.AsCString()); 306d5ffbad2SOmair Javaid } 307d5ffbad2SOmair Javaid } 308d5ffbad2SOmair Javaid 309d5ffbad2SOmair Javaid return thread_error; 310d5ffbad2SOmair Javaid } 311d5ffbad2SOmair Javaid } 312d5ffbad2SOmair Javaid 313d5ffbad2SOmair Javaid // Register new hardware breakpoint into hardware breakpoints map of current 314d5ffbad2SOmair Javaid // process. 315d5ffbad2SOmair Javaid m_hw_breakpoints_map[addr] = {addr, size}; 316d5ffbad2SOmair Javaid 31797206d57SZachary Turner return Status(); 318d5ffbad2SOmair Javaid } 319d5ffbad2SOmair Javaid 32097206d57SZachary Turner Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { 321d5ffbad2SOmair Javaid // Update the thread list 322d5ffbad2SOmair Javaid UpdateThreads(); 323d5ffbad2SOmair Javaid 32497206d57SZachary Turner Status error; 325d5ffbad2SOmair Javaid 326d5ffbad2SOmair Javaid std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 327d5ffbad2SOmair Javaid for (auto thread_sp : m_threads) { 328d5ffbad2SOmair Javaid assert(thread_sp && "thread list should not have a NULL thread!"); 329d5ffbad2SOmair Javaid if (!thread_sp) 330d5ffbad2SOmair Javaid continue; 331d5ffbad2SOmair Javaid 332d5ffbad2SOmair Javaid error = thread_sp->RemoveHardwareBreakpoint(addr); 333d5ffbad2SOmair Javaid } 334d5ffbad2SOmair Javaid 335d5ffbad2SOmair Javaid // Also remove from hardware breakpoint map of current process. 336d5ffbad2SOmair Javaid m_hw_breakpoints_map.erase(addr); 337d5ffbad2SOmair Javaid 338d5ffbad2SOmair Javaid return error; 339d5ffbad2SOmair Javaid } 340d5ffbad2SOmair Javaid 341b9c1b51eSKate Stone bool NativeProcessProtocol::RegisterNativeDelegate( 342b9c1b51eSKate Stone NativeDelegate &native_delegate) { 34316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 344b9c1b51eSKate Stone if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != 345b9c1b51eSKate Stone m_delegates.end()) 346af245d11STodd Fiala return false; 347af245d11STodd Fiala 348af245d11STodd Fiala m_delegates.push_back(&native_delegate); 349af245d11STodd Fiala native_delegate.InitializeDelegate(this); 350af245d11STodd Fiala return true; 351af245d11STodd Fiala } 352af245d11STodd Fiala 353b9c1b51eSKate Stone bool NativeProcessProtocol::UnregisterNativeDelegate( 354b9c1b51eSKate Stone NativeDelegate &native_delegate) { 35516ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 356af245d11STodd Fiala 357af245d11STodd Fiala const auto initial_size = m_delegates.size(); 358b9c1b51eSKate Stone m_delegates.erase( 359b9c1b51eSKate Stone remove(m_delegates.begin(), m_delegates.end(), &native_delegate), 360b9c1b51eSKate Stone m_delegates.end()); 361af245d11STodd Fiala 362af245d11STodd Fiala // We removed the delegate if the count of delegates shrank after 363af245d11STodd Fiala // removing all copies of the given native_delegate from the vector. 364af245d11STodd Fiala return m_delegates.size() < initial_size; 365af245d11STodd Fiala } 366af245d11STodd Fiala 367b9c1b51eSKate Stone void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( 368b9c1b51eSKate Stone lldb::StateType state) { 369af245d11STodd Fiala Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 370af245d11STodd Fiala 37116ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 372af245d11STodd Fiala for (auto native_delegate : m_delegates) 373af245d11STodd Fiala native_delegate->ProcessStateChanged(this, state); 374af245d11STodd Fiala 375b9c1b51eSKate Stone if (log) { 376b9c1b51eSKate Stone if (!m_delegates.empty()) { 377b9c1b51eSKate Stone log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " 378b9c1b51eSKate Stone "from process %" PRIu64, 379af245d11STodd Fiala __FUNCTION__, lldb_private::StateAsCString(state), GetID()); 380b9c1b51eSKate Stone } else { 381b9c1b51eSKate Stone log->Printf("NativeProcessProtocol::%s: would send state notification " 382b9c1b51eSKate Stone "[%s] from process %" PRIu64 ", but no delegates", 383af245d11STodd Fiala __FUNCTION__, lldb_private::StateAsCString(state), GetID()); 384af245d11STodd Fiala } 385af245d11STodd Fiala } 386af245d11STodd Fiala } 387af245d11STodd Fiala 388b9c1b51eSKate Stone void NativeProcessProtocol::NotifyDidExec() { 389a9882ceeSTodd Fiala Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 390a9882ceeSTodd Fiala if (log) 391b9c1b51eSKate Stone log->Printf("NativeProcessProtocol::%s - preparing to call delegates", 392b9c1b51eSKate Stone __FUNCTION__); 393a9882ceeSTodd Fiala 394a9882ceeSTodd Fiala { 39516ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 396a9882ceeSTodd Fiala for (auto native_delegate : m_delegates) 397a9882ceeSTodd Fiala native_delegate->DidExec(this); 398a9882ceeSTodd Fiala } 399a9882ceeSTodd Fiala } 400a9882ceeSTodd Fiala 40197206d57SZachary Turner Status NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, 402b9c1b51eSKate Stone uint32_t size_hint) { 403af245d11STodd Fiala Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 404af245d11STodd Fiala if (log) 405b9c1b51eSKate Stone log->Printf("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, 406b9c1b51eSKate Stone addr); 407af245d11STodd Fiala 408b9c1b51eSKate Stone return m_breakpoint_list.AddRef( 409b9c1b51eSKate Stone addr, size_hint, false, 410b9c1b51eSKate Stone [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, 41197206d57SZachary Turner NativeBreakpointSP &breakpoint_sp) -> Status { 412b9c1b51eSKate Stone return SoftwareBreakpoint::CreateSoftwareBreakpoint( 413b9c1b51eSKate Stone *this, addr, size_hint, breakpoint_sp); 414b9c1b51eSKate Stone }); 415af245d11STodd Fiala } 416af245d11STodd Fiala 41797206d57SZachary Turner Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, 418d5ffbad2SOmair Javaid bool hardware) { 419d5ffbad2SOmair Javaid if (hardware) 420d5ffbad2SOmair Javaid return RemoveHardwareBreakpoint(addr); 421d5ffbad2SOmair Javaid else 422af245d11STodd Fiala return m_breakpoint_list.DecRef(addr); 423af245d11STodd Fiala } 424af245d11STodd Fiala 42597206d57SZachary Turner Status NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { 426af245d11STodd Fiala return m_breakpoint_list.EnableBreakpoint(addr); 427af245d11STodd Fiala } 428af245d11STodd Fiala 42997206d57SZachary Turner Status NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { 430af245d11STodd Fiala return m_breakpoint_list.DisableBreakpoint(addr); 431af245d11STodd Fiala } 432af245d11STodd Fiala 433b9c1b51eSKate Stone lldb::StateType NativeProcessProtocol::GetState() const { 43416ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 435af245d11STodd Fiala return m_state; 436af245d11STodd Fiala } 437af245d11STodd Fiala 438b9c1b51eSKate Stone void NativeProcessProtocol::SetState(lldb::StateType state, 439b9c1b51eSKate Stone bool notify_delegates) { 44016ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 4415830aa75STamas Berghammer 4425830aa75STamas Berghammer if (state == m_state) 4435830aa75STamas Berghammer return; 4445830aa75STamas Berghammer 445af245d11STodd Fiala m_state = state; 446af245d11STodd Fiala 447b9c1b51eSKate Stone if (StateIsStoppedState(state, false)) { 448af245d11STodd Fiala ++m_stop_id; 449af245d11STodd Fiala 450af245d11STodd Fiala // Give process a chance to do any stop id bump processing, such as 451af245d11STodd Fiala // clearing cached data that is invalidated each time the process runs. 452af245d11STodd Fiala // Note if/when we support some threads running, we'll end up needing 453af245d11STodd Fiala // to manage this per thread and per process. 454af245d11STodd Fiala DoStopIDBumped(m_stop_id); 455af245d11STodd Fiala } 456af245d11STodd Fiala 457af245d11STodd Fiala // Optionally notify delegates of the state change. 458af245d11STodd Fiala if (notify_delegates) 459af245d11STodd Fiala SynchronouslyNotifyProcessStateChanged(state); 460af245d11STodd Fiala } 461af245d11STodd Fiala 462b9c1b51eSKate Stone uint32_t NativeProcessProtocol::GetStopID() const { 46316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 464af245d11STodd Fiala return m_stop_id; 465af245d11STodd Fiala } 466af245d11STodd Fiala 467b9c1b51eSKate Stone void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { 468af245d11STodd Fiala // Default implementation does nothing. 469af245d11STodd Fiala } 4708bc34f4dSOleksiy Vyalov 47197206d57SZachary Turner Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, 472b9c1b51eSKate Stone ArchSpec &arch) { 473e77fce0aSTodd Fiala // Grab process info for the running process. 474e77fce0aSTodd Fiala ProcessInstanceInfo process_info; 475e77fce0aSTodd Fiala if (!Host::GetProcessInfo(pid, process_info)) 47697206d57SZachary Turner return Status("failed to get process info"); 477e77fce0aSTodd Fiala 478e77fce0aSTodd Fiala // Resolve the executable module. 479e77fce0aSTodd Fiala ModuleSpecList module_specs; 480b9c1b51eSKate Stone if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, 481b9c1b51eSKate Stone 0, module_specs)) 48297206d57SZachary Turner return Status("failed to get module specifications"); 483e77fce0aSTodd Fiala lldbassert(module_specs.GetSize() == 1); 484e77fce0aSTodd Fiala 485e77fce0aSTodd Fiala arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); 486e77fce0aSTodd Fiala if (arch.IsValid()) 48797206d57SZachary Turner return Status(); 488e77fce0aSTodd Fiala else 48997206d57SZachary Turner return Status( 49097206d57SZachary Turner "failed to retrieve a valid architecture from the exe module"); 491e77fce0aSTodd Fiala } 492e77fce0aSTodd Fiala 493*96e600fcSPavel Labath NativeProcessProtocol::Factory::~Factory() = default; 494