This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/3] Use PTRACE_PEEKUSER to get fs_base/gs_base for x32


On Thu, Jun 21, 2012 at 11:15:29AM -0700, H.J. Lu wrote:
> 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.  Since x32 support was
> added to kernel 3.4.0 and PTRACE_ARCH_PRCTL support was removed for x32,
> we should always use fs_base/gs_base for x32.  OK to install? We
> 
> Thanks.

Here is a better patch to use the fs_base and gs_base fields of
struct user_regs_struct to get fs/gs base.  OK to install?

Thanks.


H.J.
---
2012-06-16  Roland McGrath  <roland@hack.frob.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* amd64-linux-nat.c: Include <sys/user.h> if
	HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE or
	HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE is defined.
	(ps_get_thread_area): Use PTRACE_PEEKUSER to get fs_base/gs_base
	if HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE or
	HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE is defined.

	* configure.ac: Check if the fs_base and gs_base members of
	`struct user_regs_struct' exist.
	* config.in: Regenerated.
	* configure: Likewise.

diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 23eadbd..781456f 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -34,6 +34,10 @@
 #include <sys/debugreg.h>
 #include <sys/syscall.h>
 #include <sys/procfs.h>
+#if defined HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE \
+    || defined HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
+#include <sys/user.h>
+#endif
 #include <asm/prctl.h>
 /* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
    <asm/ptrace.h> because the latter redefines FS and GS for no apparent
@@ -479,10 +483,39 @@ ps_get_thread_area (const struct ps_prochandle *ph,
       switch (idx)
 	{
 	case FS:
+#ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
+	    {
+	      /* 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.  */
+	      unsigned long fs;
+	      errno = 0;
+	      fs = ptrace (PTRACE_PEEKUSER, lwpid,
+			   offsetof (struct user_regs_struct, fs_base), 0);
+	      if (errno == 0)
+		{
+		  *base = (void *) fs;
+		  return PS_OK;
+		}
+	    }
+#endif
 	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
 	    return PS_OK;
 	  break;
 	case GS:
+#ifdef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
+	    {
+	      unsigned long gs;
+	      errno = 0;
+	      gs = ptrace (PTRACE_PEEKUSER, lwpid,
+			   offsetof (struct user_regs_struct, gs_base), 0);
+	      if (errno == 0)
+		{
+		  *base = (void *) gs;
+		  return PS_OK;
+		}
+	    }
+#endif
 	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
 	    return PS_OK;
 	  break;
diff --git a/gdb/config.in b/gdb/config.in
index 5767773..74f5888 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -447,6 +447,12 @@
 /* Define to 1 if `struct thread' is a member of `td_pcb'. */
 #undef HAVE_STRUCT_THREAD_TD_PCB
 
+/* Define to 1 if `struct user_regs_struct' is a member of `fs_base'. */
+#undef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
+
+/* Define to 1 if `struct user_regs_struct' is a member of `gs_base'. */
+#undef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
+
 /* Define to 1 if you have the `syscall' function. */
 #undef HAVE_SYSCALL
 
diff --git a/gdb/configure b/gdb/configure
index 1d03188..91381f1 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10612,6 +10612,31 @@ _ACEOF
 fi
 
 
+# See if <sys/user.h> supports the %fs_base and %gs_bas amd64 segment registers.
+# Older amd64 Linux's don't have the fs_base and gs_base members of
+# `struct user_regs_struct'.
+ac_fn_c_check_member "$LINENO" "struct user_regs_struct" "fs_base" "ac_cv_member_struct_user_regs_struct_fs_base" "#include <sys/user.h>
+"
+if test "x$ac_cv_member_struct_user_regs_struct_fs_base" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct user_regs_struct" "gs_base" "ac_cv_member_struct_user_regs_struct_gs_base" "#include <sys/user.h>
+"
+if test "x$ac_cv_member_struct_user_regs_struct_gs_base" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE 1
+_ACEOF
+
+
+fi
+
+
 # See if <sys/ptrace.h> provides the PTRACE_GETREGS request.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTRACE_GETREGS" >&5
 $as_echo_n "checking for PTRACE_GETREGS... " >&6; }
diff --git a/gdb/configure.ac b/gdb/configure.ac
index e48ec05..f3c8b26 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1274,6 +1274,12 @@ fi
 AC_CHECK_MEMBERS([struct reg.r_fs, struct reg.r_gs], [], [],
                  [#include <machine/reg.h>])
 
+# See if <sys/user.h> supports the %fs_base and %gs_bas amd64 segment registers.
+# Older amd64 Linux's don't have the fs_base and gs_base members of
+# `struct user_regs_struct'.
+AC_CHECK_MEMBERS([struct user_regs_struct.fs_base, struct user_regs_struct.gs_base],
+		 [], [], [#include <sys/user.h>])
+
 # See if <sys/ptrace.h> provides the PTRACE_GETREGS request.
 AC_MSG_CHECKING(for PTRACE_GETREGS)
 AC_CACHE_VAL(gdb_cv_have_ptrace_getregs,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]