@@ -3,6 +3,10 @@
*** Changes since GDB 7.10
+* show mpx-bnd-init-on-return
+ set mpx-bnd-init-on-return on i386 and amd64
+ Support for set bound registers to INIT state when using the command return.
+
* Record btrace now supports non-stop mode.
* Support for tracepoints on aarch64-linux was added in GDBserver.
@@ -708,12 +708,14 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
gdb_byte *readbuf, const gdb_byte *writebuf) {
enum amd64_reg_class theclass[2];
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int len = TYPE_LENGTH (type);
static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM };
static int sse_regnum[] = { AMD64_XMM0_REGNUM, AMD64_XMM1_REGNUM };
int integer_reg = 0;
int sse_reg = 0;
int i;
+ extern int mpx_bnd_init_on_return;
gdb_assert (!(readbuf && writebuf));
@@ -739,6 +741,25 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
read_memory (addr, readbuf, TYPE_LENGTH (type));
+
+ /* In MPX-enabled programs, if the class is MEMORY, boundary is
+ expected to be stored in bnd0 register.
+
+ if the return value we are setting is due to the use of the
+ "return" command (WRITEBUF is not NULL), it is likely that
+ the return is made prematurely, and therefore bnd0 register
+ unset could then cause the program to receive a spurious
+ bound violation, but this is only done if
+ "set mpx-bnd-init-on-return" is true. */
+
+ if (writebuf != NULL
+ && mpx_bnd_init_on_return && I387_BND0R_REGNUM (tdep) > 0)
+ {
+ gdb_byte bnd_buf[16];
+
+ memset (bnd_buf, 0, 16);
+ regcache_raw_write (regcache, I387_BND0R_REGNUM (tdep), bnd_buf);
+ }
}
return RETURN_VALUE_ABI_RETURNS_ADDRESS; @@ -833,6 +854,17 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
writebuf + i * 8);
}
+ if (I387_BND0R_REGNUM (tdep) > 0)
+ {
+ gdb_byte bnd_buf[16];
+ int i, init_bnd;
+
+ memset (bnd_buf, 0, 16);
+ if (writebuf && mpx_bnd_init_on_return)
+ for (i = 0; i < I387_NUM_BND_REGS; i++)
+ regcache_raw_write (regcache, I387_BND0R_REGNUM (tdep) + i, bnd_buf);
+ }
+
return RETURN_VALUE_REGISTER_CONVENTION; }
@@ -22072,6 +22072,18 @@ can access the whole memory, in this case the register bound register associated to it has value 0, e.g. if the register associated is bnd0raw its value will be @{0x0, 0x0@}.
+While the using the @command{return} bounds can propagate through
+execution causing a boundary violation.
+The behaviour of initializing bounds when using @command{return} can be
+controlled and vizualized via the following commands:
+@table @code
+@kindex set mpx-bnd-init-on-return
+When set to true bound registers will be set to the INIT state when
+using the "return" command.
+@kindex show mpx-bnd-init-on-return
+Show the state of mpx-bnd-init-on-return.
+@end table
+
@node Alpha
@subsection Alpha
@@ -8864,6 +8864,24 @@ i386_mpx_set_bounds (char *args, int from_tty)
bt_entry[i]);
}
+/* The value of the "set mpx-bnd-init-on-return setting. */
+
+int mpx_bnd_init_on_return = 1;
+
+/* Show state of the setting variable mpx-bnd-init-on-return. */
+
+static void
+show_mpx_bnd_init_on_return (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value) {
+ if (mpx_bnd_init_on_return)
+ fprintf_filtered (file,
+ _("BND registers will be initialized on return.\n"));
+ else
+ fprintf_filtered (file,
+ _("BND registers will not be initialized on return.\n")); }
+
static struct cmd_list_element *mpx_set_cmdlist, *mpx_show_cmdlist;
/* Helper function for the CLI commands. */ @@ -8940,6 +8958,15 @@ Show Intel(R) Memory Protection Extensions specific variables."),
in the bound table.",
&mpx_set_cmdlist);
+ add_setshow_boolean_cmd ("mpx-bnd-init-on-return", no_class,
+ &mpx_bnd_init_on_return, _("\
+ Set the bnd registers to INIT state when returning from a call."),
+_("\ Show the state of the mpx-bnd-init-on-return."),
+ NULL,
+ NULL,
+ show_mpx_bnd_init_on_return,
+ &setlist, &showlist);
+
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);
new file mode 100644
@@ -0,0 +1,126 @@
+/* Test for inferior function calls MPX context.
+
+ Copyright (C) 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 <stdio.h>
+#include "x86-cpuid.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;
+}
+
+int
+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);
+
+ value = value - value + 1;
+ return value;
+}
+
+int *
+upper_ptr (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); /* bkpt 2. */
+ value = *(d + len); /* bkpt 3. */
+ free (p);
+ p = calloc (OUR_SIZE * 2, sizeof (int));
+
+ return ++p;
+}
+
+
+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 (sx, sa, sb, sc, sd, 0); /* bkpt 1. */
+ x = upper_ptr (sx, sa, sb, sc, sd, 0);
+
+ free (x);
+ free (a);
+ free (b);
+ free (c);
+ free (d);
+ }
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,90 @@
+# Copyright (C) 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
+ }
+}
+
+# Needed by the return command.
+gdb_test_no_output "set confirm off"
+
+set break "bkpt 1."
+gdb_breakpoint [gdb_get_line_number "${break}"]
+gdb_continue_to_breakpoint "${break}" ".*${break}.*"
+gdb_test "p upper (x, a, b, c, d, 0)" "= 1"\
+ "test the call of int function - int"
+gdb_test "p upper_ptr (x, a, b, c, d, 0)"\
+ "= \\\(int \\\*\\\) $hex" "test the call of function - ptr"
+
+set break "bkpt 2."
+gdb_breakpoint [gdb_get_line_number "${break}"]
+gdb_continue_to_breakpoint "${break}" ".*${break}.*"
+gdb_test "p \$bound0 = \$bnd0" "" "Saving the\
+ bnd0 result in a convenience variable 1"
+
+gdb_test "return a" "#0 $hex in main.*" "First return"
+gdb_test "p \(\$bnd0\.ubound == \$bound0\.ubound\)"\
+ "= 0" "return with bnd initialization off - ubound"
+gdb_test "p \(\$bnd0\.lbound ==\$bound0\.lbound\)"\
+ "= 0" "return with bnd initialization off - lbound"
+
+# Retesting with initialization off.
+# All breakpoints were deleted need to recreate what we need.
+runto_main
+gdb_test_no_output "set mpx-bnd-init-on-return off"\
+ "Turn off initialization on return"
+
+set break "bkpt 3."
+gdb_breakpoint [gdb_get_line_number "${break}"]
+gdb_continue_to_breakpoint "${break}" ".*${break}.*"
+gdb_test "p \$bound0 = \$bnd0" "" "Saving the\
+ bnd0 result in a convenience variable 2"
+gdb_test "return a" "#0 $hex in main.*" "Second return"
+gdb_test "p \(\$bnd0\.ubound == \$bound0\.ubound\)"\
+ "= 1" "return with bnd initialization on - ubound"
+gdb_test "p \(\$bnd0\.lbound ==\$bound0\.lbound\)"\
+ "= 1" "return with bnd initialization on - lbound"
+
+gdb_test "show mpx-bnd-init-on-return"\
+ "BND registers will not be initialized on return\\."\
+ "double check initialization on return"
--
2.1.4