gdb, gdbserver, python, testsuite: Remove MPX.

GDB deprecated the commands "show/set mpx bound" in GDB 15.1, as Intel
listed Intel(R) Memory Protection Extensions (MPX) as removed in 2019.
MPX is also deprecated in gcc (since v9.1), the linux kernel (since v5.6)
and glibc (since v2.35).  Let's now remove MPX support in GDB completely.

This includes the removal of:
- MPX functionality including register support
- deprecated mpx commands
- i386 and amd64 implementation of the hooks report_signal_info and
  get_siginfo_type
- tests
- and pretty printer.

We keep MPX register numbers to not break compatibility with old gdbservers.

Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
This commit is contained in:
Schimpe, Christina 2024-03-06 11:22:49 +00:00
parent ee06c79b0f
commit fc14343205
41 changed files with 61 additions and 2528 deletions

View File

@ -3,6 +3,13 @@
*** Changes since GDB 15
* Debugging support for Intel MPX has been removed. This includes the
removal of
** MPX register support
** the commands "show/set mpx bound" (deprecated since GDB 15)
** i386 and amd64 implementation of the hooks report_signal_info and
get_siginfo_type.
* GDB now supports printing of asynchronous events from the Intel Processor
Trace during 'record instruction-history', 'record function-call-history'
and all stepping commands. This can be controlled with the new

View File

@ -79,6 +79,8 @@ static int amd64_linux_gregset32_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512) */

View File

@ -86,6 +86,8 @@ int amd64_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU and BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* xmm16 ... xmm31 (AVX512) */
@ -1816,9 +1818,6 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
set_gdbarch_process_record (gdbarch, i386_process_record);
set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
set_gdbarch_report_signal_info (gdbarch, i386_linux_report_signal_info);
}
static void

View File

@ -110,11 +110,6 @@ static const char * const amd64_ymmh_avx512_names[] =
"ymm28h", "ymm29h", "ymm30h", "ymm31h"
};
static const char * const amd64_mpx_names[] =
{
"bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus"
};
static const char * const amd64_k_names[] =
{
"k0", "k1", "k2", "k3",
@ -1039,13 +1034,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
/* BND registers can be in arbitrary values at the moment of the
inferior call. This can cause boundary violations that are not
due to a real bug or even desired by the user. The best to be done
is set the BND registers to allow access to the whole memory, INIT
state, before pushing the inferior call. */
i387_reset_bnd_regs (gdbarch, regcache);
/* Pass arguments. */
sp = amd64_push_arguments (regcache, nargs, args, sp, return_method);
@ -3196,13 +3184,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
tdep->ymm0h_regnum = AMD64_YMM0H_REGNUM;
}
if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL)
{
tdep->mpx_register_names = amd64_mpx_names;
tdep->bndcfgu_regnum = AMD64_BNDCFGU_REGNUM;
tdep->bnd0r_regnum = AMD64_BND0R_REGNUM;
}
if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL)
{
tdep->fsbase_regnum = AMD64_FSBASE_REGNUM;
@ -3377,11 +3358,10 @@ const struct target_desc *
amd64_target_description (uint64_t xcr0, bool segments)
{
static target_desc *amd64_tdescs \
[2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
[2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc;
tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
[(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0];

View File

@ -66,6 +66,8 @@ enum amd64_regnum
AMD64_MXCSR_REGNUM = AMD64_XMM0_REGNUM + 16,
AMD64_YMM0H_REGNUM, /* %ymm0h */
AMD64_YMM15H_REGNUM = AMD64_YMM0H_REGNUM + 15,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
AMD64_BND0R_REGNUM = AMD64_YMM15H_REGNUM + 1,
AMD64_BND3R_REGNUM = AMD64_BND0R_REGNUM + 3,
AMD64_BNDCFGU_REGNUM,

View File

@ -23,7 +23,6 @@
#include "../features/i386/64bit-avx512.c"
#include "../features/i386/64bit-core.c"
#include "../features/i386/64bit-linux.c"
#include "../features/i386/64bit-mpx.c"
#include "../features/i386/64bit-segments.c"
#include "../features/i386/64bit-sse.c"
#include "../features/i386/pkeys.c"
@ -65,13 +64,6 @@ amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
if (xcr0 & X86_XSTATE_AVX)
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_MPX)
{
/* MPX is not available on x32. */
gdb_assert (!is_x32);
regnum = create_feature_i386_64bit_mpx (tdesc.get (), regnum);
}
if (xcr0 & X86_XSTATE_AVX512)
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);

View File

@ -25,7 +25,6 @@
#include "../features/i386/32bit-sse.c"
#include "../features/i386/32bit-avx.c"
#include "../features/i386/32bit-avx512.c"
#include "../features/i386/32bit-mpx.c"
#include "../features/i386/32bit-segments.c"
#include "../features/i386/pkeys.c"
@ -59,9 +58,6 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
if (xcr0 & X86_XSTATE_AVX)
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_MPX)
regnum = create_feature_i386_32bit_mpx (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_AVX512)
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);

View File

@ -65,7 +65,6 @@ static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
{ X86_XSTATE_PKRU, true, true, true },
{ X86_XSTATE_AVX512, true, true, true },
{ X86_XSTATE_AVX, true, true, true },
{ X86_XSTATE_MPX, true, true, false },
{ X86_XSTATE_SSE, true, false, false },
{ X86_XSTATE_X87, true, false, false }
};
@ -150,9 +149,9 @@ x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
the target descriptions (see nat/x86-linux-tdesc.c), the feature order
represents the bit order within the generated index number.
i386 | x87 sse mpx avx avx512 pkru
amd64 | mpx avx avx512 pkru
i32 | avx avx512 pkru
i386 | x87 sse avx avx512 pkru
amd64 | avx avx512 pkru
i32 | avx avx512 pkru
The features are ordered so that for each mode (i386, amd64, i32) the
generated index will form a continuous range. */

View File

@ -120,8 +120,7 @@ PYTHON_FILE_LIST = \
gdb/function/as_string.py \
gdb/function/caller_is.py \
gdb/function/strfns.py \
gdb/printer/__init__.py \
gdb/printer/bound_registers.py
gdb/printer/__init__.py
@HAVE_PYTHON_TRUE@PYTHON_FILES = $(PYTHON_FILE_LIST)
@HAVE_PYTHON_FALSE@PYTHON_FILES =

View File

@ -7077,33 +7077,6 @@ $1 = (void *) 0x7ffff7ff7000
Depending on target support, @code{$_siginfo} may also be writable.
@cindex Intel MPX boundary violations
@cindex boundary violations, Intel MPX
On some targets, a @code{SIGSEGV} can be caused by a boundary
violation, i.e., accessing an address outside of the allowed range.
In those cases @value{GDBN} may displays additional information,
depending on how @value{GDBN} has been told to handle the signal.
With @code{handle stop SIGSEGV}, @value{GDBN} displays the violation
kind: "Upper" or "Lower", the memory address accessed and the
bounds, while with @code{handle nostop SIGSEGV} no additional
information is displayed.
The usual output of a segfault is:
@smallexample
Program received signal SIGSEGV, Segmentation fault
0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
68 value = *(p + len);
@end smallexample
While a bound violation is presented as:
@smallexample
Program received signal SIGSEGV, Segmentation fault
Upper bound violation while accessing address 0x7fffffffc3b3
Bounds: [lower = 0x7fffffffc390, upper = 0x7fffffffc3a3]
0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
68 value = *(p + len);
@end smallexample
@node Thread Stops
@section Stopping and Starting Multi-thread Programs
@ -26803,91 +26776,6 @@ Show the current setting of the convention to return @code{struct}s
from functions.
@end table
@subsubsection Intel @dfn{Memory Protection Extensions} (MPX).
@cindex Intel Memory Protection Extensions (MPX).
Memory Protection Extension (MPX) adds the bound registers @samp{BND0}
@footnote{The register named with capital letters represent the architecture
registers.} through @samp{BND3}. Bound registers store a pair of 64-bit values
which are the lower bound and upper bound. Bounds are effective addresses or
memory locations. The upper bounds are architecturally represented in 1's
complement form. A bound having lower bound = 0, and upper bound = 0
(1's complement of all bits set) will allow access to the entire address space.
@samp{BND0} through @samp{BND3} are represented in @value{GDBN} as @samp{bnd0raw}
through @samp{bnd3raw}. Pseudo registers @samp{bnd0} through @samp{bnd3}
display the upper bound performing the complement of one operation on the
upper bound value, i.e.@ when upper bound in @samp{bnd0raw} is 0 in the
@value{GDBN} @samp{bnd0} it will be @code{0xfff@dots{}}. In this sense it
can also be noted that the upper bounds are inclusive.
As an example, assume that the register BND0 holds bounds for a pointer having
access allowed for the range between 0x32 and 0x71. The values present on
bnd0raw and bnd registers are presented as follows:
@smallexample
bnd0raw = @{0x32, 0xffffffff8e@}
bnd0 = @{lbound = 0x32, ubound = 0x71@} : size 64
@end smallexample
This way the raw value can be accessed via bnd0raw@dots{}bnd3raw. Any
change on bnd0@dots{}bnd3 or bnd0raw@dots{}bnd3raw is reflect on its
counterpart. When the bnd0@dots{}bnd3 registers are displayed via
Python, the display includes the memory size, in bits, accessible to
the pointer.
Bounds can also be stored in bounds tables, which are stored in
application memory. These tables store bounds for pointers by specifying
the bounds pointer's value along with its bounds. Evaluating and changing
bounds located in bound tables is therefore interesting while investigating
bugs on MPX context. @value{GDBN} provides commands for this purpose:
@table @code
@item show mpx bound @var{pointer}
@kindex show mpx bound
Display bounds of the given @var{pointer}.
@item set mpx bound @var{pointer}, @var{lbound}, @var{ubound}
@kindex set mpx bound
Set the bounds of a pointer in the bound table.
This command takes three parameters: @var{pointer} is the pointers
whose bounds are to be changed, @var{lbound} and @var{ubound} are new values
for lower and upper bounds respectively.
@end table
Both commands are deprecated and will be removed in future versions of
@value{GDBN}. MPX itself was listed as removed by Intel in 2019.
When you call an inferior function on an Intel MPX enabled program,
GDB sets the inferior's bound registers to the init (disabled) state
before calling the function. As a consequence, bounds checks for the
pointer arguments passed to the function will always pass.
This is necessary because when you call an inferior function, the
program is usually in the middle of the execution of other function.
Since at that point bound registers are in an arbitrary state, not
clearing them would lead to random bound violations in the called
function.
You can still examine the influence of the bound registers on the
execution of the called function by stopping the execution of the
called function at its prologue, setting bound registers, and
continuing the execution. For example:
@smallexample
$ break *upper
Breakpoint 2 at 0x4009de: file i386-mpx-call.c, line 47.
$ print upper (a, b, c, d, 1)
Breakpoint 2, upper (a=0x0, b=0x6e0000005b, c=0x0, d=0x0, len=48)....
$ print $bnd0
@{lbound = 0x0, ubound = ffffffff@} : size -1
@end smallexample
At this last step the value of bnd0 can be changed for investigation of bound
violations caused along the execution of the call. In order to know how to
set the bound registers or bound table for the call consult the ABI.
@subsubsection x87 registers
@value{GDBN} provides access to the x87 state through the following registers:
@ -49746,16 +49634,6 @@ describe the upper 128 bits of @sc{ymm} registers:
@samp{ymm0h} through @samp{ymm15h} for amd64
@end itemize
The @samp{org.gnu.gdb.i386.mpx} is an optional feature representing Intel
Memory Protection Extension (MPX). It should describe the following registers:
@itemize @minus
@item
@samp{bnd0raw} through @samp{bnd3raw} for i386 and amd64.
@item
@samp{bndcfgu} and @samp{bndstatus} for i386 and amd64.
@end itemize
The @samp{org.gnu.gdb.i386.linux} feature is optional. It should
describe a single register, @samp{orig_eax}.

View File

@ -222,12 +222,10 @@ FEATURE_XMLFILES = aarch64-core.xml \
i386/32bit-sse.xml \
i386/32bit-linux.xml \
i386/32bit-avx.xml \
i386/32bit-mpx.xml \
i386/32bit-avx512.xml \
i386/32bit-segments.xml \
i386/64bit-avx512.xml \
i386/64bit-core.xml \
i386/64bit-mpx.xml \
i386/64bit-segments.xml \
i386/64bit-avx.xml \
i386/64bit-linux.xml \

View File

@ -1,51 +0,0 @@
/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
Original: 32bit-mpx.xml */
#include "gdbsupport/tdesc.h"
static int
create_feature_i386_32bit_mpx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_struct (feature, "br128");
tdesc_type *field_type;
field_type = tdesc_named_type (feature, "uint64");
tdesc_add_field (type_with_fields, "lbound", field_type);
field_type = tdesc_named_type (feature, "uint64");
tdesc_add_field (type_with_fields, "ubound_raw", field_type);
type_with_fields = tdesc_create_struct (feature, "_bndstatus");
tdesc_set_struct_size (type_with_fields, 8);
tdesc_add_bitfield (type_with_fields, "bde", 2, 31);
tdesc_add_bitfield (type_with_fields, "error", 0, 1);
type_with_fields = tdesc_create_union (feature, "status");
field_type = tdesc_named_type (feature, "data_ptr");
tdesc_add_field (type_with_fields, "raw", field_type);
field_type = tdesc_named_type (feature, "_bndstatus");
tdesc_add_field (type_with_fields, "status", field_type);
type_with_fields = tdesc_create_struct (feature, "_bndcfgu");
tdesc_set_struct_size (type_with_fields, 8);
tdesc_add_bitfield (type_with_fields, "base", 12, 31);
tdesc_add_bitfield (type_with_fields, "reserved", 2, 11);
tdesc_add_bitfield (type_with_fields, "preserved", 1, 1);
tdesc_add_bitfield (type_with_fields, "enabled", 0, 0);
type_with_fields = tdesc_create_union (feature, "cfgu");
field_type = tdesc_named_type (feature, "data_ptr");
tdesc_add_field (type_with_fields, "raw", field_type);
field_type = tdesc_named_type (feature, "_bndcfgu");
tdesc_add_field (type_with_fields, "config", field_type);
tdesc_create_reg (feature, "bnd0raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd1raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd2raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd3raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bndcfgu", regnum++, 1, NULL, 64, "cfgu");
tdesc_create_reg (feature, "bndstatus", regnum++, 1, NULL, 64, "status");
return regnum;
}

