xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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-exception
6 //
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 
17 using namespace lldb;
18 using namespace lldb_private;
19 
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)20 RegisterContextThreadMemory::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 
25 RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
26 
UpdateRegisterContext()27 void 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 functions
InvalidateAllRegisters()60 void RegisterContextThreadMemory::InvalidateAllRegisters() {
61   UpdateRegisterContext();
62   if (m_reg_ctx_sp)
63     m_reg_ctx_sp->InvalidateAllRegisters();
64 }
65 
GetRegisterCount()66 size_t RegisterContextThreadMemory::GetRegisterCount() {
67   UpdateRegisterContext();
68   if (m_reg_ctx_sp)
69     return m_reg_ctx_sp->GetRegisterCount();
70   return 0;
71 }
72 
73 const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)74 RegisterContextThreadMemory::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 
GetRegisterSetCount()81 size_t RegisterContextThreadMemory::GetRegisterSetCount() {
82   UpdateRegisterContext();
83   if (m_reg_ctx_sp)
84     return m_reg_ctx_sp->GetRegisterSetCount();
85   return 0;
86 }
87 
GetRegisterSet(size_t reg_set)88 const 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 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)95 bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
96                                                RegisterValue &reg_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 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)103 bool RegisterContextThreadMemory::WriteRegister(
104     const RegisterInfo *reg_info, const RegisterValue &reg_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 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)111 bool 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 
ReadAllRegisterValues(lldb_private::RegisterCheckpoint & reg_checkpoint)119 bool RegisterContextThreadMemory::ReadAllRegisterValues(
120     lldb_private::RegisterCheckpoint &reg_checkpoint) {
121   UpdateRegisterContext();
122   if (m_reg_ctx_sp)
123     return m_reg_ctx_sp->ReadAllRegisterValues(reg_checkpoint);
124   return false;
125 }
126 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)127 bool 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 
WriteAllRegisterValues(const lldb_private::RegisterCheckpoint & reg_checkpoint)135 bool RegisterContextThreadMemory::WriteAllRegisterValues(
136     const lldb_private::RegisterCheckpoint &reg_checkpoint) {
137   UpdateRegisterContext();
138   if (m_reg_ctx_sp)
139     return m_reg_ctx_sp->WriteAllRegisterValues(reg_checkpoint);
140   return false;
141 }
142 
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)143 bool 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 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)151 uint32_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 false;
157 }
158 
NumSupportedHardwareBreakpoints()159 uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
160   UpdateRegisterContext();
161   if (m_reg_ctx_sp)
162     return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
163   return false;
164 }
165 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)166 uint32_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 
ClearHardwareBreakpoint(uint32_t hw_idx)174 bool 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 
NumSupportedHardwareWatchpoints()181 uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
182   UpdateRegisterContext();
183   if (m_reg_ctx_sp)
184     return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
185   return 0;
186 }
187 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)188 uint32_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 
ClearHardwareWatchpoint(uint32_t hw_index)198 bool 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 
HardwareSingleStep(bool enable)205 bool 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 
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)212 Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
213     const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
214     uint32_t src_len, RegisterValue &reg_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 
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)222 Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
223     const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
224     uint32_t dst_len, const RegisterValue &reg_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