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/lldb-private.h"
11 #include "lldb/Core/Error.h"
12 #include "lldb/Target/OperatingSystem.h"
13 #include "lldb/Target/Process.h"
14 #include "lldb/Target/Thread.h"
15 
16 #include "RegisterContextThreadMemory.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 RegisterContextThreadMemory::RegisterContextThreadMemory (Thread &thread,
22                                                           lldb::addr_t register_data_addr) :
23     RegisterContext (thread, 0),
24     m_thread_wp (thread.shared_from_this()),
25     m_reg_ctx_sp (),
26     m_register_data_addr (register_data_addr),
27     m_stop_id(0)
28 {
29 }
30 
31 RegisterContextThreadMemory::~RegisterContextThreadMemory()
32 {
33 }
34 
35 void
36 RegisterContextThreadMemory::UpdateRegisterContext ()
37 {
38     ThreadSP thread_sp (m_thread_wp.lock());
39     if (thread_sp)
40     {
41         ProcessSP process_sp (thread_sp->GetProcess());
42 
43         if (process_sp)
44         {
45             const uint32_t stop_id = process_sp->GetModID().GetStopID();
46             if (m_stop_id != stop_id)
47             {
48                 m_stop_id = stop_id;
49                 m_reg_ctx_sp.reset();
50             }
51             if (!m_reg_ctx_sp)
52             {
53                 ThreadSP backing_thread_sp (thread_sp->GetBackingThread());
54                 if (backing_thread_sp)
55                 {
56                     m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
57                 }
58                 else
59                 {
60                     OperatingSystem *os = process_sp->GetOperatingSystem ();
61                     if (os->IsOperatingSystemPluginThread (thread_sp))
62                         m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), LLDB_INVALID_ADDRESS);
63                 }
64             }
65         }
66     }
67     else
68     {
69         m_reg_ctx_sp.reset();
70     }
71 }
72 
73 //------------------------------------------------------------------
74 // Subclasses must override these functions
75 //------------------------------------------------------------------
76 void
77 RegisterContextThreadMemory::InvalidateAllRegisters ()
78 {
79     UpdateRegisterContext ();
80     if (m_reg_ctx_sp)
81         m_reg_ctx_sp->InvalidateAllRegisters();
82 }
83 
84 size_t
85 RegisterContextThreadMemory::GetRegisterCount ()
86 {
87     UpdateRegisterContext ();
88     if (m_reg_ctx_sp)
89         return m_reg_ctx_sp->GetRegisterCount();
90     return 0;
91 }
92 
93 const RegisterInfo *
94 RegisterContextThreadMemory::GetRegisterInfoAtIndex (size_t reg)
95 {
96     UpdateRegisterContext ();
97     if (m_reg_ctx_sp)
98         return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
99     return NULL;
100 }
101 
102 size_t
103 RegisterContextThreadMemory::GetRegisterSetCount ()
104 {
105     UpdateRegisterContext ();
106     if (m_reg_ctx_sp)
107         return m_reg_ctx_sp->GetRegisterSetCount();
108     return 0;
109 }
110 
111 const RegisterSet *
112 RegisterContextThreadMemory::GetRegisterSet (size_t reg_set)
113 {
114     UpdateRegisterContext ();
115     if (m_reg_ctx_sp)
116         return m_reg_ctx_sp->GetRegisterSet(reg_set);
117     return NULL;
118 }
119 
120 bool
121 RegisterContextThreadMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
122 {
123     UpdateRegisterContext ();
124     if (m_reg_ctx_sp)
125         return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
126     return false;
127 }
128 
129 bool
130 RegisterContextThreadMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
131 {
132     UpdateRegisterContext ();
133     if (m_reg_ctx_sp)
134         return m_reg_ctx_sp->WriteRegister (reg_info, reg_value);
135     return false;
136 }
137 
138 bool
139 RegisterContextThreadMemory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
140 {
141     UpdateRegisterContext ();
142     if (m_reg_ctx_sp)
143         return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
144     return false;
145 }
146 
147 bool
148 RegisterContextThreadMemory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
149 {
150     UpdateRegisterContext ();
151     if (m_reg_ctx_sp)
152         return m_reg_ctx_sp->WriteAllRegisterValues (data_sp);
153     return false;
154 }
155 
156 bool
157 RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP reg_ctx_sp)
158 {
159     UpdateRegisterContext ();
160     if (m_reg_ctx_sp)
161         return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
162     return false;
163 }
164 
165 uint32_t
166 RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
167 {
168     UpdateRegisterContext ();
169     if (m_reg_ctx_sp)
170         return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
171     return false;
172 }
173 
174 uint32_t
175 RegisterContextThreadMemory::NumSupportedHardwareBreakpoints ()
176 {
177     UpdateRegisterContext ();
178     if (m_reg_ctx_sp)
179         return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
180     return false;
181 }
182 
183 uint32_t
184 RegisterContextThreadMemory::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
185 {
186     UpdateRegisterContext ();
187     if (m_reg_ctx_sp)
188         return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
189     return 0;
190 }
191 
192 bool
193 RegisterContextThreadMemory::ClearHardwareBreakpoint (uint32_t hw_idx)
194 {
195     UpdateRegisterContext ();
196     if (m_reg_ctx_sp)
197         return m_reg_ctx_sp->ClearHardwareBreakpoint (hw_idx);
198     return false;
199 }
200 
201 uint32_t
202 RegisterContextThreadMemory::NumSupportedHardwareWatchpoints ()
203 {
204     UpdateRegisterContext ();
205     if (m_reg_ctx_sp)
206         return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
207     return 0;
208 }
209 
210 uint32_t
211 RegisterContextThreadMemory::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
212 {
213     UpdateRegisterContext ();
214     if (m_reg_ctx_sp)
215         return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
216     return 0;
217 }
218 
219 bool
220 RegisterContextThreadMemory::ClearHardwareWatchpoint (uint32_t hw_index)
221 {
222     UpdateRegisterContext ();
223     if (m_reg_ctx_sp)
224         return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
225     return false;
226 }
227 
228 bool
229 RegisterContextThreadMemory::HardwareSingleStep (bool enable)
230 {
231     UpdateRegisterContext ();
232     if (m_reg_ctx_sp)
233         return m_reg_ctx_sp->HardwareSingleStep(enable);
234     return false;
235 }
236 
237 Error
238 RegisterContextThreadMemory::ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value)
239 {
240     UpdateRegisterContext ();
241     if (m_reg_ctx_sp)
242         return m_reg_ctx_sp->ReadRegisterValueFromMemory (reg_info, src_addr, src_len, reg_value);
243     Error error;
244     error.SetErrorString("invalid register context");
245     return error;
246 }
247 
248 Error
249 RegisterContextThreadMemory::WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value)
250 {
251     UpdateRegisterContext ();
252     if (m_reg_ctx_sp)
253         return m_reg_ctx_sp->WriteRegisterValueToMemory (reg_info, dst_addr, dst_len, reg_value);
254     Error error;
255     error.SetErrorString("invalid register context");
256     return error;
257 }
258