RegisterContextPOSIXProcessMonitor_arm64.cpp revision 287506
1//===-- RegisterContextPOSIXProcessMonitor_arm64.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/DataBufferHeap.h" 11#include "lldb/Core/RegisterValue.h" 12#include "lldb/Target/Thread.h" 13 14#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" 15#include "ProcessPOSIX.h" 16#include "ProcessMonitor.h" 17#include "RegisterContextPOSIXProcessMonitor_arm64.h" 18 19#define REG_CONTEXT_SIZE (GetGPRSize()) 20 21using namespace lldb; 22using namespace lldb_private; 23 24RegisterContextPOSIXProcessMonitor_arm64::RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread, 25 uint32_t concrete_frame_idx, 26 lldb_private::RegisterInfoInterface *register_info) 27 : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info) 28{ 29} 30 31ProcessMonitor & 32RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() 33{ 34 lldb::ProcessSP base = CalculateProcess(); 35 ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); 36 return process->GetMonitor(); 37} 38 39bool 40RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() 41{ 42 ProcessMonitor &monitor = GetMonitor(); 43 return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); 44} 45 46bool 47RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() 48{ 49 ProcessMonitor &monitor = GetMonitor(); 50 return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); 51} 52 53bool 54RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() 55{ 56 ProcessMonitor &monitor = GetMonitor(); 57 return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); 58} 59 60bool 61RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() 62{ 63 ProcessMonitor &monitor = GetMonitor(); 64 return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); 65} 66 67bool 68RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const unsigned reg, 69 lldb_private::RegisterValue &value) 70{ 71 ProcessMonitor &monitor = GetMonitor(); 72 return monitor.ReadRegisterValue(m_thread.GetID(), 73 GetRegisterOffset(reg), 74 GetRegisterName(reg), 75 GetRegisterSize(reg), 76 value); 77} 78 79bool 80RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const unsigned reg, 81 const lldb_private::RegisterValue &value) 82{ 83 unsigned reg_to_write = reg; 84 lldb_private::RegisterValue value_to_write = value; 85 86 // Check if this is a subregister of a full register. 87 const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); 88 if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 89 { 90 lldb_private::RegisterValue full_value; 91 uint32_t full_reg = reg_info->invalidate_regs[0]; 92 const lldb_private::RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 93 94 // Read the full register. 95 if (ReadRegister(full_reg_info, full_value)) 96 { 97 lldb_private::Error error; 98 lldb::ByteOrder byte_order = GetByteOrder(); 99 uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize]; 100 101 // Get the bytes for the full register. 102 const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 103 dst, 104 sizeof(dst), 105 byte_order, 106 error); 107 if (error.Success() && dest_size) 108 { 109 uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize]; 110 111 // Get the bytes for the source data. 112 const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 113 if (error.Success() && src_size && (src_size < dest_size)) 114 { 115 // Copy the src bytes to the destination. 116 ::memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 117 // Set this full register as the value to write. 118 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 119 value_to_write.SetType(full_reg_info); 120 reg_to_write = full_reg; 121 } 122 } 123 } 124 } 125 126 ProcessMonitor &monitor = GetMonitor(); 127 return monitor.WriteRegisterValue(m_thread.GetID(), 128 GetRegisterOffset(reg_to_write), 129 GetRegisterName(reg_to_write), 130 value_to_write); 131} 132 133bool 134RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) 135{ 136 if (!reg_info) 137 return false; 138 139 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 140 141 if (IsFPR(reg)) 142 { 143 if (!ReadFPR()) 144 return false; 145 } 146 else 147 { 148 uint32_t full_reg = reg; 149 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 150 151 if (is_subreg) 152 { 153 // Read the full aligned 64-bit register. 154 full_reg = reg_info->invalidate_regs[0]; 155 } 156 return ReadRegister(full_reg, value); 157 } 158 159 // Get pointer to m_fpr variable and set the data from it. 160 assert (reg_info->byte_offset < sizeof m_fpr); 161 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 162 switch (reg_info->byte_size) 163 { 164 case 2: 165 value.SetUInt16(*(uint16_t *)src); 166 return true; 167 case 4: 168 value.SetUInt32(*(uint32_t *)src); 169 return true; 170 case 8: 171 value.SetUInt64(*(uint64_t *)src); 172 return true; 173 default: 174 assert(false && "Unhandled data size."); 175 return false; 176 } 177} 178 179bool 180RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) 181{ 182 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 183 184 if (IsGPR(reg)) 185 return WriteRegister(reg, value); 186 187 return false; 188} 189 190bool 191RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) 192{ 193 bool success = false; 194 data_sp.reset (new lldb_private::DataBufferHeap (REG_CONTEXT_SIZE, 0)); 195 if (data_sp && ReadGPR () && ReadFPR ()) 196 { 197 uint8_t *dst = data_sp->GetBytes(); 198 success = dst != 0; 199 200 if (success) 201 { 202 ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 203 dst += GetGPRSize(); 204 ::memcpy (dst, &m_fpr, sizeof m_fpr); 205 } 206 } 207 return success; 208} 209 210bool 211RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) 212{ 213 bool success = false; 214 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) 215 { 216 uint8_t *src = data_sp->GetBytes(); 217 if (src) 218 { 219 ::memcpy (&m_gpr_arm64, src, GetGPRSize()); 220 if (WriteGPR()) { 221 src += GetGPRSize(); 222 ::memcpy (&m_fpr, src, sizeof m_fpr); 223 success = WriteFPR(); 224 } 225 } 226 } 227 return success; 228} 229 230uint32_t 231RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, 232 bool read, bool write) 233{ 234 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 235 uint32_t hw_index; 236 237 for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) 238 { 239 if (IsWatchpointVacant(hw_index)) 240 return SetHardwareWatchpointWithIndex(addr, size, 241 read, write, 242 hw_index); 243 } 244 245 return LLDB_INVALID_INDEX32; 246} 247 248bool 249RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(uint32_t hw_index) 250{ 251 return false; 252} 253 254bool 255RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) 256{ 257 return false; 258} 259 260bool 261RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() 262{ 263 // PC points one byte past the int3 responsible for the breakpoint. 264 lldb::addr_t pc; 265 266 if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) 267 return false; 268 269 SetPC(pc - 1); 270 return true; 271} 272 273unsigned 274RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(unsigned offset) 275{ 276 unsigned reg; 277 for (reg = 0; reg < k_num_registers_arm64; reg++) 278 { 279 if (GetRegisterInfo()[reg].byte_offset == offset) 280 break; 281 } 282 assert(reg < k_num_registers_arm64 && "Invalid register offset."); 283 return reg; 284} 285 286bool 287RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(uint32_t hw_index) 288{ 289 return false; 290} 291 292bool 293RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() 294{ 295 return false; 296} 297 298lldb::addr_t 299RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(uint32_t hw_index) 300{ 301 return LLDB_INVALID_ADDRESS; 302} 303 304bool 305RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(uint32_t hw_index) 306{ 307 return false; 308} 309 310bool 311RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, 312 bool read, bool write, 313 uint32_t hw_index) 314{ 315 return false; 316} 317 318uint32_t 319RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() 320{ 321 return 0; 322} 323