View File

@ -1,45 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2013-2024 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.i386.mpx">
<struct id="br128">
<field name="lbound" type="uint64"/>
<field name="ubound_raw" type="uint64"/>
</struct>
<struct id="_bndstatus" size="8">
<field name="bde" start="2" end="31"/>
<field name="error" start="0" end="1"/>
</struct>
<union id="status">
<field name="raw" type="data_ptr"/>
<field name="status" type="_bndstatus"/>
</union>
<struct id="_bndcfgu" size="8">
<field name="base" start="12" end="31" />
<field name="reserved" start="2" end="11"/>
<!-- Explicitly set the type here, otherwise it defaults to bool.
Perhaps this should be uint32, but the container type has size 8. -->
<field name="preserved" start="1" end="1" type="uint64"/>
<field name="enabled" start="0" end="0" type="uint64"/>
</struct>
<union id="cfgu">
<field name="raw" type="data_ptr"/>
<field name="config" type="_bndcfgu"/>
</union>
<reg name="bnd0raw" bitsize="128" type="br128"/>
<reg name="bnd1raw" bitsize="128" type="br128"/>
<reg name="bnd2raw" bitsize="128" type="br128"/>
<reg name="bnd3raw" bitsize="128" type="br128"/>
<reg name="bndcfgu" bitsize="64" type="cfgu"/>
<reg name="bndstatus" bitsize="64" type="status"/>
</feature>

View File

@ -1,51 +0,0 @@
/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
Original: 64bit-mpx.xml */
#include "gdbsupport/tdesc.h"
static int
create_feature_i386_64bit_mpx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_struct (feature, "br128");
tdesc_type *field_type;
field_type = tdesc_named_type (feature, "uint64");
tdesc_add_field (type_with_fields, "lbound", field_type);
field_type = tdesc_named_type (feature, "uint64");
tdesc_add_field (type_with_fields, "ubound_raw", field_type);
type_with_fields = tdesc_create_struct (feature, "_bndstatus");
tdesc_set_struct_size (type_with_fields, 8);
tdesc_add_bitfield (type_with_fields, "bde", 2, 63);
tdesc_add_bitfield (type_with_fields, "error", 0, 1);
type_with_fields = tdesc_create_union (feature, "status");
field_type = tdesc_named_type (feature, "data_ptr");
tdesc_add_field (type_with_fields, "raw", field_type);
field_type = tdesc_named_type (feature, "_bndstatus");
tdesc_add_field (type_with_fields, "status", field_type);
type_with_fields = tdesc_create_struct (feature, "_bndcfgu");
tdesc_set_struct_size (type_with_fields, 8);
tdesc_add_bitfield (type_with_fields, "base", 12, 63);
tdesc_add_bitfield (type_with_fields, "reserved", 2, 11);
tdesc_add_bitfield (type_with_fields, "preserved", 1, 1);
tdesc_add_bitfield (type_with_fields, "enabled", 0, 0);
type_with_fields = tdesc_create_union (feature, "cfgu");
field_type = tdesc_named_type (feature, "data_ptr");
tdesc_add_field (type_with_fields, "raw", field_type);
field_type = tdesc_named_type (feature, "_bndcfgu");
tdesc_add_field (type_with_fields, "config", field_type);
tdesc_create_reg (feature, "bnd0raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd1raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd2raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bnd3raw", regnum++, 1, NULL, 128, "br128");
tdesc_create_reg (feature, "bndcfgu", regnum++, 1, NULL, 64, "cfgu");
tdesc_create_reg (feature, "bndstatus", regnum++, 1, NULL, 64, "status");
return regnum;
}

View File

@ -1,44 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2013-2024 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.i386.mpx">
<struct id="br128">
<field name="lbound" type="uint64"/>
<field name="ubound_raw" type="uint64"/>
</struct>
<struct id="_bndstatus" size="8">
<field name="bde" start="2" end="63"/>
<field name="error" start="0" end="1"/>
</struct>
<union id="status">
<field name="raw" type="data_ptr"/>
<field name="status" type="_bndstatus"/>
</union>
<struct id="_bndcfgu" size="8">
<field name="base" start="12" end="63"/>
<field name="reserved" start="2" end="11"/>
<!-- Explicitly set the type here, otherwise it defaults to bool. -->
<field name="preserved" start="1" end="1" type="uint64"/>
<field name="enabled" start="0" end="0" type="uint64"/>
</struct>
<union id="cfgu">
<field name="raw" type="data_ptr"/>
<field name="config" type="_bndcfgu"/>
</union>
<reg name="bnd0raw" bitsize="128" type="br128"/>
<reg name="bnd1raw" bitsize="128" type="br128"/>
<reg name="bnd2raw" bitsize="128" type="br128"/>
<reg name="bnd3raw" bitsize="128" type="br128"/>
<reg name="bndcfgu" bitsize="64" type="cfgu"/>
<reg name="bndstatus" bitsize="64" type="status"/>
</feature>

View File

@ -390,62 +390,6 @@ i386_canonicalize_syscall (int syscall)
#define SIG_CODE_BOUNDARY_FAULT 3
/* i386 GNU/Linux implementation of the report_signal_info
gdbarch hook. Displays information related to MPX bound
violations. */
void
i386_linux_report_signal_info (struct gdbarch *gdbarch, struct ui_out *uiout,
enum gdb_signal siggnal)
{
/* -Wmaybe-uninitialized */
CORE_ADDR lower_bound = 0, upper_bound = 0, access = 0;
int is_upper;
long sig_code = 0;
if (!i386_mpx_enabled () || siggnal != GDB_SIGNAL_SEGV)
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 (const gdb_exception_error &exception)
{
return;
}
/* If this is not a boundary violation just return. */
if (sig_code != SIG_CODE_BOUNDARY_FAULT)
return;
is_upper = (access > upper_bound ? 1 : 0);
uiout->text ("\n");
if (is_upper)
uiout->field_string ("sigcode-meaning", _("Upper bound violation"));
else
uiout->field_string ("sigcode-meaning", _("Lower bound violation"));
uiout->text (_(" while accessing address "));
uiout->field_core_addr ("bound-access", gdbarch, access);
uiout->text (_("\nBounds: [lower = "));
uiout->field_core_addr ("lower-bound", gdbarch, lower_bound);
uiout->text (_(", upper = "));
uiout->field_core_addr ("upper-bound", gdbarch, upper_bound);
uiout->text (_("]"));
}
/* 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
@ -608,6 +552,8 @@ int i386_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1,
-1, -1, -1, -1, -1, -1, -1, -1,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512) */
@ -721,12 +667,6 @@ i386_linux_supply_xstateregset (const struct regset *regset,
i387_supply_xsave (regcache, regnum, xstateregs);
}
struct type *
x86_linux_get_siginfo_type (struct gdbarch *gdbarch)
{
return linux_get_siginfo_type_with_fields (gdbarch, LINUX_SIGINFO_FIELD_ADDR_BND);
}
/* Similar to i386_collect_fpregset, but use XSAVE extended state. */
static void
@ -1064,9 +1004,6 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_I386);
set_gdbarch_get_syscall_number (gdbarch,
i386_linux_get_syscall_number);
set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
set_gdbarch_report_signal_info (gdbarch, i386_linux_report_signal_info);
}
void _initialize_i386_linux_tdep ();

View File

@ -49,15 +49,6 @@ extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
x86_xsave_layout &layout);
/* Handle and display information related to the MPX bound violation
to the user. */
extern void i386_linux_report_signal_info (struct gdbarch *gdbarch,
struct ui_out *uiout,
enum gdb_signal siggnal);
extern int i386_linux_gregset_reg_offset[];
/* Return x86 siginfo type. */
extern struct type *x86_linux_get_siginfo_type (struct gdbarch *gdbarch);
#endif /* i386-linux-tdep.h */

View File

