231 lines · cpp
1//===-- RegisterContextThreadMemory.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/OperatingSystem.h"10#include "lldb/Target/Process.h"11#include "lldb/Target/Thread.h"12#include "lldb/Utility/Status.h"13#include "lldb/lldb-private.h"14 15#include "RegisterContextThreadMemory.h"16 17using namespace lldb;18using namespace lldb_private;19 20RegisterContextThreadMemory::RegisterContextThreadMemory(21 Thread &thread, lldb::addr_t register_data_addr)22 : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),23 m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}24 25RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;26 27void RegisterContextThreadMemory::UpdateRegisterContext() {28 std::lock_guard<std::mutex> lock(m_update_register_ctx_lock);29 30 ThreadSP thread_sp(m_thread_wp.lock());31 if (thread_sp) {32 ProcessSP process_sp(thread_sp->GetProcess());33 34 if (process_sp) {35 const uint32_t stop_id = process_sp->GetModID().GetStopID();36 if (m_stop_id != stop_id) {37 m_stop_id = stop_id;38 m_reg_ctx_sp.reset();39 }40 if (!m_reg_ctx_sp) {41 ThreadSP backing_thread_sp(thread_sp->GetBackingThread());42 if (backing_thread_sp) {43 m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();44 } else {45 OperatingSystem *os = process_sp->GetOperatingSystem();46 if (os->IsOperatingSystemPluginThread(thread_sp))47 m_reg_ctx_sp = os->CreateRegisterContextForThread(48 thread_sp.get(), m_register_data_addr);49 }50 }51 } else {52 m_reg_ctx_sp.reset();53 }54 } else {55 m_reg_ctx_sp.reset();56 }57}58 59// Subclasses must override these functions60void RegisterContextThreadMemory::InvalidateAllRegisters() {61 UpdateRegisterContext();62 if (m_reg_ctx_sp)63 m_reg_ctx_sp->InvalidateAllRegisters();64}65 66size_t RegisterContextThreadMemory::GetRegisterCount() {67 UpdateRegisterContext();68 if (m_reg_ctx_sp)69 return m_reg_ctx_sp->GetRegisterCount();70 return 0;71}72 73const RegisterInfo *74RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {75 UpdateRegisterContext();76 if (m_reg_ctx_sp)77 return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);78 return nullptr;79}80 81size_t RegisterContextThreadMemory::GetRegisterSetCount() {82 UpdateRegisterContext();83 if (m_reg_ctx_sp)84 return m_reg_ctx_sp->GetRegisterSetCount();85 return 0;86}87 88const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {89 UpdateRegisterContext();90 if (m_reg_ctx_sp)91 return m_reg_ctx_sp->GetRegisterSet(reg_set);92 return nullptr;93}94 95bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,96 RegisterValue ®_value) {97 UpdateRegisterContext();98 if (m_reg_ctx_sp)99 return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);100 return false;101}102 103bool RegisterContextThreadMemory::WriteRegister(104 const RegisterInfo *reg_info, const RegisterValue ®_value) {105 UpdateRegisterContext();106 if (m_reg_ctx_sp)107 return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);108 return false;109}110 111bool RegisterContextThreadMemory::ReadAllRegisterValues(112 lldb::WritableDataBufferSP &data_sp) {113 UpdateRegisterContext();114 if (m_reg_ctx_sp)115 return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);116 return false;117}118 119bool RegisterContextThreadMemory::ReadAllRegisterValues(120 lldb_private::RegisterCheckpoint ®_checkpoint) {121 UpdateRegisterContext();122 if (m_reg_ctx_sp)123 return m_reg_ctx_sp->ReadAllRegisterValues(reg_checkpoint);124 return false;125}126 127bool RegisterContextThreadMemory::WriteAllRegisterValues(128 const lldb::DataBufferSP &data_sp) {129 UpdateRegisterContext();130 if (m_reg_ctx_sp)131 return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);132 return false;133}134 135bool RegisterContextThreadMemory::WriteAllRegisterValues(136 const lldb_private::RegisterCheckpoint ®_checkpoint) {137 UpdateRegisterContext();138 if (m_reg_ctx_sp)139 return m_reg_ctx_sp->WriteAllRegisterValues(reg_checkpoint);140 return false;141}142 143bool RegisterContextThreadMemory::CopyFromRegisterContext(144 lldb::RegisterContextSP reg_ctx_sp) {145 UpdateRegisterContext();146 if (m_reg_ctx_sp)147 return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);148 return false;149}150 151uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(152 lldb::RegisterKind kind, uint32_t num) {153 UpdateRegisterContext();154 if (m_reg_ctx_sp)155 return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);156 return LLDB_INVALID_REGNUM;157}158 159uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {160 UpdateRegisterContext();161 if (m_reg_ctx_sp)162 return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();163 return 0;164}165 166uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,167 size_t size) {168 UpdateRegisterContext();169 if (m_reg_ctx_sp)170 return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);171 return 0;172}173 174bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {175 UpdateRegisterContext();176 if (m_reg_ctx_sp)177 return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);178 return false;179}180 181uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {182 UpdateRegisterContext();183 if (m_reg_ctx_sp)184 return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();185 return 0;186}187 188uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,189 size_t size,190 bool read,191 bool write) {192 UpdateRegisterContext();193 if (m_reg_ctx_sp)194 return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);195 return 0;196}197 198bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {199 UpdateRegisterContext();200 if (m_reg_ctx_sp)201 return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);202 return false;203}204 205bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {206 UpdateRegisterContext();207 if (m_reg_ctx_sp)208 return m_reg_ctx_sp->HardwareSingleStep(enable);209 return false;210}211 212Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(213 const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,214 uint32_t src_len, RegisterValue ®_value) {215 UpdateRegisterContext();216 if (m_reg_ctx_sp)217 return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,218 src_len, reg_value);219 return Status::FromErrorString("invalid register context");220}221 222Status RegisterContextThreadMemory::WriteRegisterValueToMemory(223 const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,224 uint32_t dst_len, const RegisterValue ®_value) {225 UpdateRegisterContext();226 if (m_reg_ctx_sp)227 return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,228 reg_value);229 return Status::FromErrorString("invalid register context");230}231