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