@ -117,23 +117,12 @@ static const char * const i386_ymmh_names[] =
"ymm4h", "ymm5h", "ymm6h", "ymm7h",
};
static const char * const i386_mpx_names[] =
{
"bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus"
};
static const char * const i386_pkeys_names[] =
{
"pkru"
};
/* Register names for MPX pseudo-registers. */
static const char * const i386_bnd_names[] =
{
"bnd0", "bnd1", "bnd2", "bnd3"
};
/* Register names for MMX pseudo-registers. */
static const char * const i386_mmx_names[] =
@ -311,21 +300,6 @@ i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
return regnum >= 0 && regnum < tdep->num_ymm_avx512_regs;
}
/* BND register? */
int
i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
int bnd0_regnum = tdep->bnd0_regnum;
if (bnd0_regnum < 0)
return 0;
regnum -= bnd0_regnum;
return regnum >= 0 && regnum < I387_NUM_BND_REGS;
}
/* SSE register? */
int
@ -393,34 +367,6 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
&& regnum < I387_XMM0_REGNUM (tdep));
}
/* BNDr (raw) register? */
static int
i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (I387_BND0R_REGNUM (tdep) < 0)
return 0;
regnum -= tdep->bnd0r_regnum;
return regnum >= 0 && regnum < I387_NUM_BND_REGS;
}
/* BND control register? */
static int
i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (I387_BNDCFGU_REGNUM (tdep) < 0)
return 0;
regnum -= I387_BNDCFGU_REGNUM (tdep);
return regnum >= 0 && regnum < I387_NUM_MPX_CTRL_REGS;
}
/* PKRU register? */
bool
@ -463,8 +409,6 @@ const char *
i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (i386_bnd_regnum_p (gdbarch, regnum))
return i386_bnd_names[regnum - tdep->bnd0_regnum];
if (i386_mmx_regnum_p (gdbarch, regnum))
return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)];
else if (i386_ymm_regnum_p (gdbarch, regnum))
@ -2738,13 +2682,6 @@ i386_thiscall_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
int write_pass;
int args_space = 0;
/* BND registers can be in arbitrary values at the moment of the
inferior call. This can cause boundary violations that are not
due to a real bug or even desired by the user. The best to be done
is set the BND registers to allow access to the whole memory, INIT
state, before pushing the inferior call. */
i387_reset_bnd_regs (gdbarch, regcache);
/* Determine the total space required for arguments and struct
return address in a first pass (allowing for 16-byte-aligned
arguments), then push arguments in a second pass. */
@ -3161,43 +3098,6 @@ i387_ext_type (struct gdbarch *gdbarch)
return tdep->i387_ext_type;
}
/* Construct type for pseudo BND registers. We can't use
tdesc_find_type since a complement of one value has to be used
to describe the upper bound. */
static struct type *
i386_bnd_type (struct gdbarch *gdbarch)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (!tdep->i386_bnd_type)
{
struct type *t;
const struct builtin_type *bt = builtin_type (gdbarch);
/* The type we're building is described bellow: */
#if 0
struct __bound128
{
void *lbound;
void *ubound; /* One complement of raw ubound field. */
};
#endif
t = arch_composite_type (gdbarch,
"__gdb_builtin_type_bound128", TYPE_CODE_STRUCT);
append_composite_type_field (t, "lbound", bt->builtin_data_ptr);
append_composite_type_field (t, "ubound", bt->builtin_data_ptr);
t->set_name ("builtin_type_bound128");
tdep->i386_bnd_type = t;
}
return tdep->i386_bnd_type;
}
/* Construct vector type for pseudo ZMM registers. We can't use
tdesc_find_type since ZMM isn't described in target description. */
@ -3364,8 +3264,6 @@ i386_mmx_type (struct gdbarch *gdbarch)
struct type *
i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
if (i386_bnd_regnum_p (gdbarch, regnum))
return i386_bnd_type (gdbarch);
if (i386_mmx_regnum_p (gdbarch, regnum))
return i386_mmx_type (gdbarch);
else if (i386_ymm_regnum_p (gdbarch, regnum))
@ -3425,39 +3323,7 @@ i386_pseudo_register_read_value (gdbarch *gdbarch, const frame_info_ptr &next_fr
else
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
{
int i = pseudo_reg_num - tdep->bnd0_regnum;
/* Extract (always little endian). Read lower 128bits. */
value *bndr_value
= value_of_register (I387_BND0R_REGNUM (tdep) + i, next_frame);
int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
value *result
= value::allocate_register (next_frame, pseudo_reg_num);
/* Copy the lower. */
bndr_value->contents_copy (result, 0, 0, size);
/* Copy the upper. */
bndr_value->contents_copy (result, size, 8, size);
/* If upper bytes are available, compute ones' complement. */
if (result->bytes_available (size, size))
{
bfd_endian byte_order
= gdbarch_byte_order (frame_unwind_arch (next_frame));
gdb::array_view<gdb_byte> upper_bytes
= result->contents_raw ().slice (size, size);
ULONGEST upper
= extract_unsigned_integer (upper_bytes, byte_order);
upper = ~upper;
store_unsigned_integer (upper_bytes, byte_order, upper);
}
return result;
}
else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
{
/* Which register is it, relative to zmm0. */
int i_0 = pseudo_reg_num - tdep->zmm0_regnum;
@ -3530,33 +3396,7 @@ i386_pseudo_register_write (gdbarch *gdbarch, const frame_info_ptr &next_frame,
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
{
int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
bfd_endian byte_order
= gdbarch_byte_order (current_inferior ()->arch ());
/* New values from input value. */
int reg_index = pseudo_reg_num - tdep->bnd0_regnum;
int raw_regnum = I387_BND0R_REGNUM (tdep) + reg_index;
value *bndr_value = value_of_register (raw_regnum, next_frame);
gdb::array_view<gdb_byte> bndr_view
= bndr_value->contents_writeable ();
/* Copy lower bytes directly. */
copy (buf.slice (0, size), bndr_view.slice (0, size));
/* Convert and then copy upper bytes. */
ULONGEST upper
= extract_unsigned_integer (buf.slice (size, size), byte_order);
upper = ~upper;
store_unsigned_integer (bndr_view.slice (8, size), byte_order,
upper);
put_frame_register (next_frame, raw_regnum, bndr_view);
}
else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
{
/* Which register is it, relative to zmm0. */
int reg_index_0 = pseudo_reg_num - tdep->zmm0_regnum;
@ -3627,12 +3467,6 @@ i386_ax_pseudo_register_collect (struct gdbarch *gdbarch,
ax_reg_mask (ax, I387_ST0_REGNUM (tdep) + i);
return 0;
}
else if (i386_bnd_regnum_p (gdbarch, regnum))
{
regnum -= tdep->bnd0_regnum;
ax_reg_mask (ax, I387_BND0R_REGNUM (tdep) + regnum);
return 0;
}
else if (i386_zmm_regnum_p (gdbarch, regnum))
{
regnum -= tdep->zmm0_regnum;
@ -4480,9 +4314,8 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
ymm_regnum_p, ymmh_regnum_p, ymm_avx512_regnum_p, ymmh_avx512_regnum_p,
bndr_regnum_p, bnd_regnum_p, zmm_regnum_p, zmmh_regnum_p,
mpx_ctrl_regnum_p, xmm_avx512_regnum_p,
avx512_p, avx_p, sse_p, pkru_regnum_p;
zmm_regnum_p, zmmh_regnum_p, xmm_avx512_regnum_p, avx512_p, avx_p,
sse_p, pkru_regnum_p;
/* Don't include pseudo registers, except for MMX, in any register
groups. */
@ -4542,21 +4375,6 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
|| zmmh_regnum_p))
return 0;
bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum);
if (group == all_reggroup
&& ((bnd_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
return bnd_regnum_p;
bndr_regnum_p = i386_bndr_regnum_p (gdbarch, regnum);
if (group == all_reggroup
&& ((bndr_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
return 0;
mpx_ctrl_regnum_p = i386_mpx_ctrl_regnum_p (gdbarch, regnum);
if (group == all_reggroup
&& ((mpx_ctrl_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
return mpx_ctrl_regnum_p;
if (group == general_reggroup)
return (!fp_regnum_p
&& !mmx_regnum_p
@ -4567,9 +4385,6 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
&& !ymmh_regnum_p
&& !ymm_avx512_regnum_p
&& !ymmh_avx512_regnum_p
&& !bndr_regnum_p
&& !bnd_regnum_p
&& !mpx_ctrl_regnum_p
&& !zmm_regnum_p
&& !zmmh_regnum_p
&& !pkru_regnum_p);
@ -8186,7 +8001,7 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
const struct tdesc_feature *feature_core;
const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
const struct tdesc_feature *feature_sse, *feature_avx,
*feature_avx512, *feature_pkeys;
/* Get core registers. */
@ -8200,9 +8015,6 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
/* Try AVX registers. */
feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
/* Try MPX registers. */
feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
/* Try AVX512 registers. */
feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
@ -8224,9 +8036,6 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
xcr0 |= X86_XSTATE_AVX;
}
if (feature_mpx)
xcr0 |= X86_XSTATE_MPX_MASK;
if (feature_avx512)
{
/* AVX512 register description requires AVX register description. */
@ -8249,8 +8058,8 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
const struct target_desc *tdesc = tdep->tdesc;
const struct tdesc_feature *feature_core;
const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
*feature_avx512, *feature_pkeys, *feature_segments;
const struct tdesc_feature *feature_sse, *feature_avx, *feature_avx512,
*feature_pkeys, *feature_segments;
int i, num_regs, valid_p;
if (! tdesc_has_registers (tdesc))
@ -8267,9 +8076,6 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
/* Try AVX registers. */
feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
/* Try MPX registers. */
feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
/* Try AVX512 registers. */
feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
@ -8368,23 +8174,6 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
tdep->register_names[i]);
}
if (feature_mpx)
{
tdep->xcr0 |= X86_XSTATE_MPX_MASK;
if (tdep->bnd0r_regnum < 0)
{
tdep->mpx_register_names = i386_mpx_names;
tdep->bnd0r_regnum = I386_BND0R_REGNUM;
tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUM;
}
for (i = 0; i < I387_NUM_MPX_REGS; i++)
valid_p &= tdesc_numbered_register (feature_mpx, tdesc_data,
I387_BND0R_REGNUM (tdep) + i,
tdep->mpx_register_names[i]);
}
if (feature_segments)
{
if (tdep->fsbase_regnum < 0)
@ -8448,8 +8237,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
const struct target_desc *tdesc;
int mm0_regnum;
int ymm0_regnum;
int bnd0_regnum;
int num_bnd_cooked;
x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
@ -8655,7 +8442,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Even though the default ABI only includes general-purpose registers,
floating-point registers and the SSE registers, we have to leave a
gap for the upper AVX, MPX and AVX512 registers. */
gap for the upper AVX, (deprecated) MPX and AVX512 registers. */
set_gdbarch_num_regs (gdbarch, I386_NUM_REGS);
set_gdbarch_gnu_triplet_regexp (gdbarch, i386_gnu_triplet_regexp);
@ -8691,10 +8478,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->num_mmx_regs = 8;
tdep->num_ymm_regs = 0;
/* No MPX registers. */
tdep->bnd0r_regnum = -1;
tdep->bndcfgu_regnum = -1;
/* No AVX512 registers. */
tdep->k0_regnum = -1;
tdep->num_zmm_regs = 0;
@ -8731,8 +8514,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
tdep->xsave_layout = xsave_layout;
num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
/* Wire in pseudo registers. Number of pseudo registers may be
changed. */
set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs
@ -8740,7 +8521,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ tdep->num_dword_regs
+ tdep->num_mmx_regs
+ tdep->num_ymm_regs
+ num_bnd_cooked
+ tdep->num_ymm_avx512_regs
+ tdep->num_zmm_regs));
@ -8794,21 +8574,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
else
tdep->zmm0_regnum = -1;
bnd0_regnum = mm0_regnum;
if (tdep->num_mmx_regs != 0)
{
/* Support MMX pseudo-register if MMX hasn't been disabled. */
tdep->mm0_regnum = mm0_regnum;
bnd0_regnum += tdep->num_mmx_regs;
}
else
tdep->mm0_regnum = -1;
if (tdep->bnd0r_regnum > 0)
tdep->bnd0_regnum = bnd0_regnum;
else
tdep-> bnd0_regnum = -1;
/* Hook in the legacy prologue-based unwinders last (fallback). */
if (info.bfd_arch_info->bits_per_word == 32)
{
@ -8838,12 +8611,11 @@ const struct target_desc *
i386_target_description (uint64_t xcr0, bool segments)
{
static target_desc *i386_tdescs \
[2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
[2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc;
tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
[(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0];
@ -8854,245 +8626,6 @@ i386_target_description (uint64_t xcr0, bool segments)
return *tdesc;
}
#define MPX_BASE_MASK (~(ULONGEST) 0xfff)
/* Find the bound directory base address. */
static unsigned long
i386_mpx_bd_base (void)
{
ULONGEST ret;
enum register_status regstatus;
regcache *rcache = get_thread_regcache (inferior_thread ());
gdbarch *arch = rcache->arch ();
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
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;
}
int
i386_mpx_enabled (void)
{
gdbarch *arch = get_current_arch ();
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (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 = (CORE_ADDR) 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 = (CORE_ADDR) MPX_BT_MASK;
if ( sizeof (CORE_ADDR) == 4)
error (_("bound table examination not supported\
for 64-bit process with 32-bit GDB"));
}
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;
LONGEST 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)
{
uiout->text ("Null bounds on map:");
uiout->text (" pointer value = ");
uiout->field_core_addr ("pointer-value", gdbarch, bt_entry[2]);
uiout->text (".");
uiout->text ("\n");
}
else
{
uiout->text ("{lbound = ");
uiout->field_core_addr ("lower-bound", gdbarch, bt_entry[0]);
uiout->text (", ubound = ");
/* The upper bound is stored in 1's complement. */
uiout->field_core_addr ("upper-bound", gdbarch, ~bt_entry[1]);
uiout->text ("}: pointer value = ");
uiout->field_core_addr ("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);
uiout->text (", size = ");
uiout->field_string ("size", plongest (size));
uiout->text (", metadata = ");
uiout->field_core_addr ("metadata", gdbarch, bt_entry[3]);
uiout->text ("\n");
}
}
/* Implement the command "show mpx bound". */
static void
i386_mpx_info_bounds (const 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 (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_i386
|| !i386_mpx_enabled ())
{
gdb_printf (_("Intel Memory Protection Extensions not "
"supported on this target.\n"));
return;
}
if (args == NULL)
{
gdb_printf (_("Address of pointer variable expected.\n"));
return;
}
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 (const 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 (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_i386
|| !i386_mpx_enabled ())
error (_("Intel 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;
void _initialize_i386_tdep ();
void
_initialize_i386_tdep ()
@ -9121,30 +8654,6 @@ is \"default\"."),
NULL, /* FIXME: i18n: */
&setlist, &showlist);
/* Add "mpx" prefix for the set and show commands. */
add_setshow_prefix_cmd
("mpx", class_support,
_("Set Intel Memory Protection Extensions specific variables."),
_("Show Intel Memory Protection Extensions specific variables."),
&mpx_set_cmdlist, &mpx_show_cmdlist, &setlist, &showlist);
/* Add "bound" command for the show mpx commands list. */
cmd_list_element *c = 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);
deprecate_cmd (c, nullptr);
/* Add "bound" command for the set mpx commands list. */
c = 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);
deprecate_cmd (c, nullptr);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
i386_svr4_init_abi);

View File

@ -166,21 +166,6 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* YMM16-31 register names. Only used for tdesc_numbered_register. */
const char * const *ymm16h_register_names = nullptr;
/* Register number for %bnd0r. Set this to -1 to indicate the absence
bound registers. */
int bnd0r_regnum = 0;
/* Register number for pseudo register %bnd0. Set this to -1 to indicate the absence
bound registers. */
int bnd0_regnum = 0;
/* Register number for %bndcfgu. Set this to -1 to indicate the absence
bound control registers. */
int bndcfgu_regnum = 0;
/* MPX register names. Only used for tdesc_numbered_register. */
const char * const *mpx_register_names = nullptr;
/* Register number for %zmm0h. Set this to -1 to indicate the absence
of ZMM_HI256 register support. */
int zmm0h_regnum = 0;
@ -246,7 +231,6 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
struct type *i386_ymm_type = nullptr;
struct type *i386_zmm_type = nullptr;
struct type *i387_ext_type = nullptr;
struct type *i386_bnd_type = nullptr;
/* Process record/replay target. */
/* The map for registers because the AMD64's registers order
@ -298,6 +282,8 @@ enum i386_regnum
I386_MXCSR_REGNUM = 40, /* %mxcsr */
I386_YMM0H_REGNUM, /* %ymm0h */
I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
I386_BND0R_REGNUM,
I386_BND3R_REGNUM = I386_BND0R_REGNUM + 3,
I386_BNDCFGU_REGNUM,
@ -346,7 +332,6 @@ enum record_i386_regnum
#define I386_SSE_NUM_REGS (I386_MXCSR_REGNUM + 1)
#define I386_AVX_NUM_REGS (I386_YMM7H_REGNUM + 1)
#define I386_MPX_NUM_REGS (I386_BNDSTATUS_REGNUM + 1)
#define I386_AVX512_NUM_REGS (I386_ZMM7H_REGNUM + 1)
#define I386_PKEYS_NUM_REGS (I386_PKRU_REGNUM + 1)
#define I386_NUM_REGS (I386_GSBASE_REGNUM + 1)
@ -365,7 +350,6 @@ extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_xmm_avx512_regnum_p (struct gdbarch * gdbarch, int regnum);
extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_k_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_zmm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_zmmh_regnum_p (struct gdbarch *gdbarch, int regnum);
@ -468,10 +452,6 @@ extern int i386_process_record (struct gdbarch *gdbarch,
extern const struct target_desc *i386_target_description (uint64_t xcr0,
bool segments);
/* Return true iff the current target is MPX enabled. */
extern int i386_mpx_enabled (void);
/* Functions and variables exported from i386-bsd-tdep.c. */
extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *);

View File

@ -818,30 +818,6 @@ static int xsave_xmm_avx512_offset[] =
(xsave + (tdep)->xsave_layout.zmm_offset \
+ xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
/* At xsave_bndregs_offset[REGNUM] you'll find the relative offset
within the BNDREGS region of the XSAVE extended state where the GDB
register BND0R + REGNUM is stored. */
static int xsave_bndregs_offset[] = {
0 * 16, /* bnd0r...bnd3r registers. */
1 * 16,
2 * 16,
3 * 16
};
#define XSAVE_BNDREGS_ADDR(tdep, xsave, regnum) \
(xsave + (tdep)->xsave_layout.bndregs_offset \
+ xsave_bndregs_offset[regnum - I387_BND0R_REGNUM (tdep)])
static int xsave_bndcfg_offset[] = {
0 * 8, /* bndcfg ... bndstatus. */
1 * 8,
};
#define XSAVE_BNDCFG_ADDR(tdep, xsave, regnum) \
(xsave + (tdep)->xsave_layout.bndcfg_offset \
+ xsave_bndcfg_offset[regnum - I387_BNDCFGU_REGNUM (tdep)])
/* At xsave_avx512_k_offset[REGNUM] you'll find the relative offset
within the K region of the XSAVE extended state where the AVX512
opmask register K0 + REGNUM is stored. */
@ -944,8 +920,6 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
{
/* Intel CPUs supporting PKRU. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
@ -964,20 +938,14 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
{
/* Intel CPUs supporting AVX512. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
}
else if (HAS_MPX (xcr0) && xsave_size == 1088)
{
/* Intel CPUs supporting MPX. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
}
else if (HAS_AVX (xcr0) && xsave_size == 832)
/* As MPX has been removed, we need the additional check
(xsave_size == 1088) to allow reading AVX registers from corefiles
on CPUs with MPX as the highest supported feature. */
else if (HAS_AVX (xcr0) && (xsave_size == 832 || xsave_size == 1088))
{
/* Intel and AMD CPUs supporting AVX. */
layout.avx_offset = 576;
@ -1000,8 +968,6 @@ i387_fallback_xsave_layout (uint64_t xcr0)
{
/* Intel CPUs supporting PKRU. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
@ -1012,21 +978,11 @@ i387_fallback_xsave_layout (uint64_t xcr0)
{
/* Intel CPUs supporting AVX512. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
layout.sizeof_xsave = 2688;
}
else if (HAS_MPX (xcr0))
{
/* Intel CPUs supporting MPX. */
layout.avx_offset = 576;
layout.bndregs_offset = 960;
layout.bndcfg_offset = 1024;
layout.sizeof_xsave = 1088;
}
else if (HAS_AVX (xcr0))
{
/* Intel and AMD CPUs supporting AVX. */
@ -1082,16 +1038,14 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
x87 = 0x1,
sse = 0x2,
avxh = 0x4,
bndregs = 0x8,
bndcfg = 0x10,
avx512_k = 0x20,
avx512_zmm0_h = 0x40,
avx512_zmm16_h = 0x80,
avx512_ymmh_avx512 = 0x100,
avx512_xmm_avx512 = 0x200,
pkeys = 0x400,
all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
| avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
avx512_k = 0x8,
avx512_zmm0_h = 0x10,
avx512_zmm16_h = 0x20,
avx512_ymmh_avx512 = 0x40,
avx512_xmm_avx512 = 0x80,
pkeys = 0x100,
all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h
| avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
} regclass;
gdb_assert (regs != NULL);
@ -1121,12 +1075,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
else if (regnum >= I387_BND0R_REGNUM (tdep)
&& regnum < I387_BNDCFGU_REGNUM (tdep))
regclass = bndregs;
else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
&& regnum < I387_MPXEND_REGNUM (tdep))
regclass = bndcfg;
else if (regnum >= I387_XMM0_REGNUM (tdep)
&& regnum < I387_MXCSR_REGNUM (tdep))
regclass = sse;
@ -1205,20 +1153,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, regnum));
return;
case bndcfg:
if ((clear_bv & X86_XSTATE_BNDCFG))
regcache->raw_supply (regnum, zero);
else
regcache->raw_supply (regnum, XSAVE_BNDCFG_ADDR (tdep, regs, regnum));
return;
case bndregs:
if ((clear_bv & X86_XSTATE_BNDREGS))
regcache->raw_supply (regnum, zero);
else
regcache->raw_supply (regnum, XSAVE_BNDREGS_ADDR (tdep, regs, regnum));
return;
case sse:
if ((clear_bv & X86_XSTATE_SSE))
regcache->raw_supply (regnum, zero);
@ -1341,40 +1275,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
}
}
/* Handle the MPX registers. */
if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
{
if (clear_bv & X86_XSTATE_BNDREGS)
{
for (i = I387_BND0R_REGNUM (tdep);
i < I387_BNDCFGU_REGNUM (tdep); i++)
regcache->raw_supply (i, zero);
}
else
{
for (i = I387_BND0R_REGNUM (tdep);
i < I387_BNDCFGU_REGNUM (tdep); i++)
regcache->raw_supply (i, XSAVE_BNDREGS_ADDR (tdep, regs, i));
}
}
/* Handle the MPX registers. */
if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
{
if (clear_bv & X86_XSTATE_BNDCFG)
{
for (i = I387_BNDCFGU_REGNUM (tdep);
i < I387_MPXEND_REGNUM (tdep); i++)
regcache->raw_supply (i, zero);
}
else
{
for (i = I387_BNDCFGU_REGNUM (tdep);
i < I387_MPXEND_REGNUM (tdep); i++)
regcache->raw_supply (i, XSAVE_BNDCFG_ADDR (tdep, regs, i));
}
}
/* Handle the XMM registers. */
if ((tdep->xcr0 & X86_XSTATE_SSE))
{
@ -1527,16 +1427,14 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
x87 = 0x2,
sse = 0x4,
avxh = 0x8,
bndregs = 0x10,
bndcfg = 0x20,
avx512_k = 0x40,
avx512_zmm0_h = 0x80,
avx512_zmm16_h = 0x100,
avx512_ymmh_avx512 = 0x200,
avx512_xmm_avx512 = 0x400,
pkeys = 0x800,
all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
| avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
avx512_k = 0x10,
avx512_zmm0_h = 0x20,
avx512_zmm16_h = 0x40,
avx512_ymmh_avx512 = 0x80,
avx512_xmm_avx512 = 0x100,
pkeys = 0x200,
all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h
| avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
} regclass;
gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
@ -1565,12 +1463,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
else if (regnum >= I387_BND0R_REGNUM (tdep)
&& regnum < I387_BNDCFGU_REGNUM (tdep))
regclass = bndregs;
else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
&& regnum < I387_MPXEND_REGNUM (tdep))
regclass = bndcfg;
else if (regnum >= I387_XMM0_REGNUM (tdep)
&& regnum < I387_MXCSR_REGNUM (tdep))
regclass = sse;
@ -1619,16 +1511,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
i < I387_PKEYSEND_REGNUM (tdep); i++)
memset (XSAVE_PKEYS_ADDR (tdep, regs, i), 0, 4);
if ((clear_bv & X86_XSTATE_BNDREGS))
for (i = I387_BND0R_REGNUM (tdep);
i < I387_BNDCFGU_REGNUM (tdep); i++)
memset (XSAVE_BNDREGS_ADDR (tdep, regs, i), 0, 16);
if ((clear_bv & X86_XSTATE_BNDCFG))
for (i = I387_BNDCFGU_REGNUM (tdep);
i < I387_MPXEND_REGNUM (tdep); i++)
memset (XSAVE_BNDCFG_ADDR (tdep, regs, i), 0, 8);
if ((clear_bv & X86_XSTATE_ZMM_H))
for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
memset (XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i), 0, 32);
@ -1771,34 +1653,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
}
}
/* Check if any upper MPX registers are changed. */
if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
for (i = I387_BND0R_REGNUM (tdep);
i < I387_BNDCFGU_REGNUM (tdep); i++)
{
regcache->raw_collect (i, raw);
p = XSAVE_BNDREGS_ADDR (tdep, regs, i);
if (memcmp (raw, p, 16))
{
xstate_bv |= X86_XSTATE_BNDREGS;
memcpy (p, raw, 16);
}
}
/* Check if any upper MPX registers are changed. */
if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
for (i = I387_BNDCFGU_REGNUM (tdep);
i < I387_MPXEND_REGNUM (tdep); i++)
{
regcache->raw_collect (i, raw);
p = XSAVE_BNDCFG_ADDR (tdep, regs, i);
if (memcmp (raw, p, 8))
{
xstate_bv |= X86_XSTATE_BNDCFG;
memcpy (p, raw, 8);
}
}
/* Check if any upper YMM registers are changed. */
if ((tdep->xcr0 & X86_XSTATE_AVX))
for (i = I387_YMM0H_REGNUM (tdep);
@ -1940,22 +1794,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
}
break;
case bndregs:
regcache->raw_collect (regnum, raw);
p = XSAVE_BNDREGS_ADDR (tdep, regs, regnum);
if (memcmp (raw, p, 16))
{
xstate_bv |= X86_XSTATE_BNDREGS;
memcpy (p, raw, 16);
}
break;
case bndcfg:
p = XSAVE_BNDCFG_ADDR (tdep, regs, regnum);
xstate_bv |= X86_XSTATE_BNDCFG;
memcpy (p, raw, 8);
break;
case sse:
/* This is an SSE register. */
p = FXSAVE_ADDR (tdep, regs, regnum);
@ -2143,20 +1981,3 @@ i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
}
/* See i387-tdep.h. */
void
i387_reset_bnd_regs (struct gdbarch *gdbarch, struct regcache *regcache)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (I387_BND0R_REGNUM (tdep) > 0)
{
gdb_byte bnd_buf[16];
memset (bnd_buf, 0, 16);
for (int i = 0; i < I387_NUM_BND_REGS; i++)
regcache->raw_write (I387_BND0R_REGNUM (tdep) + i, bnd_buf);
}
}

View File

@ -37,13 +37,7 @@ struct x86_xsave_layout;
#define I387_NUM_YMM_REGS(tdep) ((tdep)->num_ymm_regs)
#define I387_YMM0H_REGNUM(tdep) ((tdep)->ymm0h_regnum)
#define I387_BND0R_REGNUM(tdep) ((tdep)->bnd0r_regnum)
#define I387_BNDCFGU_REGNUM(tdep) ((tdep)->bndcfgu_regnum)
/* Set of constants used for 32 and 64-bit. */
#define I387_NUM_MPX_REGS 6
#define I387_NUM_BND_REGS 4
#define I387_NUM_MPX_CTRL_REGS 2
#define I387_NUM_K_REGS 8
#define I387_NUM_PKEYS_REGS 1
@ -71,8 +65,6 @@ struct x86_xsave_layout;
#define I387_YMMENDH_REGNUM(tdep) \
(I387_YMM0H_REGNUM (tdep) + I387_NUM_YMM_REGS (tdep))
#define I387_MPXEND_REGNUM(tdep) \
(I387_BND0R_REGNUM (tdep) + I387_NUM_MPX_REGS)
#define I387_KEND_REGNUM(tdep) \
(I387_K0_REGNUM (tdep) + I387_NUM_K_REGS)
@ -181,8 +173,4 @@ extern ULONGEST i387_xsave_get_clear_bv (struct gdbarch *gdbarch,
extern void i387_return_value (struct gdbarch *gdbarch,
struct regcache *regcache);
/* Set all bnd registers to the INIT state. INIT state means
all memory range can be accessed. */
extern void i387_reset_bnd_regs (struct gdbarch *gdbarch,
struct regcache *regcache);
#endif /* i387-tdep.h */

View File

@ -106,12 +106,6 @@ x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
*xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
/ sizeof (uint64_t))];
#ifdef __x86_64__
/* No MPX on x32. */
if (is_64bit && is_x32)
*xcr0_storage &= ~X86_XSTATE_MPX;
#endif /* __x86_64__ */
*xsave_layout_storage
= x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ());
}

