1314564Sdim//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp ----------*- C++ -*-===//
2285101Semaste//
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
6285101Semaste//
7314564Sdim//===----------------------------------------------------------------------===//
8285101Semaste
9285101Semaste#include "lldb/Target/Thread.h"
10321369Sdim#include "lldb/Utility/DataBufferHeap.h"
11344779Sdim#include "lldb/Utility/RegisterValue.h"
12285101Semaste
13296417Sdim#include "ProcessFreeBSD.h"
14314564Sdim#include "ProcessMonitor.h"
15285101Semaste#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
16341825Sdim#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
17285101Semaste
18285101Semasteusing namespace lldb_private;
19285101Semasteusing namespace lldb;
20285101Semaste
21285101Semaste#define REG_CONTEXT_SIZE (GetGPRSize())
22285101Semaste
23314564SdimRegisterContextPOSIXProcessMonitor_powerpc::
24314564Sdim    RegisterContextPOSIXProcessMonitor_powerpc(
25314564Sdim        Thread &thread, uint32_t concrete_frame_idx,
26314564Sdim        lldb_private::RegisterInfoInterface *register_info)
27314564Sdim    : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
28285101Semaste
29314564SdimProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
30314564Sdim  ProcessSP base = CalculateProcess();
31314564Sdim  ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
32314564Sdim  return process->GetMonitor();
33285101Semaste}
34285101Semaste
35314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() {
36314564Sdim  ProcessMonitor &monitor = GetMonitor();
37314564Sdim  return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
38285101Semaste}
39285101Semaste
40314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() {
41314564Sdim  ProcessMonitor &monitor = GetMonitor();
42314564Sdim  return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
43314564Sdim                         sizeof(m_fpr_powerpc));
44285101Semaste}
45285101Semaste
46314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() {
47314564Sdim  // XXX: Need a way to read/write process VMX registers with ptrace.
48314564Sdim  return false;
49285101Semaste}
50285101Semaste
51314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() {
52314564Sdim  ProcessMonitor &monitor = GetMonitor();
53314564Sdim  return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
54285101Semaste}
55285101Semaste
56314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() {
57314564Sdim  ProcessMonitor &monitor = GetMonitor();
58314564Sdim  return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
59314564Sdim                          sizeof(m_fpr_powerpc));
60285101Semaste}
61285101Semaste
62314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() {
63314564Sdim  // XXX: Need a way to read/write process VMX registers with ptrace.
64314564Sdim  return false;
65285101Semaste}
66285101Semaste
67314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
68314564Sdim    const unsigned reg, RegisterValue &value) {
69314564Sdim  ProcessMonitor &monitor = GetMonitor();
70314564Sdim  return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
71314564Sdim                                   GetRegisterName(reg), GetRegisterSize(reg),
72314564Sdim                                   value);
73285101Semaste}
74285101Semaste
75314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
76314564Sdim    const unsigned reg, const RegisterValue &value) {
77314564Sdim  unsigned reg_to_write = reg;
78314564Sdim  RegisterValue value_to_write = value;
79285101Semaste
80314564Sdim  // Check if this is a subregister of a full register.
81314564Sdim  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
82314564Sdim  if (reg_info->invalidate_regs &&
83314564Sdim      (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
84314564Sdim    RegisterValue full_value;
85314564Sdim    uint32_t full_reg = reg_info->invalidate_regs[0];
86314564Sdim    const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
87285101Semaste
88314564Sdim    // Read the full register.
89314564Sdim    if (ReadRegister(full_reg_info, full_value)) {
90321369Sdim      Status error;
91314564Sdim      ByteOrder byte_order = GetByteOrder();
92314564Sdim      uint8_t dst[RegisterValue::kMaxRegisterByteSize];
93285101Semaste
94314564Sdim      // Get the bytes for the full register.
95314564Sdim      const uint32_t dest_size = full_value.GetAsMemoryData(
96314564Sdim          full_reg_info, dst, sizeof(dst), byte_order, error);
97314564Sdim      if (error.Success() && dest_size) {
98314564Sdim        uint8_t src[RegisterValue::kMaxRegisterByteSize];
99285101Semaste
100314564Sdim        // Get the bytes for the source data.
101314564Sdim        const uint32_t src_size = value.GetAsMemoryData(
102314564Sdim            reg_info, src, sizeof(src), byte_order, error);
103314564Sdim        if (error.Success() && src_size && (src_size < dest_size)) {
104314564Sdim          // Copy the src bytes to the destination.
105314564Sdim          memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
106314564Sdim          // Set this full register as the value to write.
107314564Sdim          value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
108314564Sdim          value_to_write.SetType(full_reg_info);
109314564Sdim          reg_to_write = full_reg;
110285101Semaste        }
111314564Sdim      }
112285101Semaste    }
113314564Sdim  }
114285101Semaste
115314564Sdim  ProcessMonitor &monitor = GetMonitor();
116314564Sdim  // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
117314564Sdim  // registers in ptrace, but expose here 32-bit registers with a higher
118314564Sdim  // offset.
119314564Sdim  uint64_t offset = GetRegisterOffset(reg_to_write);
120314564Sdim  offset &= ~(sizeof(uintptr_t) - 1);
121314564Sdim  return monitor.WriteRegisterValue(
122314564Sdim      m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
123285101Semaste}
124285101Semaste
125314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
126314564Sdim    const RegisterInfo *reg_info, RegisterValue &value) {
127314564Sdim  if (!reg_info)
128314564Sdim    return false;
129285101Semaste
130314564Sdim  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
131285101Semaste
132314564Sdim  if (IsFPR(reg)) {
133314564Sdim    if (!ReadFPR())
134314564Sdim      return false;
135314564Sdim    uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
136314564Sdim    value.SetUInt64(*(uint64_t *)src);
137314564Sdim  } else if (IsGPR(reg)) {
138314564Sdim    bool success = ReadRegister(reg, value);
139285101Semaste
140314564Sdim    if (success) {
141314564Sdim      // If our return byte size was greater than the return value reg size,
142341825Sdim      // then use the type specified by reg_info rather than the uint64_t
143341825Sdim      // default
144314564Sdim      if (value.GetByteSize() > reg_info->byte_size)
145314564Sdim        value.SetType(reg_info);
146285101Semaste    }
147314564Sdim    return success;
148314564Sdim  }
149285101Semaste
150314564Sdim  return false;
151285101Semaste}
152285101Semaste
153314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
154314564Sdim    const RegisterInfo *reg_info, const RegisterValue &value) {
155314564Sdim  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
156285101Semaste
157314564Sdim  if (IsGPR(reg)) {
158314564Sdim    return WriteRegister(reg, value);
159314564Sdim  } else if (IsFPR(reg)) {
160314564Sdim    assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
161314564Sdim    uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
162314564Sdim    *(uint64_t *)dst = value.GetAsUInt64();
163314564Sdim    return WriteFPR();
164314564Sdim  }
165285101Semaste
166314564Sdim  return false;
167285101Semaste}
168285101Semaste
169314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(
170314564Sdim    DataBufferSP &data_sp) {
171314564Sdim  bool success = false;
172314564Sdim  data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
173353358Sdim  if (ReadGPR() && ReadFPR()) {
174314564Sdim    uint8_t *dst = data_sp->GetBytes();
175314564Sdim    success = dst != 0;
176285101Semaste
177314564Sdim    if (success) {
178314564Sdim      ::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
179314564Sdim      dst += GetGPRSize();
180285101Semaste    }
181314564Sdim  }
182314564Sdim  return success;
183285101Semaste}
184285101Semaste
185314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(
186314564Sdim    const DataBufferSP &data_sp) {
187314564Sdim  bool success = false;
188314564Sdim  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
189314564Sdim    uint8_t *src = data_sp->GetBytes();
190314564Sdim    if (src) {
191314564Sdim      ::memcpy(&m_gpr_powerpc, src, GetGPRSize());
192285101Semaste
193314564Sdim      if (WriteGPR()) {
194314564Sdim        src += GetGPRSize();
195314564Sdim        ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
196285101Semaste
197314564Sdim        success = WriteFPR();
198314564Sdim      }
199285101Semaste    }
200314564Sdim  }
201314564Sdim  return success;
202285101Semaste}
203285101Semaste
204314564Sdimuint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(
205314564Sdim    addr_t addr, size_t size, bool read, bool write) {
206314564Sdim  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
207314564Sdim  uint32_t hw_index;
208285101Semaste
209314564Sdim  for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
210314564Sdim    if (IsWatchpointVacant(hw_index))
211314564Sdim      return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
212314564Sdim  }
213285101Semaste
214314564Sdim  return LLDB_INVALID_INDEX32;
215285101Semaste}
216285101Semaste
217314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(
218314564Sdim    uint32_t hw_index) {
219314564Sdim  return false;
220285101Semaste}
221285101Semaste
222314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(
223314564Sdim    bool enable) {
224314564Sdim  return false;
225285101Semaste}
226285101Semaste
227314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() {
228314564Sdim  lldb::addr_t pc;
229285101Semaste
230314564Sdim  if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
231314564Sdim    return false;
232285101Semaste
233314564Sdim  return true;
234285101Semaste}
235285101Semaste
236314564Sdimunsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(
237314564Sdim    unsigned offset) {
238314564Sdim  unsigned reg;
239314564Sdim  for (reg = 0; reg < k_num_registers_powerpc; reg++) {
240314564Sdim    if (GetRegisterInfo()[reg].byte_offset == offset)
241314564Sdim      break;
242314564Sdim  }
243314564Sdim  assert(reg < k_num_registers_powerpc && "Invalid register offset.");
244314564Sdim  return reg;
245285101Semaste}
246285101Semaste
247314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(
248314564Sdim    uint32_t hw_index) {
249314564Sdim  return false;
250285101Semaste}
251285101Semaste
252314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() {
253314564Sdim  return false;
254285101Semaste}
255285101Semaste
256314564Sdimaddr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(
257314564Sdim    uint32_t hw_index) {
258314564Sdim  return LLDB_INVALID_ADDRESS;
259285101Semaste}
260285101Semaste
261314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(
262314564Sdim    uint32_t hw_index) {
263314564Sdim  return false;
264285101Semaste}
265285101Semaste
266314564Sdimbool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(
267314564Sdim    addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
268314564Sdim  return false;
269285101Semaste}
270285101Semaste
271285101Semasteuint32_t
272314564SdimRegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() {
273314564Sdim  return 0;
274285101Semaste}
275