1ac7ddfbfSEd Maste //===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Target/OperatingSystem.h"
11ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
12ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
13*5517e702SDimitry Andric #include "lldb/Utility/Status.h"
14435933ddSDimitry Andric #include "lldb/lldb-private.h"
15ac7ddfbfSEd Maste 
16ac7ddfbfSEd Maste #include "RegisterContextThreadMemory.h"
17ac7ddfbfSEd Maste 
18ac7ddfbfSEd Maste using namespace lldb;
19ac7ddfbfSEd Maste using namespace lldb_private;
20ac7ddfbfSEd Maste 
RegisterContextThreadMemory(Thread & thread,lldb::addr_t register_data_addr)21435933ddSDimitry Andric RegisterContextThreadMemory::RegisterContextThreadMemory(
22435933ddSDimitry Andric     Thread &thread, lldb::addr_t register_data_addr)
23435933ddSDimitry Andric     : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
24435933ddSDimitry Andric       m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
25ac7ddfbfSEd Maste 
~RegisterContextThreadMemory()26435933ddSDimitry Andric RegisterContextThreadMemory::~RegisterContextThreadMemory() {}
27ac7ddfbfSEd Maste 
UpdateRegisterContext()28435933ddSDimitry Andric void RegisterContextThreadMemory::UpdateRegisterContext() {
29ac7ddfbfSEd Maste   ThreadSP thread_sp(m_thread_wp.lock());
30435933ddSDimitry Andric   if (thread_sp) {
31ac7ddfbfSEd Maste     ProcessSP process_sp(thread_sp->GetProcess());
32ac7ddfbfSEd Maste 
33435933ddSDimitry Andric     if (process_sp) {
34ac7ddfbfSEd Maste       const uint32_t stop_id = process_sp->GetModID().GetStopID();
35435933ddSDimitry Andric       if (m_stop_id != stop_id) {
36ac7ddfbfSEd Maste         m_stop_id = stop_id;
37ac7ddfbfSEd Maste         m_reg_ctx_sp.reset();
38ac7ddfbfSEd Maste       }
39435933ddSDimitry Andric       if (!m_reg_ctx_sp) {
40ac7ddfbfSEd Maste         ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
41435933ddSDimitry Andric         if (backing_thread_sp) {
42ac7ddfbfSEd Maste           m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
43435933ddSDimitry Andric         } else {
44ac7ddfbfSEd Maste           OperatingSystem *os = process_sp->GetOperatingSystem();
45ac7ddfbfSEd Maste           if (os->IsOperatingSystemPluginThread(thread_sp))
46435933ddSDimitry Andric             m_reg_ctx_sp = os->CreateRegisterContextForThread(
47435933ddSDimitry Andric                 thread_sp.get(), m_register_data_addr);
48ac7ddfbfSEd Maste         }
49ac7ddfbfSEd Maste       }
50435933ddSDimitry Andric     } else {
51ac7ddfbfSEd Maste       m_reg_ctx_sp.reset();
52ac7ddfbfSEd Maste     }
53435933ddSDimitry Andric   } else {
54ac7ddfbfSEd Maste     m_reg_ctx_sp.reset();
55ac7ddfbfSEd Maste   }
56ac7ddfbfSEd Maste }
57ac7ddfbfSEd Maste 
58ac7ddfbfSEd Maste //------------------------------------------------------------------
59ac7ddfbfSEd Maste // Subclasses must override these functions
60ac7ddfbfSEd Maste //------------------------------------------------------------------
InvalidateAllRegisters()61435933ddSDimitry Andric void RegisterContextThreadMemory::InvalidateAllRegisters() {
62ac7ddfbfSEd Maste   UpdateRegisterContext();
63ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
64ac7ddfbfSEd Maste     m_reg_ctx_sp->InvalidateAllRegisters();
65ac7ddfbfSEd Maste }
66ac7ddfbfSEd Maste 
GetRegisterCount()67435933ddSDimitry Andric size_t RegisterContextThreadMemory::GetRegisterCount() {
68ac7ddfbfSEd Maste   UpdateRegisterContext();
69ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
70ac7ddfbfSEd Maste     return m_reg_ctx_sp->GetRegisterCount();
71ac7ddfbfSEd Maste   return 0;
72ac7ddfbfSEd Maste }
73ac7ddfbfSEd Maste 
74ac7ddfbfSEd Maste const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)75435933ddSDimitry Andric RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
76ac7ddfbfSEd Maste   UpdateRegisterContext();
77ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
78ac7ddfbfSEd Maste     return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
79ac7ddfbfSEd Maste   return NULL;
80ac7ddfbfSEd Maste }
81ac7ddfbfSEd Maste 
GetRegisterSetCount()82435933ddSDimitry Andric size_t RegisterContextThreadMemory::GetRegisterSetCount() {
83ac7ddfbfSEd Maste   UpdateRegisterContext();
84ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
85ac7ddfbfSEd Maste     return m_reg_ctx_sp->GetRegisterSetCount();
86ac7ddfbfSEd Maste   return 0;
87ac7ddfbfSEd Maste }
88ac7ddfbfSEd Maste 
GetRegisterSet(size_t reg_set)89435933ddSDimitry Andric const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
90ac7ddfbfSEd Maste   UpdateRegisterContext();
91ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
92ac7ddfbfSEd Maste     return m_reg_ctx_sp->GetRegisterSet(reg_set);
93ac7ddfbfSEd Maste   return NULL;
94ac7ddfbfSEd Maste }
95ac7ddfbfSEd Maste 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)96435933ddSDimitry Andric bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
97435933ddSDimitry Andric                                                RegisterValue &reg_value) {
98ac7ddfbfSEd Maste   UpdateRegisterContext();
99ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
100ac7ddfbfSEd Maste     return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
101ac7ddfbfSEd Maste   return false;
102ac7ddfbfSEd Maste }
103ac7ddfbfSEd Maste 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)104435933ddSDimitry Andric bool RegisterContextThreadMemory::WriteRegister(
105435933ddSDimitry Andric     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
106ac7ddfbfSEd Maste   UpdateRegisterContext();
107ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
108ac7ddfbfSEd Maste     return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
109ac7ddfbfSEd Maste   return false;
110ac7ddfbfSEd Maste }
111ac7ddfbfSEd Maste 
ReadAllRegisterValues(lldb::DataBufferSP & data_sp)112435933ddSDimitry Andric bool RegisterContextThreadMemory::ReadAllRegisterValues(
113435933ddSDimitry Andric     lldb::DataBufferSP &data_sp) {
114ac7ddfbfSEd Maste   UpdateRegisterContext();
115ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
116ac7ddfbfSEd Maste     return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
117ac7ddfbfSEd Maste   return false;
118ac7ddfbfSEd Maste }
119ac7ddfbfSEd Maste 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)120435933ddSDimitry Andric bool RegisterContextThreadMemory::WriteAllRegisterValues(
121435933ddSDimitry Andric     const lldb::DataBufferSP &data_sp) {
122ac7ddfbfSEd Maste   UpdateRegisterContext();
123ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
124ac7ddfbfSEd Maste     return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
125ac7ddfbfSEd Maste   return false;
126ac7ddfbfSEd Maste }
127ac7ddfbfSEd Maste 
CopyFromRegisterContext(lldb::RegisterContextSP reg_ctx_sp)128435933ddSDimitry Andric bool RegisterContextThreadMemory::CopyFromRegisterContext(
129435933ddSDimitry Andric     lldb::RegisterContextSP reg_ctx_sp) {
130ac7ddfbfSEd Maste   UpdateRegisterContext();
131ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
132ac7ddfbfSEd Maste     return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
133ac7ddfbfSEd Maste   return false;
134ac7ddfbfSEd Maste }
135ac7ddfbfSEd Maste 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)136435933ddSDimitry Andric uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
137435933ddSDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
138ac7ddfbfSEd Maste   UpdateRegisterContext();
139ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
140ac7ddfbfSEd Maste     return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
141ac7ddfbfSEd Maste   return false;
142ac7ddfbfSEd Maste }
143ac7ddfbfSEd Maste 
NumSupportedHardwareBreakpoints()144435933ddSDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
145ac7ddfbfSEd Maste   UpdateRegisterContext();
146ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
147ac7ddfbfSEd Maste     return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
148ac7ddfbfSEd Maste   return false;
149ac7ddfbfSEd Maste }
150ac7ddfbfSEd Maste 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)151435933ddSDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
152435933ddSDimitry Andric                                                             size_t size) {
153ac7ddfbfSEd Maste   UpdateRegisterContext();
154ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
155ac7ddfbfSEd Maste     return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
156ac7ddfbfSEd Maste   return 0;
157ac7ddfbfSEd Maste }
158ac7ddfbfSEd Maste 
ClearHardwareBreakpoint(uint32_t hw_idx)159435933ddSDimitry Andric bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
160ac7ddfbfSEd Maste   UpdateRegisterContext();
161ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
162ac7ddfbfSEd Maste     return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
163ac7ddfbfSEd Maste   return false;
164ac7ddfbfSEd Maste }
165ac7ddfbfSEd Maste 
NumSupportedHardwareWatchpoints()166435933ddSDimitry Andric uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
167ac7ddfbfSEd Maste   UpdateRegisterContext();
168ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
169ac7ddfbfSEd Maste     return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
170ac7ddfbfSEd Maste   return 0;
171ac7ddfbfSEd Maste }
172ac7ddfbfSEd Maste 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)173435933ddSDimitry Andric uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
174435933ddSDimitry Andric                                                             size_t size,
175435933ddSDimitry Andric                                                             bool read,
176435933ddSDimitry Andric                                                             bool write) {
177ac7ddfbfSEd Maste   UpdateRegisterContext();
178ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
179ac7ddfbfSEd Maste     return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
180ac7ddfbfSEd Maste   return 0;
181ac7ddfbfSEd Maste }
182ac7ddfbfSEd Maste 
ClearHardwareWatchpoint(uint32_t hw_index)183435933ddSDimitry Andric bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
184ac7ddfbfSEd Maste   UpdateRegisterContext();
185ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
186ac7ddfbfSEd Maste     return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
187ac7ddfbfSEd Maste   return false;
188ac7ddfbfSEd Maste }
189ac7ddfbfSEd Maste 
HardwareSingleStep(bool enable)190435933ddSDimitry Andric bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
191ac7ddfbfSEd Maste   UpdateRegisterContext();
192ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
193ac7ddfbfSEd Maste     return m_reg_ctx_sp->HardwareSingleStep(enable);
194ac7ddfbfSEd Maste   return false;
195ac7ddfbfSEd Maste }
196ac7ddfbfSEd Maste 
ReadRegisterValueFromMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)197*5517e702SDimitry Andric Status RegisterContextThreadMemory::ReadRegisterValueFromMemory(
198435933ddSDimitry Andric     const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
199435933ddSDimitry Andric     uint32_t src_len, RegisterValue &reg_value) {
200ac7ddfbfSEd Maste   UpdateRegisterContext();
201ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
202435933ddSDimitry Andric     return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
203435933ddSDimitry Andric                                                      src_len, reg_value);
204*5517e702SDimitry Andric   Status error;
205ac7ddfbfSEd Maste   error.SetErrorString("invalid register context");
206ac7ddfbfSEd Maste   return error;
207ac7ddfbfSEd Maste }
208ac7ddfbfSEd Maste 
WriteRegisterValueToMemory(const lldb_private::RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)209*5517e702SDimitry Andric Status RegisterContextThreadMemory::WriteRegisterValueToMemory(
210435933ddSDimitry Andric     const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
211435933ddSDimitry Andric     uint32_t dst_len, const RegisterValue &reg_value) {
212ac7ddfbfSEd Maste   UpdateRegisterContext();
213ac7ddfbfSEd Maste   if (m_reg_ctx_sp)
214435933ddSDimitry Andric     return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
215435933ddSDimitry Andric                                                     reg_value);
216*5517e702SDimitry Andric   Status error;
217ac7ddfbfSEd Maste   error.SetErrorString("invalid register context");
218ac7ddfbfSEd Maste   return error;
219ac7ddfbfSEd Maste }
220