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 10af245d11STodd Fiala #include "NativeProcessProtocol.h" 11af245d11STodd Fiala 12af245d11STodd Fiala #include "lldb/lldb-enumerations.h" 13af245d11STodd Fiala #include "lldb/Core/ArchSpec.h" 14af245d11STodd Fiala #include "lldb/Core/Log.h" 15af245d11STodd Fiala #include "lldb/Core/State.h" 16*511e5cdcSTodd Fiala #include "lldb/Host/Host.h" 17af245d11STodd Fiala #include "lldb/Target/NativeRegisterContext.h" 18af245d11STodd Fiala 19af245d11STodd Fiala #include "NativeThreadProtocol.h" 20af245d11STodd Fiala #include "SoftwareBreakpoint.h" 21af245d11STodd Fiala 22af245d11STodd Fiala using namespace lldb; 23af245d11STodd Fiala using namespace lldb_private; 24af245d11STodd Fiala 25af245d11STodd Fiala // ----------------------------------------------------------------------------- 26af245d11STodd Fiala // NativeProcessProtocol Members 27af245d11STodd Fiala // ----------------------------------------------------------------------------- 28af245d11STodd Fiala 29af245d11STodd Fiala NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) : 30af245d11STodd Fiala m_pid (pid), 31af245d11STodd Fiala m_threads (), 32af245d11STodd Fiala m_current_thread_id (LLDB_INVALID_THREAD_ID), 33af245d11STodd Fiala m_threads_mutex (Mutex::eMutexTypeRecursive), 34af245d11STodd Fiala m_state (lldb::eStateInvalid), 35af245d11STodd Fiala m_state_mutex (Mutex::eMutexTypeRecursive), 36af245d11STodd Fiala m_exit_type (eExitTypeInvalid), 37af245d11STodd Fiala m_exit_status (0), 38af245d11STodd Fiala m_exit_description (), 39af245d11STodd Fiala m_delegates_mutex (Mutex::eMutexTypeRecursive), 40af245d11STodd Fiala m_delegates (), 41af245d11STodd Fiala m_breakpoint_list (), 42af245d11STodd Fiala m_terminal_fd (-1), 43af245d11STodd Fiala m_stop_id (0) 44af245d11STodd Fiala { 45af245d11STodd Fiala } 46af245d11STodd Fiala 47af245d11STodd Fiala lldb_private::Error 48*511e5cdcSTodd Fiala NativeProcessProtocol::Interrupt () 49*511e5cdcSTodd Fiala { 50*511e5cdcSTodd Fiala Error error; 51*511e5cdcSTodd Fiala #if !defined (SIGSTOP) 52*511e5cdcSTodd Fiala error.SetErrorString ("local host does not support signaling"); 53*511e5cdcSTodd Fiala return error; 54*511e5cdcSTodd Fiala #else 55*511e5cdcSTodd Fiala return Signal (SIGSTOP); 56*511e5cdcSTodd Fiala #endif 57*511e5cdcSTodd Fiala } 58*511e5cdcSTodd Fiala 59*511e5cdcSTodd Fiala lldb_private::Error 60af245d11STodd Fiala NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) 61af245d11STodd Fiala { 62af245d11STodd Fiala // Default: not implemented. 63af245d11STodd Fiala return Error ("not implemented"); 64af245d11STodd Fiala } 65af245d11STodd Fiala 66af245d11STodd Fiala bool 67af245d11STodd Fiala NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description) 68af245d11STodd Fiala { 69af245d11STodd Fiala if (m_state == lldb::eStateExited) 70af245d11STodd Fiala { 71af245d11STodd Fiala *exit_type = m_exit_type; 72af245d11STodd Fiala *status = m_exit_status; 73af245d11STodd Fiala exit_description = m_exit_description; 74af245d11STodd Fiala return true; 75af245d11STodd Fiala } 76af245d11STodd Fiala 77af245d11STodd Fiala *status = 0; 78af245d11STodd Fiala return false; 79af245d11STodd Fiala } 80af245d11STodd Fiala 81af245d11STodd Fiala bool 82af245d11STodd Fiala NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange) 83af245d11STodd Fiala { 84af245d11STodd Fiala Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 85af245d11STodd Fiala if (log) 86af245d11STodd Fiala log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called", 87af245d11STodd Fiala __FUNCTION__, 88af245d11STodd Fiala exit_type, 89af245d11STodd Fiala status, 90af245d11STodd Fiala exit_description ? exit_description : "nullptr", 91af245d11STodd Fiala bNotifyStateChange ? "true" : "false"); 92af245d11STodd Fiala 93af245d11STodd Fiala // Exit status already set 94af245d11STodd Fiala if (m_state == lldb::eStateExited) 95af245d11STodd Fiala { 96af245d11STodd Fiala if (log) 97af245d11STodd Fiala log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status); 98af245d11STodd Fiala return false; 99af245d11STodd Fiala } 100af245d11STodd Fiala 101af245d11STodd Fiala m_state = lldb::eStateExited; 102af245d11STodd Fiala 103af245d11STodd Fiala m_exit_type = exit_type; 104af245d11STodd Fiala m_exit_status = status; 105af245d11STodd Fiala if (exit_description && exit_description[0]) 106af245d11STodd Fiala m_exit_description = exit_description; 107af245d11STodd Fiala else 108af245d11STodd Fiala m_exit_description.clear(); 109af245d11STodd Fiala 110af245d11STodd Fiala if (bNotifyStateChange) 111af245d11STodd Fiala SynchronouslyNotifyProcessStateChanged (lldb::eStateExited); 112af245d11STodd Fiala 113af245d11STodd Fiala return true; 114af245d11STodd Fiala } 115af245d11STodd Fiala 116af245d11STodd Fiala NativeThreadProtocolSP 117af245d11STodd Fiala NativeProcessProtocol::GetThreadAtIndex (uint32_t idx) 118af245d11STodd Fiala { 119af245d11STodd Fiala Mutex::Locker locker (m_threads_mutex); 120af245d11STodd Fiala if (idx < m_threads.size ()) 121af245d11STodd Fiala return m_threads[idx]; 122af245d11STodd Fiala return NativeThreadProtocolSP (); 123af245d11STodd Fiala } 124af245d11STodd Fiala 125af245d11STodd Fiala NativeThreadProtocolSP 126*511e5cdcSTodd Fiala NativeProcessProtocol::GetThreadByIDUnlocked (lldb::tid_t tid) 127af245d11STodd Fiala { 128af245d11STodd Fiala for (auto thread_sp : m_threads) 129af245d11STodd Fiala { 130af245d11STodd Fiala if (thread_sp->GetID() == tid) 131af245d11STodd Fiala return thread_sp; 132af245d11STodd Fiala } 133af245d11STodd Fiala return NativeThreadProtocolSP (); 134af245d11STodd Fiala } 135af245d11STodd Fiala 136*511e5cdcSTodd Fiala NativeThreadProtocolSP 137*511e5cdcSTodd Fiala NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) 138*511e5cdcSTodd Fiala { 139*511e5cdcSTodd Fiala Mutex::Locker locker (m_threads_mutex); 140*511e5cdcSTodd Fiala return GetThreadByIDUnlocked (tid); 141*511e5cdcSTodd Fiala } 142*511e5cdcSTodd Fiala 143af245d11STodd Fiala bool 144af245d11STodd Fiala NativeProcessProtocol::IsAlive () const 145af245d11STodd Fiala { 146af245d11STodd Fiala return m_state != eStateDetached 147af245d11STodd Fiala && m_state != eStateExited 148af245d11STodd Fiala && m_state != eStateInvalid 149af245d11STodd Fiala && m_state != eStateUnloaded; 150af245d11STodd Fiala } 151af245d11STodd Fiala 152af245d11STodd Fiala bool 153af245d11STodd Fiala NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const 154af245d11STodd Fiala { 155af245d11STodd Fiala ArchSpec process_arch; 156af245d11STodd Fiala if (!GetArchitecture (process_arch)) 157af245d11STodd Fiala return false; 158af245d11STodd Fiala byte_order = process_arch.GetByteOrder (); 159af245d11STodd Fiala return true; 160af245d11STodd Fiala } 161af245d11STodd Fiala 162af245d11STodd Fiala uint32_t 163af245d11STodd Fiala NativeProcessProtocol::GetMaxWatchpoints () const 164af245d11STodd Fiala { 165af245d11STodd Fiala // This default implementation will return the number of 166af245d11STodd Fiala // *hardware* breakpoints available. MacOSX and other OS 167af245d11STodd Fiala // implementations that support software breakpoints will want to 168af245d11STodd Fiala // override this correctly for their implementation. 169af245d11STodd Fiala Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 170af245d11STodd Fiala 171af245d11STodd Fiala // get any thread 172af245d11STodd Fiala NativeThreadProtocolSP thread_sp (const_cast<NativeProcessProtocol*> (this)->GetThreadAtIndex (0)); 173af245d11STodd Fiala if (!thread_sp) 174af245d11STodd Fiala { 175af245d11STodd Fiala if (log) 176af245d11STodd Fiala log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__); 177af245d11STodd Fiala return 0; 178af245d11STodd Fiala } 179af245d11STodd Fiala 180af245d11STodd Fiala NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ()); 181af245d11STodd Fiala if (!reg_ctx_sp) 182af245d11STodd Fiala { 183af245d11STodd Fiala if (log) 184af245d11STodd Fiala log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__); 185af245d11STodd Fiala return 0; 186af245d11STodd Fiala } 187af245d11STodd Fiala 188af245d11STodd Fiala return reg_ctx_sp->NumSupportedHardwareWatchpoints (); 189af245d11STodd Fiala } 190af245d11STodd Fiala 191af245d11STodd Fiala Error 192af245d11STodd Fiala NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) 193af245d11STodd Fiala { 194af245d11STodd Fiala // This default implementation assumes setting the watchpoint for 195af245d11STodd Fiala // the process will require setting the watchpoint for each of the 196af245d11STodd Fiala // threads. Furthermore, it will track watchpoints set for the 197af245d11STodd Fiala // process and will add them to each thread that is attached to 198af245d11STodd Fiala // via the (FIXME implement) OnThreadAttached () method. 199af245d11STodd Fiala 200af245d11STodd Fiala Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 201af245d11STodd Fiala 202af245d11STodd Fiala // FIXME save the watchpoint on the set of process watchpoint vars 203af245d11STodd Fiala // so we can add them to a thread each time a new thread is registered. 204af245d11STodd Fiala 205af245d11STodd Fiala // Update the thread list 206af245d11STodd Fiala UpdateThreads (); 207af245d11STodd Fiala 208af245d11STodd Fiala // Keep track of the threads we successfully set the watchpoint 209af245d11STodd Fiala // for. If one of the thread watchpoint setting operations fails, 210af245d11STodd Fiala // back off and remove the watchpoint for all the threads that 211af245d11STodd Fiala // were successfully set so we get back to a consistent state. 212af245d11STodd Fiala std::vector<NativeThreadProtocolSP> watchpoint_established_threads; 213af245d11STodd Fiala 214af245d11STodd Fiala // Tell each thread to set a watchpoint. In the event that 215af245d11STodd Fiala // hardware watchpoints are requested but the SetWatchpoint fails, 216af245d11STodd Fiala // try to set a software watchpoint as a fallback. It's 217af245d11STodd Fiala // conceivable that if there are more threads than hardware 218af245d11STodd Fiala // watchpoints available, some of the threads will fail to set 219af245d11STodd Fiala // hardware watchpoints while software ones may be available. 220af245d11STodd Fiala Mutex::Locker locker (m_threads_mutex); 221af245d11STodd Fiala for (auto thread_sp : m_threads) 222af245d11STodd Fiala { 223af245d11STodd Fiala assert (thread_sp && "thread list should not have a NULL thread!"); 224af245d11STodd Fiala if (!thread_sp) 225af245d11STodd Fiala continue; 226af245d11STodd Fiala 227af245d11STodd Fiala Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware); 228af245d11STodd Fiala if (thread_error.Fail () && hardware) 229af245d11STodd Fiala { 230af245d11STodd Fiala // Try software watchpoints since we failed on hardware watchpoint setting 231af245d11STodd Fiala // and we may have just run out of hardware watchpoints. 232af245d11STodd Fiala thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false); 233af245d11STodd Fiala if (thread_error.Success ()) 234af245d11STodd Fiala { 235af245d11STodd Fiala if (log) 236af245d11STodd Fiala log->Warning ("hardware watchpoint requested but software watchpoint set"); 237af245d11STodd Fiala } 238af245d11STodd Fiala } 239af245d11STodd Fiala 240af245d11STodd Fiala if (thread_error.Success ()) 241af245d11STodd Fiala { 242af245d11STodd Fiala // Remember that we set this watchpoint successfully in 243af245d11STodd Fiala // case we need to clear it later. 244af245d11STodd Fiala watchpoint_established_threads.push_back (thread_sp); 245af245d11STodd Fiala } 246af245d11STodd Fiala else 247af245d11STodd Fiala { 248af245d11STodd Fiala // Unset the watchpoint for each thread we successfully 249af245d11STodd Fiala // set so that we get back to a consistent state of "not 250af245d11STodd Fiala // set" for the watchpoint. 251af245d11STodd Fiala for (auto unwatch_thread_sp : watchpoint_established_threads) 252af245d11STodd Fiala { 253af245d11STodd Fiala Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr); 254af245d11STodd Fiala if (remove_error.Fail () && log) 255af245d11STodd Fiala { 256af245d11STodd Fiala log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", 257af245d11STodd Fiala __FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ()); 258af245d11STodd Fiala } 259af245d11STodd Fiala } 260af245d11STodd Fiala 261af245d11STodd Fiala return thread_error; 262af245d11STodd Fiala } 263af245d11STodd Fiala } 264af245d11STodd Fiala return Error (); 265af245d11STodd Fiala } 266af245d11STodd Fiala 267af245d11STodd Fiala Error 268af245d11STodd Fiala NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) 269af245d11STodd Fiala { 270af245d11STodd Fiala // FIXME remove the watchpoint on the set of process watchpoint vars 271af245d11STodd Fiala // so we can add them to a thread each time a new thread is registered. 272af245d11STodd Fiala 273af245d11STodd Fiala // Update the thread list 274af245d11STodd Fiala UpdateThreads (); 275af245d11STodd Fiala 276af245d11STodd Fiala Error overall_error; 277af245d11STodd Fiala 278af245d11STodd Fiala Mutex::Locker locker (m_threads_mutex); 279af245d11STodd Fiala for (auto thread_sp : m_threads) 280af245d11STodd Fiala { 281af245d11STodd Fiala assert (thread_sp && "thread list should not have a NULL thread!"); 282af245d11STodd Fiala if (!thread_sp) 283af245d11STodd Fiala continue; 284af245d11STodd Fiala 285af245d11STodd Fiala const Error thread_error = thread_sp->RemoveWatchpoint (addr); 286af245d11STodd Fiala if (thread_error.Fail ()) 287af245d11STodd Fiala { 288af245d11STodd Fiala // Keep track of the first thread error if any threads 289af245d11STodd Fiala // fail. We want to try to remove the watchpoint from 290af245d11STodd Fiala // every thread, though, even if one or more have errors. 291af245d11STodd Fiala if (!overall_error.Fail ()) 292af245d11STodd Fiala overall_error = thread_error; 293af245d11STodd Fiala } 294af245d11STodd Fiala } 295af245d11STodd Fiala return overall_error; 296af245d11STodd Fiala } 297af245d11STodd Fiala 298af245d11STodd Fiala bool 299af245d11STodd Fiala NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate) 300af245d11STodd Fiala { 301af245d11STodd Fiala Mutex::Locker locker (m_delegates_mutex); 302af245d11STodd Fiala if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ()) 303af245d11STodd Fiala return false; 304af245d11STodd Fiala 305af245d11STodd Fiala m_delegates.push_back (&native_delegate); 306af245d11STodd Fiala native_delegate.InitializeDelegate (this); 307af245d11STodd Fiala return true; 308af245d11STodd Fiala } 309af245d11STodd Fiala 310af245d11STodd Fiala bool 311af245d11STodd Fiala NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate) 312af245d11STodd Fiala { 313af245d11STodd Fiala Mutex::Locker locker (m_delegates_mutex); 314af245d11STodd Fiala 315af245d11STodd Fiala const auto initial_size = m_delegates.size (); 316af245d11STodd Fiala m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ()); 317af245d11STodd Fiala 318af245d11STodd Fiala // We removed the delegate if the count of delegates shrank after 319af245d11STodd Fiala // removing all copies of the given native_delegate from the vector. 320af245d11STodd Fiala return m_delegates.size () < initial_size; 321af245d11STodd Fiala } 322af245d11STodd Fiala 323af245d11STodd Fiala void 324af245d11STodd Fiala NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state) 325af245d11STodd Fiala { 326af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 327af245d11STodd Fiala 328af245d11STodd Fiala Mutex::Locker locker (m_delegates_mutex); 329af245d11STodd Fiala for (auto native_delegate: m_delegates) 330af245d11STodd Fiala native_delegate->ProcessStateChanged (this, state); 331af245d11STodd Fiala 332af245d11STodd Fiala if (log) 333af245d11STodd Fiala { 334af245d11STodd Fiala if (!m_delegates.empty ()) 335af245d11STodd Fiala { 336af245d11STodd Fiala log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64, 337af245d11STodd Fiala __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); 338af245d11STodd Fiala } 339af245d11STodd Fiala else 340af245d11STodd Fiala { 341af245d11STodd Fiala log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates", 342af245d11STodd Fiala __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); 343af245d11STodd Fiala } 344af245d11STodd Fiala } 345af245d11STodd Fiala } 346af245d11STodd Fiala 347a9882ceeSTodd Fiala void 348a9882ceeSTodd Fiala NativeProcessProtocol::NotifyDidExec () 349a9882ceeSTodd Fiala { 350a9882ceeSTodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 351a9882ceeSTodd Fiala if (log) 352a9882ceeSTodd Fiala log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); 353a9882ceeSTodd Fiala 354a9882ceeSTodd Fiala { 355a9882ceeSTodd Fiala Mutex::Locker locker (m_delegates_mutex); 356a9882ceeSTodd Fiala for (auto native_delegate: m_delegates) 357a9882ceeSTodd Fiala native_delegate->DidExec (this); 358a9882ceeSTodd Fiala } 359a9882ceeSTodd Fiala } 360a9882ceeSTodd Fiala 361a9882ceeSTodd Fiala 362af245d11STodd Fiala Error 363af245d11STodd Fiala NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint) 364af245d11STodd Fiala { 365af245d11STodd Fiala Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 366af245d11STodd Fiala if (log) 367af245d11STodd Fiala log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr); 368af245d11STodd Fiala 369af245d11STodd Fiala return m_breakpoint_list.AddRef (addr, size_hint, false, 370af245d11STodd Fiala [this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error 371af245d11STodd Fiala { return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); }); 372af245d11STodd Fiala } 373af245d11STodd Fiala 374af245d11STodd Fiala Error 375af245d11STodd Fiala NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr) 376af245d11STodd Fiala { 377af245d11STodd Fiala return m_breakpoint_list.DecRef (addr); 378af245d11STodd Fiala } 379af245d11STodd Fiala 380af245d11STodd Fiala Error 381af245d11STodd Fiala NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr) 382af245d11STodd Fiala { 383af245d11STodd Fiala return m_breakpoint_list.EnableBreakpoint (addr); 384af245d11STodd Fiala } 385af245d11STodd Fiala 386af245d11STodd Fiala Error 387af245d11STodd Fiala NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr) 388af245d11STodd Fiala { 389af245d11STodd Fiala return m_breakpoint_list.DisableBreakpoint (addr); 390af245d11STodd Fiala } 391af245d11STodd Fiala 392af245d11STodd Fiala lldb::StateType 393af245d11STodd Fiala NativeProcessProtocol::GetState () const 394af245d11STodd Fiala { 395af245d11STodd Fiala Mutex::Locker locker (m_state_mutex); 396af245d11STodd Fiala return m_state; 397af245d11STodd Fiala } 398af245d11STodd Fiala 399af245d11STodd Fiala void 400af245d11STodd Fiala NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates) 401af245d11STodd Fiala { 402af245d11STodd Fiala Mutex::Locker locker (m_state_mutex); 403af245d11STodd Fiala m_state = state; 404af245d11STodd Fiala 405af245d11STodd Fiala if (StateIsStoppedState (state, false)) 406af245d11STodd Fiala { 407af245d11STodd Fiala ++m_stop_id; 408af245d11STodd Fiala 409af245d11STodd Fiala // Give process a chance to do any stop id bump processing, such as 410af245d11STodd Fiala // clearing cached data that is invalidated each time the process runs. 411af245d11STodd Fiala // Note if/when we support some threads running, we'll end up needing 412af245d11STodd Fiala // to manage this per thread and per process. 413af245d11STodd Fiala DoStopIDBumped (m_stop_id); 414af245d11STodd Fiala } 415af245d11STodd Fiala 416af245d11STodd Fiala // Optionally notify delegates of the state change. 417af245d11STodd Fiala if (notify_delegates) 418af245d11STodd Fiala SynchronouslyNotifyProcessStateChanged (state); 419af245d11STodd Fiala } 420af245d11STodd Fiala 421af245d11STodd Fiala uint32_t NativeProcessProtocol::GetStopID () const 422af245d11STodd Fiala { 423af245d11STodd Fiala Mutex::Locker locker (m_state_mutex); 424af245d11STodd Fiala return m_stop_id; 425af245d11STodd Fiala } 426af245d11STodd Fiala 427af245d11STodd Fiala void 428af245d11STodd Fiala NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */) 429af245d11STodd Fiala { 430af245d11STodd Fiala // Default implementation does nothing. 431af245d11STodd Fiala } 432