1 //===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Target/OperatingSystem.h"
11 #include "lldb/Target/Process.h"
12 #include "lldb/Target/Thread.h"
13 #include "lldb/Utility/Status.h"
14 #include "lldb/lldb-private.h"
15
16 #include "RegisterContextThreadMemory.h"
17
18 using namespace lldb;
19 using namespace lldb_private;
20
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)21 RegisterContextThreadMemory::RegisterContextThreadMemory(
22 Thread &thread, lldb::addr_t register_data_addr)
23 : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
24 m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
25
~RegisterContextThreadMemory()26 RegisterContextThreadMemory::~RegisterContextThreadMemory() {}
27
UpdateRegisterContext()28 void RegisterContextThreadMemory::UpdateRegisterContext() {
29 ThreadSP thread_sp(m_thread_wp.lock());
30 if (thread_sp) {
31 ProcessSP process_sp(thread_sp->GetProcess());
32
33 if (process_sp) {
34 const uint32_t stop_id = process_sp->GetModID().GetStopID();
35 if (m_stop_id != stop_id) {
36 m_stop_id = stop_id;
37 m_reg_ctx_sp.reset();
38 }
39 if (!m_reg_ctx_sp) {
40 ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
41 if (backing_thread_sp) {
42 m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
43 } else {
44 OperatingSystem *os = process_sp->GetOperatingSystem();
45 if (os->IsOperatingSystemPluginThread(thread_sp))
46 m_reg_ctx_sp = os->CreateRegisterContextForThread(
47 thread_sp.get(), m_register_data_addr);
48 }
49 }
50 } else {
51 m_reg_ctx_sp.reset();
52 }
53 } else {
54 m_reg_ctx_sp.reset();
55 }
56 }
57
58 //------------------------------------------------------------------
59 // Subclasses must override these functions
60 //------------------------------------------------------------------
InvalidateAllRegisters()61 void RegisterContextThreadMemory::InvalidateAllRegisters() {
62 UpdateRegisterContext();
63 if (m_reg_ctx_sp)
64 m_reg_ctx_sp->InvalidateAllRegisters();
65 }
66
GetRegisterCount()67 size_t RegisterContextThreadMemory::GetRegisterCount() {
68 UpdateRegisterContext();
69 if (m_reg_ctx_sp)
70 return m_reg_ctx_sp->GetRegisterCount();
71 return 0;
72 }
73
74 const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)75 RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
76 UpdateRegisterContext();
77 if (m_reg_ctx_sp)
78 return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
79 return NULL;
80 }
81
GetRegisterSetCount()82 size_t RegisterContextThreadMemory::GetRegisterSetCount() {
83 UpdateRegisterContext();
84 if (m_reg_ctx_sp)
85 return m_reg_ctx_sp->GetRegisterSetCount();
86 return 0;
87 }
88
GetRegisterSet(size_t reg_set)89 const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
90 UpdateRegisterContext();
91 if (m_reg_ctx_sp)
92 return m_reg_ctx_sp->GetRegisterSet(reg_set);
93 return NULL;
94 }
95
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)96 bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
97 RegisterValue ®_value) {
98 UpdateRegisterContext();
99 if (m_reg_ctx_sp)
100 return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
101 return false;
102 }
103
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)104 bool RegisterContextThreadMemory::WriteRegister(
105 const RegisterInfo *reg_info, const RegisterValue ®_value) {
106 UpdateRegisterContext();
107 if (m_reg_ctx_sp)
108 return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
109 return false;
110 }
111
ReadAllRegisterValues(lldb::DataBufferSP & data_sp)112 bool RegisterContextThreadMemory::ReadAllRegisterValues(
113 lldb::DataBufferSP &data_sp) {
114 UpdateRegisterContext();
115 if (m_reg_ctx_sp)
116 return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
117 return false;
118 }
119
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)120 bool RegisterContextThreadMemory::WriteAllRegisterValues(
121 const lldb::DataBufferSP &data_sp) {
122 UpdateRegisterContext();
123 if (m_reg_ctx_sp)
124 return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
125 return false;
126 }
127
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)128 bool RegisterContextThreadMemory::CopyFromRegisterContext(
129 lldb::RegisterContextSP reg_ctx_sp) {
130 UpdateRegisterContext();
131 if (m_reg_ctx_sp)
132 return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
133 return false;
134 }
135
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)136 uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
137 lldb::RegisterKind kind, uint32_t num) {
138 UpdateRegisterContext();
139 if (m_reg_ctx_sp)
140 return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
141 return false;
142 }
143
NumSupportedHardwareBreakpoints()144 uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
145 UpdateRegisterContext();
146 if (m_reg_ctx_sp)
147 return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
148 return false;
149 }
150
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)151 uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
152 size_t size) {
153 UpdateRegisterContext();
154 if (m_reg_ctx_sp)
155 return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
156 return 0;
157 }
158
ClearHardwareBreakpoint(uint32_t hw_idx)159 bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
160 UpdateRegisterContext();
161 if (m_reg_ctx_sp)
162 return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
163 return false;
164 }
165
NumSupportedHardwareWatchpoints()166 uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
167 UpdateRegisterContext();
168 if (m_reg_ctx_sp)
169 return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
170 return 0;
171 }
172
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)173 uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
174 size_t size,
175 bool read,
176 bool write) {
177 UpdateRegisterContext();
178 if (m_reg_ctx_sp)
179 return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
180 return 0;
181 }
182
ClearHardwareWatchpoint(uint32_t hw_index)183 bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
184 UpdateRegisterContext();
185 if (m_reg_ctx_sp)
186 return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
187 return false;
188 }
189
HardwareSingleStep(bool enable)190 bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
191 UpdateRegisterContext();
192 if (m_reg_ctx_sp)
193 return m_reg_ctx_sp->HardwareSingleStep(enable);
194 return false;
195 }
196
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)197 Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
198 const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
199 uint32_t src_len, RegisterValue ®_value) {
200 UpdateRegisterContext();
201 if (m_reg_ctx_sp)
202 return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
203 src_len, reg_value);
204 Status error;
205 error.SetErrorString("invalid register context");
206 return error;
207 }
208
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)209 Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
210 const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
211 uint32_t dst_len, const RegisterValue ®_value) {
212 UpdateRegisterContext();
213 if (m_reg_ctx_sp)
214 return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
215 reg_value);
216 Status error;
217 error.SetErrorString("invalid register context");
218 return error;
219 }
220