Intel MPX bound violation handling

With Intel Memory Protection Extensions it was introduced the concept of
boundary violation.  A boundary violations is presented to the inferior as
a segmentation fault having SIGCODE 3.  This patch adds a
handler for a boundary violation extending the information displayed
when a bound violation is presented to the inferior.  In the stop mode
case the debugger will also display the kind of violation: "upper" or
"lower", bounds and the address accessed.
On no stop mode the information will still remain unchanged.  Additional
information about bound violations are not meaningful in that case user
does not know the line in which violation occurred as well.

When the segmentation fault handler is stop mode the out puts will be
changed as exemplified below.

The usual output of a segfault is:
Program received signal SIGSEGV, Segmentation fault
0x0000000000400d7c in upper (p=0x603010, a=0x603030, b=0x603050,
c=0x603070, d=0x603090, len=7) at i386-mpx-sigsegv.c:68
68        value = *(p + len);

In case it is a bound violation it will be presented as:
Program received signal SIGSEGV, Segmentation fault
Upper bound violation while accessing address 0x7fffffffc3b3
Bounds: [lower = 0x7fffffffc390, upper = 0x7fffffffc3a3]
0x0000000000400d7c in upper (p=0x603010, a=0x603030, b=0x603050,
c=0x603070, d=0x603090, len=7) at i386-mpx-sigsegv.c:68
68        value = *(p + len);

In mi mode the output of a segfault is:
*stopped,reason="signal-received",signal-name="SIGSEGV",
signal-meaning="Segmentation fault", frame={addr="0x0000000000400d7c",
func="upper",args=[{name="p", value="0x603010"},{name="a",value="0x603030"}
,{name="b",value="0x603050"}, {name="c",value="0x603070"},
{name="d",value="0x603090"},{name="len",value="7"}],
file="i386-mpx-sigsegv.c",fullname="i386-mpx-sigsegv.c",line="68"},
thread-id="1",stopped-threads="all",core="6"

in the case of a bound violation:
*stopped,reason="signal-received",signal-name="SIGSEGV",
signal-meaning="Segmentation fault",
sigcode-meaning="Upper bound violation",
lower-bound="0x603010",upper-bound="0x603023",bound-access="0x60302f",
frame={addr="0x0000000000400d7c",func="upper",args=[{name="p",
value="0x603010"},{name="a",value="0x603030"},{name="b",value="0x603050"},
{name="c",value="0x603070"},{name="d",value="0x603090"},
{name="len",value="7"}],file="i386-mpx-sigsegv.c",
fullname="i386-mpx-sigsegv.c",line="68"},thread-id="1",
stopped-threads="all",core="6"

2016-02-18  Walfred Tedeschi  <walfred.tedeschi@intel.com>

gdb/ChangeLog:

	* 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.

gdb/testsuite/ChangeLog:

	* 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.

gdb/doc/ChangeLog:

	* gdb.texinfo (Signals): Add bound violation display hints for
	a SIGSEGV.
This commit is contained in:
Walfred Tedeschi 2016-02-18 17:24:59 +01:00
parent 5f034a78b9
commit 012b3a217a
18 changed files with 619 additions and 3 deletions

View file

@ -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 */
@ -1035,6 +1037,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (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));
@ -1999,6 +2007,30 @@ set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
gdbarch->ax_pseudo_register_push_stack = ax_pseudo_register_push_stack;
}
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)
{