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