LLDB  mainline
RegisterContextPOSIXProcessMonitor_powerpc.cpp
Go to the documentation of this file.
1 //===-- RegisterContextPOSIXProcessMonitor_powerpc.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 
13 #include "ProcessFreeBSD.h"
14 #include "ProcessMonitor.h"
17 
18 using namespace lldb_private;
19 using namespace lldb;
20 
21 #define REG_CONTEXT_SIZE (GetGPRSize())
22 
25  Thread &thread, uint32_t concrete_frame_idx,
27  : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
28 
29 ProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
30  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_powerpc, GetGPRSize());
38 }
39 
41  ProcessMonitor &monitor = GetMonitor();
42  return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
43  sizeof(m_fpr_powerpc));
44 }
45 
47  // XXX: Need a way to read/write process VMX registers with ptrace.
48  return false;
49 }
50 
52  ProcessMonitor &monitor = GetMonitor();
53  return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
54 }
55 
57  ProcessMonitor &monitor = GetMonitor();
58  return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
59  sizeof(m_fpr_powerpc));
60 }
61 
63  // XXX: Need a way to read/write process VMX registers with ptrace.
64  return false;
65 }
66 
68  const unsigned reg, RegisterValue &value) {
69  ProcessMonitor &monitor = GetMonitor();
70  return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
72  value);
73 }
74 
76  const unsigned reg, const RegisterValue &value) {
77  unsigned reg_to_write = reg;
78  RegisterValue value_to_write = value;
79 
80  // Check if this is a subregister of a full register.
81  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
82  if (reg_info->invalidate_regs &&
83  (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
84  RegisterValue full_value;
85  uint32_t full_reg = reg_info->invalidate_regs[0];
86  const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
87 
88  // Read the full register.
89  if (ReadRegister(full_reg_info, full_value)) {
90  Status error;
91  ByteOrder byte_order = GetByteOrder();
92  uint8_t dst[RegisterValue::kMaxRegisterByteSize];
93 
94  // Get the bytes for the full register.
95  const uint32_t dest_size = full_value.GetAsMemoryData(
96  full_reg_info, dst, sizeof(dst), byte_order, error);
97  if (error.Success() && dest_size) {
98  uint8_t src[RegisterValue::kMaxRegisterByteSize];
99 
100  // Get the bytes for the source data.
101  const uint32_t src_size = value.GetAsMemoryData(
102  reg_info, src, sizeof(src), byte_order, error);
103  if (error.Success() && src_size && (src_size < dest_size)) {
104  // Copy the src bytes to the destination.
105  memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
106  // Set this full register as the value to write.
107  value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
108  value_to_write.SetType(full_reg_info);
109  reg_to_write = full_reg;
110  }
111  }
112  }
113  }
114 
115  ProcessMonitor &monitor = GetMonitor();
116  // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
117  // registers in ptrace, but expose here 32-bit registers with a higher
118  // offset.
119  uint64_t offset = GetRegisterOffset(reg_to_write);
120  offset &= ~(sizeof(uintptr_t) - 1);
121  return monitor.WriteRegisterValue(
122  m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
123 }
124 
126  const RegisterInfo *reg_info, RegisterValue &value) {
127  if (!reg_info)
128  return false;
129 
130  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
131 
132  if (IsFPR(reg)) {
133  if (!ReadFPR())
134  return false;
135  uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
136  value.SetUInt64(*(uint64_t *)src);
137  } else if (IsGPR(reg)) {
138  bool success = ReadRegister(reg, value);
139 
140  if (success) {
141  // If our return byte size was greater than the return value reg size,
142  // then use the type specified by reg_info rather than the uint64_t
143  // default
144  if (value.GetByteSize() > reg_info->byte_size)
145  value.SetType(reg_info);
146  }
147  return success;
148  }
149 
150  return false;
151 }
152 
154  const RegisterInfo *reg_info, const RegisterValue &value) {
155  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
156 
157  if (IsGPR(reg)) {
158  return WriteRegister(reg, value);
159  } else if (IsFPR(reg)) {
160  assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
161  uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
162  *(uint64_t *)dst = value.GetAsUInt64();
163  return WriteFPR();
164  }
165 
166  return false;
167 }
168 
170  DataBufferSP &data_sp) {
171  bool success = false;
172  data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
173  if (data_sp && ReadGPR() && ReadFPR()) {
174  uint8_t *dst = data_sp->GetBytes();
175  success = dst != 0;
176 
177  if (success) {
178  ::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
179  dst += GetGPRSize();
180  }
181  }
182  return success;
183 }
184 
186  const DataBufferSP &data_sp) {
187  bool success = false;
188  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
189  uint8_t *src = data_sp->GetBytes();
190  if (src) {
191  ::memcpy(&m_gpr_powerpc, src, GetGPRSize());
192 
193  if (WriteGPR()) {
194  src += GetGPRSize();
195  ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
196 
197  success = WriteFPR();
198  }
199  }
200  }
201  return success;
202 }
203 
205  addr_t addr, size_t size, bool read, bool write) {
206  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
207  uint32_t hw_index;
208 
209  for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
210  if (IsWatchpointVacant(hw_index))
211  return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
212  }
213 
214  return LLDB_INVALID_INDEX32;
215 }
216 
218  uint32_t hw_index) {
219  return false;
220 }
221 
223  bool enable) {
224  return false;
225 }
226 
229 
230  if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
231  return false;
232 
233  return true;
234 }
235 
237  unsigned offset) {
238  unsigned reg;
239  for (reg = 0; reg < k_num_registers_powerpc; reg++) {
240  if (GetRegisterInfo()[reg].byte_offset == offset)
241  break;
242  }
243  assert(reg < k_num_registers_powerpc && "Invalid register offset.");
244  return reg;
245 }
246 
248  uint32_t hw_index) {
249  return false;
250 }
251 
253  return false;
254 }
255 
257  uint32_t hw_index) {
258  return LLDB_INVALID_ADDRESS;
259 }
260 
262  uint32_t hw_index) {
263  return false;
264 }
265 
267  addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
268  return false;
269 }
270 
271 uint32_t
273  return 0;
274 }
virtual unsigned GetRegisterOffset(unsigned reg)
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]
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
uint64_t m_fpr_powerpc[k_num_fpr_registers_powerpc]
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
A subclass of DataBuffer that stores a data buffer on the heap.
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
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
bool UpdateAfterBreakpoint()
Updates the register state of the associated thread after hitting a breakpoint (if that make sense fo...
uint64_t GetPC(uint64_t fail_value=LLDB_INVALID_ADDRESS)
ProcessMonitor & GetMonitor()
bool Success() const
Test for success condition.
Definition: Status.cpp:287
virtual const lldb_private::RegisterInfo * GetRegisterInfo()
virtual unsigned GetRegisterSize(unsigned reg)
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
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write)
bool WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value)
Definition: SBAddress.h:15
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 char * GetRegisterName(unsigned reg)
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value)
unsigned GetRegisterIndexFromOffset(unsigned offset)
Determines the index in lldb&#39;s register file given a kernel byte offset.
RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *register_info)
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...
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
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