12#if defined(__powerpc64__)
30#include <sys/socket.h>
32#include <asm/ptrace.h>
34#define REG_CONTEXT_SIZE \
35 (GetGPRSize() + GetFPRSize() + sizeof(m_vmx_ppc64le) + sizeof(m_vsx_ppc64le))
40static const uint32_t g_gpr_regnums_ppc64le[] = {
55static const uint32_t g_fpr_regnums_ppc64le[] = {
68static const uint32_t g_vmx_regnums_ppc64le[] = {
81static const uint32_t g_vsx_regnums_ppc64le[] = {
106 g_gpr_regnums_ppc64le},
108 g_fpr_regnums_ppc64le},
110 g_vmx_regnums_ppc64le},
112 g_vsx_regnums_ppc64le},
115std::unique_ptr<NativeRegisterContextLinux>
118 switch (target_arch.GetMachine()) {
119 case llvm::Triple::ppc64le:
120 return std::make_unique<NativeRegisterContextLinux_ppc64le>(target_arch,
123 llvm_unreachable(
"have no register context for architecture");
127llvm::Expected<ArchSpec>
129 return HostInfo::GetArchitecture();
132NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le(
137 if (target_arch.GetMachine() != llvm::Triple::ppc64le) {
138 llvm_unreachable(
"Unhandled target architecture.");
141 ::memset(&m_gpr_ppc64le, 0,
sizeof(m_gpr_ppc64le));
142 ::memset(&m_fpr_ppc64le, 0,
sizeof(m_fpr_ppc64le));
143 ::memset(&m_vmx_ppc64le, 0,
sizeof(m_vmx_ppc64le));
144 ::memset(&m_vsx_ppc64le, 0,
sizeof(m_vsx_ppc64le));
147uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount()
const {
152NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index)
const {
159uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount()
const {
166Status NativeRegisterContextLinux_ppc64le::ReadRegister(
183 uint32_t fpr_offset = CalculateFprOffset(reg_info);
184 assert(fpr_offset <
sizeof m_fpr_ppc64le);
185 uint8_t *src = (uint8_t *)&m_fpr_ppc64le + fpr_offset;
188 }
else if (IsVSX(reg)) {
189 uint32_t vsx_offset = CalculateVsxOffset(reg_info);
190 assert(vsx_offset <
sizeof(m_vsx_ppc64le));
192 if (vsx_offset <
sizeof(m_vsx_ppc64le) / 2) {
203 dst = (uint8_t *)&value;
204 src = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2;
205 ::memcpy(dst, src, 8);
207 src = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2;
208 ::memcpy(dst, src, 8);
217 uint32_t vmx_offset = vsx_offset -
sizeof(m_vsx_ppc64le) / 2;
218 uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
222 }
else if (IsVMX(reg)) {
228 uint32_t vmx_offset = CalculateVmxOffset(reg_info);
229 assert(vmx_offset <
sizeof m_vmx_ppc64le);
230 uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
233 }
else if (IsGPR(reg)) {
238 uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->
byte_offset;
243 "failed - register wasn't recognized to be a GPR, FPR, VSX "
244 "or VMX, read strategy unknown");
250Status NativeRegisterContextLinux_ppc64le::WriteRegister(
259 "no lldb regnum for %s",
260 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
262 if (IsGPR(reg_index)) {
267 uint8_t *dst = (uint8_t *)&m_gpr_ppc64le + reg_info->
byte_offset;
277 if (IsFPR(reg_index)) {
283 uint32_t fpr_offset = CalculateFprOffset(reg_info);
284 assert(fpr_offset < GetFPRSize());
285 uint8_t *dst = (uint8_t *)&m_fpr_ppc64le + fpr_offset;
295 if (IsVMX(reg_index)) {
301 uint32_t vmx_offset = CalculateVmxOffset(reg_info);
302 assert(vmx_offset <
sizeof(m_vmx_ppc64le));
303 uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
313 if (IsVSX(reg_index)) {
314 uint32_t vsx_offset = CalculateVsxOffset(reg_info);
315 assert(vsx_offset <
sizeof(m_vsx_ppc64le));
317 if (vsx_offset <
sizeof(m_vsx_ppc64le) / 2) {
327 ::memcpy(value, reg_value.
GetBytes(), 16);
329 src = (uint8_t *)value;
330 dst = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2;
331 ::memcpy(dst, src, 8);
333 dst = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2;
334 ::memcpy(dst, src, 8);
344 uint32_t vmx_offset = vsx_offset -
sizeof(m_vsx_ppc64le) / 2;
345 uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
354 "failed - register wasn't recognized to be a GPR, FPR, VSX "
355 "or VMX, write strategy unknown");
358Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues(
379 uint8_t *dst = data_sp->GetBytes();
380 ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize());
382 ::memcpy(dst, &m_fpr_ppc64le, GetFPRSize());
384 ::memcpy(dst, &m_vmx_ppc64le,
sizeof(m_vmx_ppc64le));
385 dst +=
sizeof(m_vmx_ppc64le);
386 ::memcpy(dst, &m_vsx_ppc64le,
sizeof(m_vsx_ppc64le));
391Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues(
397 "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided",
404 "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched "
405 "data size, expected %" PRIu64
", actual %" PRIu64,
410 const uint8_t *src = data_sp->GetBytes();
411 if (src ==
nullptr) {
413 "NativeRegisterContextLinux_ppc64le::%s "
414 "DataBuffer::GetBytes() returned a null "
420 ::memcpy(&m_gpr_ppc64le, src, GetGPRSize());
427 ::memcpy(&m_fpr_ppc64le, src, GetFPRSize());
434 ::memcpy(&m_vmx_ppc64le, src,
sizeof(m_vmx_ppc64le));
440 src +=
sizeof(m_vmx_ppc64le);
441 ::memcpy(&m_vsx_ppc64le, src,
sizeof(m_vsx_ppc64le));
447bool NativeRegisterContextLinux_ppc64le::IsGPR(
unsigned reg)
const {
451bool NativeRegisterContextLinux_ppc64le::IsFPR(
unsigned reg)
const {
455uint32_t NativeRegisterContextLinux_ppc64le::CalculateFprOffset(
461uint32_t NativeRegisterContextLinux_ppc64le::CalculateVmxOffset(
467uint32_t NativeRegisterContextLinux_ppc64le::CalculateVsxOffset(
473Status NativeRegisterContextLinux_ppc64le::ReadVMX() {
474 int regset = NT_PPC_VMX;
476 ®set, &m_vmx_ppc64le,
477 sizeof(m_vmx_ppc64le));
480Status NativeRegisterContextLinux_ppc64le::WriteVMX() {
481 int regset = NT_PPC_VMX;
483 ®set, &m_vmx_ppc64le,
484 sizeof(m_vmx_ppc64le));
487Status NativeRegisterContextLinux_ppc64le::ReadVSX() {
488 int regset = NT_PPC_VSX;
490 ®set, &m_vsx_ppc64le,
491 sizeof(m_vsx_ppc64le));
494Status NativeRegisterContextLinux_ppc64le::WriteVSX() {
495 int regset = NT_PPC_VSX;
497 ®set, &m_vsx_ppc64le,
498 sizeof(m_vsx_ppc64le));
501bool NativeRegisterContextLinux_ppc64le::IsVMX(
unsigned reg) {
505bool NativeRegisterContextLinux_ppc64le::IsVSX(
unsigned reg) {
509uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() {
518 LLDB_LOG(log,
"{0}", m_max_hwp_supported);
519 return m_max_hwp_supported;
522uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint(
525 LLDB_LOG(log,
"addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
534 uint32_t control_value = 0, wp_index = 0;
536 uint32_t rw_mode = 0;
540 switch (watch_flags) {
541 case eWatchpointKindWrite:
542 rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE;
545 case eWatchpointKindRead:
546 rw_mode = PPC_BREAKPOINT_TRIGGER_READ;
549 case (eWatchpointKindRead | eWatchpointKindWrite):
550 rw_mode = PPC_BREAKPOINT_TRIGGER_RW;
557 if (size != 1 && size != 2 && size != 4 && size != 8)
565 addr_t begin = llvm::alignDown(addr, 8);
566 addr_t end = llvm::alignTo(addr + size, 8);
567 size = llvm::PowerOf2Ceil(end - begin);
569 addr = addr & (~0x07);
573 control_value = watch_flags << 3;
574 control_value |= ((1 << size) - 1) << 5;
575 control_value |= (2 << 1) | 1;
579 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
580 if ((m_hwp_regs[i].control & 1) == 0) {
582 }
else if (m_hwp_regs[i].address == addr) {
591 m_hwp_regs[wp_index].real_addr = real_addr;
592 m_hwp_regs[wp_index].address = addr;
593 m_hwp_regs[wp_index].control = control_value;
594 m_hwp_regs[wp_index].mode = rw_mode;
600 m_hwp_regs[wp_index].address = 0;
601 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
609bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint(
612 LLDB_LOG(log,
"wp_index: {0}", wp_index);
620 if (wp_index >= m_max_hwp_supported)
625 uint32_t tempControl = m_hwp_regs[wp_index].control;
626 long *tempSlot =
reinterpret_cast<long *
>(m_hwp_regs[wp_index].slot);
629 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
630 m_hwp_regs[wp_index].address = 0;
631 m_hwp_regs[wp_index].slot = 0;
632 m_hwp_regs[wp_index].mode = 0;
636 m_thread.GetID(), 0, tempSlot);
639 m_hwp_regs[wp_index].control = tempControl;
640 m_hwp_regs[wp_index].address = tempAddr;
641 m_hwp_regs[wp_index].slot =
reinterpret_cast<long>(tempSlot);
650NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) {
652 LLDB_LOG(log,
"wp_index: {0}", wp_index);
654 unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff;
655 if (llvm::isPowerOf2_32(control + 1)) {
656 return llvm::popcount(control);
662bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled(
665 LLDB_LOG(log,
"wp_index: {0}", wp_index);
667 return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1);
670Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex(
673 LLDB_LOG(log,
"wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
678 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
679 watch_size = GetWatchpointSize(wp_index);
680 watch_addr = m_hwp_regs[wp_index].address;
682 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
683 trap_addr <= watch_addr + watch_size) {
684 m_hwp_regs[wp_index].hit_addr = trap_addr;
694NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) {
696 LLDB_LOG(log,
"wp_index: {0}", wp_index);
698 if (wp_index >= m_max_hwp_supported)
701 if (WatchpointIsEnabled(wp_index))
702 return m_hwp_regs[wp_index].real_addr;
708NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) {
710 LLDB_LOG(log,
"wp_index: {0}", wp_index);
712 if (wp_index >= m_max_hwp_supported)
715 if (WatchpointIsEnabled(wp_index))
716 return m_hwp_regs[wp_index].hit_addr;
721Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() {
722 if (!m_refresh_hwdebug_info) {
726 ::pid_t tid = m_thread.GetID();
728 struct ppc_debug_info hwdebug_info;
732 PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info,
sizeof(hwdebug_info));
737 m_max_hwp_supported = hwdebug_info.num_data_bps;
738 m_max_hbp_supported = hwdebug_info.num_instruction_bps;
739 m_refresh_hwdebug_info =
false;
744Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() {
745 struct ppc_hw_breakpoint reg_state;
749 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
750 reg_state.addr = m_hwp_regs[i].address;
751 reg_state.trigger_type = m_hwp_regs[i].mode;
752 reg_state.version = 1;
753 reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
754 reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
756 reg_state.condition_value = 0;
759 m_thread.GetID(), 0, ®_state,
760 sizeof(reg_state), &ret);
765 m_hwp_regs[i].slot = ret;
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets]
A subclass of DataBuffer that stores a data buffer on the heap.
uint32_t SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
const void * GetBytes() const
uint32_t GetByteSize() const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
}
static std::unique_ptr< NativeRegisterContextLinux > CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, NativeThreadLinux &native_thread)
static llvm::Expected< ArchSpec > DetermineArchitecture(lldb::tid_t tid)
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
@ k_num_gpr_registers_ppc64le
@ k_num_vsx_registers_ppc64le
@ k_num_vmx_registers_ppc64le
@ k_num_fpr_registers_ppc64le
Status WriteHardwareDebugRegs(int hwbType, ::pid_t tid, uint32_t max_supported, const std::array< NativeRegisterContextDBReg::DREG, 16 > ®s)
Status ReadHardwareDebugInfo(::pid_t tid, uint32_t &max_hwp_supported, uint32_t &max_hbp_supported)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.