View File

@ -56,8 +56,6 @@ x86_fetch_xsave_layout (uint64_t xcr0, int len)
x86_xsave_layout layout;
layout.sizeof_xsave = len;
layout.avx_offset = xsave_feature_offset (xcr0, X86_XSTATE_AVX_ID);
layout.bndregs_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDREGS_ID);
layout.bndcfg_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDCFG_ID);
layout.k_offset = xsave_feature_offset (xcr0, X86_XSTATE_K_ID);
layout.zmm_h_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_H_ID);
layout.zmm_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_ID);

View File

@ -1,39 +0,0 @@
# Pretty-printers for bounds registers.
# Copyright (C) 2013-2024 Free Software Foundation, Inc.
# 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/>.
import gdb
import gdb.printing
class MpxBound128Printer(gdb.ValuePrinter):
"""Adds size field to a mpx __gdb_builtin_type_bound128 type."""
def __init__(self, val):
self.__val = val
def to_string(self):
upper = self.__val["ubound"]
lower = self.__val["lbound"]
size = upper - lower
if size > -1:
size = size + 1
result = "{lbound = %s, ubound = %s} : size %s" % (lower, upper, size)
return result
gdb.printing.add_builtin_pretty_printer(
"mpx_bound128", "^builtin_type_bound128", MpxBound128Printer
)

