RegisterContextPOSIXProcessMonitor_powerpc.cpp revision 321369
1266077Sdes//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp ----------*- C++ -*-===//
2266077Sdes//
3266077Sdes//                     The LLVM Compiler Infrastructure
4266077Sdes//
5266077Sdes// This file is distributed under the University of Illinois Open Source
6266077Sdes// License. See LICENSE.TXT for details.
7266077Sdes//
8266077Sdes//===----------------------------------------------------------------------===//
9266077Sdes
10266077Sdes#include "lldb/Core/RegisterValue.h"
11266077Sdes#include "lldb/Target/Thread.h"
12266077Sdes#include "lldb/Utility/DataBufferHeap.h"
13266077Sdes
14266077Sdes#include "ProcessFreeBSD.h"
15266077Sdes#include "ProcessMonitor.h"
16287915Sdes#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
17287915Sdes#include "RegisterContextPOSIX_powerpc.h"
18266077Sdes
19266077Sdesusing namespace lldb_private;
20266077Sdesusing namespace lldb;
21266077Sdes
22266077Sdes#define REG_CONTEXT_SIZE (GetGPRSize())
23266077Sdes
24266077SdesRegisterContextPOSIXProcessMonitor_powerpc::
25266077Sdes    RegisterContextPOSIXProcessMonitor_powerpc(
26266077Sdes        Thread &thread, uint32_t concrete_frame_idx,
27266077Sdes        lldb_private::RegisterInfoInterface *register_info)
28266077Sdes    : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
29266077Sdes
30266077SdesProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
31266077Sdes  ProcessSP base = CalculateProcess();
32266077Sdes  ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
33266077Sdes  return process->GetMonitor();
34266077Sdes}
35266077Sdes
36266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() {
37266077Sdes  ProcessMonitor &monitor = GetMonitor();
38266077Sdes  return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
39266077Sdes}
40266077Sdes
41266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() {
42266077Sdes  ProcessMonitor &monitor = GetMonitor();
43266077Sdes  return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
44266077Sdes                         sizeof(m_fpr_powerpc));
45266077Sdes}
46266077Sdes
47266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() {
48266077Sdes  // XXX: Need a way to read/write process VMX registers with ptrace.
49266077Sdes  return false;
50266077Sdes}
51266077Sdes
52266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() {
53266077Sdes  ProcessMonitor &monitor = GetMonitor();
54266077Sdes  return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
55266077Sdes}
56266077Sdes
57266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() {
58266077Sdes  ProcessMonitor &monitor = GetMonitor();
59266077Sdes  return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
60266077Sdes                          sizeof(m_fpr_powerpc));
61266077Sdes}
62266077Sdes
63266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() {
64266077Sdes  // XXX: Need a way to read/write process VMX registers with ptrace.
65266077Sdes  return false;
66266077Sdes}
67266077Sdes
68266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
69266077Sdes    const unsigned reg, RegisterValue &value) {
70266077Sdes  ProcessMonitor &monitor = GetMonitor();
71266077Sdes  return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
72266077Sdes                                   GetRegisterName(reg), GetRegisterSize(reg),
73266077Sdes                                   value);
74266077Sdes}
75266077Sdes
76266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
77266077Sdes    const unsigned reg, const RegisterValue &value) {
78266077Sdes  unsigned reg_to_write = reg;
79266077Sdes  RegisterValue value_to_write = value;
80266077Sdes
81266077Sdes  // Check if this is a subregister of a full register.
82266077Sdes  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
83266077Sdes  if (reg_info->invalidate_regs &&
84266077Sdes      (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
85266077Sdes    RegisterValue full_value;
86266077Sdes    uint32_t full_reg = reg_info->invalidate_regs[0];
87266077Sdes    const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
88266077Sdes
89266077Sdes    // Read the full register.
90266077Sdes    if (ReadRegister(full_reg_info, full_value)) {
91266077Sdes      Status error;
92266077Sdes      ByteOrder byte_order = GetByteOrder();
93266077Sdes      uint8_t dst[RegisterValue::kMaxRegisterByteSize];
94266077Sdes
95266077Sdes      // Get the bytes for the full register.
96266077Sdes      const uint32_t dest_size = full_value.GetAsMemoryData(
97266077Sdes          full_reg_info, dst, sizeof(dst), byte_order, error);
98266077Sdes      if (error.Success() && dest_size) {
99266077Sdes        uint8_t src[RegisterValue::kMaxRegisterByteSize];
100266077Sdes
101266077Sdes        // Get the bytes for the source data.
102266077Sdes        const uint32_t src_size = value.GetAsMemoryData(
103266077Sdes            reg_info, src, sizeof(src), byte_order, error);
104266077Sdes        if (error.Success() && src_size && (src_size < dest_size)) {
105266077Sdes          // Copy the src bytes to the destination.
106266077Sdes          memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
107266077Sdes          // Set this full register as the value to write.
108266077Sdes          value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
109266077Sdes          value_to_write.SetType(full_reg_info);
110266077Sdes          reg_to_write = full_reg;
111266077Sdes        }
112266077Sdes      }
113266077Sdes    }
114266077Sdes  }
115266077Sdes
116266077Sdes  ProcessMonitor &monitor = GetMonitor();
117266077Sdes  // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
118266077Sdes  // registers in ptrace, but expose here 32-bit registers with a higher
119266077Sdes  // offset.
120266077Sdes  uint64_t offset = GetRegisterOffset(reg_to_write);
121266077Sdes  offset &= ~(sizeof(uintptr_t) - 1);
122266077Sdes  return monitor.WriteRegisterValue(
123266077Sdes      m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
124266077Sdes}
125266077Sdes
126266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
127266077Sdes    const RegisterInfo *reg_info, RegisterValue &value) {
128266077Sdes  if (!reg_info)
129266077Sdes    return false;
130266077Sdes
131266077Sdes  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
132266077Sdes
133266077Sdes  if (IsFPR(reg)) {
134266077Sdes    if (!ReadFPR())
135266077Sdes      return false;
136266077Sdes    uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
137266077Sdes    value.SetUInt64(*(uint64_t *)src);
138266077Sdes  } else if (IsGPR(reg)) {
139266077Sdes    bool success = ReadRegister(reg, value);
140266077Sdes
141266077Sdes    if (success) {
142266077Sdes      // If our return byte size was greater than the return value reg size,
143266077Sdes      // then
144266077Sdes      // use the type specified by reg_info rather than the uint64_t default
145266077Sdes      if (value.GetByteSize() > reg_info->byte_size)
146266077Sdes        value.SetType(reg_info);
147296415Sdes    }
148296415Sdes    return success;
149296415Sdes  }
150296415Sdes
151296415Sdes  return false;
152296415Sdes}
153266077Sdes
154266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
155266077Sdes    const RegisterInfo *reg_info, const RegisterValue &value) {
156266077Sdes  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
157266077Sdes
158266077Sdes  if (IsGPR(reg)) {
159266077Sdes    return WriteRegister(reg, value);
160266077Sdes  } else if (IsFPR(reg)) {
161266077Sdes    assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
162266077Sdes    uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
163266077Sdes    *(uint64_t *)dst = value.GetAsUInt64();
164266077Sdes    return WriteFPR();
165266077Sdes  }
166266077Sdes
167266077Sdes  return false;
168266077Sdes}
169266077Sdes
170266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(
171266077Sdes    DataBufferSP &data_sp) {
172266077Sdes  bool success = false;
173266077Sdes  data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
174266077Sdes  if (data_sp && ReadGPR() && ReadFPR()) {
175266077Sdes    uint8_t *dst = data_sp->GetBytes();
176266077Sdes    success = dst != 0;
177266077Sdes
178266077Sdes    if (success) {
179266077Sdes      ::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
180266077Sdes      dst += GetGPRSize();
181266077Sdes    }
182266077Sdes  }
183266077Sdes  return success;
184266077Sdes}
185266077Sdes
186266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(
187266077Sdes    const DataBufferSP &data_sp) {
188266077Sdes  bool success = false;
189266077Sdes  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
190266077Sdes    uint8_t *src = data_sp->GetBytes();
191266077Sdes    if (src) {
192266077Sdes      ::memcpy(&m_gpr_powerpc, src, GetGPRSize());
193266077Sdes
194266077Sdes      if (WriteGPR()) {
195266077Sdes        src += GetGPRSize();
196266077Sdes        ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
197266077Sdes
198266077Sdes        success = WriteFPR();
199266077Sdes      }
200266077Sdes    }
201266077Sdes  }
202266077Sdes  return success;
203266077Sdes}
204266077Sdes
205266077Sdesuint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(
206266077Sdes    addr_t addr, size_t size, bool read, bool write) {
207266077Sdes  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
208266077Sdes  uint32_t hw_index;
209266077Sdes
210266077Sdes  for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
211266077Sdes    if (IsWatchpointVacant(hw_index))
212266077Sdes      return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
213266077Sdes  }
214266077Sdes
215266077Sdes  return LLDB_INVALID_INDEX32;
216266077Sdes}
217266077Sdes
218266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(
219266077Sdes    uint32_t hw_index) {
220266077Sdes  return false;
221266077Sdes}
222266077Sdes
223266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(
224266077Sdes    bool enable) {
225266077Sdes  return false;
226266077Sdes}
227266077Sdes
228266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() {
229266077Sdes  lldb::addr_t pc;
230266077Sdes
231266077Sdes  if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
232266077Sdes    return false;
233266077Sdes
234266077Sdes  return true;
235266077Sdes}
236266077Sdes
237266077Sdesunsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(
238266077Sdes    unsigned offset) {
239266077Sdes  unsigned reg;
240266077Sdes  for (reg = 0; reg < k_num_registers_powerpc; reg++) {
241266077Sdes    if (GetRegisterInfo()[reg].byte_offset == offset)
242266077Sdes      break;
243266077Sdes  }
244266077Sdes  assert(reg < k_num_registers_powerpc && "Invalid register offset.");
245266077Sdes  return reg;
246266077Sdes}
247266077Sdes
248266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(
249266077Sdes    uint32_t hw_index) {
250266077Sdes  return false;
251266077Sdes}
252266077Sdes
253266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() {
254266077Sdes  return false;
255266077Sdes}
256266077Sdes
257266077Sdesaddr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(
258266077Sdes    uint32_t hw_index) {
259266077Sdes  return LLDB_INVALID_ADDRESS;
260266077Sdes}
261266077Sdes
262266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(
263266077Sdes    uint32_t hw_index) {
264266077Sdes  return false;
265266077Sdes}
266266077Sdes
267266077Sdesbool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(
268266077Sdes    addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
269266077Sdes  return false;
270266077Sdes}
271266077Sdes
272266077Sdesuint32_t
273266077SdesRegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() {
274266077Sdes  return 0;
275266077Sdes}
276266077Sdes