aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/NEWS14
-rw-r--r--gdb/amd64-linux-tdep.c2
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdb.texinfo27
-rw-r--r--gdb/gdbarch.c32
-rw-r--r--gdb/gdbarch.h12
-rwxr-xr-xgdb/gdbarch.sh7
-rw-r--r--gdb/i386-linux-tdep.c68
-rw-r--r--gdb/i386-linux-tdep.h5
-rw-r--r--gdb/i386-tdep.c4
-rw-r--r--gdb/i386-tdep.h2
-rw-r--r--gdb/infrun.c18
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c120
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp76
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c66
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp140
18 files changed, 619 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c8832c9..6fee07b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2016-02-18 Walfred Tedeschi <walfred.tedeschi@intel.com>
+
+ * NEWS: Add entry for bound violation.
+ * amd64-linux-tdep.c (amd64_linux_init_abi_common):
+ Add handler for segmentation fault.
+ * gdbarch.sh (handle_segmentation_fault): New.
+ * gdbarch.c: Regenerate.
+ * gdbarch.h: Regenerate.
+ * i386-linux-tdep.c (i386_linux_handle_segmentation_fault): New.
+ (SIG_CODE_BONDARY_FAULT): New define.
+ (i386_linux_init_abi): Use i386_mpx_bound_violation_handler.
+ * i386-linux-tdep.h (i386_linux_handle_segmentation_fault) New.
+ * i386-tdep.c (i386_mpx_enabled): Add as external.
+ * i386-tdep.c (i386_mpx_enabled): Add as external.
+ * infrun.c (handle_segmentation_fault): New function.
+ (print_signal_received_reason): Use handle_segmentation_fault.
+
2016-02-18 Marcin Koƛcielnicki <koriakin@0x04.net>
* arch-utils.c (default_guess_tracepoint_registers): New function.
diff --git a/gdb/NEWS b/gdb/NEWS
index 482bec6..64c4869 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,20 @@
*** Changes since GDB 7.11
+* Intel MPX bound violation handling.
+
+ Segmentation faults caused by a Intel MPX boundary violation
+ now display the kind of violation (upper or lower), the memory
+ address accessed and the memory bounds, along with the usual
+ signal received and code location.
+
+ For example:
+
+ Program received signal SIGSEGV, Segmentation fault
+ Upper bound violation while accessing address 0x7fffffffc3b3
+ Bounds: [lower = 0x7fffffffc390, upper = 0x7fffffffc3a3]
+ 0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
+
*** Changes in GDB 7.11
* GDB now supports debugging kernel-based threads on FreeBSD.
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 21bcd99..4e82795 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1840,6 +1840,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
+ set_gdbarch_handle_segmentation_fault (gdbarch,
+ i386_linux_handle_segmentation_fault);
}
static void
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 8106d82..189dfdc 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-18 Walfred Tedeschi <walfred.tedeschi@intel.com>
+
+ * gdb.texinfo (Signals): Add bound violation display hints for
+ a SIGSEGV.
+
2016-02-18 Marcin Koƛcielnicki <koriakin@0x04.net>
* gdb.texinfo (Trace File Format): Add documentation for description
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0028eda8..5db7cf2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5852,6 +5852,33 @@ $1 = (void *) 0x7ffff7ff7000
Depending on target support, @code{$_siginfo} may also be writable.
+@cindex Intel MPX boundary violations
+@cindex boundary violations, Intel MPX
+On some targets, a @code{SIGSEGV} can be caused by a boundary
+violation, i.e., accessing an address outside of the allowed range.
+In those cases @value{GDBN} may displays additional information,
+depending on how @value{GDBN} has been told to handle the signal.
+With @code{handle stop SIGSEGV}, @value{GDBN} displays the violation
+kind: "Upper" or "Lower", the memory address accessed and the
+bounds, while with @code{handle nostop SIGSEGV} no additional
+information is displayed.
+
+The usual output of a segfault is:
+@smallexample
+Program received signal SIGSEGV, Segmentation fault
+0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
+68 value = *(p + len);
+@end smallexample
+
+While a bound violation is presented as:
+@smallexample
+Program received signal SIGSEGV, Segmentation fault
+Upper bound violation while accessing address 0x7fffffffc3b3
+Bounds: [lower = 0x7fffffffc390, upper = 0x7fffffffc3a3]
+0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
+68 value = *(p + len);
+@end smallexample
+
@node Thread Stops
@section Stopping and Starting Multi-thread Programs
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 0136c75..bd0b48c 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -189,6 +189,7 @@ struct gdbarch
int num_pseudo_regs;
gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect;
gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack;
+ gdbarch_handle_segmentation_fault_ftype *handle_segmentation_fault;
int sp_regnum;
int pc_regnum;
int ps_regnum;
@@ -534,6 +535,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of num_pseudo_regs, invalid_p == 0 */
/* Skip verify of ax_pseudo_register_collect, has predicate. */
/* Skip verify of ax_pseudo_register_push_stack, has predicate. */
+ /* Skip verify of handle_segmentation_fault, has predicate. */
/* Skip verify of sp_regnum, invalid_p == 0 */
/* Skip verify of pc_regnum, invalid_p == 0 */
/* Skip verify of ps_regnum, invalid_p == 0 */
@@ -1036,6 +1038,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: half_format = %s\n",
pformat (gdbarch->half_format));
fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_handle_segmentation_fault_p() = %d\n",
+ gdbarch_handle_segmentation_fault_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: handle_segmentation_fault = <%s>\n",
+ host_address_to_string (gdbarch->handle_segmentation_fault));
+ fprintf_unfiltered (file,
"gdbarch_dump: has_dos_based_file_system = %s\n",
plongest (gdbarch->has_dos_based_file_system));
fprintf_unfiltered (file,
@@ -2000,6 +2008,30 @@ set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
}
int
+gdbarch_handle_segmentation_fault_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->handle_segmentation_fault != NULL;
+}
+
+void
+gdbarch_handle_segmentation_fault (struct gdbarch *gdbarch, struct ui_out *uiout)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->handle_segmentation_fault != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_handle_segmentation_fault called\n");
+ gdbarch->handle_segmentation_fault (gdbarch, uiout);
+}
+
+void
+set_gdbarch_handle_segmentation_fault (struct gdbarch *gdbarch,
+ gdbarch_handle_segmentation_fault_ftype handle_segmentation_fault)
+{
+ gdbarch->handle_segmentation_fault = handle_segmentation_fault;
+}
+
+int
gdbarch_sp_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 7ffbf1f..2225c76 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -64,6 +64,7 @@ struct elf_internal_linux_prpsinfo;
struct mem_range;
struct syscalls_info;
struct thread_info;
+struct ui_out;
#include "regcache.h"
@@ -300,6 +301,17 @@ typedef int (gdbarch_ax_pseudo_register_push_stack_ftype) (struct gdbarch *gdbar
extern int gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
extern void set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack);
+/* Some targets/architectures can do extra processing/display of
+ segmentation faults. E.g., Intel MPX boundary faults.
+ Call the architecture dependent function to handle the fault.
+ UIOUT is the output stream where the handler will place information. */
+
+extern int gdbarch_handle_segmentation_fault_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_handle_segmentation_fault_ftype) (struct gdbarch *gdbarch, struct ui_out *uiout);
+extern void gdbarch_handle_segmentation_fault (struct gdbarch *gdbarch, struct ui_out *uiout);
+extern void set_gdbarch_handle_segmentation_fault (struct gdbarch *gdbarch, gdbarch_handle_segmentation_fault_ftype *handle_segmentation_fault);
+
/* GDB's standard (or well known) register numbers. These can map onto
a real register or a pseudo (computed) register or not be defined at
all (-1).
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 61cb04a..1d7377f 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -446,6 +446,12 @@ M:int:ax_pseudo_register_collect:struct agent_expr *ax, int reg:ax, reg
# Return -1 if something goes wrong, 0 otherwise.
M:int:ax_pseudo_register_push_stack:struct agent_expr *ax, int reg:ax, reg
+# Some targets/architectures can do extra processing/display of
+# segmentation faults. E.g., Intel MPX boundary faults.
+# Call the architecture dependent function to handle the fault.
+# UIOUT is the output stream where the handler will place information.
+M:void:handle_segmentation_fault:struct ui_out *uiout:uiout
+
# GDB's standard (or well known) register numbers. These can map onto
# a real register or a pseudo (computed) register or not be defined at
# all (-1).
@@ -1257,6 +1263,7 @@ struct elf_internal_linux_prpsinfo;
struct mem_range;
struct syscalls_info;
struct thread_info;
+struct ui_out;
#include "regcache.h"
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index af39e78..63cda45 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -30,6 +30,7 @@
#include "i386-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
+#include "utils.h"
#include "glibc-tdep.h"
#include "solib-svr4.h"
#include "symtab.h"
@@ -384,6 +385,71 @@ i386_canonicalize_syscall (int syscall)
return gdb_sys_no_syscall;
}
+/* Value of the sigcode in case of a boundary fault. */
+
+#define SIG_CODE_BONDARY_FAULT 3
+
+/* i386 GNU/Linux implementation of the handle_segmentation_fault
+ gdbarch hook. Displays information related to MPX bound
+ violations. */
+void
+i386_linux_handle_segmentation_fault (struct gdbarch *gdbarch,
+ struct ui_out *uiout)
+{
+ CORE_ADDR lower_bound, upper_bound, access;
+ int is_upper;
+ long sig_code = 0;
+
+ if (!i386_mpx_enabled ())
+ return;
+
+ TRY
+ {
+ /* Sigcode evaluates if the actual segfault is a boundary violation. */
+ sig_code = parse_and_eval_long ("$_siginfo.si_code\n");
+
+ lower_bound
+ = parse_and_eval_long ("$_siginfo._sifields._sigfault._addr_bnd._lower");
+ upper_bound
+ = parse_and_eval_long ("$_siginfo._sifields._sigfault._addr_bnd._upper");
+ access
+ = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
+ }
+ CATCH (exception, RETURN_MASK_ALL)
+ {
+ return;
+ }
+ END_CATCH
+
+ /* If this is not a boundary violation just return. */
+ if (sig_code != SIG_CODE_BONDARY_FAULT)
+ return;
+
+ is_upper = (access > upper_bound ? 1 : 0);
+
+ ui_out_text (uiout, "\n");
+ if (is_upper)
+ ui_out_field_string (uiout, "sigcode-meaning",
+ _("Upper bound violation"));
+ else
+ ui_out_field_string (uiout, "sigcode-meaning",
+ _("Lower bound violation"));
+
+ ui_out_text (uiout, _(" while accessing address "));
+ ui_out_field_fmt (uiout, "bound-access", "%s",
+ paddress (gdbarch, access));
+
+ ui_out_text (uiout, _("\nBounds: [lower = "));
+ ui_out_field_fmt (uiout, "lower-bound", "%s",
+ paddress (gdbarch, lower_bound));
+
+ ui_out_text (uiout, _(", upper = "));
+ ui_out_field_fmt (uiout, "upper-bound", "%s",
+ paddress (gdbarch, upper_bound));
+
+ ui_out_text (uiout, _("]"));
+}
+
/* Parse the arguments of current system call instruction and record
the values of the registers and memory that will be changed into
"record_arch_list". This instruction is "int 0x80" (Linux
@@ -1002,6 +1068,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386_linux_get_syscall_number);
set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
+ set_gdbarch_handle_segmentation_fault (gdbarch,
+ i386_linux_handle_segmentation_fault);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index ecc9e31..5c7a7f6 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -37,6 +37,11 @@
/* Get XSAVE extended state xcr0 from core dump. */
extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
+/* Handle and display information related to the MPX bound violation
+ to the user. */
+extern void i386_linux_handle_segmentation_fault (struct gdbarch *gdbarch,
+ struct ui_out *uiout);
+
/* Linux target description. */
extern struct target_desc *tdesc_i386_linux;
extern struct target_desc *tdesc_i386_mmx_linux;
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index db4cd0a..4c66edf 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8729,9 +8729,7 @@ i386_mpx_bd_base (void)
return ret & MPX_BASE_MASK;
}
-/* Check if the current target is MPX enabled. */
-
-static int
+int
i386_mpx_enabled (void)
{
const struct gdbarch_tdep *tdep = gdbarch_tdep (get_current_arch ());
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 770f59d..49dcce0 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -424,6 +424,8 @@ extern int i386_process_record (struct gdbarch *gdbarch,
struct regcache *regcache, CORE_ADDR addr);
extern const struct target_desc *i386_target_description (uint64_t xcr0);
+/* Return true iff the current target is MPX enabled. */
+extern int i386_mpx_enabled (void);
/* Functions and variables exported from i386bsd-tdep.c. */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 15210c9..3e8c9e0 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -7904,6 +7904,20 @@ print_exited_reason (struct ui_out *uiout, int exitstatus)
}
}
+/* Some targets/architectures can do extra processing/display of
+ segmentation faults. E.g., Intel MPX boundary faults.
+ Call the architecture dependent function to handle the fault. */
+
+static void
+handle_segmentation_fault (struct ui_out *uiout)
+{
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+ if (gdbarch_handle_segmentation_fault_p (gdbarch))
+ gdbarch_handle_segmentation_fault (gdbarch, uiout);
+}
+
void
print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggnal)
{
@@ -7947,6 +7961,10 @@ print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggnal)
annotate_signal_string ();
ui_out_field_string (uiout, "signal-meaning",
gdb_signal_to_string (siggnal));
+
+ if (siggnal == GDB_SIGNAL_SEGV)
+ handle_segmentation_fault (uiout);
+
annotate_signal_string_end ();
}
ui_out_text (uiout, ".\n");
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6882495..cedbb75 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-18 Walfred Tedeschi <walfred.tedeschi@intel.com>
+
+ * gdb.arch/i386-mpx-sigsegv.c: New file.
+ * gdb.arch/i386-mpx-sigsegv.exp: New file.
+ * gdb.arch/i386-mpx-simple_segv.c: New file.
+ * gdb.arch/i386-mpx-simple_segv.exp: New file.
+
2016-02-18 Yao Qi <yao.qi@linaro.org>
* gdb.base/disp-step-syscall.exp (disp_step_cross_syscall):
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c
new file mode 100644
index 0000000..70dfdb7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <walfred.tedeschi@intel.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "x86-cpuid.h"
+#include <stdio.h>
+
+#define OUR_SIZE 5
+
+int gx[OUR_SIZE];
+int ga[OUR_SIZE];
+int gb[OUR_SIZE];
+int gc[OUR_SIZE];
+int gd[OUR_SIZE];
+
+unsigned int
+have_mpx (void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return 0;
+
+ if ((ecx & bit_OSXSAVE) == bit_OSXSAVE)
+ {
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+ if ((ebx & bit_MPX) == bit_MPX)
+ return 1;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+int
+bp1 (int value)
+{
+ return 1;
+}
+
+int
+bp2 (int value)
+{
+ return 1;
+}
+
+void
+upper (int * p, int * a, int * b, int * c, int * d, int len)
+{
+ int value;
+ value = *(p + len);
+ value = *(a + len);
+ value = *(b + len);
+ value = *(c + len);
+ value = *(d + len);
+}
+
+void
+lower (int * p, int * a, int * b, int * c, int * d, int len)
+{
+ int value;
+ value = *(p - len);
+ value = *(a - len);
+ value = *(b - len);
+ value = *(c - len);
+ bp2 (value);
+ value = *(d - len);
+}
+
+int
+main (void)
+{
+ if (have_mpx ())
+ {
+ int sx[OUR_SIZE];
+ int sa[OUR_SIZE];
+ int sb[OUR_SIZE];
+ int sc[OUR_SIZE];
+ int sd[OUR_SIZE];
+ int *x, *a, *b, *c, *d;
+
+ x = calloc (OUR_SIZE, sizeof (int));
+ a = calloc (OUR_SIZE, sizeof (int));
+ b = calloc (OUR_SIZE, sizeof (int));
+ c = calloc (OUR_SIZE, sizeof (int));
+ d = calloc (OUR_SIZE, sizeof (int));
+
+ upper (x, a, b, c, d, OUR_SIZE + 2);
+ upper (sx, sa, sb, sc, sd, OUR_SIZE + 2);
+ upper (gx, ga, gb, gc, gd, OUR_SIZE + 2);
+ lower (x, a, b, c, d, 1);
+ lower (sx, sa, sb, sc, sd, 1);
+ bp1 (*x);
+ lower (gx, ga, gb, gc, gd, 1);
+
+ free (x);
+ free (a);
+ free (b);
+ free (c);
+ free (d);
+ }
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp
new file mode 100644
index 0000000..164b2d0
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp
@@ -0,0 +1,76 @@
+# Copyright (C) 2015-2016 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <walfred.tedeschi@intel.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+if { ![istarget i?86-*-*] && ![istarget x86_64-*-* ] } {
+ verbose "Skipping x86 MPX tests."
+ return
+}
+
+standard_testfile
+
+set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
+ [list debug nowarnings additional_flags=${comp_flags}]] } {
+ return -1
+}
+
+if ![runto_main] {
+ untested "could not run to main"
+ return -1
+}
+
+gdb_test_multiple "print have_mpx ()" "have mpx" {
+ -re ".. = 1\r\n$gdb_prompt " {
+ pass "check whether processor supports MPX"
+ }
+ -re ".. = 0\r\n$gdb_prompt " {
+ verbose "processor does not support MPX; skipping MPX tests"
+ return
+ }
+}
+
+set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
+ "Upper bound violation while accessing address $hex" \
+ "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
+
+set l_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
+ "Lower bound violation while accessing address $hex" \
+ "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
+
+for {set i 0} {$i < 15} {incr i} {
+ set message "MPX signal segv Upper: ${i}"
+
+ if {[gdb_test "continue" "$u_fault.*" $message] != 0} {
+ break
+ }
+
+ gdb_test "where" ".*#0 $hex in upper.*"\
+ "$message: should be in upper"
+}
+
+for {set i 0} {$i < 15} {incr i} {
+ set message "MPX signal segv Lower: ${i}"
+
+ if {[gdb_test "continue" "$l_fault.*" $message] != 0} {
+ break
+ }
+
+ gdb_test "where" ".*#0 $hex in lower.*"\
+ "$message: should be in lower"
+}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c
new file mode 100644
index 0000000..a26d238
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <walfred.tedeschi@intel.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "x86-cpuid.h"
+#include <stdio.h>
+
+#define OUR_SIZE 5
+
+unsigned int
+have_mpx (void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return 0;
+
+ if ((ecx & bit_OSXSAVE) == bit_OSXSAVE)
+ {
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+ if ((ebx & bit_MPX) == bit_MPX)
+ return 1;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+void
+upper (int * p, int len)
+{
+ int value;
+ len++; /* b0-size-test. */
+ value = *(p + len);
+}
+
+int
+main (void)
+{
+ if (have_mpx ())
+ {
+ int a = 0; /* Dummy variable for debugging purposes. */
+ int sx[OUR_SIZE];
+ a++; /* register-eval. */
+ upper (sx, OUR_SIZE + 2);
+ return sx[1];
+ }
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp
new file mode 100644
index 0000000..2eefc74
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp
@@ -0,0 +1,140 @@
+# Copyright (C) 2015-2016 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <walfred.tedeschi@intel.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Testing handle setup together with boundary violation signals.
+#
+# Some states are not allowed as reported on the manual, as noprint
+# implies nostop, but nostop might print.
+#
+# Caveat: Setting the handle to nopass, ends up in a endless loop.
+
+if { ![istarget i?86-*-*] && ![istarget x86_64-*-* ] } {
+ verbose "Skipping x86 MPX tests."
+ return
+}
+
+standard_testfile
+
+set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
+ [list debug nowarnings additional_flags=${comp_flags}]] } {
+ return -1
+}
+
+if ![runto_main] {
+ untested "could not run to main"
+ return -1
+}
+
+gdb_test_multiple "print have_mpx ()" "have mpx" {
+ -re ".. = 1\r\n$gdb_prompt " {
+ pass "check whether processor supports MPX"
+ }
+ -re ".. = 0\r\n$gdb_prompt " {
+ verbose "processor does not support MPX; skipping MPX tests"
+ return
+ }
+}
+
+set violation [multi_line "Program received signal SIGSEGV, Segmentation fault" \
+ "Upper bound violation while accessing address $hex" \
+ "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
+
+set segv_with_exit "Program received signal SIGSEGV,\
+ Segmentation fault.*$inferior_exited_re.*"
+
+
+# Test handler for segmentation fault for:
+# print pass stop
+#
+set parameters "print pass stop"
+with_test_prefix "$parameters" {
+ if ![runto_main] {
+ fail "could not run to main"
+ return -1
+ }
+
+ gdb_test "handle SIGSEGV $parameters"\
+ ".*SIGSEGV.*Yes.*Yes.*Yes.*Segmentation fault.*"\
+ "set parameters"
+
+ gdb_test "continue" ".*$violation.*" "Display"
+
+ gdb_test "where" ".*#0 $hex in upper.*"\
+ "should be in upper"
+}
+
+# Test handler for segmentation fault for:
+# print pass nostop
+#
+set parameters "print pass nostop"
+with_test_prefix "$parameters" {
+ if ![runto_main] {
+ fail "could not run to main"
+ return -1
+ }
+
+ gdb_test "handle SIGSEGV $parameters"\
+ ".*SIGSEGV.*No.*Yes.*Yes.*Segmentation fault.*"\
+ "set parameters"
+
+ gdb_test "continue" ".*$segv_with_exit.*" "Display"
+
+ gdb_test "where" "No stack." "no inferior"
+}
+
+# Test handler for segmentation fault for:
+# print nopass stop
+#
+set parameters "print nopass stop"
+with_test_prefix "$parameters" {
+ if ![runto_main] {
+ fail "could not run to main"
+ return -1
+ }
+
+ gdb_test "handle SIGSEGV $parameters"\
+ ".*SIGSEGV.*Yes.*Yes.*No.*Segmentation fault.*"\
+ "set parameters"
+
+ gdb_test "continue" ".*$violation.*" "Display"
+
+ gdb_test "where" ".*#0 $hex in upper.*"\
+ "should be in upper"
+}
+
+# Test handler for segmentation fault for:
+# print nopass stop
+#
+set parameters "noprint pass nostop"
+with_test_prefix "$parameters" {
+ if ![runto_main] {
+ fail "could not run to main"
+ return -1
+ }
+
+ gdb_test "handle SIGSEGV $parameters"\
+ ".*SIGSEGV.*No.*No.*Yes.*Segmentation fault.*"\
+ "set parameters"
+
+ gdb_test "continue" "Continuing\..*$inferior_exited_re.*"\
+ "Display"
+
+ gdb_test "where" "No stack." "no inferior"
+}
+