View File

@ -368,8 +368,6 @@ target_debug_print_x86_xsave_layout (const x86_xsave_layout &layout)
string_appendf (s, ", " #region "_offset=%d", layout.region##_offset);
POFFS(avx);
POFFS(bndregs);
POFFS(bndcfg);
POFFS(k);
POFFS(zmm_h);
POFFS(zmm);

View File

@ -1,105 +0,0 @@
/* Test for inferior function calls MPX context.
Copyright (C) 2017-2024 Free Software Foundation, Inc.
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 <stdlib.h>
#include <string.h>
/* Defined size for arrays. */
#define ARRAY_LENGTH 5
int
upper (int *a, int *b, int *c, int *d, int len)
{
int value;
value = *(a + len);
value = *(b + len);
value = *(c + len);
value = *(d + len);
value = value - *a + 1;
return value;
}
int
lower (int *a, int *b, int *c, int *d, int len)
{
int value;
value = *(a - len);
value = *(b - len);
value = *(c - len);
value = *(d - len);
value = value - *a + 1;
return value;
}
char
char_upper (char *str, int length)
{
char ch;
ch = *(str + length);
return ch;
}
char
char_lower (char *str, int length)
{
char ch;
ch = *(str - length);
return ch;
}
int
main (void)
{
int sa[ARRAY_LENGTH];
int sb[ARRAY_LENGTH];
int sc[ARRAY_LENGTH];
int sd[ARRAY_LENGTH];
int *x, *a, *b, *c, *d;
char mchar;
char hello[] = "Hello";
x = malloc (sizeof (int) * ARRAY_LENGTH);
a = malloc (sizeof (int) * ARRAY_LENGTH);
b = malloc (sizeof (int) * ARRAY_LENGTH);
c = malloc (sizeof (int) * ARRAY_LENGTH);
d = malloc (sizeof (int) * ARRAY_LENGTH);
*x = upper (sa, sb, sc, sd, 0); /* bkpt 1. */
*x = lower (a, b, c, d, 0);
mchar = char_upper (hello, 10);
mchar = char_lower (hello, 10);
free (x);
free (a);
free (b);
free (c);
free (d);
return 0;
}

View File

@ -1,398 +0,0 @@
# Copyright (C) 2017-2024 Free Software Foundation, Inc.
#
# 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/>.
require {is_any_target "i?86-*-*" "x86_64-*-*"}
standard_testfile
require supports_mpx_check_pointer_bounds have_mpx
set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat"
if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
[list debug additional_flags=${comp_flags}]] } {
return -1
}
if ![runto_main] {
return -1
}
set bounds_table 0
gdb_test_multiple "disassemble upper" "" {
-re -wrap "bndldx.*" {
set bounds_table 1
}
-re -wrap "" {
}
}
# Convenience for returning from an inferior call that causes a BND violation.
#
gdb_test_no_output "set confirm off"
# Convenience variable.
#
set bound_reg " = \\\{lbound = $hex, ubound = $hex\\\}.*"
set int_braw_reg " = \\\{lbound = 0x0, ubound_raw = 0x0\\\}.*"
set bndcfg_reg " = \\\{raw = $hex, config = \\\{base = $hex, reserved = $hex,\
preserved = $hex, enabled = $hex\\\}\\\}"
set bndstatus_reg " = \\\{raw = $hex, status = \\\{bde = $hex,\
error = $hex\\\}\\\}"
set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
"Upper bound violation while accessing address $hex" \
"Bounds: \\\[lower = $hex, upper = $hex\\\]"]
# Simplify the tests below.
#
proc sanity_check_bndregs {arglist} {
global int_braw_reg
foreach a $arglist {
gdb_test "p /x $a" "$int_braw_reg"\
"$a"
}
}
# Set bnd register to have no access to memory.
#
proc remove_memory_access {reg} {
global hex
sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"}
gdb_test "p /x $reg.lbound = $reg.ubound" "= $hex"\
"$reg lower bound set"
gdb_test "p /x $reg.ubound = 0" " = 0x0"\
"$reg upper bound set"
}
# Prepare convenience variables for bndconfig and status
# for posterior comparison.
#
proc prepare_bndcfg_bndstatus {} {
global bndcfg_reg
global bndstatus_reg
gdb_test "p /x \$temp_bndcfgu = \$bndcfgu" "$bndcfg_reg"\
"bndcfgu should not change"
gdb_test "p /x \$temp_bndstatus = \$bndstatus" "$bndstatus_reg"\
"bndstatus should not change"
}
# Compare values set for convenience variables and actual values of bndconfig
# and bndstatus registers.
#
proc compare_bndstatus_with_convenience {} {
gdb_test "p \$temp_bndcfgu == \$bndcfgu" "= 1"\
"bndcfgu compare before and after"
gdb_test "p \$temp_bndstatus == \$bndstatus" "= 1"\
"bndstatus compare before and after"
}
# Perform an inferior call defined in func.
#
proc perform_a_call {func} {
global inf_call_stopped
global gdb_prompt
gdb_test "p /x $func" [multi_line "The program being debugged\
stopped while in a function called from GDB." \
"Evaluation of the expression containing the\
function.*" \
] "inferior call stopped"
}
# Perform an inferior call defined in func.
#
proc check_bound_violation {parm parm_type is_positive} {
global u_fault bounds_table
set have_bnd_violation 0
gdb_test_multiple "continue" "continue to a bnd violation" {
-re -wrap "Continuing\." {
if { $bounds_table } {
pass $gdb_test_name
} else {
fail $gdb_test_name
}
}
-re -wrap "$u_fault.*" {
pass $gdb_test_name
set have_bnd_violation 1
}
}
if { ! $have_bnd_violation } {
return
}
set message "access only one position"
if {$is_positive == 1} {
gdb_test "p (((void *)\$_siginfo._sifields._sigfault.si_addr\
- (void*)$parm))/sizeof($parm_type) == 1"\
" = 1" $message
} else {
gdb_test "p ((void*)$parm\
- (void *)\$_siginfo._sifields._sigfault.si_addr)\
/sizeof($parm_type) == 1"\
" = 1" $message
}
gdb_test "return" "\\\#.*main.*i386-mpx-call\\\.c:.*" "return from the fault"
}
# Start testing!
#
# Set up for stopping in the middle of main for calling a function in the
# inferior.
#
set break "bkpt 1."
gdb_breakpoint [gdb_get_line_number "${break}"]
gdb_continue_to_breakpoint "${break}" ".*${break}.*"
# Consistency:
# default run execution of call should succeed without violations.
#
with_test_prefix "default_run" {
gdb_test "p \$keep_bnd0_value=\$bnd0" $bound_reg\
"store bnd0 register in a convenience variable"
gdb_test "p /x upper (a, b, c, d, 0)" " = $hex"\
"default inferior call"
gdb_test "p ((\$bnd0.lbound==\$keep_bnd0_value.lbound) &&\
(\$bnd0.ubound==\$keep_bnd0_value.ubound))" "= 1" \
"bnd register value after and before call"
}
# Consistency: Examine bnd registers values before and after the call.
#
#
with_test_prefix "verify_default_values" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*upper"
perform_a_call "upper (a, b, c, d, 1)"
sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"}
compare_bndstatus_with_convenience
gdb_test_multiple "continue" "inferior call test" {
-re ".*Continuing.\r\n$gdb_prompt " {
pass "inferior call performed"
}
}
}
# Examine: Cause an upper bound violation changing BND0.
#
#
with_test_prefix "upper_bnd0" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*upper"
perform_a_call "upper (a, b, c, d, 1)"
remove_memory_access "\$bnd0"
compare_bndstatus_with_convenience
check_bound_violation "a" "int" 1
}
# Examine: Cause an upper bound violation changing BND1.
#
#
with_test_prefix "upper_bnd1" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*upper"
perform_a_call "upper (a, b, c, d, 1)"
remove_memory_access "\$bnd1"
compare_bndstatus_with_convenience
check_bound_violation "b" "int" 1
}
# Examine: Cause an upper bound violation changing BND2.
#
#
with_test_prefix "upper_bnd2" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*upper"
perform_a_call "upper (a, b, c, d, 1)"
remove_memory_access "\$bnd2"
compare_bndstatus_with_convenience
check_bound_violation "c" "int" 1
}
# Examine: Cause an upper bound violation changing BND3.
#
#
with_test_prefix "upper_bnd3" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*upper"
perform_a_call "upper (a, b, c, d, 1)"
remove_memory_access "\$bnd3"
compare_bndstatus_with_convenience
check_bound_violation "d" "int" 1
}
# Examine: Cause a lower bound violation changing BND0.
#
#
with_test_prefix "lower_bnd0" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*lower"
perform_a_call "lower (a, b, c, d, 1)"
remove_memory_access "\$bnd0"
compare_bndstatus_with_convenience
check_bound_violation "a" "int" 0
}
# Examine: Cause a lower bound violation changing BND1.
#
#
with_test_prefix "lower_bnd1" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*lower"
perform_a_call "lower (a, b, c, d, 1)"
remove_memory_access "\$bnd1"
compare_bndstatus_with_convenience
check_bound_violation "b" "int" 0
}
# Examine: Cause a lower bound violation changing BND2.
#
#
with_test_prefix "lower_bnd2" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*lower"
perform_a_call "lower (a, b, c, d, 1)"
remove_memory_access "\$bnd2"
compare_bndstatus_with_convenience
check_bound_violation "c" "int" 0
}
# Examine: Cause a lower bound violation changing BND3.
#
#
with_test_prefix "lower_bnd3" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*lower"
perform_a_call "lower (a, b, c, d, 1)"
remove_memory_access "\$bnd3"
compare_bndstatus_with_convenience
check_bound_violation "d" "int" 0
}
# Examine: String causing a upper bound violation changing BND0.
#
#
with_test_prefix "chars_up" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*char_upper"
perform_a_call "char_upper (hello, 1)"
remove_memory_access "\$bnd0"
compare_bndstatus_with_convenience
check_bound_violation "str" "char" 1
}
# Examine: String causing an lower bound violation changing BND0.
#
#
with_test_prefix "chars_low" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*char_lower"
perform_a_call "char_lower (hello, 1)"
remove_memory_access "\$bnd0"
compare_bndstatus_with_convenience
check_bound_violation "str" "char" 0
}
# Examine: String causing an lower bound violation changing BND0.
#
#
with_test_prefix "chars_low_adhoc_parm" {
prepare_bndcfg_bndstatus
gdb_breakpoint "*char_lower"
perform_a_call "char_lower (\"tryme\", 1)"
remove_memory_access "\$bnd0"
compare_bndstatus_with_convenience
check_bound_violation "str" "char" 0
}

