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