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
18using namespace lldb;
19using namespace lldb_private;
20
21RegisterContextThreadMemory::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
31RegisterContextThreadMemory::~RegisterContextThreadMemory()
32{
33}
34
35void
36RegisterContextThreadMemory::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//------------------------------------------------------------------
80void
81RegisterContextThreadMemory::InvalidateAllRegisters ()
82{
83    UpdateRegisterContext ();
84    if (m_reg_ctx_sp)
85        m_reg_ctx_sp->InvalidateAllRegisters();
86}
87
88size_t
89RegisterContextThreadMemory::GetRegisterCount ()
90{
91    UpdateRegisterContext ();
92    if (m_reg_ctx_sp)
93        return m_reg_ctx_sp->GetRegisterCount();
94    return 0;
95}
96
97const RegisterInfo *
98RegisterContextThreadMemory::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
106size_t
107RegisterContextThreadMemory::GetRegisterSetCount ()
108{
109    UpdateRegisterContext ();
110    if (m_reg_ctx_sp)
111        return m_reg_ctx_sp->GetRegisterSetCount();
112    return 0;
113}
114
115const RegisterSet *
116RegisterContextThreadMemory::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
124bool
125RegisterContextThreadMemory::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
133bool
134RegisterContextThreadMemory::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
142bool
143RegisterContextThreadMemory::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
151bool
152RegisterContextThreadMemory::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
160bool
161RegisterContextThreadMemory::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
169uint32_t
170RegisterContextThreadMemory::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
178uint32_t
179RegisterContextThreadMemory::NumSupportedHardwareBreakpoints ()
180{
181    UpdateRegisterContext ();
182    if (m_reg_ctx_sp)
183        return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
184    return false;
185}
186
187uint32_t
188RegisterContextThreadMemory::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
196bool
197RegisterContextThreadMemory::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
205uint32_t
206RegisterContextThreadMemory::NumSupportedHardwareWatchpoints ()
207{
208    UpdateRegisterContext ();
209    if (m_reg_ctx_sp)
210        return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
211    return 0;
212}
213
214uint32_t
215RegisterContextThreadMemory::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
223bool
224RegisterContextThreadMemory::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
232bool
233RegisterContextThreadMemory::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
241Error
242RegisterContextThreadMemory::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
252Error
253RegisterContextThreadMemory::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