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 ®_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 ®_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 ®_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 ®_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 ®_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 ®_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