12#if defined(__powerpc64__)
29#include <asm/ptrace.h>
31#include <sys/socket.h>
33#define REG_CONTEXT_SIZE \
34 (GetGPRSize() + GetFPRSize() + sizeof(m_vmx_ppc64le) + sizeof(m_vsx_ppc64le))
39static const uint32_t g_gpr_regnums_ppc64le[] = {
54static const uint32_t g_fpr_regnums_ppc64le[] = {
67static const uint32_t g_vmx_regnums_ppc64le[] = {
80static const uint32_t g_vsx_regnums_ppc64le[] = {
105 g_gpr_regnums_ppc64le},
107 g_fpr_regnums_ppc64le},
109 g_vmx_regnums_ppc64le},
111 g_vsx_regnums_ppc64le},
114std::unique_ptr<NativeRegisterContextLinux>
117 switch (target_arch.GetMachine()) {
118 case llvm::Triple::ppc64le:
119 return std::make_unique<NativeRegisterContextLinux_ppc64le>(target_arch,
122 llvm_unreachable(
"have no register context for architecture");
126llvm::Expected<ArchSpec>
128 return HostInfo::GetArchitecture();
131NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le(
136 if (target_arch.GetMachine() != llvm::Triple::ppc64le) {
137 llvm_unreachable(
"Unhandled target architecture.");
140 ::memset(&m_gpr_ppc64le, 0,
sizeof(m_gpr_ppc64le));
141 ::memset(&m_fpr_ppc64le, 0,
sizeof(m_fpr_ppc64le));
142 ::memset(&m_vmx_ppc64le, 0,
sizeof(m_vmx_ppc64le));
143 ::memset(&m_vsx_ppc64le, 0,
sizeof(m_vsx_ppc64le));
146uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount()
const {
151NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index)
const {
158uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount()
const {
165Status NativeRegisterContextLinux_ppc64le::ReadRegister(
182 uint32_t fpr_offset = CalculateFprOffset(reg_info);
183 assert(fpr_offset <
sizeof m_fpr_ppc64le);
184 uint8_t *src = (uint8_t *)&m_fpr_ppc64le + fpr_offset;
187 }
else if (IsVSX(reg)) {
188 uint32_t vsx_offset = CalculateVsxOffset(reg_info);
189 assert(vsx_offset <
sizeof(m_vsx_ppc64le));
191 if (vsx_offset <
sizeof(m_vsx_ppc64le) / 2) {
202 dst = (uint8_t *)&value;
203 src = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2;
204 ::memcpy(dst, src, 8);
206 src = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2;
207 ::memcpy(dst, src, 8);
216 uint32_t vmx_offset = vsx_offset -
sizeof(m_vsx_ppc64le) / 2;
217 uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
221 }
else if (IsVMX(reg)) {
227 uint32_t vmx_offset = CalculateVmxOffset(reg_info);
228 assert(vmx_offset <
sizeof m_vmx_ppc64le);
229 uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
232 }
else if (IsGPR(reg)) {
237 uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->
byte_offset;
242 "failed - register wasn't recognized to be a GPR, FPR, VSX "
243 "or VMX, read strategy unknown");
249Status NativeRegisterContextLinux_ppc64le::WriteRegister(
258 "no lldb regnum for %s",
259 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
261 if (IsGPR(reg_index)) {
266 uint8_t *dst = (uint8_t *)&m_gpr_ppc64le + reg_info->
byte_offset;
276 if (IsFPR(reg_index)) {
282 uint32_t fpr_offset = CalculateFprOffset(reg_info);
283 assert(fpr_offset < GetFPRSize());
284 uint8_t *dst = (uint8_t *)&m_fpr_ppc64le + fpr_offset;
294 if (IsVMX(reg_index)) {
300 uint32_t vmx_offset = CalculateVmxOffset(reg_info);
301 assert(vmx_offset <
sizeof(m_vmx_ppc64le));
302 uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
312 if (IsVSX(reg_index)) {
313 uint32_t vsx_offset = CalculateVsxOffset(reg_info);
314 assert(vsx_offset <
sizeof(m_vsx_ppc64le));
316 if (vsx_offset <
sizeof(m_vsx_ppc64le) / 2) {
326 ::memcpy(value, reg_value.
GetBytes(), 16);
328 src = (uint8_t *)value;
329 dst = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2;
330 ::memcpy(dst, src, 8);
332 dst = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2;
333 ::memcpy(dst, src, 8);
343 uint32_t vmx_offset = vsx_offset -
sizeof(m_vsx_ppc64le) / 2;
344 uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset;
353 "failed - register wasn't recognized to be a GPR, FPR, VSX "
354 "or VMX, write strategy unknown");
357Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues(
378 uint8_t *dst = data_sp->GetBytes();
379 ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize());
381 ::memcpy(dst, &m_fpr_ppc64le, GetFPRSize());
383 ::memcpy(dst, &m_vmx_ppc64le,
sizeof(m_vmx_ppc64le));
384 dst +=
sizeof(m_vmx_ppc64le);
385 ::memcpy(dst, &m_vsx_ppc64le,
sizeof(m_vsx_ppc64le));
390Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues(
396 "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided",
403 "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched "
404 "data size, expected %" PRIu64
", actual %" PRIu64,
409 const uint8_t *src = data_sp->GetBytes();
410 if (src ==
nullptr) {
412 "NativeRegisterContextLinux_ppc64le::%s "
413 "DataBuffer::GetBytes() returned a null "
419 ::memcpy(&m_gpr_ppc64le, src, GetGPRSize());
426 ::memcpy(&m_fpr_ppc64le, src, GetFPRSize());
433 ::memcpy(&m_vmx_ppc64le, src,
sizeof(m_vmx_ppc64le));
439 src +=
sizeof(m_vmx_ppc64le);
440 ::memcpy(&m_vsx_ppc64le, src,
sizeof(m_vsx_ppc64le));
446bool NativeRegisterContextLinux_ppc64le::IsGPR(
unsigned reg)
const {
450bool NativeRegisterContextLinux_ppc64le::IsFPR(
unsigned reg)
const {
454uint32_t NativeRegisterContextLinux_ppc64le::CalculateFprOffset(
460uint32_t NativeRegisterContextLinux_ppc64le::CalculateVmxOffset(
466uint32_t NativeRegisterContextLinux_ppc64le::CalculateVsxOffset(
472Status NativeRegisterContextLinux_ppc64le::ReadVMX() {
473 int regset = NT_PPC_VMX;
475 ®set, &m_vmx_ppc64le,
476 sizeof(m_vmx_ppc64le));
479Status NativeRegisterContextLinux_ppc64le::WriteVMX() {
480 int regset = NT_PPC_VMX;
482 ®set, &m_vmx_ppc64le,
483 sizeof(m_vmx_ppc64le));
486Status NativeRegisterContextLinux_ppc64le::ReadVSX() {
487 int regset = NT_PPC_VSX;
489 ®set, &m_vsx_ppc64le,
490 sizeof(m_vsx_ppc64le));
493Status NativeRegisterContextLinux_ppc64le::WriteVSX() {
494 int regset = NT_PPC_VSX;
496 ®set, &m_vsx_ppc64le,
497 sizeof(m_vsx_ppc64le));
500bool NativeRegisterContextLinux_ppc64le::IsVMX(
unsigned reg) {
504bool NativeRegisterContextLinux_ppc64le::IsVSX(
unsigned reg) {
508uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() {
517 LLDB_LOG(log,
"{0}", m_max_hwp_supported);
518 return m_max_hwp_supported;
521uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint(
524 LLDB_LOG(log,
"addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
533 uint32_t control_value = 0, wp_index = 0;
535 uint32_t rw_mode = 0;
539 switch (watch_flags) {
540 case eWatchpointKindWrite:
541 rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE;
544 case eWatchpointKindRead:
545 rw_mode = PPC_BREAKPOINT_TRIGGER_READ;
548 case (eWatchpointKindRead | eWatchpointKindWrite):
549 rw_mode = PPC_BREAKPOINT_TRIGGER_RW;
556 if (size != 1 && size != 2 && size != 4 && size != 8)
564 addr_t begin = llvm::alignDown(addr, 8);
565 addr_t end = llvm::alignTo(addr + size, 8);
566 size = llvm::PowerOf2Ceil(end - begin);
568 addr = addr & (~0x07);
572 control_value = watch_flags << 3;
573 control_value |= ((1 << size) - 1) << 5;
574 control_value |= (2 << 1) | 1;
578 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
579 if ((m_hwp_regs[i].control & 1) == 0) {
581 }
else if (m_hwp_regs[i].address == addr) {
590 m_hwp_regs[wp_index].real_addr = real_addr;
591 m_hwp_regs[wp_index].address = addr;
592 m_hwp_regs[wp_index].control = control_value;
593 m_hwp_regs[wp_index].mode = rw_mode;
599 m_hwp_regs[wp_index].address = 0;
600 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
608bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint(
611 LLDB_LOG(log,
"wp_index: {0}", wp_index);
619 if (wp_index >= m_max_hwp_supported)
624 uint32_t tempControl = m_hwp_regs[wp_index].control;
625 long *tempSlot =
reinterpret_cast<long *
>(m_hwp_regs[wp_index].slot);
628 m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
629 m_hwp_regs[wp_index].address = 0;
630 m_hwp_regs[wp_index].slot = 0;
631 m_hwp_regs[wp_index].mode = 0;
635 m_thread.GetID(), 0, tempSlot);
638 m_hwp_regs[wp_index].control = tempControl;
639 m_hwp_regs[wp_index].address = tempAddr;
640 m_hwp_regs[wp_index].slot =
reinterpret_cast<long>(tempSlot);
649NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) {
651 LLDB_LOG(log,
"wp_index: {0}", wp_index);
653 unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff;
654 if (llvm::isPowerOf2_32(control + 1)) {
655 return llvm::popcount(control);
661bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled(
664 LLDB_LOG(log,
"wp_index: {0}", wp_index);
666 return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1);
669Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex(
672 LLDB_LOG(log,
"wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
677 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
678 watch_size = GetWatchpointSize(wp_index);
679 watch_addr = m_hwp_regs[wp_index].address;
681 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
682 trap_addr <= watch_addr + watch_size) {
683 m_hwp_regs[wp_index].hit_addr = trap_addr;
693NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) {
695 LLDB_LOG(log,
"wp_index: {0}", wp_index);
697 if (wp_index >= m_max_hwp_supported)
700 if (WatchpointIsEnabled(wp_index))
701 return m_hwp_regs[wp_index].real_addr;
707NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) {
709 LLDB_LOG(log,
"wp_index: {0}", wp_index);
711 if (wp_index >= m_max_hwp_supported)
714 if (WatchpointIsEnabled(wp_index))
715 return m_hwp_regs[wp_index].hit_addr;
720Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() {
721 if (!m_refresh_hwdebug_info) {
725 ::pid_t tid = m_thread.GetID();
727 struct ppc_debug_info hwdebug_info;
731 PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info,
sizeof(hwdebug_info));
736 m_max_hwp_supported = hwdebug_info.num_data_bps;
737 m_max_hbp_supported = hwdebug_info.num_instruction_bps;
738 m_refresh_hwdebug_info =
false;
743Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() {
744 struct ppc_hw_breakpoint reg_state;
748 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
749 reg_state.addr = m_hwp_regs[i].address;
750 reg_state.trigger_type = m_hwp_regs[i].mode;
751 reg_state.version = 1;
752 reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
753 reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
755 reg_state.condition_value = 0;
758 m_thread.GetID(), 0, ®_state,
759 sizeof(reg_state), &ret);
764 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.