View File

@ -1,61 +0,0 @@
/* Test program for MPX map allocated bounds.
Copyright 2015-2024 Free Software Foundation, Inc.
Contributed by Intel Corp. <walfred.tedeschi@intel.com>
<mircea.gherzan@intel.com>
This file is part of GDB.
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 <stdlib.h>
#define SIZE 5
typedef int T;
void
foo (T *p)
{
T *x;
#if defined __GNUC__ && !defined __INTEL_COMPILER
__bnd_store_ptr_bounds (p, &p);
#endif
x = p + SIZE - 1;
#if defined __GNUC__ && !defined __INTEL_COMPILER
__bnd_store_ptr_bounds (x, &x);
#endif
/* Dummy assign. */
x = x + 1; /* after-assign */
return;
}
int
main (void)
{
T *a = NULL;
a = calloc (SIZE, sizeof (T)); /* after-decl */
#if defined __GNUC__ && !defined __INTEL_COMPILER
__bnd_store_ptr_bounds (a, &a);
#endif
foo (a); /* after-alloc */
free (a);
return 0;
}

View File

@ -1,56 +0,0 @@
# Copyright 2015-2024 Free Software Foundation, Inc.
#
# Contributed by Intel Corp. <walfred.tedeschi@intel.com>,
# <mircea.gherzan@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/>.
require {is_any_target i?86-*-* x86_64-*-*}
standard_testfile
require supports_mpx_check_pointer_bounds have_mpx
set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
[list debug nowarnings additional_flags=${comp_flags}]] } {
return -1
}
if ![runto_main] {
return -1
}
gdb_breakpoint [ gdb_get_line_number "after-decl" ]
gdb_breakpoint [ gdb_get_line_number "after-alloc" ]
gdb_breakpoint [ gdb_get_line_number "after-assign" ]
gdb_test "show mpx bound 0x0" "Invalid bounds directory entry at $hex." "NULL address of the pointer"
gdb_continue_to_breakpoint "after-decl" ".*after-decl.*"
gdb_test "show mpx bound a" "Invalid bounds directory entry at $hex." "pointer instead of pointer address"
gdb_continue_to_breakpoint "after-alloc" ".*after-alloc.*"
gdb_test "show mpx bound a" "\\\{lbound = $hex, ubound = $hex\\\}: pointer value = $hex, size = \[8, 4\], metadata = 0x0+" "pointer after allocation"
gdb_continue_to_breakpoint "after-assign" ".*after-assign.*"
gdb_test "show mpx bound x" "\\\{lbound = $hex, ubound = $hex\\\}: pointer value = $hex, size = \[8, 4\], metadata = 0x0+" "pointer after assignment"
gdb_test "set mpx bound 0x0, 0x1, 0x2" "Invalid bounds directory entry at $hex." "set mpx bound: NULL address of the pointer"
gdb_test_no_output "set mpx bound x, 0xcafebabe, 0xdeadbeef" "set mpx bound: set bounds for a valid pointer address"
gdb_test "show mpx bound x" "\\\{lbound = .*cafebabe, ubound = .*deadbeef\\\}: pointer value = $hex, size = $decimal, metadata = 0x0+" "set mpx bound: bounds map entry after set mpx bound"
gdb_test "set mpx bound 0x0, 0x1 0x2" "A syntax error in expression.*" "set mpx bound: Controlling syntax error, missing comma "
gdb_test "set mpx bound 0x0, 0x1" "Wrong number of arguments.*" "set mpx bound: Controlling syntax error, missing argument "

View File

@ -1,92 +0,0 @@
/* Copyright (C) 2015-2024 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/>. */
#define OUR_SIZE 5
int gx[OUR_SIZE];
int ga[OUR_SIZE];
int gb[OUR_SIZE];
int gc[OUR_SIZE];
int gd[OUR_SIZE];
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 = *(p + len);
value = *(a + len);
value = *(b + len);
value = *(c + len);
value = *(d + len);
}
void
lower (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);
bp2 (value);
value = *(d - len);
}
int
main (void)
{
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 (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;
}

View File

@ -1,64 +0,0 @@
# Copyright (C) 2015-2024 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/>.
require {is_any_target "i?86-*-*" "x86_64-*-*"}
standard_testfile
require supports_mpx_check_pointer_bounds have_mpx
set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
[list debug nowarnings additional_flags=${comp_flags}]] } {
return -1
}
if ![runto_main] {
return -1
}
set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
"Upper bound violation while accessing address $hex" \
"Bounds: \\\[lower = $hex, upper = $hex\\\]"]
set l_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
"Lower bound violation while accessing address $hex" \
"Bounds: \\\[lower = $hex, upper = $hex\\\]"]
for {set i 0} {$i < 15} {incr i} {
set message "MPX signal segv Upper: ${i}"
if {[gdb_test "continue" "$u_fault.*" $message] != 0} {
break
}
gdb_test "where" ".*#0 $hex in upper.*"\
"$message: should be in upper"
}
for {set i 0} {$i < 15} {incr i} {
set message "MPX signal segv Lower: ${i}"
if {[gdb_test "continue" "$l_fault.*" $message] != 0} {
break
}
gdb_test "where" ".*#0 $hex in lower.*"\
"$message: should be in lower"
}

