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