1*0b57cec5SDimitry Andric //===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "lldb/Host/common/NativeProcessProtocol.h" 10*0b57cec5SDimitry Andric #include "lldb/Host/Host.h" 11*0b57cec5SDimitry Andric #include "lldb/Host/common/NativeBreakpointList.h" 12*0b57cec5SDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h" 13*0b57cec5SDimitry Andric #include "lldb/Host/common/NativeThreadProtocol.h" 14*0b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h" 15*0b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 16*0b57cec5SDimitry Andric #include "lldb/Utility/State.h" 17*0b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace lldb; 20*0b57cec5SDimitry Andric using namespace lldb_private; 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric // NativeProcessProtocol Members 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, 25*0b57cec5SDimitry Andric NativeDelegate &delegate) 26*0b57cec5SDimitry Andric : m_pid(pid), m_terminal_fd(terminal_fd) { 27*0b57cec5SDimitry Andric bool registered = RegisterNativeDelegate(delegate); 28*0b57cec5SDimitry Andric assert(registered); 29*0b57cec5SDimitry Andric (void)registered; 30*0b57cec5SDimitry Andric } 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric lldb_private::Status NativeProcessProtocol::Interrupt() { 33*0b57cec5SDimitry Andric Status error; 34*0b57cec5SDimitry Andric #if !defined(SIGSTOP) 35*0b57cec5SDimitry Andric error.SetErrorString("local host does not support signaling"); 36*0b57cec5SDimitry Andric return error; 37*0b57cec5SDimitry Andric #else 38*0b57cec5SDimitry Andric return Signal(SIGSTOP); 39*0b57cec5SDimitry Andric #endif 40*0b57cec5SDimitry Andric } 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric Status NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef<int> signals) { 43*0b57cec5SDimitry Andric m_signals_to_ignore.clear(); 44*0b57cec5SDimitry Andric m_signals_to_ignore.insert(signals.begin(), signals.end()); 45*0b57cec5SDimitry Andric return Status(); 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric lldb_private::Status 49*0b57cec5SDimitry Andric NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, 50*0b57cec5SDimitry Andric MemoryRegionInfo &range_info) { 51*0b57cec5SDimitry Andric // Default: not implemented. 52*0b57cec5SDimitry Andric return Status("not implemented"); 53*0b57cec5SDimitry Andric } 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric llvm::Optional<WaitStatus> NativeProcessProtocol::GetExitStatus() { 56*0b57cec5SDimitry Andric if (m_state == lldb::eStateExited) 57*0b57cec5SDimitry Andric return m_exit_status; 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric return llvm::None; 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric bool NativeProcessProtocol::SetExitStatus(WaitStatus status, 63*0b57cec5SDimitry Andric bool bNotifyStateChange) { 64*0b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 65*0b57cec5SDimitry Andric LLDB_LOG(log, "status = {0}, notify = {1}", status, bNotifyStateChange); 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric // Exit status already set 68*0b57cec5SDimitry Andric if (m_state == lldb::eStateExited) { 69*0b57cec5SDimitry Andric if (m_exit_status) 70*0b57cec5SDimitry Andric LLDB_LOG(log, "exit status already set to {0}", *m_exit_status); 71*0b57cec5SDimitry Andric else 72*0b57cec5SDimitry Andric LLDB_LOG(log, "state is exited, but status not set"); 73*0b57cec5SDimitry Andric return false; 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric m_state = lldb::eStateExited; 77*0b57cec5SDimitry Andric m_exit_status = status; 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric if (bNotifyStateChange) 80*0b57cec5SDimitry Andric SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric return true; 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric NativeThreadProtocol *NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { 86*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 87*0b57cec5SDimitry Andric if (idx < m_threads.size()) 88*0b57cec5SDimitry Andric return m_threads[idx].get(); 89*0b57cec5SDimitry Andric return nullptr; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric NativeThreadProtocol * 93*0b57cec5SDimitry Andric NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { 94*0b57cec5SDimitry Andric for (const auto &thread : m_threads) { 95*0b57cec5SDimitry Andric if (thread->GetID() == tid) 96*0b57cec5SDimitry Andric return thread.get(); 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric return nullptr; 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric NativeThreadProtocol *NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { 102*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 103*0b57cec5SDimitry Andric return GetThreadByIDUnlocked(tid); 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric bool NativeProcessProtocol::IsAlive() const { 107*0b57cec5SDimitry Andric return m_state != eStateDetached && m_state != eStateExited && 108*0b57cec5SDimitry Andric m_state != eStateInvalid && m_state != eStateUnloaded; 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric const NativeWatchpointList::WatchpointMap & 112*0b57cec5SDimitry Andric NativeProcessProtocol::GetWatchpointMap() const { 113*0b57cec5SDimitry Andric return m_watchpoint_list.GetWatchpointMap(); 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric llvm::Optional<std::pair<uint32_t, uint32_t>> 117*0b57cec5SDimitry Andric NativeProcessProtocol::GetHardwareDebugSupportInfo() const { 118*0b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric // get any thread 121*0b57cec5SDimitry Andric NativeThreadProtocol *thread( 122*0b57cec5SDimitry Andric const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); 123*0b57cec5SDimitry Andric if (!thread) { 124*0b57cec5SDimitry Andric LLDB_LOG(log, "failed to find a thread to grab a NativeRegisterContext!"); 125*0b57cec5SDimitry Andric return llvm::None; 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric NativeRegisterContext ®_ctx = thread->GetRegisterContext(); 129*0b57cec5SDimitry Andric return std::make_pair(reg_ctx.NumSupportedHardwareBreakpoints(), 130*0b57cec5SDimitry Andric reg_ctx.NumSupportedHardwareWatchpoints()); 131*0b57cec5SDimitry Andric } 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, 134*0b57cec5SDimitry Andric uint32_t watch_flags, 135*0b57cec5SDimitry Andric bool hardware) { 136*0b57cec5SDimitry Andric // This default implementation assumes setting the watchpoint for the process 137*0b57cec5SDimitry Andric // will require setting the watchpoint for each of the threads. Furthermore, 138*0b57cec5SDimitry Andric // it will track watchpoints set for the process and will add them to each 139*0b57cec5SDimitry Andric // thread that is attached to via the (FIXME implement) OnThreadAttached () 140*0b57cec5SDimitry Andric // method. 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric // Update the thread list 145*0b57cec5SDimitry Andric UpdateThreads(); 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric // Keep track of the threads we successfully set the watchpoint for. If one 148*0b57cec5SDimitry Andric // of the thread watchpoint setting operations fails, back off and remove the 149*0b57cec5SDimitry Andric // watchpoint for all the threads that were successfully set so we get back 150*0b57cec5SDimitry Andric // to a consistent state. 151*0b57cec5SDimitry Andric std::vector<NativeThreadProtocol *> watchpoint_established_threads; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric // Tell each thread to set a watchpoint. In the event that hardware 154*0b57cec5SDimitry Andric // watchpoints are requested but the SetWatchpoint fails, try to set a 155*0b57cec5SDimitry Andric // software watchpoint as a fallback. It's conceivable that if there are 156*0b57cec5SDimitry Andric // more threads than hardware watchpoints available, some of the threads will 157*0b57cec5SDimitry Andric // fail to set hardware watchpoints while software ones may be available. 158*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 159*0b57cec5SDimitry Andric for (const auto &thread : m_threads) { 160*0b57cec5SDimitry Andric assert(thread && "thread list should not have a NULL thread!"); 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric Status thread_error = 163*0b57cec5SDimitry Andric thread->SetWatchpoint(addr, size, watch_flags, hardware); 164*0b57cec5SDimitry Andric if (thread_error.Fail() && hardware) { 165*0b57cec5SDimitry Andric // Try software watchpoints since we failed on hardware watchpoint 166*0b57cec5SDimitry Andric // setting and we may have just run out of hardware watchpoints. 167*0b57cec5SDimitry Andric thread_error = thread->SetWatchpoint(addr, size, watch_flags, false); 168*0b57cec5SDimitry Andric if (thread_error.Success()) 169*0b57cec5SDimitry Andric LLDB_LOG(log, 170*0b57cec5SDimitry Andric "hardware watchpoint requested but software watchpoint set"); 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric if (thread_error.Success()) { 174*0b57cec5SDimitry Andric // Remember that we set this watchpoint successfully in case we need to 175*0b57cec5SDimitry Andric // clear it later. 176*0b57cec5SDimitry Andric watchpoint_established_threads.push_back(thread.get()); 177*0b57cec5SDimitry Andric } else { 178*0b57cec5SDimitry Andric // Unset the watchpoint for each thread we successfully set so that we 179*0b57cec5SDimitry Andric // get back to a consistent state of "not set" for the watchpoint. 180*0b57cec5SDimitry Andric for (auto unwatch_thread_sp : watchpoint_established_threads) { 181*0b57cec5SDimitry Andric Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); 182*0b57cec5SDimitry Andric if (remove_error.Fail()) 183*0b57cec5SDimitry Andric LLDB_LOG(log, "RemoveWatchpoint failed for pid={0}, tid={1}: {2}", 184*0b57cec5SDimitry Andric GetID(), unwatch_thread_sp->GetID(), remove_error); 185*0b57cec5SDimitry Andric } 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric return thread_error; 188*0b57cec5SDimitry Andric } 189*0b57cec5SDimitry Andric } 190*0b57cec5SDimitry Andric return m_watchpoint_list.Add(addr, size, watch_flags, hardware); 191*0b57cec5SDimitry Andric } 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { 194*0b57cec5SDimitry Andric // Update the thread list 195*0b57cec5SDimitry Andric UpdateThreads(); 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric Status overall_error; 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 200*0b57cec5SDimitry Andric for (const auto &thread : m_threads) { 201*0b57cec5SDimitry Andric assert(thread && "thread list should not have a NULL thread!"); 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric const Status thread_error = thread->RemoveWatchpoint(addr); 204*0b57cec5SDimitry Andric if (thread_error.Fail()) { 205*0b57cec5SDimitry Andric // Keep track of the first thread error if any threads fail. We want to 206*0b57cec5SDimitry Andric // try to remove the watchpoint from every thread, though, even if one or 207*0b57cec5SDimitry Andric // more have errors. 208*0b57cec5SDimitry Andric if (!overall_error.Fail()) 209*0b57cec5SDimitry Andric overall_error = thread_error; 210*0b57cec5SDimitry Andric } 211*0b57cec5SDimitry Andric } 212*0b57cec5SDimitry Andric const Status error = m_watchpoint_list.Remove(addr); 213*0b57cec5SDimitry Andric return overall_error.Fail() ? overall_error : error; 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric const HardwareBreakpointMap & 217*0b57cec5SDimitry Andric NativeProcessProtocol::GetHardwareBreakpointMap() const { 218*0b57cec5SDimitry Andric return m_hw_breakpoints_map; 219*0b57cec5SDimitry Andric } 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, 222*0b57cec5SDimitry Andric size_t size) { 223*0b57cec5SDimitry Andric // This default implementation assumes setting a hardware breakpoint for this 224*0b57cec5SDimitry Andric // process will require setting same hardware breakpoint for each of its 225*0b57cec5SDimitry Andric // existing threads. New thread will do the same once created. 226*0b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andric // Update the thread list 229*0b57cec5SDimitry Andric UpdateThreads(); 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric // Exit here if target does not have required hardware breakpoint capability. 232*0b57cec5SDimitry Andric auto hw_debug_cap = GetHardwareDebugSupportInfo(); 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || 235*0b57cec5SDimitry Andric hw_debug_cap->first <= m_hw_breakpoints_map.size()) 236*0b57cec5SDimitry Andric return Status("Target does not have required no of hardware breakpoints"); 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric // Vector below stores all thread pointer for which we have we successfully 239*0b57cec5SDimitry Andric // set this hardware breakpoint. If any of the current process threads fails 240*0b57cec5SDimitry Andric // to set this hardware breakpoint then roll back and remove this breakpoint 241*0b57cec5SDimitry Andric // for all the threads that had already set it successfully. 242*0b57cec5SDimitry Andric std::vector<NativeThreadProtocol *> breakpoint_established_threads; 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric // Request to set a hardware breakpoint for each of current process threads. 245*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 246*0b57cec5SDimitry Andric for (const auto &thread : m_threads) { 247*0b57cec5SDimitry Andric assert(thread && "thread list should not have a NULL thread!"); 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric Status thread_error = thread->SetHardwareBreakpoint(addr, size); 250*0b57cec5SDimitry Andric if (thread_error.Success()) { 251*0b57cec5SDimitry Andric // Remember that we set this breakpoint successfully in case we need to 252*0b57cec5SDimitry Andric // clear it later. 253*0b57cec5SDimitry Andric breakpoint_established_threads.push_back(thread.get()); 254*0b57cec5SDimitry Andric } else { 255*0b57cec5SDimitry Andric // Unset the breakpoint for each thread we successfully set so that we 256*0b57cec5SDimitry Andric // get back to a consistent state of "not set" for this hardware 257*0b57cec5SDimitry Andric // breakpoint. 258*0b57cec5SDimitry Andric for (auto rollback_thread_sp : breakpoint_established_threads) { 259*0b57cec5SDimitry Andric Status remove_error = 260*0b57cec5SDimitry Andric rollback_thread_sp->RemoveHardwareBreakpoint(addr); 261*0b57cec5SDimitry Andric if (remove_error.Fail()) 262*0b57cec5SDimitry Andric LLDB_LOG(log, 263*0b57cec5SDimitry Andric "RemoveHardwareBreakpoint failed for pid={0}, tid={1}: {2}", 264*0b57cec5SDimitry Andric GetID(), rollback_thread_sp->GetID(), remove_error); 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric return thread_error; 268*0b57cec5SDimitry Andric } 269*0b57cec5SDimitry Andric } 270*0b57cec5SDimitry Andric 271*0b57cec5SDimitry Andric // Register new hardware breakpoint into hardware breakpoints map of current 272*0b57cec5SDimitry Andric // process. 273*0b57cec5SDimitry Andric m_hw_breakpoints_map[addr] = {addr, size}; 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric return Status(); 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { 279*0b57cec5SDimitry Andric // Update the thread list 280*0b57cec5SDimitry Andric UpdateThreads(); 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric Status error; 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); 285*0b57cec5SDimitry Andric for (const auto &thread : m_threads) { 286*0b57cec5SDimitry Andric assert(thread && "thread list should not have a NULL thread!"); 287*0b57cec5SDimitry Andric error = thread->RemoveHardwareBreakpoint(addr); 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric // Also remove from hardware breakpoint map of current process. 291*0b57cec5SDimitry Andric m_hw_breakpoints_map.erase(addr); 292*0b57cec5SDimitry Andric 293*0b57cec5SDimitry Andric return error; 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric bool NativeProcessProtocol::RegisterNativeDelegate( 297*0b57cec5SDimitry Andric NativeDelegate &native_delegate) { 298*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 299*0b57cec5SDimitry Andric if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != 300*0b57cec5SDimitry Andric m_delegates.end()) 301*0b57cec5SDimitry Andric return false; 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric m_delegates.push_back(&native_delegate); 304*0b57cec5SDimitry Andric native_delegate.InitializeDelegate(this); 305*0b57cec5SDimitry Andric return true; 306*0b57cec5SDimitry Andric } 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric bool NativeProcessProtocol::UnregisterNativeDelegate( 309*0b57cec5SDimitry Andric NativeDelegate &native_delegate) { 310*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric const auto initial_size = m_delegates.size(); 313*0b57cec5SDimitry Andric m_delegates.erase( 314*0b57cec5SDimitry Andric remove(m_delegates.begin(), m_delegates.end(), &native_delegate), 315*0b57cec5SDimitry Andric m_delegates.end()); 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric // We removed the delegate if the count of delegates shrank after removing 318*0b57cec5SDimitry Andric // all copies of the given native_delegate from the vector. 319*0b57cec5SDimitry Andric return m_delegates.size() < initial_size; 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( 323*0b57cec5SDimitry Andric lldb::StateType state) { 324*0b57cec5SDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 325*0b57cec5SDimitry Andric 326*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 327*0b57cec5SDimitry Andric for (auto native_delegate : m_delegates) 328*0b57cec5SDimitry Andric native_delegate->ProcessStateChanged(this, state); 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric if (log) { 331*0b57cec5SDimitry Andric if (!m_delegates.empty()) { 332*0b57cec5SDimitry Andric log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " 333*0b57cec5SDimitry Andric "from process %" PRIu64, 334*0b57cec5SDimitry Andric __FUNCTION__, lldb_private::StateAsCString(state), GetID()); 335*0b57cec5SDimitry Andric } else { 336*0b57cec5SDimitry Andric log->Printf("NativeProcessProtocol::%s: would send state notification " 337*0b57cec5SDimitry Andric "[%s] from process %" PRIu64 ", but no delegates", 338*0b57cec5SDimitry Andric __FUNCTION__, lldb_private::StateAsCString(state), GetID()); 339*0b57cec5SDimitry Andric } 340*0b57cec5SDimitry Andric } 341*0b57cec5SDimitry Andric } 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric void NativeProcessProtocol::NotifyDidExec() { 344*0b57cec5SDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 345*0b57cec5SDimitry Andric if (log) 346*0b57cec5SDimitry Andric log->Printf("NativeProcessProtocol::%s - preparing to call delegates", 347*0b57cec5SDimitry Andric __FUNCTION__); 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric { 350*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); 351*0b57cec5SDimitry Andric for (auto native_delegate : m_delegates) 352*0b57cec5SDimitry Andric native_delegate->DidExec(this); 353*0b57cec5SDimitry Andric } 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric Status NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, 357*0b57cec5SDimitry Andric uint32_t size_hint) { 358*0b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 359*0b57cec5SDimitry Andric LLDB_LOG(log, "addr = {0:x}, size_hint = {1}", addr, size_hint); 360*0b57cec5SDimitry Andric 361*0b57cec5SDimitry Andric auto it = m_software_breakpoints.find(addr); 362*0b57cec5SDimitry Andric if (it != m_software_breakpoints.end()) { 363*0b57cec5SDimitry Andric ++it->second.ref_count; 364*0b57cec5SDimitry Andric return Status(); 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric auto expected_bkpt = EnableSoftwareBreakpoint(addr, size_hint); 367*0b57cec5SDimitry Andric if (!expected_bkpt) 368*0b57cec5SDimitry Andric return Status(expected_bkpt.takeError()); 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric m_software_breakpoints.emplace(addr, std::move(*expected_bkpt)); 371*0b57cec5SDimitry Andric return Status(); 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric Status NativeProcessProtocol::RemoveSoftwareBreakpoint(lldb::addr_t addr) { 375*0b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 376*0b57cec5SDimitry Andric LLDB_LOG(log, "addr = {0:x}", addr); 377*0b57cec5SDimitry Andric auto it = m_software_breakpoints.find(addr); 378*0b57cec5SDimitry Andric if (it == m_software_breakpoints.end()) 379*0b57cec5SDimitry Andric return Status("Breakpoint not found."); 380*0b57cec5SDimitry Andric assert(it->second.ref_count > 0); 381*0b57cec5SDimitry Andric if (--it->second.ref_count > 0) 382*0b57cec5SDimitry Andric return Status(); 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric // This is the last reference. Let's remove the breakpoint. 385*0b57cec5SDimitry Andric Status error; 386*0b57cec5SDimitry Andric 387*0b57cec5SDimitry Andric // Clear a software breakpoint instruction 388*0b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 4> curr_break_op( 389*0b57cec5SDimitry Andric it->second.breakpoint_opcodes.size(), 0); 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric // Read the breakpoint opcode 392*0b57cec5SDimitry Andric size_t bytes_read = 0; 393*0b57cec5SDimitry Andric error = 394*0b57cec5SDimitry Andric ReadMemory(addr, curr_break_op.data(), curr_break_op.size(), bytes_read); 395*0b57cec5SDimitry Andric if (error.Fail() || bytes_read < curr_break_op.size()) { 396*0b57cec5SDimitry Andric return Status("addr=0x%" PRIx64 397*0b57cec5SDimitry Andric ": tried to read %zu bytes but only read %zu", 398*0b57cec5SDimitry Andric addr, curr_break_op.size(), bytes_read); 399*0b57cec5SDimitry Andric } 400*0b57cec5SDimitry Andric const auto &saved = it->second.saved_opcodes; 401*0b57cec5SDimitry Andric // Make sure the breakpoint opcode exists at this address 402*0b57cec5SDimitry Andric if (makeArrayRef(curr_break_op) != it->second.breakpoint_opcodes) { 403*0b57cec5SDimitry Andric if (curr_break_op != it->second.saved_opcodes) 404*0b57cec5SDimitry Andric return Status("Original breakpoint trap is no longer in memory."); 405*0b57cec5SDimitry Andric LLDB_LOG(log, 406*0b57cec5SDimitry Andric "Saved opcodes ({0:@[x]}) have already been restored at {1:x}.", 407*0b57cec5SDimitry Andric llvm::make_range(saved.begin(), saved.end()), addr); 408*0b57cec5SDimitry Andric } else { 409*0b57cec5SDimitry Andric // We found a valid breakpoint opcode at this address, now restore the 410*0b57cec5SDimitry Andric // saved opcode. 411*0b57cec5SDimitry Andric size_t bytes_written = 0; 412*0b57cec5SDimitry Andric error = WriteMemory(addr, saved.data(), saved.size(), bytes_written); 413*0b57cec5SDimitry Andric if (error.Fail() || bytes_written < saved.size()) { 414*0b57cec5SDimitry Andric return Status("addr=0x%" PRIx64 415*0b57cec5SDimitry Andric ": tried to write %zu bytes but only wrote %zu", 416*0b57cec5SDimitry Andric addr, saved.size(), bytes_written); 417*0b57cec5SDimitry Andric } 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric // Verify that our original opcode made it back to the inferior 420*0b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 4> verify_opcode(saved.size(), 0); 421*0b57cec5SDimitry Andric size_t verify_bytes_read = 0; 422*0b57cec5SDimitry Andric error = ReadMemory(addr, verify_opcode.data(), verify_opcode.size(), 423*0b57cec5SDimitry Andric verify_bytes_read); 424*0b57cec5SDimitry Andric if (error.Fail() || verify_bytes_read < verify_opcode.size()) { 425*0b57cec5SDimitry Andric return Status("addr=0x%" PRIx64 426*0b57cec5SDimitry Andric ": tried to read %zu verification bytes but only read %zu", 427*0b57cec5SDimitry Andric addr, verify_opcode.size(), verify_bytes_read); 428*0b57cec5SDimitry Andric } 429*0b57cec5SDimitry Andric if (verify_opcode != saved) 430*0b57cec5SDimitry Andric LLDB_LOG(log, "Restoring bytes at {0:x}: {1:@[x]}", addr, 431*0b57cec5SDimitry Andric llvm::make_range(saved.begin(), saved.end())); 432*0b57cec5SDimitry Andric } 433*0b57cec5SDimitry Andric 434*0b57cec5SDimitry Andric m_software_breakpoints.erase(it); 435*0b57cec5SDimitry Andric return Status(); 436*0b57cec5SDimitry Andric } 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric llvm::Expected<NativeProcessProtocol::SoftwareBreakpoint> 439*0b57cec5SDimitry Andric NativeProcessProtocol::EnableSoftwareBreakpoint(lldb::addr_t addr, 440*0b57cec5SDimitry Andric uint32_t size_hint) { 441*0b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 442*0b57cec5SDimitry Andric 443*0b57cec5SDimitry Andric auto expected_trap = GetSoftwareBreakpointTrapOpcode(size_hint); 444*0b57cec5SDimitry Andric if (!expected_trap) 445*0b57cec5SDimitry Andric return expected_trap.takeError(); 446*0b57cec5SDimitry Andric 447*0b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 4> saved_opcode_bytes(expected_trap->size(), 0); 448*0b57cec5SDimitry Andric // Save the original opcodes by reading them so we can restore later. 449*0b57cec5SDimitry Andric size_t bytes_read = 0; 450*0b57cec5SDimitry Andric Status error = ReadMemory(addr, saved_opcode_bytes.data(), 451*0b57cec5SDimitry Andric saved_opcode_bytes.size(), bytes_read); 452*0b57cec5SDimitry Andric if (error.Fail()) 453*0b57cec5SDimitry Andric return error.ToError(); 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric // Ensure we read as many bytes as we expected. 456*0b57cec5SDimitry Andric if (bytes_read != saved_opcode_bytes.size()) { 457*0b57cec5SDimitry Andric return llvm::createStringError( 458*0b57cec5SDimitry Andric llvm::inconvertibleErrorCode(), 459*0b57cec5SDimitry Andric "Failed to read memory while attempting to set breakpoint: attempted " 460*0b57cec5SDimitry Andric "to read {0} bytes but only read {1}.", 461*0b57cec5SDimitry Andric saved_opcode_bytes.size(), bytes_read); 462*0b57cec5SDimitry Andric } 463*0b57cec5SDimitry Andric 464*0b57cec5SDimitry Andric LLDB_LOG( 465*0b57cec5SDimitry Andric log, "Overwriting bytes at {0:x}: {1:@[x]}", addr, 466*0b57cec5SDimitry Andric llvm::make_range(saved_opcode_bytes.begin(), saved_opcode_bytes.end())); 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric // Write a software breakpoint in place of the original opcode. 469*0b57cec5SDimitry Andric size_t bytes_written = 0; 470*0b57cec5SDimitry Andric error = WriteMemory(addr, expected_trap->data(), expected_trap->size(), 471*0b57cec5SDimitry Andric bytes_written); 472*0b57cec5SDimitry Andric if (error.Fail()) 473*0b57cec5SDimitry Andric return error.ToError(); 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric // Ensure we wrote as many bytes as we expected. 476*0b57cec5SDimitry Andric if (bytes_written != expected_trap->size()) { 477*0b57cec5SDimitry Andric return llvm::createStringError( 478*0b57cec5SDimitry Andric llvm::inconvertibleErrorCode(), 479*0b57cec5SDimitry Andric "Failed write memory while attempting to set " 480*0b57cec5SDimitry Andric "breakpoint: attempted to write {0} bytes but only wrote {1}", 481*0b57cec5SDimitry Andric expected_trap->size(), bytes_written); 482*0b57cec5SDimitry Andric } 483*0b57cec5SDimitry Andric 484*0b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 4> verify_bp_opcode_bytes(expected_trap->size(), 485*0b57cec5SDimitry Andric 0); 486*0b57cec5SDimitry Andric size_t verify_bytes_read = 0; 487*0b57cec5SDimitry Andric error = ReadMemory(addr, verify_bp_opcode_bytes.data(), 488*0b57cec5SDimitry Andric verify_bp_opcode_bytes.size(), verify_bytes_read); 489*0b57cec5SDimitry Andric if (error.Fail()) 490*0b57cec5SDimitry Andric return error.ToError(); 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric // Ensure we read as many verification bytes as we expected. 493*0b57cec5SDimitry Andric if (verify_bytes_read != verify_bp_opcode_bytes.size()) { 494*0b57cec5SDimitry Andric return llvm::createStringError( 495*0b57cec5SDimitry Andric llvm::inconvertibleErrorCode(), 496*0b57cec5SDimitry Andric "Failed to read memory while " 497*0b57cec5SDimitry Andric "attempting to verify breakpoint: attempted to read {0} bytes " 498*0b57cec5SDimitry Andric "but only read {1}", 499*0b57cec5SDimitry Andric verify_bp_opcode_bytes.size(), verify_bytes_read); 500*0b57cec5SDimitry Andric } 501*0b57cec5SDimitry Andric 502*0b57cec5SDimitry Andric if (llvm::makeArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) != 503*0b57cec5SDimitry Andric *expected_trap) { 504*0b57cec5SDimitry Andric return llvm::createStringError( 505*0b57cec5SDimitry Andric llvm::inconvertibleErrorCode(), 506*0b57cec5SDimitry Andric "Verification of software breakpoint " 507*0b57cec5SDimitry Andric "writing failed - trap opcodes not successfully read back " 508*0b57cec5SDimitry Andric "after writing when setting breakpoint at {0:x}", 509*0b57cec5SDimitry Andric addr); 510*0b57cec5SDimitry Andric } 511*0b57cec5SDimitry Andric 512*0b57cec5SDimitry Andric LLDB_LOG(log, "addr = {0:x}: SUCCESS", addr); 513*0b57cec5SDimitry Andric return SoftwareBreakpoint{1, saved_opcode_bytes, *expected_trap}; 514*0b57cec5SDimitry Andric } 515*0b57cec5SDimitry Andric 516*0b57cec5SDimitry Andric llvm::Expected<llvm::ArrayRef<uint8_t>> 517*0b57cec5SDimitry Andric NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { 518*0b57cec5SDimitry Andric static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; 519*0b57cec5SDimitry Andric static const uint8_t g_i386_opcode[] = {0xCC}; 520*0b57cec5SDimitry Andric static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; 521*0b57cec5SDimitry Andric static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; 522*0b57cec5SDimitry Andric static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; 523*0b57cec5SDimitry Andric static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap 524*0b57cec5SDimitry Andric 525*0b57cec5SDimitry Andric switch (GetArchitecture().GetMachine()) { 526*0b57cec5SDimitry Andric case llvm::Triple::aarch64: 527*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_aarch64_opcode); 528*0b57cec5SDimitry Andric 529*0b57cec5SDimitry Andric case llvm::Triple::x86: 530*0b57cec5SDimitry Andric case llvm::Triple::x86_64: 531*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_i386_opcode); 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric case llvm::Triple::mips: 534*0b57cec5SDimitry Andric case llvm::Triple::mips64: 535*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_mips64_opcode); 536*0b57cec5SDimitry Andric 537*0b57cec5SDimitry Andric case llvm::Triple::mipsel: 538*0b57cec5SDimitry Andric case llvm::Triple::mips64el: 539*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_mips64el_opcode); 540*0b57cec5SDimitry Andric 541*0b57cec5SDimitry Andric case llvm::Triple::systemz: 542*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_s390x_opcode); 543*0b57cec5SDimitry Andric 544*0b57cec5SDimitry Andric case llvm::Triple::ppc64le: 545*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_ppc64le_opcode); 546*0b57cec5SDimitry Andric 547*0b57cec5SDimitry Andric default: 548*0b57cec5SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 549*0b57cec5SDimitry Andric "CPU type not supported!"); 550*0b57cec5SDimitry Andric } 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() { 554*0b57cec5SDimitry Andric switch (GetArchitecture().GetMachine()) { 555*0b57cec5SDimitry Andric case llvm::Triple::x86: 556*0b57cec5SDimitry Andric case llvm::Triple::x86_64: 557*0b57cec5SDimitry Andric case llvm::Triple::systemz: 558*0b57cec5SDimitry Andric // These architectures report increment the PC after breakpoint is hit. 559*0b57cec5SDimitry Andric return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size(); 560*0b57cec5SDimitry Andric 561*0b57cec5SDimitry Andric case llvm::Triple::arm: 562*0b57cec5SDimitry Andric case llvm::Triple::aarch64: 563*0b57cec5SDimitry Andric case llvm::Triple::mips64: 564*0b57cec5SDimitry Andric case llvm::Triple::mips64el: 565*0b57cec5SDimitry Andric case llvm::Triple::mips: 566*0b57cec5SDimitry Andric case llvm::Triple::mipsel: 567*0b57cec5SDimitry Andric case llvm::Triple::ppc64le: 568*0b57cec5SDimitry Andric // On these architectures the PC doesn't get updated for breakpoint hits. 569*0b57cec5SDimitry Andric return 0; 570*0b57cec5SDimitry Andric 571*0b57cec5SDimitry Andric default: 572*0b57cec5SDimitry Andric llvm_unreachable("CPU type not supported!"); 573*0b57cec5SDimitry Andric } 574*0b57cec5SDimitry Andric } 575*0b57cec5SDimitry Andric 576*0b57cec5SDimitry Andric void NativeProcessProtocol::FixupBreakpointPCAsNeeded( 577*0b57cec5SDimitry Andric NativeThreadProtocol &thread) { 578*0b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); 579*0b57cec5SDimitry Andric 580*0b57cec5SDimitry Andric Status error; 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric // Find out the size of a breakpoint (might depend on where we are in the 583*0b57cec5SDimitry Andric // code). 584*0b57cec5SDimitry Andric NativeRegisterContext &context = thread.GetRegisterContext(); 585*0b57cec5SDimitry Andric 586*0b57cec5SDimitry Andric uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset(); 587*0b57cec5SDimitry Andric LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); 588*0b57cec5SDimitry Andric if (breakpoint_size == 0) 589*0b57cec5SDimitry Andric return; 590*0b57cec5SDimitry Andric 591*0b57cec5SDimitry Andric // First try probing for a breakpoint at a software breakpoint location: PC - 592*0b57cec5SDimitry Andric // breakpoint size. 593*0b57cec5SDimitry Andric const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation(); 594*0b57cec5SDimitry Andric lldb::addr_t breakpoint_addr = initial_pc_addr; 595*0b57cec5SDimitry Andric // Do not allow breakpoint probe to wrap around. 596*0b57cec5SDimitry Andric if (breakpoint_addr >= breakpoint_size) 597*0b57cec5SDimitry Andric breakpoint_addr -= breakpoint_size; 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric if (m_software_breakpoints.count(breakpoint_addr) == 0) { 600*0b57cec5SDimitry Andric // We didn't find one at a software probe location. Nothing to do. 601*0b57cec5SDimitry Andric LLDB_LOG(log, 602*0b57cec5SDimitry Andric "pid {0} no lldb software breakpoint found at current pc with " 603*0b57cec5SDimitry Andric "adjustment: {1}", 604*0b57cec5SDimitry Andric GetID(), breakpoint_addr); 605*0b57cec5SDimitry Andric return; 606*0b57cec5SDimitry Andric } 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric // 609*0b57cec5SDimitry Andric // We have a software breakpoint and need to adjust the PC. 610*0b57cec5SDimitry Andric // 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric // Change the program counter. 613*0b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), 614*0b57cec5SDimitry Andric thread.GetID(), initial_pc_addr, breakpoint_addr); 615*0b57cec5SDimitry Andric 616*0b57cec5SDimitry Andric error = context.SetPC(breakpoint_addr); 617*0b57cec5SDimitry Andric if (error.Fail()) { 618*0b57cec5SDimitry Andric // This can happen in case the process was killed between the time we read 619*0b57cec5SDimitry Andric // the PC and when we are updating it. There's nothing better to do than to 620*0b57cec5SDimitry Andric // swallow the error. 621*0b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), 622*0b57cec5SDimitry Andric thread.GetID(), error); 623*0b57cec5SDimitry Andric } 624*0b57cec5SDimitry Andric } 625*0b57cec5SDimitry Andric 626*0b57cec5SDimitry Andric Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, 627*0b57cec5SDimitry Andric bool hardware) { 628*0b57cec5SDimitry Andric if (hardware) 629*0b57cec5SDimitry Andric return RemoveHardwareBreakpoint(addr); 630*0b57cec5SDimitry Andric else 631*0b57cec5SDimitry Andric return RemoveSoftwareBreakpoint(addr); 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric 634*0b57cec5SDimitry Andric Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr, 635*0b57cec5SDimitry Andric void *buf, size_t size, 636*0b57cec5SDimitry Andric size_t &bytes_read) { 637*0b57cec5SDimitry Andric Status error = ReadMemory(addr, buf, size, bytes_read); 638*0b57cec5SDimitry Andric if (error.Fail()) 639*0b57cec5SDimitry Andric return error; 640*0b57cec5SDimitry Andric 641*0b57cec5SDimitry Andric auto data = 642*0b57cec5SDimitry Andric llvm::makeMutableArrayRef(static_cast<uint8_t *>(buf), bytes_read); 643*0b57cec5SDimitry Andric for (const auto &pair : m_software_breakpoints) { 644*0b57cec5SDimitry Andric lldb::addr_t bp_addr = pair.first; 645*0b57cec5SDimitry Andric auto saved_opcodes = makeArrayRef(pair.second.saved_opcodes); 646*0b57cec5SDimitry Andric 647*0b57cec5SDimitry Andric if (bp_addr + saved_opcodes.size() < addr || addr + bytes_read <= bp_addr) 648*0b57cec5SDimitry Andric continue; // Breapoint not in range, ignore 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric if (bp_addr < addr) { 651*0b57cec5SDimitry Andric saved_opcodes = saved_opcodes.drop_front(addr - bp_addr); 652*0b57cec5SDimitry Andric bp_addr = addr; 653*0b57cec5SDimitry Andric } 654*0b57cec5SDimitry Andric auto bp_data = data.drop_front(bp_addr - addr); 655*0b57cec5SDimitry Andric std::copy_n(saved_opcodes.begin(), 656*0b57cec5SDimitry Andric std::min(saved_opcodes.size(), bp_data.size()), 657*0b57cec5SDimitry Andric bp_data.begin()); 658*0b57cec5SDimitry Andric } 659*0b57cec5SDimitry Andric return Status(); 660*0b57cec5SDimitry Andric } 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric lldb::StateType NativeProcessProtocol::GetState() const { 663*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 664*0b57cec5SDimitry Andric return m_state; 665*0b57cec5SDimitry Andric } 666*0b57cec5SDimitry Andric 667*0b57cec5SDimitry Andric void NativeProcessProtocol::SetState(lldb::StateType state, 668*0b57cec5SDimitry Andric bool notify_delegates) { 669*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 670*0b57cec5SDimitry Andric 671*0b57cec5SDimitry Andric if (state == m_state) 672*0b57cec5SDimitry Andric return; 673*0b57cec5SDimitry Andric 674*0b57cec5SDimitry Andric m_state = state; 675*0b57cec5SDimitry Andric 676*0b57cec5SDimitry Andric if (StateIsStoppedState(state, false)) { 677*0b57cec5SDimitry Andric ++m_stop_id; 678*0b57cec5SDimitry Andric 679*0b57cec5SDimitry Andric // Give process a chance to do any stop id bump processing, such as 680*0b57cec5SDimitry Andric // clearing cached data that is invalidated each time the process runs. 681*0b57cec5SDimitry Andric // Note if/when we support some threads running, we'll end up needing to 682*0b57cec5SDimitry Andric // manage this per thread and per process. 683*0b57cec5SDimitry Andric DoStopIDBumped(m_stop_id); 684*0b57cec5SDimitry Andric } 685*0b57cec5SDimitry Andric 686*0b57cec5SDimitry Andric // Optionally notify delegates of the state change. 687*0b57cec5SDimitry Andric if (notify_delegates) 688*0b57cec5SDimitry Andric SynchronouslyNotifyProcessStateChanged(state); 689*0b57cec5SDimitry Andric } 690*0b57cec5SDimitry Andric 691*0b57cec5SDimitry Andric uint32_t NativeProcessProtocol::GetStopID() const { 692*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_state_mutex); 693*0b57cec5SDimitry Andric return m_stop_id; 694*0b57cec5SDimitry Andric } 695*0b57cec5SDimitry Andric 696*0b57cec5SDimitry Andric void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { 697*0b57cec5SDimitry Andric // Default implementation does nothing. 698*0b57cec5SDimitry Andric } 699*0b57cec5SDimitry Andric 700*0b57cec5SDimitry Andric NativeProcessProtocol::Factory::~Factory() = default; 701