View File

@ -1,36 +0,0 @@
/* Copyright (C) 2015-2024 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/>. */
#define OUR_SIZE 5
void
upper (int * p, int len)
{
int value;
len++; /* b0-size-test. */
value = *(p + len);
}
int
main (void)
{
int a = 0; /* Dummy variable for debugging purposes. */
int sx[OUR_SIZE];
a++; /* register-eval. */
upper (sx, OUR_SIZE + 2);
return sx[1];
}

View File

@ -1,124 +0,0 @@
# Copyright (C) 2015-2024 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/>.
# Testing handle setup together with boundary violation signals.
#
# Some states are not allowed as reported on the manual, as noprint
# implies nostop, but nostop might print.
#
# Caveat: Setting the handle to nopass, ends up in a endless loop.
require {is_any_target i?86-*-* x86_64-*-*}
standard_testfile
require supports_mpx_check_pointer_bounds have_mpx
set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
[list debug nowarnings additional_flags=${comp_flags}]] } {
return -1
}
if ![runto_main] {
return -1
}
set violation [multi_line "Program received signal SIGSEGV, Segmentation fault" \
"Upper bound violation while accessing address $hex" \
"Bounds: \\\[lower = $hex, upper = $hex\\\]"]
set segv_with_exit "Program received signal SIGSEGV,\
Segmentation fault.*$inferior_exited_re.*"
# Test handler for segmentation fault for:
# print pass stop
#
set parameters "print pass stop"
with_test_prefix "$parameters" {
if ![runto_main] {
return -1
}
gdb_test "handle SIGSEGV $parameters"\
".*SIGSEGV.*Yes.*Yes.*Yes.*Segmentation fault.*"\
"set parameters"
gdb_test "continue" ".*$violation.*" "display"
gdb_test "where" ".*#0 $hex in upper.*"\
"should be in upper"
}
# Test handler for segmentation fault for:
# print pass nostop
#
set parameters "print pass nostop"
with_test_prefix "$parameters" {
if ![runto_main] {
return -1
}
gdb_test "handle SIGSEGV $parameters"\
".*SIGSEGV.*No.*Yes.*Yes.*Segmentation fault.*"\
"set parameters"
gdb_test "continue" ".*$segv_with_exit.*" "display"
gdb_test "where" "No stack." "no inferior"
}
# Test handler for segmentation fault for:
# print nopass stop
#
set parameters "print nopass stop"
with_test_prefix "$parameters" {
if ![runto_main] {
return -1
}
gdb_test "handle SIGSEGV $parameters"\
".*SIGSEGV.*Yes.*Yes.*No.*Segmentation fault.*"\
"set parameters"
gdb_test "continue" ".*$violation.*" "display"
gdb_test "where" ".*#0 $hex in upper.*"\
"should be in upper"
}
# Test handler for segmentation fault for:
# print nopass stop
#
set parameters "noprint pass nostop"
with_test_prefix "$parameters" {
if ![runto_main] {
return -1
}
gdb_test "handle SIGSEGV $parameters"\
".*SIGSEGV.*No.*No.*Yes.*Segmentation fault.*"\
"set parameters"
gdb_test "continue" "Continuing\..*$inferior_exited_re.*"\
"Display"
gdb_test "where" "No stack." "no inferior"
}

View File

@ -1,59 +0,0 @@
/* Test program for MPX registers.
Copyright 2013-2024 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
int
main (void)
{
#ifdef __x86_64__
asm ("mov $10, %rax\n\t"
"mov $9, %rdx\n\t"
"bndmk (%rax,%rdx), %bnd0\n\t"
"mov $20, %rax\n\t"
"mov $9, %rdx\n\t"
"bndmk (%rax,%rdx), %bnd1\n\t"
"mov $30, %rax\n\t"
"mov $9, %rdx\n\t"
"bndmk (%rax,%rdx), %bnd2\n\t"
"mov $40, %rax\n\t"
"mov $9, %rdx\n\t"
"bndmk (%rax,%rdx), %bnd3\n\t"
"bndstx %bnd3, (%rax) \n\t"
"nop\n\t"
);
#else
asm ("mov $10, %eax\n\t"
"mov $9, %edx\n\t"
"bndmk (%eax,%edx), %bnd0\n\t"
"mov $20, %eax\n\t"
"mov $9, %edx\n\t"
"bndmk (%eax,%edx), %bnd1\n\t"
"mov $30, %eax\n\t"
"mov $9, %edx\n\t"
"bndmk (%eax,%edx), %bnd2\n\t"
"mov $40, %eax\n\t"
"mov $9, %edx\n\t"
"bndmk (%eax,%edx), %bnd3\n\t"
"bndstx %bnd3, (%eax)\n\t"
"nop\n\t"
);
#endif
asm ("nop\n\t"); /* break here. */
return 0;
}

View File

@ -1,123 +0,0 @@
# Copyright 2013-2024 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/>.
require {is_any_target i?86-*-* x86_64-*-*}
standard_testfile
require {is_any_target i?86-*-* x86_64-*-*}
require supports_mpx_check_pointer_bounds have_mpx
set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
[list debug nowarnings additional_flags=${comp_flags}]] } {
return -1
}
if ![runto_main] {
return -1
}
# Test bndcfg register and bndstatus at startup
set test_string "\\\{raw = 0x\[0-9a-f\]+, config = \\\{base = \[0-9\]+,\
reserved = \[0-9\]+, preserved = \[0-9\]+, enabled = \[0-9\]+\\\}\\\}"
gdb_test "print \$bndcfgu" $test_string "bndcfgu formating"
gdb_test "print \$bndcfgu.config.enabled" "= 1" "test if bndstatus is enabled"
gdb_test "print \$bndstatus" "\\\{raw = 0x0, status = \\\{bde = 0, error = 0\\\}\\\}" \
"bndstatus formating"
gdb_test "print \$bndstatus.raw" "= \\\(void \\\*\\\) 0x0" "bndstatus is zero by startup"
# Read values from pseudo registers.
gdb_breakpoint [ gdb_get_line_number "break here" ]
gdb_continue_to_breakpoint "break here" ".*break here.*"
set test_string ".*\\\{lbound = 0xa, ubound = 0x13\\\}.*"
gdb_test "info register bnd0" ".*bnd0$test_string" "pure bnd0 register"
set test_string ".*\\\{lbound = 0x14, ubound = 0x1d\\\}.*"
gdb_test "info register bnd1" ".*bnd1$test_string" "pure bnd1 register"
set test_string ".*\\\{lbound = 0x1e, ubound = 0x27\\\}.*"
gdb_test "info register bnd2" ".*bnd2$test_string" "pure bnd2 register"
set test_string ".*\\\{lbound = 0x28, ubound = 0x31\\\}.*"
gdb_test "info register bnd3" ".*bnd3$test_string" "pure bnd3 register"
# Read value from registers bndrs.
set test_string ".*\\\{lbound = 0xa, ubound_raw = 0x\[f\]+ec\\\}.*"
gdb_test "info register bnd0raw" ".*bnd0$test_string" "pure bnd0r register"
set test_string ".*\\\{lbound = 0x14, ubound_raw = 0x\[f\]+e2\\\}.*"
gdb_test "info register bnd1raw" ".*bnd1$test_string" "pure bnd1r register"
set test_string ".*\\\{lbound = 0x1e, ubound_raw = 0x\[f\]+d8\\\}.*"
gdb_test "info register bnd2raw" ".*bnd2$test_string" "pure bnd2r register"
set test_string ".*\\\{lbound = 0x28, ubound_raw = 0x\[f\]+ce\\\}.*"
gdb_test "info register bnd3raw" ".*bnd3$test_string" "pure bnd3r register"
# Setting fields on bnds
set test_string ".*\\\{lbound = 0xa, ubound = 0x400\\\}.*"
gdb_test "print \$bnd0.ubound = 0x400" "= \\\(void \\\*\\\) 0x400" "set value for bnd0.ubound"
gdb_test "print \$bnd0" "$test_string" "after setting bnd0.ubound"
set test_string ".*\\\{lbound = 0xa, ubound_raw = 0x\[f\]+bff\\\}.*"
gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after set bnd0.ubound"
set test_string ".*\\\{lbound = 0x1, ubound = 0x400\\\}.*"
gdb_test "print \$bnd0.lbound = 0x1" "= \\\(void \\\*\\\) 0x1" "set value for bnd0.lbound"
gdb_test "print \$bnd0" "$test_string" "after setting bnd0.lbound"
set test_string ".*\\\{lbound = 0x1, ubound_raw = 0x\[f\]+bff\\\}.*"
gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after set bnd0.lbound"
# Setting fields on bnd0raw.
set test_string ".*\\\{lbound = 0x1, ubound_raw = 0x600\\\}.*"
gdb_test "print /x \$bnd0raw.ubound_raw = 0x600" "= 0x600" "set value for bnd0raw.ubound"
gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting bnd0raw.ubound"
set test_string ".*\\\{lbound = 0x1, ubound = 0x\[f\]+9ff\\\}.*"
gdb_test "print /x \$bnd0" "$test_string" "bnd0 after set bnd0raw.ubound"
set test_string ".*\\\{lbound = 0x100, ubound_raw = 0x600\\\}.*"
gdb_test "print /x \$bnd0raw.lbound = 0x100" "= 0x100" "set value for bnd0raw.lbound"
gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting bnd0raw.lbound"
set test_string ".*\\\{lbound = 0x100, ubound = 0x\[f\]+9ff\\\}.*"
gdb_test "print /x \$bnd0" "$test_string" "bnd0 after set bnd0raw.lbound"
# Set full value bnd raw
set test_string ".*\\\{lbound = 0x10, ubound_raw = 0x\[f\]+cff\\\}.*"
gdb_test "print /x \$bnd0raw = {0x10, ~0x300}" "$test_string" "set full value for bnd0raw"
set test_string ".*\\\{lbound = 0x10, ubound = 0x300\\\}.*"
gdb_test "print /x \$bnd0" "$test_string" "bnd0raw after setting full bnd0raw"
# Set full value bnd
set test_string ".*\\\{lbound = 0x10, ubound = 0x300\\\}.*"
gdb_test "print /x \$bnd0 = {0x10, 0x300}" "$test_string" "set full value for bnd0"
set test_string ".*\\\{lbound = 0x10, ubound_raw = 0x\[f\]+cff\\\}.*"
gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting full bnd0"
# Test bndcfg register and bndstatus after a failure on bndstr
gdb_test "print \$bndstatus.status.error" "= 2" "bndstatus error is 2\
after a failure on allocating an entry"
# Going to test the python extension for lenght.
if { ![allow_python_tests] } { continue }
# Verify if size is right
set test_string ".*\\\: size 0x11.*"
gdb_test "print /x \$bnd0 = {0x10, 0x20}" "$test_string" "verify size for bnd0"

View File

