10b57cec5SDimitry Andric //===-- ThreadGDBRemote.cpp -------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "ThreadGDBRemote.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Breakpoint/Watchpoint.h" 120b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 130b57cec5SDimitry Andric #include "lldb/Target/Process.h" 140b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 150b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 160b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h" 170b57cec5SDimitry Andric #include "lldb/Target/Target.h" 180b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h" 190b57cec5SDimitry Andric #include "lldb/Target/Unwind.h" 200b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h" 210b57cec5SDimitry Andric #include "lldb/Utility/State.h" 220b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 230b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #include "ProcessGDBRemote.h" 260b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include <memory> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace lldb; 310b57cec5SDimitry Andric using namespace lldb_private; 320b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric // Thread Registers 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) 370b57cec5SDimitry Andric : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), 380b57cec5SDimitry Andric m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), 390b57cec5SDimitry Andric m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown), 400b57cec5SDimitry Andric m_queue_serial_number(LLDB_INVALID_QUEUE_ID), 410b57cec5SDimitry Andric m_associated_with_libdispatch_queue(eLazyBoolCalculate) { 420b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); 430b57cec5SDimitry Andric LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(), 440b57cec5SDimitry Andric GetID()); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric ThreadGDBRemote::~ThreadGDBRemote() { 480b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 490b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); 500b57cec5SDimitry Andric LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, 510b57cec5SDimitry Andric process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); 520b57cec5SDimitry Andric DestroyThread(); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric const char *ThreadGDBRemote::GetName() { 560b57cec5SDimitry Andric if (m_thread_name.empty()) 570b57cec5SDimitry Andric return nullptr; 580b57cec5SDimitry Andric return m_thread_name.c_str(); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric void ThreadGDBRemote::ClearQueueInfo() { 620b57cec5SDimitry Andric m_dispatch_queue_name.clear(); 630b57cec5SDimitry Andric m_queue_kind = eQueueKindUnknown; 640b57cec5SDimitry Andric m_queue_serial_number = 0; 650b57cec5SDimitry Andric m_dispatch_queue_t = LLDB_INVALID_ADDRESS; 660b57cec5SDimitry Andric m_associated_with_libdispatch_queue = eLazyBoolCalculate; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name, 700b57cec5SDimitry Andric QueueKind queue_kind, uint64_t queue_serial, 710b57cec5SDimitry Andric addr_t dispatch_queue_t, 720b57cec5SDimitry Andric LazyBool associated_with_libdispatch_queue) { 730b57cec5SDimitry Andric m_dispatch_queue_name = queue_name; 740b57cec5SDimitry Andric m_queue_kind = queue_kind; 750b57cec5SDimitry Andric m_queue_serial_number = queue_serial; 760b57cec5SDimitry Andric m_dispatch_queue_t = dispatch_queue_t; 770b57cec5SDimitry Andric m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric const char *ThreadGDBRemote::GetQueueName() { 810b57cec5SDimitry Andric // If our cached queue info is valid, then someone called 820b57cec5SDimitry Andric // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned 830b57cec5SDimitry Andric // from the stop reply packet. In this case we trust that the info is valid 840b57cec5SDimitry Andric // in m_dispatch_queue_name without refetching it 850b57cec5SDimitry Andric if (CachedQueueInfoIsValid()) { 860b57cec5SDimitry Andric if (m_dispatch_queue_name.empty()) 870b57cec5SDimitry Andric return nullptr; 880b57cec5SDimitry Andric else 890b57cec5SDimitry Andric return m_dispatch_queue_name.c_str(); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric // Always re-fetch the dispatch queue name since it can change 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric if (m_associated_with_libdispatch_queue == eLazyBoolNo) 940b57cec5SDimitry Andric return nullptr; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric if (m_thread_dispatch_qaddr != 0 && 970b57cec5SDimitry Andric m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { 980b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 990b57cec5SDimitry Andric if (process_sp) { 1000b57cec5SDimitry Andric SystemRuntime *runtime = process_sp->GetSystemRuntime(); 1010b57cec5SDimitry Andric if (runtime) 1020b57cec5SDimitry Andric m_dispatch_queue_name = 1030b57cec5SDimitry Andric runtime->GetQueueNameFromThreadQAddress(m_thread_dispatch_qaddr); 1040b57cec5SDimitry Andric else 1050b57cec5SDimitry Andric m_dispatch_queue_name.clear(); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric if (!m_dispatch_queue_name.empty()) 1080b57cec5SDimitry Andric return m_dispatch_queue_name.c_str(); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric return nullptr; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric QueueKind ThreadGDBRemote::GetQueueKind() { 1150b57cec5SDimitry Andric // If our cached queue info is valid, then someone called 1160b57cec5SDimitry Andric // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned 1170b57cec5SDimitry Andric // from the stop reply packet. In this case we trust that the info is valid 1180b57cec5SDimitry Andric // in m_dispatch_queue_name without refetching it 1190b57cec5SDimitry Andric if (CachedQueueInfoIsValid()) { 1200b57cec5SDimitry Andric return m_queue_kind; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric if (m_associated_with_libdispatch_queue == eLazyBoolNo) 1240b57cec5SDimitry Andric return eQueueKindUnknown; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric if (m_thread_dispatch_qaddr != 0 && 1270b57cec5SDimitry Andric m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { 1280b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 1290b57cec5SDimitry Andric if (process_sp) { 1300b57cec5SDimitry Andric SystemRuntime *runtime = process_sp->GetSystemRuntime(); 1310b57cec5SDimitry Andric if (runtime) 1320b57cec5SDimitry Andric m_queue_kind = runtime->GetQueueKind(m_thread_dispatch_qaddr); 1330b57cec5SDimitry Andric return m_queue_kind; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric return eQueueKindUnknown; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric queue_id_t ThreadGDBRemote::GetQueueID() { 1400b57cec5SDimitry Andric // If our cached queue info is valid, then someone called 1410b57cec5SDimitry Andric // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned 1420b57cec5SDimitry Andric // from the stop reply packet. In this case we trust that the info is valid 1430b57cec5SDimitry Andric // in m_dispatch_queue_name without refetching it 1440b57cec5SDimitry Andric if (CachedQueueInfoIsValid()) 1450b57cec5SDimitry Andric return m_queue_serial_number; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (m_associated_with_libdispatch_queue == eLazyBoolNo) 1480b57cec5SDimitry Andric return LLDB_INVALID_QUEUE_ID; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (m_thread_dispatch_qaddr != 0 && 1510b57cec5SDimitry Andric m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { 1520b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 1530b57cec5SDimitry Andric if (process_sp) { 1540b57cec5SDimitry Andric SystemRuntime *runtime = process_sp->GetSystemRuntime(); 1550b57cec5SDimitry Andric if (runtime) { 1560b57cec5SDimitry Andric return runtime->GetQueueIDFromThreadQAddress(m_thread_dispatch_qaddr); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric return LLDB_INVALID_QUEUE_ID; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric QueueSP ThreadGDBRemote::GetQueue() { 1640b57cec5SDimitry Andric queue_id_t queue_id = GetQueueID(); 1650b57cec5SDimitry Andric QueueSP queue; 1660b57cec5SDimitry Andric if (queue_id != LLDB_INVALID_QUEUE_ID) { 1670b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 1680b57cec5SDimitry Andric if (process_sp) { 1690b57cec5SDimitry Andric queue = process_sp->GetQueueList().FindQueueByID(queue_id); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric return queue; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric addr_t ThreadGDBRemote::GetQueueLibdispatchQueueAddress() { 1760b57cec5SDimitry Andric if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS) { 1770b57cec5SDimitry Andric if (m_thread_dispatch_qaddr != 0 && 1780b57cec5SDimitry Andric m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { 1790b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 1800b57cec5SDimitry Andric if (process_sp) { 1810b57cec5SDimitry Andric SystemRuntime *runtime = process_sp->GetSystemRuntime(); 1820b57cec5SDimitry Andric if (runtime) { 1830b57cec5SDimitry Andric m_dispatch_queue_t = 1840b57cec5SDimitry Andric runtime->GetLibdispatchQueueAddressFromThreadQAddress( 1850b57cec5SDimitry Andric m_thread_dispatch_qaddr); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric return m_dispatch_queue_t; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric void ThreadGDBRemote::SetQueueLibdispatchQueueAddress( 1940b57cec5SDimitry Andric lldb::addr_t dispatch_queue_t) { 1950b57cec5SDimitry Andric m_dispatch_queue_t = dispatch_queue_t; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric bool ThreadGDBRemote::ThreadHasQueueInformation() const { 1990b57cec5SDimitry Andric return m_thread_dispatch_qaddr != 0 && 2000b57cec5SDimitry Andric m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS && 2010b57cec5SDimitry Andric m_dispatch_queue_t != LLDB_INVALID_ADDRESS && 2020b57cec5SDimitry Andric m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() { 2060b57cec5SDimitry Andric return m_associated_with_libdispatch_queue; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue( 2100b57cec5SDimitry Andric LazyBool associated_with_libdispatch_queue) { 2110b57cec5SDimitry Andric m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { 2150b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 2160b57cec5SDimitry Andric const lldb::user_id_t tid = GetProtocolID(); 2170b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); 218*9dba64beSDimitry Andric LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid); 2190b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 2200b57cec5SDimitry Andric if (process_sp) { 2210b57cec5SDimitry Andric ProcessGDBRemote *gdb_process = 2220b57cec5SDimitry Andric static_cast<ProcessGDBRemote *>(process_sp.get()); 2230b57cec5SDimitry Andric object_sp = gdb_process->GetExtendedInfoForThread(tid); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric return object_sp; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void ThreadGDBRemote::WillResume(StateType resume_state) { 2290b57cec5SDimitry Andric int signo = GetResumeSignal(); 2300b57cec5SDimitry Andric const lldb::user_id_t tid = GetProtocolID(); 2310b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); 232*9dba64beSDimitry Andric LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid, 2330b57cec5SDimitry Andric StateAsCString(resume_state)); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 2360b57cec5SDimitry Andric if (process_sp) { 2370b57cec5SDimitry Andric ProcessGDBRemote *gdb_process = 2380b57cec5SDimitry Andric static_cast<ProcessGDBRemote *>(process_sp.get()); 2390b57cec5SDimitry Andric switch (resume_state) { 2400b57cec5SDimitry Andric case eStateSuspended: 2410b57cec5SDimitry Andric case eStateStopped: 2420b57cec5SDimitry Andric // Don't append anything for threads that should stay stopped. 2430b57cec5SDimitry Andric break; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric case eStateRunning: 2460b57cec5SDimitry Andric if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) 2470b57cec5SDimitry Andric gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo)); 2480b57cec5SDimitry Andric else 2490b57cec5SDimitry Andric gdb_process->m_continue_c_tids.push_back(tid); 2500b57cec5SDimitry Andric break; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric case eStateStepping: 2530b57cec5SDimitry Andric if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) 2540b57cec5SDimitry Andric gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo)); 2550b57cec5SDimitry Andric else 2560b57cec5SDimitry Andric gdb_process->m_continue_s_tids.push_back(tid); 2570b57cec5SDimitry Andric break; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric default: 2600b57cec5SDimitry Andric break; 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void ThreadGDBRemote::RefreshStateAfterStop() { 2660b57cec5SDimitry Andric // Invalidate all registers in our register context. We don't set "force" to 2670b57cec5SDimitry Andric // true because the stop reply packet might have had some register values 2680b57cec5SDimitry Andric // that were expedited and these will already be copied into the register 2690b57cec5SDimitry Andric // context by the time this function gets called. The 2700b57cec5SDimitry Andric // GDBRemoteRegisterContext class has been made smart enough to detect when 2710b57cec5SDimitry Andric // it needs to invalidate which registers are valid by putting hooks in the 2720b57cec5SDimitry Andric // register read and register supply functions where they check the process 2730b57cec5SDimitry Andric // stop ID and do the right thing. 2740b57cec5SDimitry Andric const bool force = false; 2750b57cec5SDimitry Andric GetRegisterContext()->InvalidateIfNeeded(force); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric bool ThreadGDBRemote::ThreadIDIsValid(lldb::tid_t thread) { 2790b57cec5SDimitry Andric return thread != 0; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric void ThreadGDBRemote::Dump(Log *log, uint32_t index) {} 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; } 2850b57cec5SDimitry Andric lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() { 2860b57cec5SDimitry Andric if (!m_reg_context_sp) 2870b57cec5SDimitry Andric m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 2880b57cec5SDimitry Andric return m_reg_context_sp; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric lldb::RegisterContextSP 2920b57cec5SDimitry Andric ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) { 2930b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp; 2940b57cec5SDimitry Andric uint32_t concrete_frame_idx = 0; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (frame) 2970b57cec5SDimitry Andric concrete_frame_idx = frame->GetConcreteFrameIndex(); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric if (concrete_frame_idx == 0) { 3000b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 3010b57cec5SDimitry Andric if (process_sp) { 3020b57cec5SDimitry Andric ProcessGDBRemote *gdb_process = 3030b57cec5SDimitry Andric static_cast<ProcessGDBRemote *>(process_sp.get()); 3040b57cec5SDimitry Andric // read_all_registers_at_once will be true if 'p' packet is not 3050b57cec5SDimitry Andric // supported. 3060b57cec5SDimitry Andric bool read_all_registers_at_once = 3070b57cec5SDimitry Andric !gdb_process->GetGDBRemote().GetpPacketSupported(GetID()); 3080b57cec5SDimitry Andric reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>( 3090b57cec5SDimitry Andric *this, concrete_frame_idx, gdb_process->m_register_info, 3100b57cec5SDimitry Andric read_all_registers_at_once); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric } else { 3130b57cec5SDimitry Andric Unwind *unwinder = GetUnwinder(); 3140b57cec5SDimitry Andric if (unwinder != nullptr) 3150b57cec5SDimitry Andric reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric return reg_ctx_sp; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, 3210b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> data) { 3220b57cec5SDimitry Andric GDBRemoteRegisterContext *gdb_reg_ctx = 3230b57cec5SDimitry Andric static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get()); 3240b57cec5SDimitry Andric assert(gdb_reg_ctx); 3250b57cec5SDimitry Andric return gdb_reg_ctx->PrivateSetRegisterValue(reg, data); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, uint64_t regval) { 3290b57cec5SDimitry Andric GDBRemoteRegisterContext *gdb_reg_ctx = 3300b57cec5SDimitry Andric static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get()); 3310b57cec5SDimitry Andric assert(gdb_reg_ctx); 3320b57cec5SDimitry Andric return gdb_reg_ctx->PrivateSetRegisterValue(reg, regval); 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric bool ThreadGDBRemote::CalculateStopInfo() { 3360b57cec5SDimitry Andric ProcessSP process_sp(GetProcess()); 3370b57cec5SDimitry Andric if (process_sp) 3380b57cec5SDimitry Andric return static_cast<ProcessGDBRemote *>(process_sp.get()) 3390b57cec5SDimitry Andric ->CalculateThreadStopInfo(this); 3400b57cec5SDimitry Andric return false; 3410b57cec5SDimitry Andric } 342