mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 01:53:38 +08:00
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:
parent
ee06c79b0f
commit
fc14343205
7
gdb/NEWS
7
gdb/NEWS
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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 =
|
||||
|
@ -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}.
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
@ -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>
|
@ -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;
|
||||
}
|
@ -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>
|
@ -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 ();
|
||||
|
@ -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 */
|
||||
|
509
gdb/i386-tdep.c
509
gdb/i386-tdep.c
@ -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);
|
||||
|
||||
|
@ -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 *);
|
||||
|
219
gdb/i387-tdep.c
219
gdb/i387-tdep.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 ());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
)
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 "
|
@ -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;
|
||||
}
|
@ -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"
|
||||
}
|
@ -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];
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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"
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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) */
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user