[Lldb-commits] [lldb] [lldb][AIX] Implement read/write handling for GPR and SPR registers (PR #193205)
Hemang Gadhavi via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 24 03:40:46 PDT 2026
https://github.com/HemangGadhavi updated https://github.com/llvm/llvm-project/pull/193205
>From 4f2de03941db5c3d12cd95c880a2c1b1d7de56bd Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Tue, 21 Apr 2026 06:35:38 -0500
Subject: [PATCH 1/3] [lldb][AIX] Implement read/write handling for GPR and SPR
registers
---
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 83 ++++++++++++++++++-
.../Process/AIX/NativeRegisterContextAIX.cpp | 20 ++++-
.../Process/AIX/NativeRegisterContextAIX.h | 16 +++-
.../AIX/NativeRegisterContextAIX_ppc64.cpp | 77 ++++++++++++++++-
.../AIX/NativeRegisterContextAIX_ppc64.h | 19 +++++
.../Plugins/Process/AIX/NativeThreadAIX.cpp | 5 +-
.../Plugins/Process/AIX/NativeThreadAIX.h | 2 +
.../Utility/RegisterInfoPOSIX_ppc64.cpp | 21 ++++-
.../Process/Utility/RegisterInfoPOSIX_ppc64.h | 1 +
.../Process/Utility/RegisterInfos_ppc64.h | 52 ++++++++++++
10 files changed, 285 insertions(+), 11 deletions(-)
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index af54b043cc44c..24f91704272b8 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -22,10 +22,14 @@
#include <cerrno>
#include <cstdint>
#include <cstring>
+#include <dirent.h>
#include <sstream>
#include <string>
#include <sys/ptrace.h>
#include <unistd.h>
+#define DECLARE_REGISTER_INFOS_PPC64_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64.h"
+#undef DECLARE_REGISTER_INFOS_PPC64_STRUCT
using namespace lldb;
using namespace lldb_private;
@@ -279,13 +283,90 @@ llvm::Error NativeProcessAIX::Detach(lldb::tid_t tid) {
return PtraceWrapper(PT_DETACH, tid).takeError();
}
+template <typename GPR_T, typename PTSPRS_T>
+llvm::Expected<int> GetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
+ PTSPRS_T sprs;
+
+ int ret = ptrace64(req, tid, (long long)&sprs, 0, 0);
+
+ if (ret != -1) {
+ gpr->cr = sprs.pt_cr;
+ gpr->msr = sprs.pt_msr;
+ gpr->xer = sprs.pt_xer;
+ gpr->lr = sprs.pt_lr;
+ gpr->ctr = sprs.pt_ctr;
+ gpr->pc = sprs.pt_iar;
+ }
+ return ret;
+}
+
+template <typename GPR_T, typename PTSPRS_T>
+llvm::Expected<int> SetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
+ PTSPRS_T sprs;
+
+ sprs.pt_cr = gpr->cr;
+ sprs.pt_msr = gpr->msr;
+ sprs.pt_xer = gpr->xer;
+ sprs.pt_lr = gpr->lr;
+ sprs.pt_ctr = gpr->ctr;
+ sprs.pt_iar = gpr->pc;
+
+ return (ptrace64(req, tid, (long long)&sprs, 0, 0));
+}
+
llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
void *addr, void *data,
size_t data_size) {
int ret;
-
Log *log = GetLog(POSIXLog::Ptrace);
+ // for PTT_*
+ const char procdir[] = "/proc/";
+ const char lwpdir[] = "/lwp/";
+ std::string process_task_dir = procdir + std::to_string(pid) + lwpdir;
+ DIR *dirproc = opendir(process_task_dir.c_str());
+
+ lldb::tid_t tid = 0;
+ if (dirproc) {
+ struct dirent *direntry = nullptr;
+ while ((direntry = readdir(dirproc)) != nullptr) {
+ if (strcmp(direntry->d_name, ".") == 0 ||
+ strcmp(direntry->d_name, "..") == 0) {
+ continue;
+ }
+ tid = atoi(direntry->d_name);
+ break;
+ }
+ closedir(dirproc);
+ }
+
switch (req) {
+ case PTT_READ_GPRS:
+ if (data_size == sizeof(GPR_PPC)) // 32bit SPRs read
+ ret = GetSPRs<GPR_PPC, ptsprs>(PTT_READ_SPRS, tid,
+ static_cast<GPR_PPC *>(data))
+ .get();
+ else if (data_size == sizeof(GPR_PPC64)) // 64bit SPRs read
+ ret = GetSPRs<GPR_PPC64, ptxsprs>(PTT_READ_SPRS, tid,
+ static_cast<GPR_PPC64 *>(data))
+ .get();
+
+ if (ret != -1)
+ ret = ptrace64(req, tid, (long long)data, 0, 0); // read GPRs
+ break;
+
+ case PTT_WRITE_GPRS:
+ if (data_size == sizeof(GPR_PPC)) // 32bit SPRs write
+ ret = SetSPRs<GPR_PPC, ptsprs>(PTT_WRITE_SPRS, tid,
+ static_cast<GPR_PPC *>(data))
+ .get();
+ else if (data_size == sizeof(GPR_PPC64)) // 64bit SPRS write
+ ret = SetSPRs<GPR_PPC64, ptxsprs>(PTT_WRITE_SPRS, tid,
+ static_cast<GPR_PPC64 *>(data))
+ .get();
+
+ if (ret != -1)
+ ret = ptrace64(req, tid, (long long)data, 0, 0); // write GPRs
+ break;
case PT_ATTACH:
case PT_DETACH:
case PT_KILL:
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp
index e44cd7b5a30f5..7c3f538e93b11 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp
@@ -27,9 +27,25 @@ NativeRegisterContextAIX::WriteRegisterRaw(uint32_t reg_index,
return Status("unimplemented");
}
-Status NativeRegisterContextAIX::ReadGPR() { return Status("unimplemented"); }
+Status NativeRegisterContextAIX::ReadGPR() {
+ auto result = NativeProcessAIX::PtraceWrapper(
+ PTT_READ_GPRS, m_thread.GetID(), nullptr, GetGPRBuffer(), GetGPRSize());
-Status NativeRegisterContextAIX::WriteGPR() { return Status("unimplemented"); }
+ if (!result)
+ return Status::FromError(result.takeError());
+
+ return Status();
+}
+
+Status NativeRegisterContextAIX::WriteGPR() {
+ auto result = NativeProcessAIX::PtraceWrapper(
+ PTT_WRITE_GPRS, m_thread.GetID(), nullptr, GetGPRBuffer(), GetGPRSize());
+
+ if (!result)
+ return Status::FromError(result.takeError());
+
+ return Status();
+}
Status NativeRegisterContextAIX::ReadFPR() { return Status("unimplemented"); }
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
index e78483a7670f6..5f80c9d90fed4 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
@@ -13,8 +13,20 @@
namespace lldb_private::process_aix {
+class NativeThreadAIX;
+
class NativeRegisterContextAIX
: public virtual NativeRegisterContextRegisterInfo {
+public:
+ // This function is implemented in the NativeRegisterContextAIX_ppc64
+ // subclasses to create a new instance of the host specific
+ // NativeRegisterContextAIX. The implementations can't collide as only one
+ // NativeRegisterContextAIX_ppc64 variant should be compiled into the final
+ // executable.
+ static std::unique_ptr<NativeRegisterContextAIX>
+ CreateHostNativeRegisterContextAIX(const ArchSpec &target_arch,
+ NativeThreadAIX &native_thread);
+
protected:
NativeRegisterContextAIX(NativeThreadProtocol &thread)
: NativeRegisterContextRegisterInfo(thread, nullptr) {}
@@ -50,7 +62,9 @@ class NativeRegisterContextAIX
virtual void *GetGPRBuffer() = 0;
- virtual size_t GetGPRSize() = 0;
+ virtual size_t GetGPRSize() const {
+ return GetRegisterInfoInterface().GetGPRSize();
+ }
virtual void *GetFPRBuffer() = 0;
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
index aba785753055c..2096641dd272e 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
@@ -9,6 +9,9 @@
#if defined(__powerpc64__)
#include "NativeRegisterContextAIX_ppc64.h"
+#include "NativeThreadAIX.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb;
using namespace lldb_private;
@@ -87,11 +90,34 @@ static const RegisterSet g_reg_sets_ppc64[k_num_register_sets] = {
{"VSX Registers", "vsx", k_num_vsx_registers_ppc64, g_vsx_regnums_ppc64},
};
+std::unique_ptr<NativeRegisterContextAIX>
+NativeRegisterContextAIX::CreateHostNativeRegisterContextAIX(
+ const ArchSpec &target_arch, NativeThreadAIX &native_thread) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ return std::make_unique<NativeRegisterContextAIX_ppc64>(target_arch,
+ native_thread);
+ default:
+ llvm_unreachable("have no register context for architecture");
+ }
+}
+
NativeRegisterContextAIX_ppc64::NativeRegisterContextAIX_ppc64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextAIX(native_thread) {
- if (target_arch.GetMachine() != llvm::Triple::ppc64)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_ppc64(target_arch)),
+ NativeRegisterContextAIX(native_thread) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc:
+ m_gpr = &m_gpr_storage.gpr32;
+ break;
+ case llvm::Triple::ppc64:
+ m_gpr = &m_gpr_storage.gpr64;
+ break;
+ default:
llvm_unreachable("Unhandled target architecture.");
+ }
}
uint32_t NativeRegisterContextAIX_ppc64::GetRegisterSetCount() const {
@@ -116,13 +142,56 @@ uint32_t NativeRegisterContextAIX_ppc64::GetUserRegisterCount() const {
Status
NativeRegisterContextAIX_ppc64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue ®_value) {
- return Status("unimplemented");
+ Status error;
+ if (!reg_info)
+ return Status::FromErrorString("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (IsGPR(reg)) {
+ error = ReadGPR();
+ if (error.Fail())
+ return error;
+
+ const uint8_t *src = reinterpret_cast<const uint8_t *>(GetGPRBuffer()) +
+ reg_info->byte_offset;
+ reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size,
+ eByteOrderBig, error);
+
+ return error;
+ } else if (IsFPR(reg) || IsVSX(reg) || IsVMX(reg)) {
+ return Status::FromErrorString("unimplemented");
+ }
+
+ return Status::FromErrorString("failed - register wasn't recognized to be a "
+ "GPR, FPR, VSX or VMX, read strategy unknown");
}
Status
NativeRegisterContextAIX_ppc64::WriteRegister(const RegisterInfo *reg_info,
const RegisterValue ®_value) {
- return Status("unimplemented");
+ Status error;
+ if (!reg_info)
+ return Status::FromErrorString("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (IsGPR(reg)) {
+ error = ReadGPR();
+ if (error.Fail())
+ return error;
+
+ uint8_t *dst =
+ reinterpret_cast<uint8_t *>(GetGPRBuffer()) + reg_info->byte_offset;
+ ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize());
+
+ return (WriteGPR());
+ } else if (IsFPR(reg) || IsVMX(reg) || IsVSX(reg)) {
+ return Status::FromErrorString("unimplemented");
+ }
+
+ return Status::FromErrorString("failed - register wasn't recognized to be a "
+ "GPR, FPR, VSX or VMX, read strategy unknown");
}
Status NativeRegisterContextAIX_ppc64::ReadAllRegisterValues(
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
index 77f75777737d1..b86d9f887f4e5 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
@@ -14,6 +14,10 @@
#include "Plugins/Process/AIX/NativeRegisterContextAIX.h"
#include "Plugins/Process/Utility/lldb-ppc64-register-enums.h"
+#define DECLARE_REGISTER_INFOS_PPC64_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64.h"
+#undef DECLARE_REGISTER_INFOS_PPC64_STRUCT
+
namespace lldb_private {
namespace process_aix {
@@ -40,6 +44,13 @@ class NativeRegisterContextAIX_ppc64 : public NativeRegisterContextAIX {
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+protected:
+ void *GetGPRBuffer() override { return m_gpr; }
+
+ void *GetFPRBuffer() override { return nullptr; }
+
+ size_t GetFPRSize() override { return 0; }
+
private:
bool IsGPR(unsigned reg) const;
@@ -54,6 +65,14 @@ class NativeRegisterContextAIX_ppc64 : public NativeRegisterContextAIX {
uint32_t CalculateVmxOffset(const RegisterInfo *reg_info) const;
uint32_t CalculateVsxOffset(const RegisterInfo *reg_info) const;
+
+ union GPRStorage {
+ GPR_PPC gpr32; // 32-bit general purpose registers.
+ GPR_PPC64 gpr64; // 64-bit general purpose registers.
+ };
+
+ GPRStorage m_gpr_storage;
+ void *m_gpr = nullptr;
};
} // namespace process_aix
diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
index 3bb608168ce30..264106fe56d92 100644
--- a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
@@ -15,7 +15,10 @@ using namespace lldb_private;
using namespace lldb_private::process_aix;
NativeThreadAIX::NativeThreadAIX(NativeProcessAIX &process, lldb::tid_t tid)
- : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid) {}
+ : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
+ m_reg_context_up(
+ NativeRegisterContextAIX::CreateHostNativeRegisterContextAIX(
+ process.GetArchitecture(), *this)) {}
std::string NativeThreadAIX::GetName() { return ""; }
diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h
index e32d3db2c5fa2..5c374b399c5c3 100644
--- a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h
+++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h
@@ -9,6 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_AIX_NATIVETHREADAIX_H_
#define LLDB_SOURCE_PLUGINS_PROCESS_AIX_NATIVETHREADAIX_H_
+#include "Plugins/Process/AIX/NativeRegisterContextAIX.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
namespace lldb_private::process_aix {
@@ -47,6 +48,7 @@ class NativeThreadAIX : public NativeThreadProtocol {
private:
lldb::StateType m_state;
+ std::unique_ptr<NativeRegisterContextAIX> m_reg_context_up;
};
} // namespace lldb_private::process_aix
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.cpp
index 1550f00bea28e..e4969d4b306b7 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.cpp
@@ -23,6 +23,8 @@
static const lldb_private::RegisterInfo *
GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc:
+ return g_register_infos_ppc;
case llvm::Triple::ppc64:
return g_register_infos_ppc64;
default:
@@ -34,6 +36,9 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
static uint32_t
GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc:
+ return static_cast<uint32_t>(sizeof(g_register_infos_ppc) /
+ sizeof(g_register_infos_ppc[0]));
case llvm::Triple::ppc64:
return static_cast<uint32_t>(sizeof(g_register_infos_ppc64) /
sizeof(g_register_infos_ppc64[0]));
@@ -47,9 +52,21 @@ RegisterInfoPOSIX_ppc64::RegisterInfoPOSIX_ppc64(
const lldb_private::ArchSpec &target_arch)
: lldb_private::RegisterInfoInterface(target_arch),
m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)) {}
+ m_register_info_count(GetRegisterInfoCount(target_arch)), m_gpr_size(0) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc:
+ m_gpr_size = sizeof(GPR_PPC);
+ break;
+ case llvm::Triple::ppc64:
+ m_gpr_size = sizeof(GPR_PPC64);
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+}
-size_t RegisterInfoPOSIX_ppc64::GetGPRSize() const { return sizeof(GPR_PPC64); }
+size_t RegisterInfoPOSIX_ppc64::GetGPRSize() const { return m_gpr_size; }
const lldb_private::RegisterInfo *
RegisterInfoPOSIX_ppc64::GetRegisterInfo() const {
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.h
index 177ff439828e8..e33d32ae98ad3 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64.h
@@ -26,6 +26,7 @@ class RegisterInfoPOSIX_ppc64 : public lldb_private::RegisterInfoInterface {
private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
+ size_t m_gpr_size;
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_PPC64_H
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
index 5ea561fe22b42..ba0b6d45d95ba 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -334,6 +334,48 @@ typedef struct _GPR_PPC64 {
uint64_t pad[3];
} GPR_PPC64;
+typedef struct _GPR_PPC {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r12;
+ uint32_t r13;
+ uint32_t r14;
+ uint32_t r15;
+ uint32_t r16;
+ uint32_t r17;
+ uint32_t r18;
+ uint32_t r19;
+ uint32_t r20;
+ uint32_t r21;
+ uint32_t r22;
+ uint32_t r23;
+ uint32_t r24;
+ uint32_t r25;
+ uint32_t r26;
+ uint32_t r27;
+ uint32_t r28;
+ uint32_t r29;
+ uint32_t r30;
+ uint32_t r31;
+ uint32_t cr;
+ uint32_t msr;
+ uint32_t xer;
+ uint32_t lr;
+ uint32_t ctr;
+ uint32_t pc;
+ uint32_t pad[3];
+} GPR_PPC;
+
typedef struct _FPR_PPC64 {
uint64_t f0;
uint64_t f1;
@@ -481,6 +523,16 @@ static_assert((sizeof(g_register_infos_ppc64) /
sizeof(g_register_infos_ppc64[0])) == k_num_registers_ppc64,
"g_register_infos_powerpc64 has wrong number of register infos");
+static lldb_private::RegisterInfo g_register_infos_ppc[] = {
+#define GPR_PPC64 GPR_PPC
+ PPC64_REGS
+#undef GPR_PPC64
+};
+
+static_assert((sizeof(g_register_infos_ppc) /
+ sizeof(g_register_infos_ppc[0])) == k_num_registers_ppc64,
+ "g_register_infos_powerpc has wrong number of register infos");
+
#undef DEFINE_FPR_PPC64
#undef DEFINE_GPR_PPC64
#undef DEFINE_VMX_PPC64
>From 328f75ec3d250e7712547ac330f5f41907a2c01c Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Fri, 24 Apr 2026 02:23:08 -0500
Subject: [PATCH 2/3] Addressed review comments
---
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 38 +++++++++++--------
.../Process/AIX/NativeRegisterContextAIX.h | 8 ++--
.../AIX/NativeRegisterContextAIX_ppc64.cpp | 2 +
.../AIX/NativeRegisterContextAIX_ppc64.h | 3 +-
4 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index 24f91704272b8..c42f30a495c3d 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -284,10 +284,10 @@ llvm::Error NativeProcessAIX::Detach(lldb::tid_t tid) {
}
template <typename GPR_T, typename PTSPRS_T>
-llvm::Expected<int> GetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
+int GetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
PTSPRS_T sprs;
- int ret = ptrace64(req, tid, (long long)&sprs, 0, 0);
+ int ret = ptrace64(req, tid, reinterpret_cast<long long>(&sprs), 0, 0);
if (ret != -1) {
gpr->cr = sprs.pt_cr;
@@ -301,7 +301,7 @@ llvm::Expected<int> GetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
}
template <typename GPR_T, typename PTSPRS_T>
-llvm::Expected<int> SetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
+int SetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
PTSPRS_T sprs;
sprs.pt_cr = gpr->cr;
@@ -311,13 +311,13 @@ llvm::Expected<int> SetSPRs(int req, lldb::tid_t tid, GPR_T *gpr) {
sprs.pt_ctr = gpr->ctr;
sprs.pt_iar = gpr->pc;
- return (ptrace64(req, tid, (long long)&sprs, 0, 0));
+ return ptrace64(req, tid, reinterpret_cast<long long>(&sprs), 0, 0);
}
llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
void *addr, void *data,
size_t data_size) {
- int ret;
+ int ret = 0;
Log *log = GetLog(POSIXLog::Ptrace);
// for PTT_*
const char procdir[] = "/proc/";
@@ -325,6 +325,12 @@ llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
std::string process_task_dir = procdir + std::to_string(pid) + lwpdir;
DIR *dirproc = opendir(process_task_dir.c_str());
+ // PTT_* requests require a thread ID (TID).
+ // Each entry under /proc/<pid>/lwp/ represents a thread,
+ // and the directory name corresponds to its thread ID (TID).
+ // A process may contain multiple threads.
+ // TODO: With multi-threading support, iterate over all entries to enumerate
+ // available TIDs and retrieve the target debugging thread ID.
lldb::tid_t tid = 0;
if (dirproc) {
struct dirent *direntry = nullptr;
@@ -340,32 +346,34 @@ llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
}
switch (req) {
+ // On AIX, ptrace exposes differently. GPRs and SPRs are handled via separate
+ // requests: PTT_READ_GPRS reads only GPRs & PTT_READ_SPRS is required to
+ // fetch SPRs. Similarly, writes are also split across:
+ // PTT_WRITE_GPRS & PTT_WRITE_SPRS.
case PTT_READ_GPRS:
if (data_size == sizeof(GPR_PPC)) // 32bit SPRs read
ret = GetSPRs<GPR_PPC, ptsprs>(PTT_READ_SPRS, tid,
- static_cast<GPR_PPC *>(data))
- .get();
+ static_cast<GPR_PPC *>(data));
else if (data_size == sizeof(GPR_PPC64)) // 64bit SPRs read
ret = GetSPRs<GPR_PPC64, ptxsprs>(PTT_READ_SPRS, tid,
- static_cast<GPR_PPC64 *>(data))
- .get();
+ static_cast<GPR_PPC64 *>(data));
if (ret != -1)
- ret = ptrace64(req, tid, (long long)data, 0, 0); // read GPRs
+ ret = ptrace64(req, tid, reinterpret_cast<long long>(data), 0,
+ 0); // read GPRs
break;
case PTT_WRITE_GPRS:
if (data_size == sizeof(GPR_PPC)) // 32bit SPRs write
ret = SetSPRs<GPR_PPC, ptsprs>(PTT_WRITE_SPRS, tid,
- static_cast<GPR_PPC *>(data))
- .get();
+ static_cast<GPR_PPC *>(data));
else if (data_size == sizeof(GPR_PPC64)) // 64bit SPRS write
ret = SetSPRs<GPR_PPC64, ptxsprs>(PTT_WRITE_SPRS, tid,
- static_cast<GPR_PPC64 *>(data))
- .get();
+ static_cast<GPR_PPC64 *>(data));
if (ret != -1)
- ret = ptrace64(req, tid, (long long)data, 0, 0); // write GPRs
+ ret = ptrace64(req, tid, reinterpret_cast<long long>(data), 0,
+ 0); // write GPRs
break;
case PT_ATTACH:
case PT_DETACH:
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
index 5f80c9d90fed4..1372affd0044a 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
@@ -19,10 +19,10 @@ class NativeRegisterContextAIX
: public virtual NativeRegisterContextRegisterInfo {
public:
// This function is implemented in the NativeRegisterContextAIX_ppc64
- // subclasses to create a new instance of the host specific
- // NativeRegisterContextAIX. The implementations can't collide as only one
- // NativeRegisterContextAIX_ppc64 variant should be compiled into the final
- // executable.
+ // subclasses to create a new instance (for both 32-bit or 64-bit) of the host
+ // specific NativeRegisterContextAIX. Only one variant (e.g., 32-bit or
+ // 64-bit) is
+ // compiled into the final executable, so there is no conflict between them.
static std::unique_ptr<NativeRegisterContextAIX>
CreateHostNativeRegisterContextAIX(const ArchSpec &target_arch,
NativeThreadAIX &native_thread);
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
index 2096641dd272e..847a1b486a998 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp
@@ -110,9 +110,11 @@ NativeRegisterContextAIX_ppc64::NativeRegisterContextAIX_ppc64(
NativeRegisterContextAIX(native_thread) {
switch (target_arch.GetMachine()) {
case llvm::Triple::ppc:
+ new (&m_gpr_storage.gpr32) GPR_PPC{};
m_gpr = &m_gpr_storage.gpr32;
break;
case llvm::Triple::ppc64:
+ new (&m_gpr_storage.gpr32) GPR_PPC64{};
m_gpr = &m_gpr_storage.gpr64;
break;
default:
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
index b86d9f887f4e5..aa0a6b8549900 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h
@@ -69,9 +69,8 @@ class NativeRegisterContextAIX_ppc64 : public NativeRegisterContextAIX {
union GPRStorage {
GPR_PPC gpr32; // 32-bit general purpose registers.
GPR_PPC64 gpr64; // 64-bit general purpose registers.
- };
+ } m_gpr_storage;
- GPRStorage m_gpr_storage;
void *m_gpr = nullptr;
};
>From d7e5c4e07d1aa5b4e7768ce151f07f92313bcf85 Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Fri, 24 Apr 2026 05:15:39 -0500
Subject: [PATCH 3/3] Use llvm code style for get TID
---
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 29 +++++++++----------
.../Process/AIX/NativeRegisterContextAIX.h | 6 ++--
2 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index c42f30a495c3d..9c7e66cb79028 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -22,7 +22,6 @@
#include <cerrno>
#include <cstdint>
#include <cstring>
-#include <dirent.h>
#include <sstream>
#include <string>
#include <sys/ptrace.h>
@@ -319,30 +318,30 @@ llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
size_t data_size) {
int ret = 0;
Log *log = GetLog(POSIXLog::Ptrace);
- // for PTT_*
- const char procdir[] = "/proc/";
- const char lwpdir[] = "/lwp/";
- std::string process_task_dir = procdir + std::to_string(pid) + lwpdir;
- DIR *dirproc = opendir(process_task_dir.c_str());
-
// PTT_* requests require a thread ID (TID).
// Each entry under /proc/<pid>/lwp/ represents a thread,
// and the directory name corresponds to its thread ID (TID).
// A process may contain multiple threads.
// TODO: With multi-threading support, iterate over all entries to enumerate
// available TIDs and retrieve the target debugging thread ID.
+ llvm::SmallString<128> proc_lwp_dir;
+ llvm::sys::path::append(proc_lwp_dir, "/proc/", std::to_string(pid), "/lwp/");
+
lldb::tid_t tid = 0;
- if (dirproc) {
- struct dirent *direntry = nullptr;
- while ((direntry = readdir(dirproc)) != nullptr) {
- if (strcmp(direntry->d_name, ".") == 0 ||
- strcmp(direntry->d_name, "..") == 0) {
+ std::error_code ec;
+ bool result;
+ if (!llvm::sys::fs::is_directory(proc_lwp_dir, result) && result) {
+ for (sys::fs::directory_iterator it(proc_lwp_dir, ec), end;
+ it != end && !ec; it.increment(ec)) {
+ llvm::StringRef name = llvm::sys::path::filename(it->path());
+
+ if (name == "." || name == "..")
continue;
+
+ if (!name.getAsInteger(10, tid)) {
+ break;
}
- tid = atoi(direntry->d_name);
- break;
}
- closedir(dirproc);
}
switch (req) {
diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
index 1372affd0044a..1f4f79627db41 100644
--- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
+++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h
@@ -20,9 +20,9 @@ class NativeRegisterContextAIX
public:
// This function is implemented in the NativeRegisterContextAIX_ppc64
// subclasses to create a new instance (for both 32-bit or 64-bit) of the host
- // specific NativeRegisterContextAIX. Only one variant (e.g., 32-bit or
- // 64-bit) is
- // compiled into the final executable, so there is no conflict between them.
+ // specific NativeRegisterContextAIX.
+ // The appropriate implementation is selected at runtime based on the
+ // target process architecture, so only the relevant code path is used.
static std::unique_ptr<NativeRegisterContextAIX>
CreateHostNativeRegisterContextAIX(const ArchSpec &target_arch,
NativeThreadAIX &native_thread);
More information about the lldb-commits
mailing list