LLDB  mainline
RegisterContextPOSIXProcessMonitor_arm64.cpp
Go to the documentation of this file.
1 //===-- RegisterContextPOSIXProcessMonitor_arm64.cpp -----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===---------------------------------------------------------------------===//
8 
9 #include "lldb/Target/Thread.h"
12 
14 #include "ProcessFreeBSD.h"
15 #include "ProcessMonitor.h"
17 
18 #define REG_CONTEXT_SIZE (GetGPRSize())
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
25  lldb_private::Thread &thread, uint32_t concrete_frame_idx,
27  : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info) {}
28 
29 ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() {
30  lldb::ProcessSP base = CalculateProcess();
31  ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
32  return process->GetMonitor();
33 }
34 
36  ProcessMonitor &monitor = GetMonitor();
37  return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
38 }
39 
41  ProcessMonitor &monitor = GetMonitor();
42  return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
43 }
44 
46  ProcessMonitor &monitor = GetMonitor();
47  return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
48 }
49 
51  ProcessMonitor &monitor = GetMonitor();
52  return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
53 }
54 
56  const unsigned reg, lldb_private::RegisterValue &value) {
57  ProcessMonitor &monitor = GetMonitor();
58  return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
60  value);
61 }
62 
64  const unsigned reg, const lldb_private::RegisterValue &value) {
65  unsigned reg_to_write = reg;
66  lldb_private::RegisterValue value_to_write = value;
67 
68  // Check if this is a subregister of a full register.
69  const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
70  if (reg_info->invalidate_regs &&
71  (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
72  lldb_private::RegisterValue full_value;
73  uint32_t full_reg = reg_info->invalidate_regs[0];
74  const lldb_private::RegisterInfo *full_reg_info =
75  GetRegisterInfoAtIndex(full_reg);
76 
77  // Read the full register.
78  if (ReadRegister(full_reg_info, full_value)) {
80  lldb::ByteOrder byte_order = GetByteOrder();
82 
83  // Get the bytes for the full register.
84  const uint32_t dest_size = full_value.GetAsMemoryData(
85  full_reg_info, dst, sizeof(dst), byte_order, error);
86  if (error.Success() && dest_size) {
88 
89  // Get the bytes for the source data.
90  const uint32_t src_size = value.GetAsMemoryData(
91  reg_info, src, sizeof(src), byte_order, error);
92  if (error.Success() && src_size && (src_size < dest_size)) {
93  // Copy the src bytes to the destination.
94  ::memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
95  // Set this full register as the value to write.
96  value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
97  value_to_write.SetType(full_reg_info);
98  reg_to_write = full_reg;
99  }
100  }
101  }
102  }
103 
104  ProcessMonitor &monitor = GetMonitor();
105  return monitor.WriteRegisterValue(
106  m_thread.GetID(), GetRegisterOffset(reg_to_write),
107  GetRegisterName(reg_to_write), value_to_write);
108 }
109 
111  const lldb_private::RegisterInfo *reg_info,
113  if (!reg_info)
114  return false;
115 
116  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
117 
118  if (IsFPR(reg)) {
119  if (!ReadFPR())
120  return false;
121  } else {
122  uint32_t full_reg = reg;
123  bool is_subreg = reg_info->invalidate_regs &&
124  (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
125 
126  if (is_subreg) {
127  // Read the full aligned 64-bit register.
128  full_reg = reg_info->invalidate_regs[0];
129  }
130  return ReadRegister(full_reg, value);
131  }
132 
133  // Get pointer to m_fpr variable and set the data from it.
134  assert(reg_info->byte_offset < sizeof m_fpr);
135  uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
136  switch (reg_info->byte_size) {
137  case 2:
138  value.SetUInt16(*(uint16_t *)src);
139  return true;
140  case 4:
141  value.SetUInt32(*(uint32_t *)src);
142  return true;
143  case 8:
144  value.SetUInt64(*(uint64_t *)src);
145  return true;
146  default:
147  assert(false && "Unhandled data size.");
148  return false;
149  }
150 }
151 
153  const lldb_private::RegisterInfo *reg_info,
154  const lldb_private::RegisterValue &value) {
155  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
156 
157  if (IsGPR(reg))
158  return WriteRegister(reg, value);
159 
160  return false;
161 }
162 
164  lldb::DataBufferSP &data_sp) {
165  bool success = false;
166  data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0));
167  if (data_sp && ReadGPR() && ReadFPR()) {
168  uint8_t *dst = data_sp->GetBytes();
169  success = dst != 0;
170 
171  if (success) {
172  ::memcpy(dst, &m_gpr_arm64, GetGPRSize());
173  dst += GetGPRSize();
174  ::memcpy(dst, &m_fpr, sizeof m_fpr);
175  }
176  }
177  return success;
178 }
179 
181  const lldb::DataBufferSP &data_sp) {
182  bool success = false;
183  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
184  uint8_t *src = data_sp->GetBytes();
185  if (src) {
186  ::memcpy(&m_gpr_arm64, src, GetGPRSize());
187  if (WriteGPR()) {
188  src += GetGPRSize();
189  ::memcpy(&m_fpr, src, sizeof m_fpr);
190  success = WriteFPR();
191  }
192  }
193  }
194  return success;
195 }
196 
198  lldb::addr_t addr, size_t size, bool read, bool write) {
199  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
200  uint32_t hw_index;
201 
202  for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
203  if (IsWatchpointVacant(hw_index))
204  return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
205  }
206 
207  return LLDB_INVALID_INDEX32;
208 }
209 
211  uint32_t hw_index) {
212  return false;
213 }
214 
216  return false;
217 }
218 
220  if (GetPC() == LLDB_INVALID_ADDRESS)
221  return false;
222 
223  return true;
224 }
225 
227  unsigned offset) {
228  unsigned reg;
229  for (reg = 0; reg < k_num_registers_arm64; reg++) {
230  if (GetRegisterInfo()[reg].byte_offset == offset)
231  break;
232  }
233  assert(reg < k_num_registers_arm64 && "Invalid register offset.");
234  return reg;
235 }
236 
238  uint32_t hw_index) {
239  return false;
240 }
241 
243  return false;
244 }
245 
247  uint32_t hw_index) {
248  return LLDB_INVALID_ADDRESS;
249 }
250 
252  uint32_t hw_index) {
253  return false;
254 }
255 
257  lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
258  return false;
259 }
260 
261 uint32_t
263  return 0;
264 }
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
uint64_t m_gpr_arm64[lldb_private::k_num_gpr_registers_arm64]
RegisterInfo interface to patch RegisterInfo structure for archs.
uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
bool WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value)
bool UpdateAfterBreakpoint()
Updates the register state of the associated thread after hitting a breakpoint (if that make sense fo...
A subclass of DataBuffer that stores a data buffer on the heap.
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
const char * GetRegisterName(unsigned reg)
void SetUInt16(uint16_t uint)
bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
Reads all floating point registers into the specified buffer.
Manages communication with the inferior (debugee) process.
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
#define LLDB_INVALID_INDEX32
Definition: lldb-defines.h:86
struct RegisterContextPOSIX_arm64::FPU m_fpr
uint64_t GetPC(uint64_t fail_value=LLDB_INVALID_ADDRESS)
ProcessMonitor & GetMonitor()
unsigned GetRegisterIndexFromOffset(unsigned offset)
Determines the index in lldb&#39;s register file given a kernel byte offset.
RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *register_info)
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write)
bool Success() const
Test for success condition.
Definition: Status.cpp:287
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index)
bool WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
Writes all floating point registers into the specified buffer.
uint64_t addr_t
Definition: lldb-types.h:83
virtual unsigned GetRegisterOffset(unsigned reg)
Definition: SBAddress.h:15
virtual unsigned GetRegisterSize(unsigned reg)
virtual const lldb_private::RegisterInfo * GetRegisterInfo()
bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size, lldb_private::RegisterValue &value)
Reads the contents from the register identified by the given (architecture dependent) offset...
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
lldb::ProcessSP CalculateProcess() override
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
void SetType(RegisterValue::Type type)
Definition: RegisterValue.h:83
bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
Reads all general purpose registers into the specified buffer.
bool WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, const lldb_private::RegisterValue &value)
Writes the given value to the register identified by the given (architecture dependent) offset...
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value)
An error handling class.
Definition: Status.h:44
bool WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
Writes all general purpose registers into the specified buffer.
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90