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
17using namespace lldb;
18using namespace lldb_private;
19
20RegisterContextThreadMemory::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
25RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
26
27void 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: thread_sp.get(), reg_data_addr: 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
60void RegisterContextThreadMemory::InvalidateAllRegisters() {
61 UpdateRegisterContext();
62 if (m_reg_ctx_sp)
63 m_reg_ctx_sp->InvalidateAllRegisters();
64}
65
66size_t RegisterContextThreadMemory::GetRegisterCount() {
67 UpdateRegisterContext();
68 if (m_reg_ctx_sp)
69 return m_reg_ctx_sp->GetRegisterCount();
70 return 0;
71}
72
73const RegisterInfo *
74RegisterContextThreadMemory::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
81size_t RegisterContextThreadMemory::GetRegisterSetCount() {
82 UpdateRegisterContext();
83 if (m_reg_ctx_sp)
84 return m_reg_ctx_sp->GetRegisterSetCount();
85 return 0;
86}
87
88const 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
95bool 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
103bool 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
111bool 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
119bool 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
127bool 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
135bool 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
143bool RegisterContextThreadMemory::CopyFromRegisterContext(
144 lldb::RegisterContextSP reg_ctx_sp) {
145 UpdateRegisterContext();
146 if (m_reg_ctx_sp)
147 return m_reg_ctx_sp->CopyFromRegisterContext(context: reg_ctx_sp);
148 return false;
149}
150
151uint32_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
159uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
160 UpdateRegisterContext();
161 if (m_reg_ctx_sp)
162 return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
163 return false;
164}
165
166uint32_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
174bool 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
181uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
182 UpdateRegisterContext();
183 if (m_reg_ctx_sp)
184 return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
185 return 0;
186}
187
188uint32_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
198bool 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
205bool 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
212Status 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(str: "invalid register context");
220}
221
222Status 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(str: "invalid register context");
230}
231

source code of lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp