1 //===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===//
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 
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() {}
26 
27 void RegisterContextThreadMemory::UpdateRegisterContext() {
28   ThreadSP thread_sp(m_thread_wp.lock());
29   if (thread_sp) {
30     ProcessSP process_sp(thread_sp->GetProcess());
31 
32     if (process_sp) {
33       const uint32_t stop_id = process_sp->GetModID().GetStopID();
34       if (m_stop_id != stop_id) {
35         m_stop_id = stop_id;
36         m_reg_ctx_sp.reset();
37       }
38       if (!m_reg_ctx_sp) {
39         ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
40         if (backing_thread_sp) {
41           m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
42         } else {
43           OperatingSystem *os = process_sp->GetOperatingSystem();
44           if (os->IsOperatingSystemPluginThread(thread_sp))
45             m_reg_ctx_sp = os->CreateRegisterContextForThread(
46                 thread_sp.get(), m_register_data_addr);
47         }
48       }
49     } else {
50       m_reg_ctx_sp.reset();
51     }
52   } else {
53     m_reg_ctx_sp.reset();
54   }
55 }
56 
57 //------------------------------------------------------------------
58 // Subclasses must override these functions
59 //------------------------------------------------------------------
60 void RegisterContextThreadMemory::InvalidateAllRegisters() {
61   UpdateRegisterContext();
62   if (m_reg_ctx_sp)
63     m_reg_ctx_sp->InvalidateAllRegisters();
64 }
65 
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 *
74 RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
75   UpdateRegisterContext();
76   if (m_reg_ctx_sp)
77     return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
78   return NULL;
79 }
80 
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 
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 NULL;
93 }
94 
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 
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 
111 bool RegisterContextThreadMemory::ReadAllRegisterValues(
112     lldb::DataBufferSP &data_sp) {
113   UpdateRegisterContext();
114   if (m_reg_ctx_sp)
115     return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
116   return false;
117 }
118 
119 bool RegisterContextThreadMemory::WriteAllRegisterValues(
120     const lldb::DataBufferSP &data_sp) {
121   UpdateRegisterContext();
122   if (m_reg_ctx_sp)
123     return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
124   return false;
125 }
126 
127 bool RegisterContextThreadMemory::CopyFromRegisterContext(
128     lldb::RegisterContextSP reg_ctx_sp) {
129   UpdateRegisterContext();
130   if (m_reg_ctx_sp)
131     return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
132   return false;
133 }
134 
135 uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
136     lldb::RegisterKind kind, uint32_t num) {
137   UpdateRegisterContext();
138   if (m_reg_ctx_sp)
139     return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
140   return false;
141 }
142 
143 uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
144   UpdateRegisterContext();
145   if (m_reg_ctx_sp)
146     return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
147   return false;
148 }
149 
150 uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
151                                                             size_t size) {
152   UpdateRegisterContext();
153   if (m_reg_ctx_sp)
154     return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
155   return 0;
156 }
157 
158 bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
159   UpdateRegisterContext();
160   if (m_reg_ctx_sp)
161     return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
162   return false;
163 }
164 
165 uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
166   UpdateRegisterContext();
167   if (m_reg_ctx_sp)
168     return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
169   return 0;
170 }
171 
172 uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
173                                                             size_t size,
174                                                             bool read,
175                                                             bool write) {
176   UpdateRegisterContext();
177   if (m_reg_ctx_sp)
178     return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
179   return 0;
180 }
181 
182 bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
183   UpdateRegisterContext();
184   if (m_reg_ctx_sp)
185     return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
186   return false;
187 }
188 
189 bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
190   UpdateRegisterContext();
191   if (m_reg_ctx_sp)
192     return m_reg_ctx_sp->HardwareSingleStep(enable);
193   return false;
194 }
195 
196 Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
197     const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
198     uint32_t src_len, RegisterValue &reg_value) {
199   UpdateRegisterContext();
200   if (m_reg_ctx_sp)
201     return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
202                                                      src_len, reg_value);
203   Status error;
204   error.SetErrorString("invalid register context");
205   return error;
206 }
207 
208 Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
209     const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
210     uint32_t dst_len, const RegisterValue &reg_value) {
211   UpdateRegisterContext();
212   if (m_reg_ctx_sp)
213     return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
214                                                     reg_value);
215   Status error;
216   error.SetErrorString("invalid register context");
217   return error;
218 }
219