15ffd83dbSDimitry Andric //===-- RegisterContextThreadMemory.cpp -----------------------------------===//
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 "lldb/Target/OperatingSystem.h"
100b57cec5SDimitry Andric #include "lldb/Target/Process.h"
110b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
120b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
130b57cec5SDimitry Andric #include "lldb/lldb-private.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "RegisterContextThreadMemory.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric using namespace lldb;
180b57cec5SDimitry Andric using namespace lldb_private;
190b57cec5SDimitry Andric
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)200b57cec5SDimitry Andric RegisterContextThreadMemory::RegisterContextThreadMemory(
210b57cec5SDimitry Andric Thread &thread, lldb::addr_t register_data_addr)
220b57cec5SDimitry Andric : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
230b57cec5SDimitry Andric m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
240b57cec5SDimitry Andric
25*5f7ddb14SDimitry Andric RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
260b57cec5SDimitry Andric
UpdateRegisterContext()270b57cec5SDimitry Andric void RegisterContextThreadMemory::UpdateRegisterContext() {
280b57cec5SDimitry Andric ThreadSP thread_sp(m_thread_wp.lock());
290b57cec5SDimitry Andric if (thread_sp) {
300b57cec5SDimitry Andric ProcessSP process_sp(thread_sp->GetProcess());
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric if (process_sp) {
330b57cec5SDimitry Andric const uint32_t stop_id = process_sp->GetModID().GetStopID();
340b57cec5SDimitry Andric if (m_stop_id != stop_id) {
350b57cec5SDimitry Andric m_stop_id = stop_id;
360b57cec5SDimitry Andric m_reg_ctx_sp.reset();
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric if (!m_reg_ctx_sp) {
390b57cec5SDimitry Andric ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
400b57cec5SDimitry Andric if (backing_thread_sp) {
410b57cec5SDimitry Andric m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
420b57cec5SDimitry Andric } else {
430b57cec5SDimitry Andric OperatingSystem *os = process_sp->GetOperatingSystem();
440b57cec5SDimitry Andric if (os->IsOperatingSystemPluginThread(thread_sp))
450b57cec5SDimitry Andric m_reg_ctx_sp = os->CreateRegisterContextForThread(
460b57cec5SDimitry Andric thread_sp.get(), m_register_data_addr);
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric } else {
500b57cec5SDimitry Andric m_reg_ctx_sp.reset();
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric } else {
530b57cec5SDimitry Andric m_reg_ctx_sp.reset();
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric // Subclasses must override these functions
InvalidateAllRegisters()580b57cec5SDimitry Andric void RegisterContextThreadMemory::InvalidateAllRegisters() {
590b57cec5SDimitry Andric UpdateRegisterContext();
600b57cec5SDimitry Andric if (m_reg_ctx_sp)
610b57cec5SDimitry Andric m_reg_ctx_sp->InvalidateAllRegisters();
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric
GetRegisterCount()640b57cec5SDimitry Andric size_t RegisterContextThreadMemory::GetRegisterCount() {
650b57cec5SDimitry Andric UpdateRegisterContext();
660b57cec5SDimitry Andric if (m_reg_ctx_sp)
670b57cec5SDimitry Andric return m_reg_ctx_sp->GetRegisterCount();
680b57cec5SDimitry Andric return 0;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)720b57cec5SDimitry Andric RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
730b57cec5SDimitry Andric UpdateRegisterContext();
740b57cec5SDimitry Andric if (m_reg_ctx_sp)
750b57cec5SDimitry Andric return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
760b57cec5SDimitry Andric return nullptr;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
GetRegisterSetCount()790b57cec5SDimitry Andric size_t RegisterContextThreadMemory::GetRegisterSetCount() {
800b57cec5SDimitry Andric UpdateRegisterContext();
810b57cec5SDimitry Andric if (m_reg_ctx_sp)
820b57cec5SDimitry Andric return m_reg_ctx_sp->GetRegisterSetCount();
830b57cec5SDimitry Andric return 0;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
GetRegisterSet(size_t reg_set)860b57cec5SDimitry Andric const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
870b57cec5SDimitry Andric UpdateRegisterContext();
880b57cec5SDimitry Andric if (m_reg_ctx_sp)
890b57cec5SDimitry Andric return m_reg_ctx_sp->GetRegisterSet(reg_set);
900b57cec5SDimitry Andric return nullptr;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)930b57cec5SDimitry Andric bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
940b57cec5SDimitry Andric RegisterValue ®_value) {
950b57cec5SDimitry Andric UpdateRegisterContext();
960b57cec5SDimitry Andric if (m_reg_ctx_sp)
970b57cec5SDimitry Andric return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
980b57cec5SDimitry Andric return false;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)1010b57cec5SDimitry Andric bool RegisterContextThreadMemory::WriteRegister(
1020b57cec5SDimitry Andric const RegisterInfo *reg_info, const RegisterValue ®_value) {
1030b57cec5SDimitry Andric UpdateRegisterContext();
1040b57cec5SDimitry Andric if (m_reg_ctx_sp)
1050b57cec5SDimitry Andric return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
1060b57cec5SDimitry Andric return false;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
ReadAllRegisterValues(lldb::DataBufferSP & data_sp)1090b57cec5SDimitry Andric bool RegisterContextThreadMemory::ReadAllRegisterValues(
1100b57cec5SDimitry Andric lldb::DataBufferSP &data_sp) {
1110b57cec5SDimitry Andric UpdateRegisterContext();
1120b57cec5SDimitry Andric if (m_reg_ctx_sp)
1130b57cec5SDimitry Andric return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
1140b57cec5SDimitry Andric return false;
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)1170b57cec5SDimitry Andric bool RegisterContextThreadMemory::WriteAllRegisterValues(
1180b57cec5SDimitry Andric const lldb::DataBufferSP &data_sp) {
1190b57cec5SDimitry Andric UpdateRegisterContext();
1200b57cec5SDimitry Andric if (m_reg_ctx_sp)
1210b57cec5SDimitry Andric return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
1220b57cec5SDimitry Andric return false;
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)1250b57cec5SDimitry Andric bool RegisterContextThreadMemory::CopyFromRegisterContext(
1260b57cec5SDimitry Andric lldb::RegisterContextSP reg_ctx_sp) {
1270b57cec5SDimitry Andric UpdateRegisterContext();
1280b57cec5SDimitry Andric if (m_reg_ctx_sp)
1290b57cec5SDimitry Andric return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
1300b57cec5SDimitry Andric return false;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)1330b57cec5SDimitry Andric uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
1340b57cec5SDimitry Andric lldb::RegisterKind kind, uint32_t num) {
1350b57cec5SDimitry Andric UpdateRegisterContext();
1360b57cec5SDimitry Andric if (m_reg_ctx_sp)
1370b57cec5SDimitry Andric return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
1380b57cec5SDimitry Andric return false;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
NumSupportedHardwareBreakpoints()1410b57cec5SDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
1420b57cec5SDimitry Andric UpdateRegisterContext();
1430b57cec5SDimitry Andric if (m_reg_ctx_sp)
1440b57cec5SDimitry Andric return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
1450b57cec5SDimitry Andric return false;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)1480b57cec5SDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
1490b57cec5SDimitry Andric size_t size) {
1500b57cec5SDimitry Andric UpdateRegisterContext();
1510b57cec5SDimitry Andric if (m_reg_ctx_sp)
1520b57cec5SDimitry Andric return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
1530b57cec5SDimitry Andric return 0;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
ClearHardwareBreakpoint(uint32_t hw_idx)1560b57cec5SDimitry Andric bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
1570b57cec5SDimitry Andric UpdateRegisterContext();
1580b57cec5SDimitry Andric if (m_reg_ctx_sp)
1590b57cec5SDimitry Andric return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
1600b57cec5SDimitry Andric return false;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
NumSupportedHardwareWatchpoints()1630b57cec5SDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
1640b57cec5SDimitry Andric UpdateRegisterContext();
1650b57cec5SDimitry Andric if (m_reg_ctx_sp)
1660b57cec5SDimitry Andric return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
1670b57cec5SDimitry Andric return 0;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)1700b57cec5SDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
1710b57cec5SDimitry Andric size_t size,
1720b57cec5SDimitry Andric bool read,
1730b57cec5SDimitry Andric bool write) {
1740b57cec5SDimitry Andric UpdateRegisterContext();
1750b57cec5SDimitry Andric if (m_reg_ctx_sp)
1760b57cec5SDimitry Andric return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
1770b57cec5SDimitry Andric return 0;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
ClearHardwareWatchpoint(uint32_t hw_index)1800b57cec5SDimitry Andric bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
1810b57cec5SDimitry Andric UpdateRegisterContext();
1820b57cec5SDimitry Andric if (m_reg_ctx_sp)
1830b57cec5SDimitry Andric return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
1840b57cec5SDimitry Andric return false;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
HardwareSingleStep(bool enable)1870b57cec5SDimitry Andric bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
1880b57cec5SDimitry Andric UpdateRegisterContext();
1890b57cec5SDimitry Andric if (m_reg_ctx_sp)
1900b57cec5SDimitry Andric return m_reg_ctx_sp->HardwareSingleStep(enable);
1910b57cec5SDimitry Andric return false;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)1940b57cec5SDimitry Andric Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
1950b57cec5SDimitry Andric const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
1960b57cec5SDimitry Andric uint32_t src_len, RegisterValue ®_value) {
1970b57cec5SDimitry Andric UpdateRegisterContext();
1980b57cec5SDimitry Andric if (m_reg_ctx_sp)
1990b57cec5SDimitry Andric return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
2000b57cec5SDimitry Andric src_len, reg_value);
2010b57cec5SDimitry Andric Status error;
2020b57cec5SDimitry Andric error.SetErrorString("invalid register context");
2030b57cec5SDimitry Andric return error;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)2060b57cec5SDimitry Andric Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
2070b57cec5SDimitry Andric const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
2080b57cec5SDimitry Andric uint32_t dst_len, const RegisterValue ®_value) {
2090b57cec5SDimitry Andric UpdateRegisterContext();
2100b57cec5SDimitry Andric if (m_reg_ctx_sp)
2110b57cec5SDimitry Andric return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
2120b57cec5SDimitry Andric reg_value);
2130b57cec5SDimitry Andric Status error;
2140b57cec5SDimitry Andric error.SetErrorString("invalid register context");
2150b57cec5SDimitry Andric return error;
2160b57cec5SDimitry Andric }
217