xref: /src/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1cfca06d7SDimitry Andric //===-- RegisterContextThreadMemory.cpp -----------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Target/OperatingSystem.h"
10f034231aSEd Maste #include "lldb/Target/Process.h"
11f034231aSEd Maste #include "lldb/Target/Thread.h"
12b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
1314f1b3e8SDimitry Andric #include "lldb/lldb-private.h"
14f034231aSEd Maste 
15f034231aSEd Maste #include "RegisterContextThreadMemory.h"
16f034231aSEd Maste 
17f034231aSEd Maste using namespace lldb;
18f034231aSEd Maste using namespace lldb_private;
19f034231aSEd Maste 
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)2014f1b3e8SDimitry Andric RegisterContextThreadMemory::RegisterContextThreadMemory(
2114f1b3e8SDimitry Andric     Thread &thread, lldb::addr_t register_data_addr)
2214f1b3e8SDimitry Andric     : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
2314f1b3e8SDimitry Andric       m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
24f034231aSEd Maste 
25344a3780SDimitry Andric RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
26f034231aSEd Maste 
UpdateRegisterContext()2714f1b3e8SDimitry Andric void RegisterContextThreadMemory::UpdateRegisterContext() {
28f034231aSEd Maste   ThreadSP thread_sp(m_thread_wp.lock());
2914f1b3e8SDimitry Andric   if (thread_sp) {
30f034231aSEd Maste     ProcessSP process_sp(thread_sp->GetProcess());
31f034231aSEd Maste 
3214f1b3e8SDimitry Andric     if (process_sp) {
33f034231aSEd Maste       const uint32_t stop_id = process_sp->GetModID().GetStopID();
3414f1b3e8SDimitry Andric       if (m_stop_id != stop_id) {
35f034231aSEd Maste         m_stop_id = stop_id;
36f034231aSEd Maste         m_reg_ctx_sp.reset();
37f034231aSEd Maste       }
3814f1b3e8SDimitry Andric       if (!m_reg_ctx_sp) {
39f034231aSEd Maste         ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
4014f1b3e8SDimitry Andric         if (backing_thread_sp) {
41f034231aSEd Maste           m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
4214f1b3e8SDimitry Andric         } else {
43f034231aSEd Maste           OperatingSystem *os = process_sp->GetOperatingSystem();
44f034231aSEd Maste           if (os->IsOperatingSystemPluginThread(thread_sp))
4514f1b3e8SDimitry Andric             m_reg_ctx_sp = os->CreateRegisterContextForThread(
4614f1b3e8SDimitry Andric                 thread_sp.get(), m_register_data_addr);
47f034231aSEd Maste         }
48f034231aSEd Maste       }
4914f1b3e8SDimitry Andric     } else {
50f034231aSEd Maste       m_reg_ctx_sp.reset();
51f034231aSEd Maste     }
5214f1b3e8SDimitry Andric   } else {
53f034231aSEd Maste     m_reg_ctx_sp.reset();
54f034231aSEd Maste   }
55f034231aSEd Maste }
56f034231aSEd Maste 
57f034231aSEd Maste // Subclasses must override these functions
InvalidateAllRegisters()5814f1b3e8SDimitry Andric void RegisterContextThreadMemory::InvalidateAllRegisters() {
59f034231aSEd Maste   UpdateRegisterContext();
60f034231aSEd Maste   if (m_reg_ctx_sp)
61f034231aSEd Maste     m_reg_ctx_sp->InvalidateAllRegisters();
62f034231aSEd Maste }
63f034231aSEd Maste 
GetRegisterCount()6414f1b3e8SDimitry Andric size_t RegisterContextThreadMemory::GetRegisterCount() {
65f034231aSEd Maste   UpdateRegisterContext();
66f034231aSEd Maste   if (m_reg_ctx_sp)
67f034231aSEd Maste     return m_reg_ctx_sp->GetRegisterCount();
68f034231aSEd Maste   return 0;
69f034231aSEd Maste }
70f034231aSEd Maste 
71f034231aSEd Maste const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)7214f1b3e8SDimitry Andric RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
73f034231aSEd Maste   UpdateRegisterContext();
74f034231aSEd Maste   if (m_reg_ctx_sp)
75f034231aSEd Maste     return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
765f29bb8aSDimitry Andric   return nullptr;
77f034231aSEd Maste }
78f034231aSEd Maste 
GetRegisterSetCount()7914f1b3e8SDimitry Andric size_t RegisterContextThreadMemory::GetRegisterSetCount() {
80f034231aSEd Maste   UpdateRegisterContext();
81f034231aSEd Maste   if (m_reg_ctx_sp)
82f034231aSEd Maste     return m_reg_ctx_sp->GetRegisterSetCount();
83f034231aSEd Maste   return 0;
84f034231aSEd Maste }
85f034231aSEd Maste 
GetRegisterSet(size_t reg_set)8614f1b3e8SDimitry Andric const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
87f034231aSEd Maste   UpdateRegisterContext();
88f034231aSEd Maste   if (m_reg_ctx_sp)
89f034231aSEd Maste     return m_reg_ctx_sp->GetRegisterSet(reg_set);
905f29bb8aSDimitry Andric   return nullptr;
91f034231aSEd Maste }
92f034231aSEd Maste 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)9314f1b3e8SDimitry Andric bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
9414f1b3e8SDimitry Andric                                                RegisterValue &reg_value) {
95f034231aSEd Maste   UpdateRegisterContext();
96f034231aSEd Maste   if (m_reg_ctx_sp)
97f034231aSEd Maste     return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
98f034231aSEd Maste   return false;
99f034231aSEd Maste }
100f034231aSEd Maste 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)10114f1b3e8SDimitry Andric bool RegisterContextThreadMemory::WriteRegister(
10214f1b3e8SDimitry Andric     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
103f034231aSEd Maste   UpdateRegisterContext();
104f034231aSEd Maste   if (m_reg_ctx_sp)
105f034231aSEd Maste     return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
106f034231aSEd Maste   return false;
107f034231aSEd Maste }
108f034231aSEd Maste 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)10914f1b3e8SDimitry Andric bool RegisterContextThreadMemory::ReadAllRegisterValues(
110145449b1SDimitry Andric     lldb::WritableDataBufferSP &data_sp) {
111f034231aSEd Maste   UpdateRegisterContext();
112f034231aSEd Maste   if (m_reg_ctx_sp)
113f034231aSEd Maste     return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
114f034231aSEd Maste   return false;
115f034231aSEd Maste }
116f034231aSEd Maste 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)11714f1b3e8SDimitry Andric bool RegisterContextThreadMemory::WriteAllRegisterValues(
11814f1b3e8SDimitry Andric     const lldb::DataBufferSP &data_sp) {
119f034231aSEd Maste   UpdateRegisterContext();
120f034231aSEd Maste   if (m_reg_ctx_sp)
121f034231aSEd Maste     return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
122f034231aSEd Maste   return false;
123f034231aSEd Maste }
124f034231aSEd Maste 
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)12514f1b3e8SDimitry Andric bool RegisterContextThreadMemory::CopyFromRegisterContext(
12614f1b3e8SDimitry Andric     lldb::RegisterContextSP reg_ctx_sp) {
127f034231aSEd Maste   UpdateRegisterContext();
128f034231aSEd Maste   if (m_reg_ctx_sp)
129f034231aSEd Maste     return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
130f034231aSEd Maste   return false;
131f034231aSEd Maste }
132f034231aSEd Maste 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)13314f1b3e8SDimitry Andric uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
13414f1b3e8SDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
135f034231aSEd Maste   UpdateRegisterContext();
136f034231aSEd Maste   if (m_reg_ctx_sp)
137f034231aSEd Maste     return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
138f034231aSEd Maste   return false;
139f034231aSEd Maste }
140f034231aSEd Maste 
NumSupportedHardwareBreakpoints()14114f1b3e8SDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
142f034231aSEd Maste   UpdateRegisterContext();
143f034231aSEd Maste   if (m_reg_ctx_sp)
144f034231aSEd Maste     return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
145f034231aSEd Maste   return false;
146f034231aSEd Maste }
147f034231aSEd Maste 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)14814f1b3e8SDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
14914f1b3e8SDimitry Andric                                                             size_t size) {
150f034231aSEd Maste   UpdateRegisterContext();
151f034231aSEd Maste   if (m_reg_ctx_sp)
152f034231aSEd Maste     return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
153f034231aSEd Maste   return 0;
154f034231aSEd Maste }
155f034231aSEd Maste 
ClearHardwareBreakpoint(uint32_t hw_idx)15614f1b3e8SDimitry Andric bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
157f034231aSEd Maste   UpdateRegisterContext();
158f034231aSEd Maste   if (m_reg_ctx_sp)
159f034231aSEd Maste     return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
160f034231aSEd Maste   return false;
161f034231aSEd Maste }
162f034231aSEd Maste 
NumSupportedHardwareWatchpoints()16314f1b3e8SDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
164f034231aSEd Maste   UpdateRegisterContext();
165f034231aSEd Maste   if (m_reg_ctx_sp)
166f034231aSEd Maste     return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
167f034231aSEd Maste   return 0;
168f034231aSEd Maste }
169f034231aSEd Maste 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)17014f1b3e8SDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
17114f1b3e8SDimitry Andric                                                             size_t size,
17214f1b3e8SDimitry Andric                                                             bool read,
17314f1b3e8SDimitry Andric                                                             bool write) {
174f034231aSEd Maste   UpdateRegisterContext();
175f034231aSEd Maste   if (m_reg_ctx_sp)
176f034231aSEd Maste     return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
177f034231aSEd Maste   return 0;
178f034231aSEd Maste }
179f034231aSEd Maste 
ClearHardwareWatchpoint(uint32_t hw_index)18014f1b3e8SDimitry Andric bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
181f034231aSEd Maste   UpdateRegisterContext();
182f034231aSEd Maste   if (m_reg_ctx_sp)
183f034231aSEd Maste     return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
184f034231aSEd Maste   return false;
185f034231aSEd Maste }
186f034231aSEd Maste 
HardwareSingleStep(bool enable)18714f1b3e8SDimitry Andric bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
188f034231aSEd Maste   UpdateRegisterContext();
189f034231aSEd Maste   if (m_reg_ctx_sp)
190f034231aSEd Maste     return m_reg_ctx_sp->HardwareSingleStep(enable);
191f034231aSEd Maste   return false;
192f034231aSEd Maste }
193f034231aSEd Maste 
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)194b76161e4SDimitry Andric Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
19514f1b3e8SDimitry Andric     const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
19614f1b3e8SDimitry Andric     uint32_t src_len, RegisterValue &reg_value) {
197f034231aSEd Maste   UpdateRegisterContext();
198f034231aSEd Maste   if (m_reg_ctx_sp)
19914f1b3e8SDimitry Andric     return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
20014f1b3e8SDimitry Andric                                                      src_len, reg_value);
201b76161e4SDimitry Andric   Status error;
202f034231aSEd Maste   error.SetErrorString("invalid register context");
203f034231aSEd Maste   return error;
204f034231aSEd Maste }
205f034231aSEd Maste 
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)206b76161e4SDimitry Andric Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
20714f1b3e8SDimitry Andric     const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
20814f1b3e8SDimitry Andric     uint32_t dst_len, const RegisterValue &reg_value) {
209f034231aSEd Maste   UpdateRegisterContext();
210f034231aSEd Maste   if (m_reg_ctx_sp)
21114f1b3e8SDimitry Andric     return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
21214f1b3e8SDimitry Andric                                                     reg_value);
213b76161e4SDimitry Andric   Status error;
214f034231aSEd Maste   error.SetErrorString("invalid register context");
215f034231aSEd Maste   return error;
216f034231aSEd Maste }
217