1254721Semaste//===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "lldb/Target/OperatingSystem.h"
10254721Semaste#include "lldb/Target/Process.h"
11254721Semaste#include "lldb/Target/Thread.h"
12321369Sdim#include "lldb/Utility/Status.h"
13314564Sdim#include "lldb/lldb-private.h"
14254721Semaste
15254721Semaste#include "RegisterContextThreadMemory.h"
16254721Semaste
17254721Semasteusing namespace lldb;
18254721Semasteusing namespace lldb_private;
19254721Semaste
20314564SdimRegisterContextThreadMemory::RegisterContextThreadMemory(
21314564Sdim    Thread &thread, lldb::addr_t register_data_addr)
22314564Sdim    : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
23314564Sdim      m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
24254721Semaste
25314564SdimRegisterContextThreadMemory::~RegisterContextThreadMemory() {}
26254721Semaste
27314564Sdimvoid RegisterContextThreadMemory::UpdateRegisterContext() {
28314564Sdim  ThreadSP thread_sp(m_thread_wp.lock());
29314564Sdim  if (thread_sp) {
30314564Sdim    ProcessSP process_sp(thread_sp->GetProcess());
31254721Semaste
32314564Sdim    if (process_sp) {
33314564Sdim      const uint32_t stop_id = process_sp->GetModID().GetStopID();
34314564Sdim      if (m_stop_id != stop_id) {
35314564Sdim        m_stop_id = stop_id;
36314564Sdim        m_reg_ctx_sp.reset();
37314564Sdim      }
38314564Sdim      if (!m_reg_ctx_sp) {
39314564Sdim        ThreadSP backing_thread_sp(thread_sp->GetBackingThread());
40314564Sdim        if (backing_thread_sp) {
41314564Sdim          m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
42314564Sdim        } else {
43314564Sdim          OperatingSystem *os = process_sp->GetOperatingSystem();
44314564Sdim          if (os->IsOperatingSystemPluginThread(thread_sp))
45314564Sdim            m_reg_ctx_sp = os->CreateRegisterContextForThread(
46314564Sdim                thread_sp.get(), m_register_data_addr);
47254721Semaste        }
48314564Sdim      }
49314564Sdim    } else {
50314564Sdim      m_reg_ctx_sp.reset();
51254721Semaste    }
52314564Sdim  } else {
53314564Sdim    m_reg_ctx_sp.reset();
54314564Sdim  }
55254721Semaste}
56254721Semaste
57254721Semaste// Subclasses must override these functions
58314564Sdimvoid RegisterContextThreadMemory::InvalidateAllRegisters() {
59314564Sdim  UpdateRegisterContext();
60314564Sdim  if (m_reg_ctx_sp)
61314564Sdim    m_reg_ctx_sp->InvalidateAllRegisters();
62254721Semaste}
63254721Semaste
64314564Sdimsize_t RegisterContextThreadMemory::GetRegisterCount() {
65314564Sdim  UpdateRegisterContext();
66314564Sdim  if (m_reg_ctx_sp)
67314564Sdim    return m_reg_ctx_sp->GetRegisterCount();
68314564Sdim  return 0;
69254721Semaste}
70254721Semaste
71254721Semasteconst RegisterInfo *
72314564SdimRegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) {
73314564Sdim  UpdateRegisterContext();
74314564Sdim  if (m_reg_ctx_sp)
75314564Sdim    return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
76353358Sdim  return nullptr;
77254721Semaste}
78254721Semaste
79314564Sdimsize_t RegisterContextThreadMemory::GetRegisterSetCount() {
80314564Sdim  UpdateRegisterContext();
81314564Sdim  if (m_reg_ctx_sp)
82314564Sdim    return m_reg_ctx_sp->GetRegisterSetCount();
83314564Sdim  return 0;
84254721Semaste}
85254721Semaste
86314564Sdimconst RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) {
87314564Sdim  UpdateRegisterContext();
88314564Sdim  if (m_reg_ctx_sp)
89314564Sdim    return m_reg_ctx_sp->GetRegisterSet(reg_set);
90353358Sdim  return nullptr;
91254721Semaste}
92254721Semaste
93314564Sdimbool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info,
94314564Sdim                                               RegisterValue &reg_value) {
95314564Sdim  UpdateRegisterContext();
96314564Sdim  if (m_reg_ctx_sp)
97314564Sdim    return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
98314564Sdim  return false;
99254721Semaste}
100254721Semaste
101314564Sdimbool RegisterContextThreadMemory::WriteRegister(
102314564Sdim    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
103314564Sdim  UpdateRegisterContext();
104314564Sdim  if (m_reg_ctx_sp)
105314564Sdim    return m_reg_ctx_sp->WriteRegister(reg_info, reg_value);
106314564Sdim  return false;
107254721Semaste}
108254721Semaste
109314564Sdimbool RegisterContextThreadMemory::ReadAllRegisterValues(
110314564Sdim    lldb::DataBufferSP &data_sp) {
111314564Sdim  UpdateRegisterContext();
112314564Sdim  if (m_reg_ctx_sp)
113314564Sdim    return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
114314564Sdim  return false;
115254721Semaste}
116254721Semaste
117314564Sdimbool RegisterContextThreadMemory::WriteAllRegisterValues(
118314564Sdim    const lldb::DataBufferSP &data_sp) {
119314564Sdim  UpdateRegisterContext();
120314564Sdim  if (m_reg_ctx_sp)
121314564Sdim    return m_reg_ctx_sp->WriteAllRegisterValues(data_sp);
122314564Sdim  return false;
123254721Semaste}
124254721Semaste
125314564Sdimbool RegisterContextThreadMemory::CopyFromRegisterContext(
126314564Sdim    lldb::RegisterContextSP reg_ctx_sp) {
127314564Sdim  UpdateRegisterContext();
128314564Sdim  if (m_reg_ctx_sp)
129314564Sdim    return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
130314564Sdim  return false;
131254721Semaste}
132254721Semaste
133314564Sdimuint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber(
134314564Sdim    lldb::RegisterKind kind, uint32_t num) {
135314564Sdim  UpdateRegisterContext();
136314564Sdim  if (m_reg_ctx_sp)
137314564Sdim    return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
138314564Sdim  return false;
139254721Semaste}
140254721Semaste
141314564Sdimuint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() {
142314564Sdim  UpdateRegisterContext();
143314564Sdim  if (m_reg_ctx_sp)
144314564Sdim    return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
145314564Sdim  return false;
146254721Semaste}
147254721Semaste
148314564Sdimuint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr,
149314564Sdim                                                            size_t size) {
150314564Sdim  UpdateRegisterContext();
151314564Sdim  if (m_reg_ctx_sp)
152314564Sdim    return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
153314564Sdim  return 0;
154254721Semaste}
155254721Semaste
156314564Sdimbool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) {
157314564Sdim  UpdateRegisterContext();
158314564Sdim  if (m_reg_ctx_sp)
159314564Sdim    return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx);
160314564Sdim  return false;
161254721Semaste}
162254721Semaste
163314564Sdimuint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() {
164314564Sdim  UpdateRegisterContext();
165314564Sdim  if (m_reg_ctx_sp)
166314564Sdim    return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
167314564Sdim  return 0;
168254721Semaste}
169254721Semaste
170314564Sdimuint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr,
171314564Sdim                                                            size_t size,
172314564Sdim                                                            bool read,
173314564Sdim                                                            bool write) {
174314564Sdim  UpdateRegisterContext();
175314564Sdim  if (m_reg_ctx_sp)
176314564Sdim    return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
177314564Sdim  return 0;
178254721Semaste}
179254721Semaste
180314564Sdimbool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) {
181314564Sdim  UpdateRegisterContext();
182314564Sdim  if (m_reg_ctx_sp)
183314564Sdim    return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
184314564Sdim  return false;
185254721Semaste}
186254721Semaste
187314564Sdimbool RegisterContextThreadMemory::HardwareSingleStep(bool enable) {
188314564Sdim  UpdateRegisterContext();
189314564Sdim  if (m_reg_ctx_sp)
190314564Sdim    return m_reg_ctx_sp->HardwareSingleStep(enable);
191314564Sdim  return false;
192254721Semaste}
193254721Semaste
194321369SdimStatus RegisterContextThreadMemory::ReadRegisterValueFromMemory(
195314564Sdim    const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr,
196314564Sdim    uint32_t src_len, RegisterValue &reg_value) {
197314564Sdim  UpdateRegisterContext();
198314564Sdim  if (m_reg_ctx_sp)
199314564Sdim    return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr,
200314564Sdim                                                     src_len, reg_value);
201321369Sdim  Status error;
202314564Sdim  error.SetErrorString("invalid register context");
203314564Sdim  return error;
204254721Semaste}
205254721Semaste
206321369SdimStatus RegisterContextThreadMemory::WriteRegisterValueToMemory(
207314564Sdim    const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr,
208314564Sdim    uint32_t dst_len, const RegisterValue &reg_value) {
209314564Sdim  UpdateRegisterContext();
210314564Sdim  if (m_reg_ctx_sp)
211314564Sdim    return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len,
212314564Sdim                                                    reg_value);
213321369Sdim  Status error;
214314564Sdim  error.SetErrorString("invalid register context");
215314564Sdim  return error;
216254721Semaste}
217