2017-01-05 Walfred Tedeschi <walfred.tedeschi@intel.com>
Richard Henderson <rth@redhat.com>
gdb/ChangeLog:
* amd64-linux-nat.c (PTRACE_ARCH_PRCTL): New define.
(amd64_linux_fetch_inferior_registers): Add case to fetch FS_BASE
GS_BASE for older kernels.
(amd64_linux_store_inferior_registers): Add case to store FS_BASE
GS_BASE for older kernels.
* amd64-linux-tdep.c (amd64_linux_gregset_reg_offset): Add FS_BASE
and GS_BASE to the offset table.
(amd64_linux_register_reggroup_p): Add FS_BASE and GS_BASE to the
system register group.
* amd64-linux-tdep.h (AMD64_LINUX_ORIG_RAX_REGNUM): Set the value
to AMD64_NUM_REGS.
* amd64-nat.c (amd64_native_gregset_reg_offset): Adds valid_regnum
to test validit of the register. Implements case for older
kernels.
* amd64-tdep.c (amd64_init_abi): Add segment registers for the
amd64 ABI.
* amd64-tdep.h (amd64_regnum): Add AMD64_FSBASE_REGNUM and
AMD64_GSBASE_REGNUM.
(AMD64_NUM_REGS): Set to AMD64_GSBASE_REGNUM + 1.
* features/Makefile (amd64-linux.dat, amd64-avx-linux.dat)
(amd64-mpx-linux.dat, amd64-avx512-linux.dat, x32-linux.dat)
(x32-avx-linux.dat, x32-avx512-linux.dat): Add
i386/64bit-segments.xml in those rules.
* features/i386/64bit-segments.xml: New file.
* features/i386/amd64-avx-mpx-linux.xml: Add 64bit-segments.xml.
* features/i386/amd64-avx-linux.xml: Add 64bit-segments.xml.
* features/i386/amd64-avx512-linux.xml: Add 64bit-segments.xml.
* features/i386/amd64-mpx-linux.xml: Add 64bit-segments.xml.
* features/i386/x32-avx512-linux.xml: Add 64bit-segments.xml.
* features/i386/x32-avx-linux.xml: Add 64bit-segments.xml.
* features/i386/amd64-linux.xml: Add 64bit-segments.xml.
* features/i386/amd64-avx-linux.c: Regenerated.
* features/i386/amd64-avx-mpx-linux.c: Regenerated.
* features/i386/amd64-avx-mpx.c: Regenerated.
* features/i386/amd64-avx512-linux.c: Regenerated.
* features/i386/amd64-linux.c: Regenerated.
* features/i386/amd64-mpx-linux.c: Regenerated.
* features/i386/i386-avx-mpx-linux.c: Regenerated.
* features/i386/i386-avx-mpx.c: Regenerated.
* features/i386/x32-avx-linux.c: Regenerated.
* features/i386/x32-avx512-linux.c: Regenerated.
* regformats/i386/amd64-avx-linux.dat: Regenerated.
* regformats/i386/amd64-avx-mpx-linux.dat: Regenerated.
* regformats/i386/amd64-avx512-linux.dat: Regenerated.
* regformats/i386/amd64-linux.dat: Regenerated.
* regformats/i386/amd64-mpx-linux.dat: Regenerated.
* regformats/i386/x32-avx-linux.dat: Regenerated.
* regformats/i386/x32-avx512-linux.dat: Regenerated.
* regformats/i386/x32-linux.dat: Regenerated.
gdb/doc/ChangeLog:
* gdb.texinfo (i386 Features): Add system segment registers
as feature.
gdb/gdbserver/ChangeLog:
* linux-x86-low.c (x86_64_regmap): Add fs_base and gs_base
to the register table.
(x86_fill_gregset): Add support for old kernels for the
fs_base and gs_base system registers.
(x86_store_gregset): Likewise.
* configure.srv (srv_i386_64bit_xmlfiles): Add 64bit-segments.xml.
gdb/testsuite/ChangeLog:
* gdb.arch/amd64-gs_base.c: New file.
* gdb.arch/amd64-gs_base.exp: New file.
---
gdb/amd64-linux-nat.c | 53 ++++++++
gdb/amd64-linux-tdep.c | 7 +-
gdb/amd64-linux-tdep.h | 2 +-
gdb/amd64-nat.c | 19 ++-
gdb/amd64-tdep.c | 13 ++
gdb/amd64-tdep.h | 6 +-
gdb/doc/gdb.texinfo | 3 +
gdb/features/Makefile | 17 +--
gdb/features/i386/64bit-segments.xml | 12 ++
gdb/features/i386/amd64-avx-linux.c | 36 +++---
gdb/features/i386/amd64-avx-linux.xml | 1 +
gdb/features/i386/amd64-avx-mpx-linux.c | 48 +++----
gdb/features/i386/amd64-avx-mpx-linux.xml | 1 +
gdb/features/i386/amd64-avx512-linux.c | 192 ++++++++++++++--------------
gdb/features/i386/amd64-avx512-linux.xml | 1 +
gdb/features/i386/amd64-linux.c | 4 +
gdb/features/i386/amd64-linux.xml | 1 +
gdb/features/i386/amd64-mpx-linux.c | 16 ++-
gdb/features/i386/amd64-mpx-linux.xml | 1 +
gdb/features/i386/x32-avx-linux.c | 36 +++---
gdb/features/i386/x32-avx-linux.xml | 1 +
gdb/features/i386/x32-avx512-linux.c | 192 ++++++++++++++--------------
gdb/features/i386/x32-avx512-linux.xml | 1 +
gdb/features/i386/x32-linux.c | 4 +
gdb/features/i386/x32-linux.xml | 1 +
gdb/gdbserver/configure.srv | 2 +-
gdb/gdbserver/linux-x86-low.c | 32 +++++
gdb/regformats/i386/amd64-avx-linux.dat | 2 +
gdb/regformats/i386/amd64-avx-mpx-linux.dat | 2 +
gdb/regformats/i386/amd64-avx512-linux.dat | 2 +
gdb/regformats/i386/amd64-linux.dat | 2 +
gdb/regformats/i386/amd64-mpx-linux.dat | 2 +
gdb/regformats/i386/x32-avx-linux.dat | 2 +
gdb/regformats/i386/x32-avx512-linux.dat | 2 +
gdb/regformats/i386/x32-linux.dat | 2 +
gdb/testsuite/gdb.arch/amd64-gs_base.c | 26 ++++
gdb/testsuite/gdb.arch/amd64-gs_base.exp | 51 ++++++++
37 files changed, 531 insertions(+), 264 deletions(-)
create mode 100644 gdb/features/i386/64bit-segments.xml
create mode 100644 gdb/testsuite/gdb.arch/amd64-gs_base.c
create mode 100644 gdb/testsuite/gdb.arch/amd64-gs_base.exp
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 4a2036b..0ec22cb 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -40,6 +40,11 @@
#include "nat/linux-ptrace.h"
#include "nat/amd64-linux-siginfo.h"
+/* This definition comes from prctl.h, but some kernels may not have it. */
+#ifndef PTRACE_ARCH_PRCTL
+#define PTRACE_ARCH_PRCTL 30
+#endif
+
/* Mapping between the general-purpose registers in GNU/Linux x86-64
`struct user' format and GDB's register cache layout for GNU/Linux
i386.
@@ -171,6 +176,30 @@ amd64_linux_fetch_inferior_registers (struct target_ops *ops,
amd64_supply_fxsave (regcache, -1, &fpregs);
}
+#ifndef 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 base;
+
+ if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
+ {
+ if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_FS) < 0)
+ perror_with_name (_("Couldn't get segment register fs_base"));
+
+ regcache_raw_supply (regcache, AMD64_FSBASE_REGNUM, &base);
+ }
+
+ if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
+ {
+ if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_GS) < 0)
+ perror_with_name (_("Couldn't get segment register gs_base"));
+
+ regcache_raw_supply (regcache, AMD64_GSBASE_REGNUM, &base);
+ }
+ }
+#endif
}
}
@@ -237,6 +266,30 @@ amd64_linux_store_inferior_registers (struct target_ops *ops,
if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name (_("Couldn't write floating point status"));
}
+
+#ifndef 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. */
+ void *base;
+
+ if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
+ {
+ regcache_raw_collect (regcache, AMD64_FSBASE_REGNUM, &base);
+
+ if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_FS) < 0)
+ perror_with_name (_("Couldn't write fs_base"));
+ }
+ if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
+ {
+
+ regcache_raw_collect (regcache, AMD64_GSBASE_REGNUM, &base);
+ if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_GS) < 0)
+ perror_with_name (_("Couldn't write gs_base"));
+ }
+ }
+#endif
}
}
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 1e9f75f..b9d7176 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -103,6 +103,9 @@ int amd64_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+
+ /* End of hardware registers */
+ 21 * 8, 22 * 8, /* fs_base and gs_base. */
15 * 8 /* "orig_rax" */
};
@@ -284,7 +287,9 @@ static int
amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *group)
{
- if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM)
+ if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM
+ || regnum == AMD64_FSBASE_REGNUM
+ || regnum == AMD64_GSBASE_REGNUM)
return (group == system_reggroup
|| group == save_reggroup
|| group == restore_reggroup);
diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h
index 5d032a6..3704caa 100644
--- a/gdb/amd64-linux-tdep.h
+++ b/gdb/amd64-linux-tdep.h
@@ -26,7 +26,7 @@
/* Register number for the "orig_rax" register. If this register
contains a value >= 0 it is interpreted as the system call number
that the kernel is supposed to restart. */
-#define AMD64_LINUX_ORIG_RAX_REGNUM (AMD64_ZMM31H_REGNUM + 1)
+#define AMD64_LINUX_ORIG_RAX_REGNUM (AMD64_NUM_REGS)
/* Total number of registers for GNU/Linux. */
#define AMD64_LINUX_NUM_REGS (AMD64_LINUX_ORIG_RAX_REGNUM + 1)
diff --git a/gdb/amd64-nat.c b/gdb/amd64-nat.c
index 18c8a99..0143632 100644
--- a/gdb/amd64-nat.c
+++ b/gdb/amd64-nat.c
@@ -53,6 +53,7 @@ amd64_native_gregset_reg_offset (struct gdbarch *gdbarch, int regnum)
{
int *reg_offset = amd64_native_gregset64_reg_offset;
int num_regs = amd64_native_gregset64_num_regs;
+ bool valid_regnum = false;
gdb_assert (regnum >= 0);
@@ -65,10 +66,22 @@ amd64_native_gregset_reg_offset (struct gdbarch *gdbarch, int regnum)
if (num_regs > gdbarch_num_regs (gdbarch))
num_regs = gdbarch_num_regs (gdbarch);
- if (regnum < num_regs && regnum < gdbarch_num_regs (gdbarch))
- return reg_offset[regnum];
+ /* Looks like we do not need the second part of the &&.
+ Register validity is already guaranteed in the first part due to the
+ comparison above. */