1 //===-- NativeRegisterContextLinux_ppc64le.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 // This implementation is related to the OpenPOWER ABI for Power Architecture 11 // 64-bit ELF V2 ABI 12 13 #if defined(__powerpc64__) 14 15 #include "NativeRegisterContextLinux_ppc64le.h" 16 17 #include "lldb/Core/RegisterValue.h" 18 #include "lldb/Host/common/NativeProcessProtocol.h" 19 #include "lldb/Utility/DataBufferHeap.h" 20 #include "lldb/Utility/Log.h" 21 #include "lldb/Utility/Status.h" 22 23 #include "Plugins/Process/Linux/NativeProcessLinux.h" 24 #include "Plugins/Process/Linux/Procfs.h" 25 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 26 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" 27 28 // System includes - They have to be included after framework includes because 29 // they define some 30 // macros which collide with variable names in other modules 31 #include <sys/socket.h> 32 #include <elf.h> 33 #include <asm/ptrace.h> 34 35 #define REG_CONTEXT_SIZE GetGPRSize() 36 37 using namespace lldb; 38 using namespace lldb_private; 39 using namespace lldb_private::process_linux; 40 41 static const uint32_t g_gpr_regnums_ppc64le[] = { 42 gpr_r0_ppc64le, gpr_r1_ppc64le, gpr_r2_ppc64le, gpr_r3_ppc64le, 43 gpr_r4_ppc64le, gpr_r5_ppc64le, gpr_r6_ppc64le, gpr_r7_ppc64le, 44 gpr_r8_ppc64le, gpr_r9_ppc64le, gpr_r10_ppc64le, gpr_r11_ppc64le, 45 gpr_r12_ppc64le, gpr_r13_ppc64le, gpr_r14_ppc64le, gpr_r15_ppc64le, 46 gpr_r16_ppc64le, gpr_r17_ppc64le, gpr_r18_ppc64le, gpr_r19_ppc64le, 47 gpr_r20_ppc64le, gpr_r21_ppc64le, gpr_r22_ppc64le, gpr_r23_ppc64le, 48 gpr_r24_ppc64le, gpr_r25_ppc64le, gpr_r26_ppc64le, gpr_r27_ppc64le, 49 gpr_r28_ppc64le, gpr_r29_ppc64le, gpr_r30_ppc64le, gpr_r31_ppc64le, 50 gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le, 51 gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le, 52 gpr_trap_ppc64le, 53 }; 54 55 namespace { 56 // Number of register sets provided by this context. 57 enum { k_num_register_sets = 1 }; 58 } 59 60 static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = { 61 {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le, 62 g_gpr_regnums_ppc64le}, 63 }; 64 65 NativeRegisterContextLinux * 66 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 67 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 68 uint32_t concrete_frame_idx) { 69 switch (target_arch.GetMachine()) { 70 case llvm::Triple::ppc64le: 71 return new NativeRegisterContextLinux_ppc64le(target_arch, native_thread, 72 concrete_frame_idx); 73 default: 74 llvm_unreachable("have no register context for architecture"); 75 } 76 } 77 78 NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le( 79 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 80 uint32_t concrete_frame_idx) 81 : NativeRegisterContextLinux(native_thread, concrete_frame_idx, 82 new RegisterInfoPOSIX_ppc64le(target_arch)) { 83 if (target_arch.GetMachine() != llvm::Triple::ppc64le) { 84 llvm_unreachable("Unhandled target architecture."); 85 } 86 87 ::memset(&m_gpr_ppc64le, 0, sizeof(m_gpr_ppc64le)); 88 ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 89 } 90 91 uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount() const { 92 return k_num_register_sets; 93 } 94 95 const RegisterSet * 96 NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index) const { 97 if (set_index < k_num_register_sets) 98 return &g_reg_sets_ppc64le[set_index]; 99 100 return nullptr; 101 } 102 103 uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount() const { 104 uint32_t count = 0; 105 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) 106 count += g_reg_sets_ppc64le[set_index].num_registers; 107 return count; 108 } 109 110 Status NativeRegisterContextLinux_ppc64le::ReadRegister( 111 const RegisterInfo *reg_info, RegisterValue ®_value) { 112 Status error; 113 114 if (!reg_info) { 115 error.SetErrorString("reg_info NULL"); 116 return error; 117 } 118 119 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 120 121 if (IsGPR(reg)) { 122 error = ReadGPR(); 123 if (error.Fail()) 124 return error; 125 126 uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset; 127 reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 128 eByteOrderLittle, error); 129 } else { 130 return Status("failed - register wasn't recognized to be a GPR, " 131 "read strategy unknown"); 132 } 133 134 return error; 135 } 136 137 Status NativeRegisterContextLinux_ppc64le::WriteRegister( 138 const RegisterInfo *reg_info, const RegisterValue ®_value) { 139 Status error; 140 if (!reg_info) 141 return Status("reg_info NULL"); 142 143 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 144 if (reg_index == LLDB_INVALID_REGNUM) 145 return Status("no lldb regnum for %s", reg_info && reg_info->name 146 ? reg_info->name 147 : "<unknown register>"); 148 149 if (IsGPR(reg_index)) { 150 error = ReadGPR(); 151 if (error.Fail()) 152 return error; 153 154 uint8_t *dst = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset; 155 ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); 156 157 error = WriteGPR(); 158 if (error.Fail()) 159 return error; 160 161 return Status(); 162 } 163 164 return Status("failed - register wasn't recognized to be a GPR, " 165 "write strategy unknown"); 166 } 167 168 Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues( 169 lldb::DataBufferSP &data_sp) { 170 Status error; 171 172 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 173 if (!data_sp) 174 return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, 175 REG_CONTEXT_SIZE); 176 177 error = ReadGPR(); 178 if (error.Fail()) 179 return error; 180 181 uint8_t *dst = data_sp->GetBytes(); 182 if (dst == nullptr) { 183 error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 184 " returned a null pointer", 185 REG_CONTEXT_SIZE); 186 return error; 187 } 188 189 ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize()); 190 191 return error; 192 } 193 194 Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues( 195 const lldb::DataBufferSP &data_sp) { 196 Status error; 197 198 if (!data_sp) { 199 error.SetErrorStringWithFormat( 200 "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided", 201 __FUNCTION__); 202 return error; 203 } 204 205 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 206 error.SetErrorStringWithFormat( 207 "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched " 208 "data size, expected %" PRIu64 ", actual %" PRIu64, 209 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 210 return error; 211 } 212 213 uint8_t *src = data_sp->GetBytes(); 214 if (src == nullptr) { 215 error.SetErrorStringWithFormat("NativeRegisterContextLinux_ppc64le::%s " 216 "DataBuffer::GetBytes() returned a null " 217 "pointer", 218 __FUNCTION__); 219 return error; 220 } 221 222 ::memcpy(&m_gpr_ppc64le, src, GetGPRSize()); 223 error = WriteGPR(); 224 225 return error; 226 } 227 228 bool NativeRegisterContextLinux_ppc64le::IsGPR(unsigned reg) const { 229 return reg <= k_last_gpr_ppc64le; // GPR's come first. 230 } 231 232 Status NativeRegisterContextLinux_ppc64le::DoReadGPR( 233 void *buf, size_t buf_size) { 234 int regset = NT_PRSTATUS; 235 return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), 236 ®set, buf, buf_size); 237 } 238 239 Status NativeRegisterContextLinux_ppc64le::DoWriteGPR( 240 void *buf, size_t buf_size) { 241 int regset = NT_PRSTATUS; 242 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), 243 ®set, buf, buf_size); 244 } 245 246 uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() { 247 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 248 249 // Read hardware breakpoint and watchpoint information. 250 Status error = ReadHardwareDebugInfo(); 251 252 if (error.Fail()) 253 return 0; 254 255 LLDB_LOG(log, "{0}", m_max_hwp_supported); 256 return m_max_hwp_supported; 257 } 258 259 uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint( 260 lldb::addr_t addr, size_t size, uint32_t watch_flags) { 261 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 262 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, 263 watch_flags); 264 265 // Read hardware breakpoint and watchpoint information. 266 Status error = ReadHardwareDebugInfo(); 267 268 if (error.Fail()) 269 return LLDB_INVALID_INDEX32; 270 271 uint32_t control_value = 0, wp_index = 0; 272 lldb::addr_t real_addr = addr; 273 uint32_t rw_mode = 0; 274 275 // Check if we are setting watchpoint other than read/write/access 276 // Update watchpoint flag to match ppc64le write-read bit configuration. 277 switch (watch_flags) { 278 case eWatchpointKindWrite: 279 rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE; 280 watch_flags = 2; 281 break; 282 case eWatchpointKindRead: 283 rw_mode = PPC_BREAKPOINT_TRIGGER_READ; 284 watch_flags = 1; 285 break; 286 case (eWatchpointKindRead | eWatchpointKindWrite): 287 rw_mode = PPC_BREAKPOINT_TRIGGER_RW; 288 break; 289 default: 290 return LLDB_INVALID_INDEX32; 291 } 292 293 // Check if size has a valid hardware watchpoint length. 294 if (size != 1 && size != 2 && size != 4 && size != 8) 295 return LLDB_INVALID_INDEX32; 296 297 // Check 8-byte alignment for hardware watchpoint target address. 298 // Below is a hack to recalculate address and size in order to 299 // make sure we can watch non 8-byte alligned addresses as well. 300 if (addr & 0x07) { 301 302 addr_t begin = llvm::alignDown(addr, 8); 303 addr_t end = llvm::alignTo(addr + size, 8); 304 size = llvm::PowerOf2Ceil(end - begin); 305 306 addr = addr & (~0x07); 307 } 308 309 // Setup control value 310 control_value = watch_flags << 3; 311 control_value |= ((1 << size) - 1) << 5; 312 control_value |= (2 << 1) | 1; 313 314 // Iterate over stored watchpoints and find a free wp_index 315 wp_index = LLDB_INVALID_INDEX32; 316 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 317 if ((m_hwp_regs[i].control & 1) == 0) { 318 wp_index = i; // Mark last free slot 319 } else if (m_hwp_regs[i].address == addr) { 320 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. 321 } 322 } 323 324 if (wp_index == LLDB_INVALID_INDEX32) 325 return LLDB_INVALID_INDEX32; 326 327 // Update watchpoint in local cache 328 m_hwp_regs[wp_index].real_addr = real_addr; 329 m_hwp_regs[wp_index].address = addr; 330 m_hwp_regs[wp_index].control = control_value; 331 m_hwp_regs[wp_index].mode = rw_mode; 332 333 // PTRACE call to set corresponding watchpoint register. 334 error = WriteHardwareDebugRegs(); 335 336 if (error.Fail()) { 337 m_hwp_regs[wp_index].address = 0; 338 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); 339 340 return LLDB_INVALID_INDEX32; 341 } 342 343 return wp_index; 344 } 345 346 bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint( 347 uint32_t wp_index) { 348 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 349 LLDB_LOG(log, "wp_index: {0}", wp_index); 350 351 // Read hardware breakpoint and watchpoint information. 352 Status error = ReadHardwareDebugInfo(); 353 354 if (error.Fail()) 355 return false; 356 357 if (wp_index >= m_max_hwp_supported) 358 return false; 359 360 // Create a backup we can revert to in case of failure. 361 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 362 uint32_t tempControl = m_hwp_regs[wp_index].control; 363 long *tempSlot = reinterpret_cast<long *>(m_hwp_regs[wp_index].slot); 364 365 // Update watchpoint in local cache 366 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); 367 m_hwp_regs[wp_index].address = 0; 368 m_hwp_regs[wp_index].slot = 0; 369 m_hwp_regs[wp_index].mode = 0; 370 371 // Ptrace call to update hardware debug registers 372 error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_DELHWDEBUG, 373 m_thread.GetID(), 0, tempSlot); 374 375 if (error.Fail()) { 376 m_hwp_regs[wp_index].control = tempControl; 377 m_hwp_regs[wp_index].address = tempAddr; 378 m_hwp_regs[wp_index].slot = reinterpret_cast<long>(tempSlot); 379 380 return false; 381 } 382 383 return true; 384 } 385 386 uint32_t 387 NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) { 388 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 389 LLDB_LOG(log, "wp_index: {0}", wp_index); 390 391 unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff; 392 assert(llvm::isPowerOf2_32(control + 1)); 393 return llvm::countPopulation(control); 394 } 395 396 bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled( 397 uint32_t wp_index) { 398 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 399 LLDB_LOG(log, "wp_index: {0}", wp_index); 400 401 return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1); 402 } 403 404 Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex( 405 uint32_t &wp_index, lldb::addr_t trap_addr) { 406 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 407 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); 408 409 uint32_t watch_size; 410 lldb::addr_t watch_addr; 411 412 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { 413 watch_size = GetWatchpointSize(wp_index); 414 watch_addr = m_hwp_regs[wp_index].address; 415 416 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && 417 trap_addr <= watch_addr + watch_size) { 418 m_hwp_regs[wp_index].hit_addr = trap_addr; 419 return Status(); 420 } 421 } 422 423 wp_index = LLDB_INVALID_INDEX32; 424 return Status(); 425 } 426 427 lldb::addr_t 428 NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) { 429 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 430 LLDB_LOG(log, "wp_index: {0}", wp_index); 431 432 if (wp_index >= m_max_hwp_supported) 433 return LLDB_INVALID_ADDRESS; 434 435 if (WatchpointIsEnabled(wp_index)) 436 return m_hwp_regs[wp_index].real_addr; 437 else 438 return LLDB_INVALID_ADDRESS; 439 } 440 441 lldb::addr_t 442 NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) { 443 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 444 LLDB_LOG(log, "wp_index: {0}", wp_index); 445 446 if (wp_index >= m_max_hwp_supported) 447 return LLDB_INVALID_ADDRESS; 448 449 if (WatchpointIsEnabled(wp_index)) 450 return m_hwp_regs[wp_index].hit_addr; 451 452 return LLDB_INVALID_ADDRESS; 453 } 454 455 Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() { 456 if (!m_refresh_hwdebug_info) { 457 return Status(); 458 } 459 460 ::pid_t tid = m_thread.GetID(); 461 462 struct ppc_debug_info hwdebug_info; 463 Status error; 464 465 error = NativeProcessLinux::PtraceWrapper( 466 PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info, sizeof(hwdebug_info)); 467 468 if (error.Fail()) 469 return error; 470 471 m_max_hwp_supported = hwdebug_info.num_data_bps; 472 m_max_hbp_supported = hwdebug_info.num_instruction_bps; 473 m_refresh_hwdebug_info = false; 474 475 return error; 476 } 477 478 Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() { 479 struct ppc_hw_breakpoint reg_state; 480 Status error; 481 long ret; 482 483 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 484 reg_state.addr = m_hwp_regs[i].address; 485 reg_state.trigger_type = m_hwp_regs[i].mode; 486 reg_state.version = 1; 487 reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT; 488 reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; 489 reg_state.addr2 = 0; 490 reg_state.condition_value = 0; 491 492 error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_SETHWDEBUG, 493 m_thread.GetID(), 0, ®_state, 494 sizeof(reg_state), &ret); 495 496 if (error.Fail()) 497 return error; 498 499 m_hwp_regs[i].slot = ret; 500 } 501 502 return error; 503 } 504 505 #endif // defined(__powerpc64__) 506