This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: PATCH: Add x32 arch_prctl support
> Change it to unsigned long long int makes it impossible
> to get address as pointer since it will override memory on stack.
There is some misunderstanding. What I suggested would not make any
difference to the compiled code of arch_prctl.
> I am trying to limit my x32 GDB change as small as possible:
>
> hjl@gnu-6 gdb]$ grep PTRACE_ARCH_PRCTL amd64-linux-nat.c
> #ifndef PTRACE_ARCH_PRCTL
> #define PTRACE_ARCH_PRCTL 30
> if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
> if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
> [hjl@gnu-6 gdb]$
>
> Without PTRACE_ARCH_PRCTL means I have to write a whole
> new patch to use the new interface. It will make it harder to enable
> x32 in GDB.
Sometimes the least change everywhere is not the cleanest answer anywhere.
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 5ebba3a..aaa1e62 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -479,11 +479,41 @@ ps_get_thread_area (const struct ps_prochandle *ph,
switch (idx)
{
case FS:
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
+ if (sizeof(unsigned long) == 4)
+ {
+ /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
+ fs_base and gs_base fields of user_regs_struct can be
+ used directly. We use it only to support older
+ kernels. But x32 kernels do not support it, so we
+ don't try to use it. There were no x32 kernels so old
+ that fs_base wasn't usable. */
+ unsigned long fs;
+ errno = 0;
+ fs = ptrace (PTRACE_PEEKUSR, lwpid,
+ offsetof (struct user_regs_struct, fs_base), 0);
+ if (errno == 0)
+ {
+ *base = fs;
+ return PS_OK;
+ }
+ }
+ else if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
return PS_OK;
break;
case GS:
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
+ if (sizeof(unsigned long) == 4)
+ {
+ unsigned long gs;
+ errno = 0;
+ gs = ptrace (PTRACE_PEEKUSR, lwpid,
+ offsetof (struct user_regs_struct, gs_base), 0);
+ if (errno == 0)
+ {
+ *base = gs;
+ return PS_OK;
+ }
+ }
+ else if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
return PS_OK;
break;
default: /* Should not happen. */