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