diff options
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r-- | gdb/i386-tdep.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index b4ffe1b..6304591 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -8619,6 +8619,251 @@ i386_target_description (uint64_t xcr0) } } +#define MPX_BASE_MASK (~(ULONGEST) 0xfff) + +/* Find the bound directory base address. */ + +static unsigned long +i386_mpx_bd_base (void) +{ + struct regcache *rcache; + struct gdbarch_tdep *tdep; + ULONGEST ret; + enum register_status regstatus; + struct gdb_exception except; + + rcache = get_current_regcache (); + tdep = gdbarch_tdep (get_regcache_arch (rcache)); + + regstatus = regcache_raw_read_unsigned (rcache, tdep->bndcfgu_regnum, &ret); + + if (regstatus != REG_VALID) + error (_("BNDCFGU register invalid, read status %d."), regstatus); + + return ret & MPX_BASE_MASK; +} + +/* Check if the current target is MPX enabled. */ + +static int +i386_mpx_enabled (void) +{ + const struct gdbarch_tdep *tdep = gdbarch_tdep (get_current_arch ()); + const struct target_desc *tdesc = tdep->tdesc; + + return (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL); +} + +#define MPX_BD_MASK 0xfffffff00000ULL /* select bits [47:20] */ +#define MPX_BT_MASK 0x0000000ffff8 /* select bits [19:3] */ +#define MPX_BD_MASK_32 0xfffff000 /* select bits [31:12] */ +#define MPX_BT_MASK_32 0x00000ffc /* select bits [11:2] */ + +/* Find the bound table entry given the pointer location and the base + address of the table. */ + +static CORE_ADDR +i386_mpx_get_bt_entry (CORE_ADDR ptr, CORE_ADDR bd_base) +{ + CORE_ADDR offset1; + CORE_ADDR offset2; + CORE_ADDR mpx_bd_mask, bd_ptr_r_shift, bd_ptr_l_shift; + CORE_ADDR bt_mask, bt_select_r_shift, bt_select_l_shift; + CORE_ADDR bd_entry_addr; + CORE_ADDR bt_addr; + CORE_ADDR bd_entry; + struct gdbarch *gdbarch = get_current_arch (); + struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + + + if (gdbarch_ptr_bit (gdbarch) == 64) + { + mpx_bd_mask = MPX_BD_MASK; + bd_ptr_r_shift = 20; + bd_ptr_l_shift = 3; + bt_select_r_shift = 3; + bt_select_l_shift = 5; + bt_mask = MPX_BT_MASK; + } + else + { + mpx_bd_mask = MPX_BD_MASK_32; + bd_ptr_r_shift = 12; + bd_ptr_l_shift = 2; + bt_select_r_shift = 2; + bt_select_l_shift = 4; + bt_mask = MPX_BT_MASK_32; + } + + offset1 = ((ptr & mpx_bd_mask) >> bd_ptr_r_shift) << bd_ptr_l_shift; + bd_entry_addr = bd_base + offset1; + bd_entry = read_memory_typed_address (bd_entry_addr, data_ptr_type); + + if ((bd_entry & 0x1) == 0) + error (_("Invalid bounds directory entry at %s."), + paddress (get_current_arch (), bd_entry_addr)); + + /* Clearing status bit. */ + bd_entry--; + bt_addr = bd_entry & ~bt_select_r_shift; + offset2 = ((ptr & bt_mask) >> bt_select_r_shift) << bt_select_l_shift; + + return bt_addr + offset2; +} + +/* Print routine for the mpx bounds. */ + +static void +i386_mpx_print_bounds (const CORE_ADDR bt_entry[4]) +{ + struct ui_out *uiout = current_uiout; + long long int size; + struct gdbarch *gdbarch = get_current_arch (); + CORE_ADDR onecompl = ~((CORE_ADDR) 0); + int bounds_in_map = ((~bt_entry[1] == 0 && bt_entry[0] == onecompl) ? 1 : 0); + + if (bounds_in_map == 1) + { + ui_out_text (uiout, "Null bounds on map:"); + ui_out_text (uiout, " pointer value = "); + ui_out_field_core_addr (uiout, "pointer-value", gdbarch, bt_entry[2]); + ui_out_text (uiout, "."); + ui_out_text (uiout, "\n"); + } + else + { + ui_out_text (uiout, "{lbound = "); + ui_out_field_core_addr (uiout, "lower-bound", gdbarch, bt_entry[0]); + ui_out_text (uiout, ", ubound = "); + + /* The upper bound is stored in 1's complement. */ + ui_out_field_core_addr (uiout, "upper-bound", gdbarch, ~bt_entry[1]); + ui_out_text (uiout, "}: pointer value = "); + ui_out_field_core_addr (uiout, "pointer-value", gdbarch, bt_entry[2]); + + if (gdbarch_ptr_bit (gdbarch) == 64) + size = ( (~(int64_t) bt_entry[1]) - (int64_t) bt_entry[0]); + else + size = ( ~((int32_t) bt_entry[1]) - (int32_t) bt_entry[0]); + + /* In case the bounds are 0x0 and 0xffff... the difference will be -1. + -1 represents in this sense full memory access, and there is no need + one to the size. */ + + size = (size > -1 ? size + 1 : size); + ui_out_text (uiout, ", size = "); + ui_out_field_fmt (uiout, "size", "%lld", size); + + ui_out_text (uiout, ", metadata = "); + ui_out_field_core_addr (uiout, "metadata", gdbarch, bt_entry[3]); + ui_out_text (uiout, "\n"); + } +} + +/* Implement the command "show mpx bound". */ + +static void +i386_mpx_info_bounds (char *args, int from_tty) +{ + CORE_ADDR bd_base = 0; + CORE_ADDR addr; + CORE_ADDR bt_entry_addr = 0; + CORE_ADDR bt_entry[4]; + int i; + struct gdbarch *gdbarch = get_current_arch (); + struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + + if (!i386_mpx_enabled ()) + error (_("Intel(R) Memory Protection Extensions not\ + supported on this target.")); + + if (args == NULL) + error (_("Address of pointer variable expected.")); + + addr = parse_and_eval_address (args); + + bd_base = i386_mpx_bd_base (); + bt_entry_addr = i386_mpx_get_bt_entry (addr, bd_base); + + memset (bt_entry, 0, sizeof (bt_entry)); + + for (i = 0; i < 4; i++) + bt_entry[i] = read_memory_typed_address (bt_entry_addr + + i * data_ptr_type->length, + data_ptr_type); + + i386_mpx_print_bounds (bt_entry); +} + +/* Implement the command "set mpx bound". */ + +static void +i386_mpx_set_bounds (char *args, int from_tty) +{ + CORE_ADDR bd_base = 0; + CORE_ADDR addr, lower, upper; + CORE_ADDR bt_entry_addr = 0; + CORE_ADDR bt_entry[2]; + const char *input = args; + int i; + struct gdbarch *gdbarch = get_current_arch (); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + + if (!i386_mpx_enabled ()) + error (_("Intel(R) Memory Protection Extensions not supported\ + on this target.")); + + if (args == NULL) + error (_("Pointer value expected.")); + + addr = value_as_address (parse_to_comma_and_eval (&input)); + + if (input[0] == ',') + ++input; + if (input[0] == '\0') + error (_("wrong number of arguments: missing lower and upper bound.")); + lower = value_as_address (parse_to_comma_and_eval (&input)); + + if (input[0] == ',') + ++input; + if (input[0] == '\0') + error (_("Wrong number of arguments; Missing upper bound.")); + upper = value_as_address (parse_to_comma_and_eval (&input)); + + bd_base = i386_mpx_bd_base (); + bt_entry_addr = i386_mpx_get_bt_entry (addr, bd_base); + for (i = 0; i < 2; i++) + bt_entry[i] = read_memory_typed_address (bt_entry_addr + + i * data_ptr_type->length, + data_ptr_type); + bt_entry[0] = (uint64_t) lower; + bt_entry[1] = ~(uint64_t) upper; + + for (i = 0; i < 2; i++) + write_memory_unsigned_integer (bt_entry_addr + i * data_ptr_type->length, + data_ptr_type->length, byte_order, + bt_entry[i]); +} + +static struct cmd_list_element *mpx_set_cmdlist, *mpx_show_cmdlist; + +/* Helper function for the CLI commands. */ + +static void +set_mpx_cmd (char *args, int from_tty) +{ + help_list (mpx_set_cmdlist, "set mpx", all_commands, gdb_stdout); +} + +/* Helper function for the CLI commands. */ + +static void +show_mpx_cmd (char *args, int from_tty) +{ + cmd_show_list (mpx_show_cmdlist, from_tty, ""); +} + /* Provide a prototype to silence -Wmissing-prototypes. */ void _initialize_i386_tdep (void); @@ -8649,6 +8894,34 @@ is \"default\"."), NULL, /* FIXME: i18n: */ &setlist, &showlist); + /* Add "mpx" prefix for the set commands. */ + + add_prefix_cmd ("mpx", class_support, set_mpx_cmd, _("\ +Set Intel(R) Memory Protection Extensions specific variables."), + &mpx_set_cmdlist, "set tdesc ", + 0 /* allow-unknown */, &setlist); + + /* Add "mpx" prefix for the show commands. */ + + add_prefix_cmd ("mpx", class_support, show_mpx_cmd, _("\ +Show Intel(R) Memory Protection Extensions specific variables."), + &mpx_show_cmdlist, "show mpx ", + 0 /* allow-unknown */, &showlist); + + /* Add "bound" command for the show mpx commands list. */ + + add_cmd ("bound", no_class, i386_mpx_info_bounds, + "Show the memory bounds for a given array/pointer storage\ + in the bound table.", + &mpx_show_cmdlist); + + /* Add "bound" command for the set mpx commands list. */ + + add_cmd ("bound", no_class, i386_mpx_set_bounds, + "Set the memory bounds for a given array/pointer storage\ + in the bound table.", + &mpx_set_cmdlist); + gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour, i386_coff_osabi_sniffer); |