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