xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- RegisterContextThreadMemory.cpp -----------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Target/OperatingSystem.h"
10061da546Spatrick #include "lldb/Target/Process.h"
11061da546Spatrick #include "lldb/Target/Thread.h"
12061da546Spatrick #include "lldb/Utility/Status.h"
13061da546Spatrick #include "lldb/lldb-private.h"
14061da546Spatrick 
15061da546Spatrick #include "RegisterContextThreadMemory.h"
16061da546Spatrick 
17061da546Spatrick using namespace lldb;
18061da546Spatrick using namespace lldb_private;
19061da546Spatrick 
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)20061da546Spatrick RegisterContextThreadMemory::RegisterContextThreadMemory(
21061da546Spatrick     Thread &thread, lldb::addr_t register_data_addr)
22061da546Spatrick     : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
23061da546Spatrick       m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
24061da546Spatrick 
25be691f3bSpatrick RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
26061da546Spatrick 
UpdateRegisterContext()27061da546Spatrick void RegisterContextThreadMemory::UpdateRegisterContext() {
28061da546Spatrick   ThreadSP thread_sp(m_thread_wp.lock());
29061da546Spatrick   if (thread_sp) {
30061da546Spatrick     ProcessSP process_sp(thread_sp->GetProcess());
31061da546Spatrick 
32061da546Spatrick     if (process_sp) {
33061da546Spatrick       const uint32_t stop_id = process_sp->GetModID().GetStopID();
34061da546Spatrick       if (m_stop_id != stop_id) {
35061da546Spatrick         m_stop_id = stop_id;
36061da546Spatrick         m_reg_ctx_sp.reset();
37061da546Spatrick       }
38061da546Spatrick       if (!m_reg_ctx_sp) {
39061da546Spatrick         ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
40061da546Spatrick         if (backing_thread_sp) {
41061da546Spatrick           m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
42061da546Spatrick         } else {
43061da546Spatrick           OperatingSystem *os = process_sp->GetOperatingSystem();
44061da546Spatrick           if (os->IsOperatingSystemPluginThread(thread_sp))
45061da546Spatrick             m_reg_ctx_sp = os->CreateRegisterContextForThread(
46061da546Spatrick                 thread_sp.get(), m_register_data_addr);
47061da546Spatrick         }
48061da546Spatrick       }
49061da546Spatrick     } else {
50061da546Spatrick       m_reg_ctx_sp.reset();
51061da546Spatrick     }
52061da546Spatrick   } else {
53061da546Spatrick     m_reg_ctx_sp.reset();
54061da546Spatrick   }
55061da546Spatrick }
56061da546Spatrick 
57061da546Spatrick // Subclasses must override these functions
InvalidateAllRegisters()58061da546Spatrick void RegisterContextThreadMemory::InvalidateAllRegisters() {
59061da546Spatrick   UpdateRegisterContext();
60061da546Spatrick   if (m_reg_ctx_sp)
61061da546Spatrick     m_reg_ctx_sp->InvalidateAllRegisters();
62061da546Spatrick }
63061da546Spatrick 
GetRegisterCount()64061da546Spatrick size_t RegisterContextThreadMemory::GetRegisterCount() {
65061da546Spatrick   UpdateRegisterContext();
66061da546Spatrick   if (m_reg_ctx_sp)
67061da546Spatrick     return m_reg_ctx_sp->GetRegisterCount();
68061da546Spatrick   return 0;
69061da546Spatrick }
70061da546Spatrick 
71061da546Spatrick const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)72061da546Spatrick RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
73061da546Spatrick   UpdateRegisterContext();
74061da546Spatrick   if (m_reg_ctx_sp)
75061da546Spatrick     return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
76061da546Spatrick   return nullptr;
77061da546Spatrick }
78061da546Spatrick 
GetRegisterSetCount()79061da546Spatrick size_t RegisterContextThreadMemory::GetRegisterSetCount() {
80061da546Spatrick   UpdateRegisterContext();
81061da546Spatrick   if (m_reg_ctx_sp)
82061da546Spatrick     return m_reg_ctx_sp->GetRegisterSetCount();
83061da546Spatrick   return 0;
84061da546Spatrick }
85061da546Spatrick 
GetRegisterSet(size_t reg_set)86061da546Spatrick const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
87061da546Spatrick   UpdateRegisterContext();
88061da546Spatrick   if (m_reg_ctx_sp)
89061da546Spatrick     return m_reg_ctx_sp->GetRegisterSet(reg_set);
90061da546Spatrick   return nullptr;
91061da546Spatrick }
92061da546Spatrick 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)93061da546Spatrick bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
94061da546Spatrick                                                RegisterValue &reg_value) {
95061da546Spatrick   UpdateRegisterContext();
96061da546Spatrick   if (m_reg_ctx_sp)
97061da546Spatrick     return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
98061da546Spatrick   return false;
99061da546Spatrick }
100061da546Spatrick 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)101061da546Spatrick bool RegisterContextThreadMemory::WriteRegister(
102061da546Spatrick     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
103061da546Spatrick   UpdateRegisterContext();
104061da546Spatrick   if (m_reg_ctx_sp)
105061da546Spatrick     return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
106061da546Spatrick   return false;
107061da546Spatrick }
108061da546Spatrick 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)109061da546Spatrick bool RegisterContextThreadMemory::ReadAllRegisterValues(
110*f6aab3d8Srobert     lldb::WritableDataBufferSP &data_sp) {
111061da546Spatrick   UpdateRegisterContext();
112061da546Spatrick   if (m_reg_ctx_sp)
113061da546Spatrick     return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
114061da546Spatrick   return false;
115061da546Spatrick }
116061da546Spatrick 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)117061da546Spatrick bool RegisterContextThreadMemory::WriteAllRegisterValues(
118061da546Spatrick     const lldb::DataBufferSP &data_sp) {
119061da546Spatrick   UpdateRegisterContext();
120061da546Spatrick   if (m_reg_ctx_sp)
121061da546Spatrick     return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
122061da546Spatrick   return false;
123061da546Spatrick }
124061da546Spatrick 
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)125061da546Spatrick bool RegisterContextThreadMemory::CopyFromRegisterContext(
126061da546Spatrick     lldb::RegisterContextSP reg_ctx_sp) {
127061da546Spatrick   UpdateRegisterContext();
128061da546Spatrick   if (m_reg_ctx_sp)
129061da546Spatrick     return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
130061da546Spatrick   return false;
131061da546Spatrick }
132061da546Spatrick 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)133061da546Spatrick uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
134061da546Spatrick     lldb::RegisterKind kind, uint32_t num) {
135061da546Spatrick   UpdateRegisterContext();
136061da546Spatrick   if (m_reg_ctx_sp)
137061da546Spatrick     return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
138061da546Spatrick   return false;
139061da546Spatrick }
140061da546Spatrick 
NumSupportedHardwareBreakpoints()141061da546Spatrick uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
142061da546Spatrick   UpdateRegisterContext();
143061da546Spatrick   if (m_reg_ctx_sp)
144061da546Spatrick     return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
145061da546Spatrick   return false;
146061da546Spatrick }
147061da546Spatrick 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)148061da546Spatrick uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
149061da546Spatrick                                                             size_t size) {
150061da546Spatrick   UpdateRegisterContext();
151061da546Spatrick   if (m_reg_ctx_sp)
152061da546Spatrick     return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
153061da546Spatrick   return 0;
154061da546Spatrick }
155061da546Spatrick 
ClearHardwareBreakpoint(uint32_t hw_idx)156061da546Spatrick bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
157061da546Spatrick   UpdateRegisterContext();
158061da546Spatrick   if (m_reg_ctx_sp)
159061da546Spatrick     return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
160061da546Spatrick   return false;
161061da546Spatrick }
162061da546Spatrick 
NumSupportedHardwareWatchpoints()163061da546Spatrick uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
164061da546Spatrick   UpdateRegisterContext();
165061da546Spatrick   if (m_reg_ctx_sp)
166061da546Spatrick     return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
167061da546Spatrick   return 0;
168061da546Spatrick }
169061da546Spatrick 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)170061da546Spatrick uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
171061da546Spatrick                                                             size_t size,
172061da546Spatrick                                                             bool read,
173061da546Spatrick                                                             bool write) {
174061da546Spatrick   UpdateRegisterContext();
175061da546Spatrick   if (m_reg_ctx_sp)
176061da546Spatrick     return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
177061da546Spatrick   return 0;
178061da546Spatrick }
179061da546Spatrick 
ClearHardwareWatchpoint(uint32_t hw_index)180061da546Spatrick bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
181061da546Spatrick   UpdateRegisterContext();
182061da546Spatrick   if (m_reg_ctx_sp)
183061da546Spatrick     return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
184061da546Spatrick   return false;
185061da546Spatrick }
186061da546Spatrick 
HardwareSingleStep(bool enable)187061da546Spatrick bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
188061da546Spatrick   UpdateRegisterContext();
189061da546Spatrick   if (m_reg_ctx_sp)
190061da546Spatrick     return m_reg_ctx_sp->HardwareSingleStep(enable);
191061da546Spatrick   return false;
192061da546Spatrick }
193061da546Spatrick 
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)194061da546Spatrick Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
195061da546Spatrick     const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
196061da546Spatrick     uint32_t src_len, RegisterValue &reg_value) {
197061da546Spatrick   UpdateRegisterContext();
198061da546Spatrick   if (m_reg_ctx_sp)
199061da546Spatrick     return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
200061da546Spatrick                                                      src_len, reg_value);
201061da546Spatrick   Status error;
202061da546Spatrick   error.SetErrorString("invalid register context");
203061da546Spatrick   return error;
204061da546Spatrick }
205061da546Spatrick 
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)206061da546Spatrick Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
207061da546Spatrick     const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
208061da546Spatrick     uint32_t dst_len, const RegisterValue &reg_value) {
209061da546Spatrick   UpdateRegisterContext();
210061da546Spatrick   if (m_reg_ctx_sp)
211061da546Spatrick     return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
212061da546Spatrick                                                     reg_value);
213061da546Spatrick   Status error;
214061da546Spatrick   error.SetErrorString("invalid register context");
215061da546Spatrick   return error;
216061da546Spatrick }
217