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