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 &reg_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 &reg_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 &reg_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 &reg_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