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