aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-linux-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/i386-linux-tdep.c')
-rw-r--r--gdb/i386-linux-tdep.c68
1 files changed, 68 insertions, 0 deletions
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. */