@ -55,7 +55,7 @@ gdb_test "print flt" " = x=<42> y=<43>" \
gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" \
"print ss enabled #1"
set num_pp 7
set num_pp 6
gdb_test "disable pretty-printer" \
"$num_pp printers disabled.*0 of $num_pp printers enabled"
@ -75,7 +75,7 @@ gdb_test "disable pretty-printer global lookup_function_lookup_test" \
"1 printer disabled.*[expr $num_pp - 1] of $num_pp printers enabled"
gdb_test "disable pretty-printer global pp-test;.*" \
"[expr $num_pp - 2] printers disabled.*1 of $num_pp printers enabled"
"[expr 5] printers disabled.*0 of $num_pp printers enabled"
gdb_test "info pretty-printer global .*function" \
{.*function_lookup_test \[disabled\].*} \
@ -92,13 +92,13 @@ gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \
"print ss disabled"
gdb_test "enable pretty-printer global lookup_function_lookup_test" \
"1 printer enabled.*2 of $num_pp printers enabled"
"1 printer enabled.*1 of $num_pp printers enabled"
# This doesn't enable any printers because each subprinter in the collection
# is still individually disabled. But this is still needed, to enable the
# collection itself.
gdb_test "enable pretty-printer global pp-test" \
"0 printers enabled.*2 of $num_pp printers enabled"
"0 printers enabled.*1 of $num_pp printers enabled"
gdb_test "enable pretty-printer global pp-test;.*ss.*" \
"2 printers enabled.*[expr $num_pp - 3] of $num_pp printers enabled"

View File

@ -9815,18 +9815,6 @@ gdb_caching_proc supports_statement_frontiers {} {
} executable "additional_flags=-gstatement-frontiers"]
}
# Return 1 if compiler supports -mmpx -fcheck-pointer-bounds. Otherwise,
# return 0.
gdb_caching_proc supports_mpx_check_pointer_bounds {} {
set flags "additional_flags=-mmpx additional_flags=-fcheck-pointer-bounds"
return [gdb_can_simple_compile supports_mpx_check_pointer_bounds {
int main () {
return 0;
}
} executable $flags]
}
# Return 1 if compiler supports -fcf-protection=. Otherwise,
# return 0.
@ -10255,83 +10243,6 @@ gdb_caching_proc supports_gnuc {} {
return [gdb_simple_compile $me $src object ""]
}
# Return 1 if target supports mpx, otherwise return 0.
gdb_caching_proc have_mpx {} {
global srcdir
set me "have_mpx"
if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
verbose "$me: target does not support mpx, returning 0" 2
return 0
}
# Compile a test program.
set src {
#include "nat/x86-cpuid.h"
int main() {
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, (void *)0) < 7)
return 0;
__cpuid_count (7, 0, eax, ebx, ecx, edx);
if ((ebx & bit_MPX) == bit_MPX)
return 1;
}
return 0;
}
}
set compile_flags "incdir=${srcdir}/.."
if {![gdb_simple_compile $me $src executable $compile_flags]} {
return 0
}
set target_obj [gdb_remote_download target $obj]
set result [remote_exec target $target_obj]
set status [lindex $result 0]
set output [lindex $result 1]
if { $output != "" } {
set status 0
}
remote_file build delete $obj
if { $status == 0 } {
verbose "$me: returning $status" 2
return $status
}
# Compile program with -mmpx -fcheck-pointer-bounds, try to trigger
# 'No MPX support', in other words, see if kernel supports mpx.
set src { int main (void) { return 0; } }
set comp_flags {}
append comp_flags " additional_flags=-mmpx"
append comp_flags " additional_flags=-fcheck-pointer-bounds"
if {![gdb_simple_compile $me-2 $src executable $comp_flags]} {
return 0
}
set target_obj [gdb_remote_download target $obj]
set result [remote_exec target $target_obj]
set status [lindex $result 0]
set output [lindex $result 1]
set status [expr ($status == 0) \
&& ![regexp "^No MPX support\r?\n" $output]]
remote_file build delete $obj
verbose "$me: returning $status" 2
return $status
}
# Return 1 if target supports avx, otherwise return 0.
gdb_caching_proc have_avx {} {
global srcdir

View File

@ -23,8 +23,6 @@
/* Default to SSE. */
static uint64_t x86_xcr0 = X86_XSTATE_SSE_MASK;
static const int num_mpx_bnd_registers = 4;
static const int num_mpx_cfg_registers = 2;
static const int num_avx512_k_registers = 8;
static const int num_pkeys_registers = 1;
@ -118,15 +116,6 @@ public:
unsigned char *ymmh_space ()
{ return xsave () + xsave_layout.avx_offset; }
/* Memory address of 4 bound registers values of 128 bits. */
unsigned char *bndregs_space ()
{ return xsave () + xsave_layout.bndregs_offset; }
/* Memory address of 2 MPX configuration registers of 64 bits
plus reserved space. */
unsigned char *bndcfg_space ()
{ return xsave () + xsave_layout.bndcfg_offset; }
/* Memory address of 8 OpMask register values of 64 bits. */
unsigned char *k_space ()
{ return xsave () + xsave_layout.k_offset; }
@ -308,14 +297,6 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
memset (((char *) &fp->mxcsr), 0, 4);
if ((clear_bv & X86_XSTATE_BNDREGS))
for (i = 0; i < num_mpx_bnd_registers; i++)
memset (fp->bndregs_space () + i * 16, 0, 16);
if ((clear_bv & X86_XSTATE_BNDCFG))
for (i = 0; i < num_mpx_cfg_registers; i++)
memset (fp->bndcfg_space () + i * 8, 0, 8);
if ((clear_bv & X86_XSTATE_K))
for (i = 0; i < num_avx512_k_registers; i++)
memset (fp->k_space () + i * 8, 0, 8);
@ -384,40 +365,6 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
}
}
/* Check if any bound register has changed. */
if ((x86_xcr0 & X86_XSTATE_BNDREGS))
{
int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
for (i = 0; i < num_mpx_bnd_registers; i++)
{
collect_register (regcache, i + bnd0r_regnum, raw);
p = fp->bndregs_space () + i * 16;
if (memcmp (raw, p, 16))
{
xstate_bv |= X86_XSTATE_BNDREGS;
memcpy (p, raw, 16);
}
}
}
/* Check if any status register has changed. */
if ((x86_xcr0 & X86_XSTATE_BNDCFG))
{
int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
for (i = 0; i < num_mpx_cfg_registers; i++)
{
collect_register (regcache, i + bndcfg_regnum, raw);
p = fp->bndcfg_space () + i * 8;
if (memcmp (raw, p, 8))
{
xstate_bv |= X86_XSTATE_BNDCFG;
memcpy (p, raw, 8);
}
}
}
/* Check if any K registers are changed. */
if ((x86_xcr0 & X86_XSTATE_K))
{
@ -765,42 +712,6 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
}
}
if ((x86_xcr0 & X86_XSTATE_BNDREGS))
{
int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
if ((clear_bv & X86_XSTATE_BNDREGS) != 0)
{
for (i = 0; i < num_mpx_bnd_registers; i++)
supply_register_zeroed (regcache, i + bnd0r_regnum);
}
else
{
p = fp->bndregs_space ();
for (i = 0; i < num_mpx_bnd_registers; i++)
supply_register (regcache, i + bnd0r_regnum, p + i * 16);
}
}
if ((x86_xcr0 & X86_XSTATE_BNDCFG))
{
int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
if ((clear_bv & X86_XSTATE_BNDCFG) != 0)
{
for (i = 0; i < num_mpx_cfg_registers; i++)
supply_register_zeroed (regcache, i + bndcfg_regnum);
}
else
{
p = fp->bndcfg_space ();
for (i = 0; i < num_mpx_cfg_registers; i++)
supply_register (regcache, i + bndcfg_regnum, p + i * 8);
}
}
if ((x86_xcr0 & X86_XSTATE_K) != 0)
{
int k0_regnum = find_regno (regcache->tdesc, "k0");

View File

@ -240,6 +240,8 @@ static const int x86_64_regmap[] =
-1, -1, -1, -1, -1, -1, -1, -1,
ORIG_RAX * 8,
21 * 8, 22 * 8,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbs. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* xmm16 ... xmm31 (AVX512) */

View File

@ -63,6 +63,8 @@ enum netbsd_x86_64_gdb_regnum
AMD64_MXCSR_REGNUM = AMD64_XMM0_REGNUM + 16,
AMD64_YMM0H_REGNUM, /* %ymm0h */
AMD64_YMM15H_REGNUM = AMD64_YMM0H_REGNUM + 15,
/* MPX is deprecated. Yet we keep this to not give the registers below
a new number. That could break older gdbservers. */
AMD64_BND0R_REGNUM = AMD64_YMM15H_REGNUM + 1,
AMD64_BND3R_REGNUM = AMD64_BND0R_REGNUM + 3,
AMD64_BNDCFGU_REGNUM,

View File

@ -24,8 +24,6 @@
#define X86_XSTATE_X87_ID 0
#define X86_XSTATE_SSE_ID 1
#define X86_XSTATE_AVX_ID 2
#define X86_XSTATE_BNDREGS_ID 3
#define X86_XSTATE_BNDCFG_ID 4
#define X86_XSTATE_K_ID 5
#define X86_XSTATE_ZMM_H_ID 6
#define X86_XSTATE_ZMM_ID 7
@ -35,9 +33,6 @@
#define X86_XSTATE_X87 (1ULL << X86_XSTATE_X87_ID)
#define X86_XSTATE_SSE (1ULL << X86_XSTATE_SSE_ID)
#define X86_XSTATE_AVX (1ULL << X86_XSTATE_AVX_ID)
#define X86_XSTATE_BNDREGS (1ULL << X86_XSTATE_BNDREGS_ID)
#define X86_XSTATE_BNDCFG (1ULL << X86_XSTATE_BNDCFG_ID)
#define X86_XSTATE_MPX (X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
/* AVX 512 adds three feature bits. All three must be enabled. */
#define X86_XSTATE_K (1ULL << X86_XSTATE_K_ID)
@ -56,8 +51,6 @@ struct x86_xsave_layout
{
int sizeof_xsave = 0;
int avx_offset = 0;
int bndregs_offset = 0;
int bndcfg_offset = 0;
int k_offset = 0;
int zmm_h_offset = 0;
int zmm_offset = 0;
@ -69,8 +62,6 @@ constexpr bool operator== (const x86_xsave_layout &lhs,
{
return lhs.sizeof_xsave == rhs.sizeof_xsave
&& lhs.avx_offset == rhs.avx_offset
&& lhs.bndregs_offset == rhs.bndregs_offset
&& lhs.bndcfg_offset == rhs.bndcfg_offset
&& lhs.k_offset == rhs.k_offset
&& lhs.zmm_h_offset == rhs.zmm_h_offset
&& lhs.zmm_offset == rhs.zmm_offset
@ -88,21 +79,17 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
#define X86_XSTATE_X87_MASK X86_XSTATE_X87
#define X86_XSTATE_SSE_MASK (X86_XSTATE_X87 | X86_XSTATE_SSE)
#define X86_XSTATE_AVX_MASK (X86_XSTATE_SSE_MASK | X86_XSTATE_AVX)
#define X86_XSTATE_MPX_MASK (X86_XSTATE_SSE_MASK | X86_XSTATE_MPX)
#define X86_XSTATE_AVX_MPX_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_MPX)
#define X86_XSTATE_AVX_AVX512_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_AVX512)
#define X86_XSTATE_AVX_MPX_AVX512_PKU_MASK (X86_XSTATE_AVX_MPX_MASK\
#define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\
| X86_XSTATE_AVX512 | X86_XSTATE_PKRU)
#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_MPX_AVX512_PKU_MASK)
#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK)
#define X86_XSTATE_SSE_SIZE 576
#define X86_XSTATE_AVX_SIZE 832
/* In case one of the MPX XCR0 bits is set we consider we have MPX. */
#define HAS_MPX(XCR0) (((XCR0) & X86_XSTATE_MPX) != 0)
#define HAS_AVX(XCR0) (((XCR0) & X86_XSTATE_AVX) != 0)
#define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0)
#define HAS_PKRU(XCR0) (((XCR0) & X86_XSTATE_PKRU) != 0)