From: Aditya Vidyadhar Kamath <akamath996@gmail.com>
To: ulrich.weigand@de.ibm.com, simon.marchi@polymtl.ca, tom@tromey.com
Cc: gdb-patches@sourceware.org, Aditya.Kamath1@ibm.com,
sangamesh.swamy@in.ibm.com,
Aditya Vidyadhar Kamath <aditya.kamath1@ibm.com>
Subject: [PATCH v5 1/4] Remove stale legacy code from rs6000-aix-nat.c file.
Date: Tue, 13 Oct 2026 16:49:15 +0530 [thread overview]
Message-ID: <20261013111917.68981-2-akamath996@gmail.com> (raw)
From: Aditya Vidyadhar Kamath <aditya.kamath1@ibm.com>
GDB on AIX is built in 64-bit mode only. A 64-bit program cannot link
against the legacy 32-bit ptrace () and ptracex () symbols; trying to
do so fails with:
CXXLD gdb
ld: 0711-317 ERROR: Undefined symbol: .ptrace
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more
information.
collect2: error: ld returned 8 exit status
gmake[2]: *** [Makefile:2367: gdb] Error 1
A 64-bit GDB must use ptrace64 () exclusively.
The rs6000_ptrace32 () and rs6000_ptrace64 () wrappers conditionally
called ptrace (), ptracex () or ptrace64 () and relied on the ARCH3264
macro. With 32-bit GDB builds deprecated and ptrace64 () available on
AIX 7.2 and 7.3, neither the wrappers nor ARCH3264 are needed.
The IBM documentation for ptrace64 ()
https://www.ibm.com/docs/en/aix/7.2.0?topic=p-ptrace-ptracex-ptrace64-subroutine
says that calling it with a
32-bit debuggee makes GPR/SPR requests fail with EIO. Testing shows
that ptrace64 () handles 32-bit debuggees correctly:
1: For 32-bit debuggees, PT_READ_GPR returns the register value as the
return value of ptrace64 (), and PT_WRITE_GPR takes the register
value by value in the data argument.
2: For 64-bit debuggees, PT_READ_GPR and PT_WRITE_GPR use an 8-byte
buffer passed as the 5th argument.
3: PT_READ_FPR and PT_WRITE_FPR work for both 32-bit and 64-bit
debuggees.
The changes are:
1: Remove rs6000_ptrace32 () and rs6000_ptrace64 () and call
ptrace64 () directly.
2: Simplify ARCH64 () to check the inferior register size, and remove
the ARCH3264 macro.
3: Move the duplicated kernel thread ID lookup for the VSX and AltiVec
requests into get_thread_id ().
4: Remove the dead "#if 0" block in fetch_register.
Testing
I ran the gdb.base testsuite before and after this patch, from the
gdb/testsuite directory, with 64-bit and 32-bit test programs.
64-bit:
gmake check RUNTESTFLAGS='--directory=gdb.base \
CC_FOR_TARGET="/opt/freeware/bin/gcc" \
CXX_FOR_TARGET="/opt/freeware/bin/g++" \
CXXFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64" \
CFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64"'
32-bit (same command without -maix64):
gmake check RUNTESTFLAGS='--directory=gdb.base \
CC_FOR_TARGET="/opt/freeware/bin/gcc" \
CXX_FOR_TARGET="/opt/freeware/bin/g++" \
CXXFLAGS_FOR_TARGET="-O0 -w -g -gdwarf" \
CFLAGS_FOR_TARGET="-O0 -w -g -gdwarf"'
64-bit 32-bit
before after before after
expected passes 41792 41802 41687 41541
unexpected failures 2346 2343 2302 2294
unexpected successes 1 1 1 1
expected failures 17 17 15 15
known failures 30 30 30 30
unresolved testcases 30 29 11 86
untested testcases 104 104 107 107
unsupported tests 179 178 179 179
The number of unexpected failures does not go up in either mode. The
failures that remain were there before this patch. I grouped the
64-bit failures by test file to check that none of them are in code
touched here.
Group Failures Test files
--------------------------------- -------- --------------------------
Casts in whatis-ptype-typedefs 1060 whatis-ptype-typedefs
(gdb reports "Cannot access
memory at address 0xefffffff")
Type printing, alignment, value 336 max-depth-c, max-depth-c++,
size and print limits align-c, align-c++,
limited-length,
max-value-size, printcmds
Inferior function calls, stores 208 nodebug, store,
and no-debug-info symbols return-nodebug, callfuncs,
recurse,
backtrace-through-cu-nodebug
fork, vfork and follow-exec 158 vfork-follow-parent,
multi-forks, foll-fork,
catch-fork-kill,
fork-running-state,
kill-detach-inferiors-cmd,
and 3 more
Signals 98 sigstep, catch-signal,
exitsignal, sigaltstack,
and 4 more
Attach, background execution and 108 attach, infcall-timeout,
interrupt (mostly timeouts) cli-suppress-notification,
bg-execution-repeat,
dprintf-detach,
quit-live, and 14 more
Everything else (83 test files) 375 dump (34), bp-permanent
(24), skip-tree (22),
value-history-unavailable
(19), memattr (17),
find (16), list-ambiguous
and -readnow (28),
and others
--------------------------------- --------
Total 2343
Similarly even 32 bit failures as the above table.
---
gdb/rs6000-aix-nat.c | 207 ++++++++++---------------------------------
1 file changed, 47 insertions(+), 160 deletions(-)
diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c
index 276df378824..3d1cf2542db 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -60,24 +60,9 @@
/* Header files for alti-vec reg. */
#include <sys/context.h>
-/* On AIX4.3+, sys/ldr.h provides different versions of struct ld_info for
- debugging 32-bit and 64-bit processes. Define a typedef and macros for
- accessing fields in the appropriate structures. */
-
-/* In 32-bit compilation mode (which is the only mode from which ptrace()
- works on 4.3), __ld_info32 is #defined as equivalent to ld_info. */
-
-#if defined (__ld_info32) || defined (__ld_info64)
-# define ARCH3264
-#endif
-
/* Return whether the current architecture is 64-bit. */
-#ifndef ARCH3264
-# define ARCH64() 0
-#else
-# define ARCH64() (register_size (current_inferior ()->arch (), 0) == 8)
-#endif
+#define ARCH64() (register_size (current_inferior ()->arch (), 0) == 8)
class rs6000_nat_target final : public inf_ptrace_target
{
@@ -246,42 +231,20 @@ regmap (struct gdbarch *gdbarch, int regno, int *isfloat)
return -1;
}
-/* Call ptrace(REQ, ID, ADDR, DATA, BUF). */
+/* Return the thread ID of the first kernel thread in PID, or 0 on
+ failure. Used to call PTT_* requests which require a tid rather
+ than a pid. */
-static int
-rs6000_ptrace32 (int req, int id, int *addr, int data, int *buf)
+static tid64_t
+get_thread_id (pid_t pid)
{
-#ifdef HAVE_PTRACE64
- int ret = ptrace64 (req, id, (uintptr_t) addr, data, buf);
-#else
- int ret = ptrace (req, id, (int *)addr, data, buf);
-#endif
-#if 0
- printf ("rs6000_ptrace32 (%d, %d, 0x%x, %08x, 0x%x) = 0x%x\n",
- req, id, (unsigned int)addr, data, (unsigned int)buf, ret);
-#endif
- return ret;
-}
-
-/* Call ptracex(REQ, ID, ADDR, DATA, BUF). */
+ struct thrdentry64 thrdentry;
+ tid64_t thrd_i = 0;
-static int
-rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf)
-{
-#ifdef ARCH3264
-# ifdef HAVE_PTRACE64
- int ret = ptrace64 (req, id, addr, data, (PTRACE_TYPE_ARG5) buf);
-# else
- int ret = ptracex (req, id, addr, data, (PTRACE_TYPE_ARG5) buf);
-# endif
-#else
- int ret = 0;
-#endif
-#if 0
- printf ("rs6000_ptrace64 (%d, %d, %s, %08x, 0x%x) = 0x%x\n",
- req, id, hex_string (addr), data, (unsigned int)buf, ret);
-#endif
- return ret;
+ if (getthrds64 (pid, &thrdentry, sizeof (struct thrdentry64),
+ &thrd_i, 1) == 1)
+ return thrdentry.ti_tid;
+ return 0;
}
/* Store the vsx registers. */
@@ -292,32 +255,21 @@ store_vsx_register_aix (struct regcache *regcache, int regno)
int ret;
struct gdbarch *gdbarch = regcache->arch ();
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
- struct thrdentry64 thrdentry;
__vsx_context_t vsx;
pid_t pid = inferior_ptid.pid ();
- tid64_t thrd_i = 0;
-
- if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
- &thrd_i, 1) == 1)
- thrd_i = thrdentry.ti_tid;
+ tid64_t thrd_i = get_thread_id (pid);
memset(&vsx, 0, sizeof(__vsx_context_t));
if (__power_vsx() && thrd_i > 0)
{
- if (ARCH64 ())
- ret = rs6000_ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
- else
- ret = rs6000_ptrace32 (PTT_READ_VSX, thrd_i, (int *)&vsx, 0, 0);
+ ret = ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
if (ret < 0)
return;
regcache->raw_collect (regno, &(vsx.__vsr_dw1[0])+
regno - tdep->ppc_vsr0_upper_regnum);
- if (ARCH64 ())
- ret = rs6000_ptrace64 (PTT_WRITE_VSX, thrd_i, (long long) &vsx, 0, 0);
- else
- ret = rs6000_ptrace32 (PTT_WRITE_VSX, thrd_i, (int *) &vsx, 0, 0);
+ ret = ptrace64 (PTT_WRITE_VSX, thrd_i, (long long) &vsx, 0, 0);
if (ret < 0)
perror_with_name (_("Unable to write VSX registers after reading it"));
@@ -332,32 +284,21 @@ store_altivec_register_aix (struct regcache *regcache, int regno)
int ret;
struct gdbarch *gdbarch = regcache->arch ();
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
- struct thrdentry64 thrdentry;
__vmx_context_t vmx;
pid_t pid = inferior_ptid.pid ();
- tid64_t thrd_i = 0;
-
- if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
- &thrd_i, 1) == 1)
- thrd_i = thrdentry.ti_tid;
+ tid64_t thrd_i = get_thread_id (pid);
memset(&vmx, 0, sizeof(__vmx_context_t));
if (__power_vmx() && thrd_i > 0)
{
- if (ARCH64 ())
- ret = rs6000_ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
- else
- ret = rs6000_ptrace32 (PTT_READ_VEC, thrd_i, (int *) &vmx, 0, 0);
+ ret = ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
if (ret < 0)
return;
regcache->raw_collect (regno, &(vmx.__vr[0]) + regno
- tdep->ppc_vr0_regnum);
- if (ARCH64 ())
- ret = rs6000_ptrace64 (PTT_WRITE_VEC, thrd_i, (long long) &vmx, 0, 0);
- else
- ret = rs6000_ptrace32 (PTT_WRITE_VEC, thrd_i, (int *) &vmx, 0, 0);
+ ret = ptrace64 (PTT_WRITE_VEC, thrd_i, (long long) &vmx, 0, 0);
if (ret < 0)
perror_with_name (_("Unable to store AltiVec register after reading it"));
}
@@ -385,22 +326,14 @@ supply_vrregset_aix (struct regcache *regcache, __vmx_context_t *vmx)
static void
fetch_altivec_registers_aix (struct regcache *regcache)
{
- struct thrdentry64 thrdentry;
__vmx_context_t vmx;
pid_t pid = current_inferior ()->pid;
- tid64_t thrd_i = 0;
-
- if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
- &thrd_i, 1) == 1)
- thrd_i = thrdentry.ti_tid;
+ tid64_t thrd_i = get_thread_id (pid);
memset(&vmx, 0, sizeof(__vmx_context_t));
if (__power_vmx() && thrd_i > 0)
{
- if (ARCH64 ())
- rs6000_ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
- else
- rs6000_ptrace32 (PTT_READ_VEC, thrd_i, (int *) &vmx, 0, 0);
+ ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
supply_vrregset_aix (regcache, &vmx);
}
}
@@ -423,38 +356,27 @@ supply_vsxregset_aix (struct regcache *regcache, __vsx_context_t *vsx)
static void
fetch_vsx_registers_aix (struct regcache *regcache)
{
- struct thrdentry64 thrdentry;
__vsx_context_t vsx;
pid_t pid = current_inferior ()->pid;
- tid64_t thrd_i = 0;
-
- if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
- &thrd_i, 1) == 1)
- thrd_i = thrdentry.ti_tid;
+ tid64_t thrd_i = get_thread_id (pid);
memset(&vsx, 0, sizeof(__vsx_context_t));
if (__power_vsx() && thrd_i > 0)
{
- if (ARCH64 ())
- rs6000_ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
- else
- rs6000_ptrace32 (PTT_READ_VSX, thrd_i, (int *) &vsx, 0, 0);
+ ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
supply_vsxregset_aix (regcache, &vsx);
}
}
void rs6000_nat_target::post_startup_inferior (ptid_t ptid)
{
-
/* In AIX to turn on multi process debugging in ptrace
PT_MULTI is the option to be passed,
with the process ID which can fork () and
- the data parameter [fourth parameter] must be 1. */
+ the data parameter [fourth parameter] must be 1. ptrace64 is
+ used for both 32-bit and 64-bit inferiors. */
- if (!ARCH64 ())
- rs6000_ptrace32 (PT_MULTI, ptid.pid(), 0, 1, 0);
- else
- rs6000_ptrace64 (PT_MULTI, ptid.pid(), 0, 1, 0);
+ ptrace64 (PT_MULTI, ptid.pid (), 0, 1, 0);
}
void
@@ -477,10 +399,7 @@ rs6000_nat_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
if (detach_fork && !follow_child)
{
- if (ARCH64 ())
- rs6000_ptrace64 (PT_DETACH, child_ptid.pid (), 0, 0, 0);
- else
- rs6000_ptrace32 (PT_DETACH, child_ptid.pid (), 0, 0, 0);
+ ptrace64 (PT_DETACH, child_ptid.pid (), 0, 0, 0);
}
}
@@ -528,7 +447,7 @@ fetch_register (struct regcache *regcache, int regno)
/* Floating-point registers. */
if (isfloat)
- rs6000_ptrace32 (PT_READ_FPR, pid, addr, nr, 0);
+ ptrace64 (PT_READ_FPR, pid, (long long) addr, nr, 0);
/* Bogus register number. */
else if (nr < 0)
@@ -543,31 +462,24 @@ fetch_register (struct regcache *regcache, int regno)
/* Fixed-point registers. */
else
{
- if (!ARCH64 ())
- *addr = rs6000_ptrace32 (PT_READ_GPR, pid, (int *) nr, 0, 0);
- else
+ if (ARCH64 ())
{
- /* PT_READ_GPR requires the buffer parameter to point to long long,
- even if the register is really only 32 bits. */
+ /* The buffer parameter must point to a long long area. */
long long buf;
- rs6000_ptrace64 (PT_READ_GPR, pid, nr, 0, &buf);
+ ptrace64 (PT_READ_GPR, pid, nr, 0, (PTRACE_TYPE_ARG5) &buf);
if (register_size (gdbarch, regno) == 8)
memcpy (addr, &buf, 8);
else
*addr = buf;
}
+ else
+ *addr = ptrace64 (PT_READ_GPR, pid, nr, 0, 0);
}
if (!errno)
regcache->raw_supply (regno, (char *) addr);
else
- {
-#if 0
- /* FIXME: this happens 3 times at the start of each 64-bit program. */
- perror (_("ptrace read"));
-#endif
- errno = 0;
- }
+ errno = 0;
}
/* Store register REGNO back into the inferior. */
@@ -602,7 +514,7 @@ store_register (struct regcache *regcache, int regno)
/* Floating-point registers. */
if (isfloat)
- rs6000_ptrace32 (PT_WRITE_FPR, pid, addr, nr, 0);
+ ptrace64 (PT_WRITE_FPR, pid, (long long) addr, nr, 0);
/* Bogus register number. */
else if (nr < 0)
@@ -616,22 +528,18 @@ store_register (struct regcache *regcache, int regno)
/* Fixed-point registers. */
else
{
- /* The PT_WRITE_GPR operation is rather odd. For 32-bit inferiors,
- the register's value is passed by value, but for 64-bit inferiors,
- the address of a buffer containing the value is passed. */
- if (!ARCH64 ())
- rs6000_ptrace32 (PT_WRITE_GPR, pid, (int *) nr, *addr, 0);
- else
+ if (ARCH64 ())
{
- /* PT_WRITE_GPR requires the buffer parameter to point to an 8-byte
- area, even if the register is really only 32 bits. */
+ /* The buffer parameter must point to an 8-byte area. */
long long buf;
if (register_size (gdbarch, regno) == 8)
memcpy (&buf, addr, 8);
else
buf = *addr;
- rs6000_ptrace64 (PT_WRITE_GPR, pid, nr, 0, &buf);
+ ptrace64 (PT_WRITE_GPR, pid, nr, 0, (PTRACE_TYPE_ARG5) &buf);
}
+ else
+ ptrace64 (PT_WRITE_GPR, pid, nr, *addr, 0);
}
if (errno)
@@ -760,7 +668,6 @@ rs6000_nat_target::xfer_partial (enum target_object object,
ULONGEST *xfered_len)
{
pid_t pid = inferior_ptid.pid ();
- int arch64 = ARCH64 ();
switch (object)
{
@@ -801,14 +708,8 @@ rs6000_nat_target::xfer_partial (enum target_object object,
< rounded_offset + sizeof (PTRACE_TYPE_RET)))
{
/* Need part of initial word -- fetch it. */
- if (arch64)
- buffer.word = rs6000_ptrace64 (PT_READ_I, pid,
- rounded_offset, 0, NULL);
- else
- buffer.word = rs6000_ptrace32 (PT_READ_I, pid,
- (int *) (uintptr_t)
- rounded_offset,
- 0, NULL);
+ buffer.word = ptrace64 (PT_READ_I, pid,
+ rounded_offset, 0, NULL);
}
/* Copy data to be written over corresponding part of
@@ -817,13 +718,8 @@ rs6000_nat_target::xfer_partial (enum target_object object,
writebuf, partial_len);
errno = 0;
- if (arch64)
- rs6000_ptrace64 (PT_WRITE_D, pid,
- rounded_offset, buffer.word, NULL);
- else
- rs6000_ptrace32 (PT_WRITE_D, pid,
- (int *) (uintptr_t) rounded_offset,
- buffer.word, NULL);
+ ptrace64 (PT_WRITE_D, pid,
+ rounded_offset, buffer.word, NULL);
if (errno)
return TARGET_XFER_EOF;
}
@@ -831,13 +727,8 @@ rs6000_nat_target::xfer_partial (enum target_object object,
if (readbuf)
{
errno = 0;
- if (arch64)
- buffer.word = rs6000_ptrace64 (PT_READ_I, pid,
- rounded_offset, 0, NULL);
- else
- buffer.word = rs6000_ptrace32 (PT_READ_I, pid,
- (int *)(uintptr_t)rounded_offset,
- 0, NULL);
+ buffer.word = ptrace64 (PT_READ_I, pid,
+ rounded_offset, 0, NULL);
if (errno)
return TARGET_XFER_EOF;
@@ -1014,12 +905,8 @@ rs6000_ptrace_ldinfo (ptid_t ptid)
while (1)
{
- if (ARCH64 ())
- rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi.data (),
- ldi.size (), NULL);
- else
- rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi.data (),
- ldi.size (), NULL);
+ rc = ptrace64 (PT_LDINFO, pid, (long long) ldi.data (), ldi.size (),
+ NULL);
if (rc != -1)
break; /* Success, we got the entire ld_info data. */
--
2.51.2
next reply other threads:[~2026-10-13 11:20 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 11:19 Aditya Vidyadhar Kamath [this message]
2026-10-13 11:19 ` [PATCH v5 2/4] Remove obsolete getthrds and HAVE_PTRACE64 configure checks Aditya Vidyadhar Kamath
2026-10-13 11:19 ` [PATCH v5 3/4] Modernise aix-thread.c by combining ptrace wrappers Aditya Vidyadhar Kamath
2026-10-13 11:19 ` [PATCH v5 4/4] Fix 32-bit GPR and SPR register reads/writes in pthdb callbacks Aditya Vidyadhar Kamath
2026-10-13 12:00 ` [PATCH v5 1/4] Remove stale legacy code from rs6000-aix-nat.c file Ulrich Weigand
2026-10-13 12:55 ` Aditya Kamath
2026-10-13 13:31 ` Ulrich Weigand
2026-10-13 17:16 ` Simon Marchi
2026-10-14 9:15 ` Aditya Kamath
2026-10-14 10:44 ` Ulrich Weigand
2026-10-15 13:38 ` Aditya Kamath
2026-10-15 14:37 ` Ulrich Weigand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013111917.68981-2-akamath996@gmail.com \
--to=akamath996@gmail.com \
--cc=Aditya.Kamath1@ibm.com \
--cc=gdb-patches@sourceware.org \
--cc=sangamesh.swamy@in.ibm.com \
--cc=simon.marchi@polymtl.ca \
--cc=tom@tromey.com \
--cc=ulrich.weigand@de.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox