From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13343 invoked by alias); 17 Dec 2015 17:12:15 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 13325 invoked by uid 89); 17 Dec 2015 17:12:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=AWL,BAYES_05,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=UD:arch, UD:gdb.arch, gdb.arch, sk:signal- X-HELO: mga02.intel.com Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 17 Dec 2015 17:12:07 +0000 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga101.jf.intel.com with ESMTP; 17 Dec 2015 09:12:03 -0800 X-ExtLoop1: 1 Received: from irsmsx101.ger.corp.intel.com ([163.33.3.153]) by fmsmga004.fm.intel.com with ESMTP; 17 Dec 2015 09:11:52 -0800 Received: from irsmsx104.ger.corp.intel.com ([169.254.5.138]) by IRSMSX101.ger.corp.intel.com ([169.254.1.236]) with mapi id 14.03.0248.002; Thu, 17 Dec 2015 17:11:50 +0000 From: "Tedeschi, Walfred" To: "palves@redhat.com" , "brobecker@adacore.com" CC: "gdb-patches@sourceware.org" Subject: RE: [PATCH V2 2/2] Bound violation handling. Date: Thu, 17 Dec 2015 17:12:00 -0000 Message-ID: References: <1450371947-25528-1-git-send-email-walfred.tedeschi@intel.com> <1450371947-25528-2-git-send-email-walfred.tedeschi@intel.com> In-Reply-To: <1450371947-25528-2-git-send-email-walfred.tedeschi@intel.com> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2015-12/txt/msg00350.txt.bz2 Joel, Pedro and all, Please disregard this review! There is code missing related to the evaluations.=20 I have added also a try and catch block that is not in. Thanks and regards, -Fred -----Original Message----- From: Tedeschi, Walfred=20 Sent: Thursday, December 17, 2015 6:06 PM To: palves@redhat.com; brobecker@adacore.com Cc: gdb-patches@sourceware.org; Tedeschi, Walfred Subject: [PATCH V2 2/2] Bound violation handling. With Intel(R) Memory Protection Extensions it was introduced the concept of= boundary violation. A boundary violations is presented to the inferior as= a segmentation fault having as sigcode the value 3. This patch adds a han= dler for a boundary violation extending the information displayed when a bo= und violation is presented to the inferior (segfault with code 3). In this case the debugger will also display the kind of violation upper or = lower the violated bounds and the address accessed. The usual output of a segfault, which is indeed a bound violation will be p= resented to the user as: Program received signal SIGSEGV, Segmentation fault upper bound violation -= bounds {lbound =3D 0x603010, ubound =3D 0x603023} accessing 0x60302f. 0x0000000000400d7c in upper (p=3D0x603010, a=3D0x603030, b=3D0x603050, c=3D= 0x603070, d=3D0x603090, len=3D7) at i386-mpx-sigsegv.c:68 68 value =3D *(p + len); In mi mode the output of a segfault which is indeed a bound violation will = be presented as: *stopped,reason=3D"signal-received",signal-name=3D"SIGSEGV", signal-meaning=3D"Segmentation fault",sigcode-meaning=3D"upper bound violat= ion", lower-bound=3D"0x603010",upper-bound=3D"0x603023",bound-access=3D"0x6= 0302f", frame=3D{addr=3D"0x0000000000400d7c",func=3D"upper",args=3D[{name=3D"p", value=3D"0x603010"},{name=3D"a",value=3D"0x603030"},{name=3D"b",value=3D"0x= 603050"}, {name=3D"c",value=3D"0x603070"},{name=3D"d",value=3D"0x603090"}, {name=3D"len",value=3D"7"}],file=3D"i386-mpx-sigsegv.c", fullname=3D"i386-mpx-sigsegv.c",line=3D"68"},thread-id=3D"1", stopped-threads=3D"all",core=3D"6" Changelog: 2015-12-15 Walfred Tedeschi * amd64-linux-tdep.c (amd64_linux_init_abi_common): Add handler for bound violation signal. * gdbarch.sh (bound_violation_handler): New. * i386-linux-tdep.c (i386_mpx_bound_violation_handler): New. (i386_linux_init_abi): Use i386_mpx_bound_violation_handler. * i386-linux-tdep.h (i386_mpx_bound_violation_handler) New. * i386-tdep.c (i386_mpx_enabled): Add as external. * i386-tdep.c (i386_mpx_enabled): Add as external. * infrun.c (process_segmentation_faults): New. (print_signal_received_reason): Use process_segmentation_faults. testsuite/gdb.arch * i386-mpx-sigsegv.c: New. * i386-mpx-sigsegv.exp: New. * i386-mpx-simple_segv.c: New. * i386-mpx-simple_segv.exp: New. --- gdb/amd64-linux-tdep.c | 3 + gdb/gdbarch.c | 32 ++++++ gdb/gdbarch.h | 11 +++ gdb/gdbarch.sh | 6 ++ gdb/i386-linux-tdep.c | 39 ++++++++ gdb/i386-linux-tdep.h | 5 + gdb/i386-tdep.c | 4 +- gdb/i386-tdep.h | 3 + gdb/infrun.c | 27 +++++ gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c | 120 ++++++++++++++++++++= ++ gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp | 87 ++++++++++++++++ gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c | 66 +++++++++++++ gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp | 126 ++++++++++++++++++++= ++++ 13 files changed, 526 insertions(+), 3 deletions(-) create mode 100644 gd= b/testsuite/gdb.arch/i386-mpx-sigsegv.c create mode 100644 gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp create mode 100644 gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c create mode 100644 gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index bde751f.= .954855b 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1840,6 +1840,9 @@ amd64_linux_init_abi_common(struct gdbarch_info info,= struct gdbarch *gdbarch) set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal); =20 set_gdbarch_get_siginfo_type (gdbarch, x86_get_siginfo_type_with_fields); + set_gdbarch_bound_violation_handler(gdbarch, +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20 + i386_mpx_bound_violation_handler); + } =20 static void diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index f04eef9..42eb4db 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_sta= ck; + gdbarch_bound_violation_handler_ftype *bound_violation_handler; int sp_regnum; int pc_regnum; int ps_regnum; @@ -531,6 +532,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of num_pseudo_regs, invalid_p =3D=3D 0 */ /* Skip verify of ax_pseudo_register_collect, has predicate. */ /* Skip verify of ax_pseudo_register_push_stack, has predicate. */ + /* Skip verify of bound_violation_handler, has predicate. */ /* Skip verify of sp_regnum, invalid_p =3D=3D 0 */ /* Skip verify of pc_regnum, invalid_p =3D=3D 0 */ /* Skip verify of ps_regnum, invalid_p =3D=3D 0 */ @@ -773,6 +775,12 @@ = gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: bits_big_endian =3D %s\n", plongest (gdbarch->bits_big_endian)); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_bound_violation_handler_p() = =3D %d\n", + gdbarch_bound_violation_handler_p (gdbarch));=20=20 + fprintf_unfiltered (file, + "gdbarch_dump: bound_violation_handler =3D <%s>\n", + host_address_to_string=20 + (gdbarch->bound_violation_handler)); + fprintf_unfiltered (file, "gdbarch_dump: breakpoint_from_pc =3D <%s>\n", host_address_to_string (gdbarch->breakpoint_from_pc)= ); fprintf_unfiltered (file, @@ -1986,6 +1994,30 @@ set_gdbarch_ax_pseudo_register_push_stack (struct gd= barch *gdbarch, } =20 int +gdbarch_bound_violation_handler_p (struct gdbarch *gdbarch) { + gdb_assert (gdbarch !=3D NULL); + return gdbarch->bound_violation_handler !=3D NULL; } + +void +gdbarch_bound_violation_handler (struct gdbarch *gdbarch, struct ui_out=20 +*uiout) { + gdb_assert (gdbarch !=3D NULL); + gdb_assert (gdbarch->bound_violation_handler !=3D NULL); + if (gdbarch_debug >=3D 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_bound_violation_handler=20 +called\n"); + gdbarch->bound_violation_handler (gdbarch, uiout); } + +void +set_gdbarch_bound_violation_handler (struct gdbarch *gdbarch, +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20 +gdbarch_bound_violation_handler_ftype bound_violation_handler) { + gdbarch->bound_violation_handler =3D bound_violation_handler; } + +int gdbarch_sp_regnum (struct gdbarch *gdbarch) { gdb_assert (gdbarch !=3D NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index b9b2290..f1436d8 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -63,6 +63,7 @@ struct ravenscar_arch_ops; struct elf_internal_linux_prp= sinfo; struct mem_range; struct syscalls_info; +struct ui_out; =20 #include "regcache.h" =20 @@ -299,6 +300,16 @@ typedef int (gdbarch_ax_pseudo_register_push_stack_fty= pe) (struct gdbarch *gdbar extern int gdbarch_ax_pseudo_register_push_stac= k (struct gdbarch *gdbarch, struct agent_expr *ax, int reg); extern void s= et_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, gdbarch_= ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack); =20 +/* Function called when a segmentation fault signal is received by the inf= erior, + having sigcode =3D 3 (SIG_CODE_BOUNDARY_FAULT). + UIOUT is the output stream where the handler will place information.=20 +*/ + +extern int gdbarch_bound_violation_handler_p (struct gdbarch *gdbarch); + +typedef void (gdbarch_bound_violation_handler_ftype) (struct gdbarch=20 +*gdbarch, struct ui_out *uiout); extern void=20 +gdbarch_bound_violation_handler (struct gdbarch *gdbarch, struct ui_out=20 +*uiout); extern void set_gdbarch_bound_violation_handler (struct=20 +gdbarch *gdbarch, gdbarch_bound_violation_handler_ftype=20 +*bound_violation_handler); + /* 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 236ce41..f36f0e0 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -446,6 +446,11 @@ 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 =20 +# Function called when a segmentation fault signal is received by the=20 +inferior, # having sigcode =3D 3 (SIG_CODE_BOUNDARY_FAULT). +# UIOUT is the output stream where the handler will place information. +M:void:bound_violation_handler: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). @@ -1247,6 +1252,7 @@ struct ravenscar_arch_ops; struct elf_internal_linux= _prpsinfo; struct mem_range; struct syscalls_info; +struct ui_out; =20 #include "regcache.h" =20 diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 766f193..2= a4e875 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,41 @@ i386_canonicalize_syscall (int syscall) return gdb_sys_no_syscall; } =20 +void +i386_mpx_bound_violation_handler (struct gdbarch *gdbarch, struct=20 +ui_out *uiout) { + CORE_ADDR lower_bound, upper_bound, access; + int is_upper; + + if (!i386_mpx_enabled ()) + return; + + lower_bound + =3D parse_and_eval_long=20 + ("$_siginfo._sifields._sigfault._addr_bnd._lower"); + upper_bound + =3D parse_and_eval_long=20 + ("$_siginfo._sifields._sigfault._addr_bnd._upper"); + access + =3D parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr"); + is_upper =3D (access > upper_bound ? 1 : 0); + + ui_out_text (uiout, "\n"); + if (is_upper) + ui_out_field_string (uiout, "sigcode-meaning", "upper bound=20 + violation"); else + ui_out_field_string (uiout, "sigcode-meaning", "lower bound=20 + violation"); + + ui_out_text (uiout, " - bounds {lbound =3D "); ui_out_field_fmt=20 + (uiout,"lower-bound", "%s", paddress (gdbarch, lower_bound));=20=20 + ui_out_text (uiout, ", ubound =3D "); ui_out_field_fmt=20 + (uiout,"upper-bound", "%s", paddress (gdbarch, upper_bound));=20=20 + ui_out_text (uiout, "}"); ui_out_text (uiout, " accessing ");=20=20 + ui_out_field_fmt (uiout,"bound-access", "%s", paddress (gdbarch,=20 + access)); + + return; +} + + /* 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 += 1038,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gd= barch) i386_linux_get_syscall_number); =20 set_gdbarch_get_siginfo_type (gdbarch, x86_get_siginfo_type_with_fields); + set_gdbarch_bound_violation_handler(gdbarch, +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20 + i386_mpx_bound_violation_handler); + } =20 /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/g= db/i386-linux-tdep.h b/gdb/i386-linux-tdep.h index f42bf7a..78efa76 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); =20 +/* Handles and displays information related to the MPX bound violation + to the user. */ +void +i386_mpx_bound_violation_handler (struct gdbarch *gdbarch, struct=20 +ui_out *uiout); + /* Linux target description. */ extern struct target_desc *tdesc_i386_linux; extern struct target_desc *t= desc_i386_mmx_linux; diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index e= bb21fc..60be128 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -8651,9 +8651,7 @@ i386_mpx_bd_base (void) return ret & MPX_BASE_MASK; } =20 -/* Check if the current target is MPX enabled. */ - -static int +int i386_mpx_enabled (void) { const struct gdbarch_tdep *tdep =3D gdbarch_tdep (get_current_arch ()); = diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 95288ba..4e81288 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -420,6 +420,9 @@ 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); =20 +/* Verify if target is MPX enabled. */ extern int i386_mpx_enabled=20 +(void); + =20 =20 /* Functions and variables exported from i386bsd-tdep.c. */ diff --git a/= gdb/infrun.c b/gdb/infrun.c index 2ed807c..ec3720d 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -7893,6 +7893,29 @@ print_exited_reason (struct ui_out *uiout, int exits= tatus) } } =20 +/* Value of the sigcode in case of a boundary fault. */ + +#define SIG_CODE_BONDARY_FAULT 3 + +/* Verifies if a received segmentation fault is a boundary fault. + In the case it is it calls the architecture dependent function + to handle the boundary fault. */ + +static void +handle_segmentation_faults (struct ui_out *uiout) { + long sig_code; + struct regcache *regcache =3D get_current_regcache (); + struct gdbarch *gdbarch =3D get_regcache_arch (regcache); + + set_running (user_visible_resume_ptid (1), 0); sig_code =3D=20 + parse_and_eval_long ("$_siginfo.si_code\n"); + + if (sig_code =3D=3D SIG_CODE_BONDARY_FAULT + && gdbarch_bound_violation_handler_p (gdbarch)) + gdbarch_bound_violation_handler (gdbarch, uiout); } + void print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggna= l) { @@ -7922,6 +7945,10 @@ print_signal_received_reason (struct ui_out *u= iout, enum gdb_signal siggnal) annotate_signal_string (); ui_out_field_string (uiout, "signal-meaning", gdb_signal_to_string (siggnal)); + + if (siggnal =3D=3D GDB_SIGNAL_SEGV) + handle_segmentation_faults (uiout); + annotate_signal_string_end (); } ui_out_text (uiout, ".\n"); 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..3bbd5b8 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c @@ -0,0 +1,120 @@ +/* Copyright 2015 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + 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=20 + . */ + +#include "x86-cpuid.h" +#include + +#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) =3D=3D bit_OSXSAVE) + { + if (__get_cpuid_max (0, NULL) < 7) + return 0; + + __cpuid_count (7, 0, eax, ebx, ecx, edx); + + if ((ebx & bit_MPX) =3D=3D 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 =3D *(p + len); + value =3D *(a + len); + value =3D *(b + len); + value =3D *(c + len); + value =3D *(d + len); +} + +void +lower (int * p, int * a, int * b, int * c, int * d, int len) { + int value; + value =3D *(p - len); + value =3D *(a - len); + value =3D *(b - len); + value =3D *(c - len); + bp2 (value); + value =3D *(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 =3D calloc (OUR_SIZE, sizeof (int)); + a =3D calloc (OUR_SIZE, sizeof (int)); + b =3D calloc (OUR_SIZE, sizeof (int)); + c =3D calloc (OUR_SIZE, sizeof (int)); + d =3D 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/gd= b.arch/i386-mpx-sigsegv.exp new file mode 100644 index 0000000..2ddd331 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp @@ -0,0 +1,87 @@ +# Copyright 2015 Free Software Foundation, Inc. +# +# Contributed by Intel Corp. # # This=20 +program is free software; you can redistribute it and/or modify # it=20 +under the terms of the GNU General Public License as published by # the=20 +Free Software Foundation; either version 3 of the License, or # (at=20 +your option) any later version. +# +# This program is distributed in the hope that it will be useful, # but=20 +WITHOUT ANY WARRANTY; without even the implied warranty of #=20 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU=20 +General Public License for more details. +# +# You should have received a copy of the GNU General Public License #=20 +along with this program. If not, see . + + +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} \=20=20 +[list debug nowarnings additional_flags=3D${comp_flags}]] } { + return -1 +} + +if ![runto_main] { + untested "could not run to main" + return -1 +} + +gdb_test_multiple "print have_mpx ()" "have mpx" { + -re ".. =3D 1\r\n$gdb_prompt " { + pass "check whether processor supports MPX" + } + -re ".. =3D 0\r\n$gdb_prompt " { + verbose "processor does not support MPX; skipping MPX tests" + return + } +} + +set segv_lower_bound ".*Program received signal SIGSEGV,\ + Segmentation fault\r\nlower bound violation - bounds \\\{lbound\ + =3D 0x\[0-9a-fA-F\]+, ubound =3D 0x\[0-9a-fA-F\]+\\\} accessing\ + 0x\[0-9a-fA-F\]+.*$gdb_prompt $" + +set segv_upper_bound ".*Program received signal SIGSEGV,\ + Segmentation fault\r\nupper bound violation - bounds \\\{lbound\ + =3D 0x\[0-9a-fA-F\]+, ubound =3D 0x\[0-9a-fA-F\]+\\\} accessing\ + 0x\[0-9a-fA-F\]+.*$gdb_prompt $" + +for {set i 0} {$i < 15} {incr i} { + set message "MPX signal segv Upper: ${i}" + gdb_test_multiple "continue" "$message ${i}" { + -re $segv_upper_bound { + pass "$message" + } + -re ".*$inferior_exited_re normally.*$gdb_prompt $" { + fail "$message"=20 + break + } + } +=09 + gdb_test "where" ".*#0 0x\[0-9a-fA-F\]+ in upper.*"\ + "$message: should be in upper" +} + +for {set i 0} {$i < 15} {incr i} { + set message "MPX signal segv Lower: ${i}" + gdb_test_multiple "continue" "$message ${i}" { + -re $segv_lower_bound { + pass "$message ${i}" + } + -re ".*$inferior_exited_re normally.*$gdb_prompt $" { + fail "$message ${i}" + break + } + } + gdb_test "where" ".*#0 0x\[0-9a-fA-F\]+ 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..2c187d0 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c @@ -0,0 +1,66 @@ +/* Copyright 2012 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + 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=20 + . */ + +#include "x86-cpuid.h" +#include + +#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) =3D=3D bit_OSXSAVE) + { + if (__get_cpuid_max (0, NULL) < 7) + return 0; + + __cpuid_count (7, 0, eax, ebx, ecx, edx); + + if ((ebx & bit_MPX) =3D=3D bit_MPX) + return 1; + else + return 0; + } + return 0; +} + +void +upper (int * p, int len) +{ + int value; + len++; /* b0-size-test. */ + value =3D *(p + len); +} + +int +main (void) +{ + if (have_mpx ()) + { + int a =3D 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/testsuit= e/gdb.arch/i386-mpx-simple_segv.exp new file mode 100644 index 0000000..7f0c7e4 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp @@ -0,0 +1,126 @@ +# Copyright 2015 Free Software Foundation, Inc. +# +# Contributed by Intel Corp. # # This=20 +program is free software; you can redistribute it and/or modify # it=20 +under the terms of the GNU General Public License as published by # the=20 +Free Software Foundation; either version 3 of the License, or # (at=20 +your option) any later version. +# +# This program is distributed in the hope that it will be useful, # but=20 +WITHOUT ANY WARRANTY; without even the implied warranty of #=20 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU=20 +General Public License for more details. +# +# You should have received a copy of the GNU General Public License #=20 +along with this program. If not, see . + +# Testing handle setup together with boundary violation signals. +# +# Some states are not allowed as reported on the manual, as noprint #=20 +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} \=20=20 +[list debug nowarnings additional_flags=3D${comp_flags}]] } { + return -1 +} + +if ![runto_main] { + untested "could not run to main" + return -1 +} + +send_gdb "print have_mpx ()\r" +gdb_expect { + -re ".. =3D 1\r\n$gdb_prompt " { + pass "check whether processor supports MPX" + } + -re ".. =3D 0\r\n$gdb_prompt " { + verbose "processor does not support MPX; skipping MPX tests" + return + } +} + +set segv_bound_with_prompt ".*Program received signal SIGSEGV,\ + Segmentation fault\r\nupper bound violation - bounds \\\{lbound\ + =3D 0x\[0-9a-fA-F\]+, ubound =3D 0x\[0-9a-fA-F\]+\\\} accessing\ + 0x\[0-9a-fA-F\]+.*$gdb_prompt $" + +set segv_bound_with_exit ".*Program received signal SIGSEGV,\ + Segmentation fault\r\nupper bound violation - bounds \\\{lbound\ + =3D 0x\[0-9a-fA-F\]+, ubound =3D 0x\[0-9a-fA-F\]+\\\} accessing\ + 0x\[0-9a-fA-F\]+.*$inferior_exited_re.*" + +# Using the handler for SIGSEGV as "print pass stop" +set parameters "print pass stop" +runto_main +send_gdb "handle SIGSEGV $parameters\n" +send_gdb "continue\n" + +gdb_expect { + -re $segv_bound_with_prompt { + pass $parameters + } +} +gdb_test "where" ".*#0 0x\[0-9a-fA-F\]+ in upper.*"\ + "should be in upper; $parameters" + +# Using the handler for SIGSEGV as "print pass nostop" +set parameters "print pass nostop" +runto_main + +gdb_test "handle SIGSEGV $parameters" "" "Setting\ the handler for=20 +segfault 0" + +gdb_test_multiple "continue" "test 0" { + -re $segv_bound_with_exit { + pass $parameters + } + -re "$gdb_prompt $" { + fail $parameters + } +} + +gdb_test "where" "No stack." "no inferior $parameters" + +# Using the handler for SIGSEGV as "print nopass stop" +set parameters "print nopass stop" + +runto_main +gdb_test "handle SIGSEGV $parameters" "" "Setting\ the handler for=20 +segfault 1" + +gdb_test_multiple "continue" "test 1" { + -re $segv_bound_with_prompt { + pass $parameters + } +} + +gdb_test "where" ".*#0 0x\[0-9a-fA-F\]+ in upper.*"\ + "should be in upper $parameters" + +# print nopass stop +set parameters "noprint pass nostop" +runto_main + +gdb_test "handle SIGSEGV $parameters" "" "Setting\ the handler for=20 +segfault 2" + +gdb_test_multiple "continue" "test 2" { + -re "Continuing\..*$inferior_exited_re.*" { + pass $parameters + } +} + +gdb_test "where" "No stack." "no inferior $parameters" -- 2.1.4 Intel Deutschland GmbH Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Christin Eisenschmid, Christian Lamprechter Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928