diff options
Diffstat (limited to 'gdbserver')
-rwxr-xr-x | gdbserver/configure | 225 | ||||
-rw-r--r-- | gdbserver/configure.ac | 2 | ||||
-rw-r--r-- | gdbserver/gdbreplay.cc | 2 | ||||
-rw-r--r-- | gdbserver/i387-fp.cc | 40 | ||||
-rw-r--r-- | gdbserver/linux-aarch64-low.cc | 46 | ||||
-rw-r--r-- | gdbserver/linux-amd64-ipa.cc | 10 | ||||
-rw-r--r-- | gdbserver/linux-i386-ipa.cc | 6 | ||||
-rw-r--r-- | gdbserver/linux-low.cc | 50 | ||||
-rw-r--r-- | gdbserver/linux-low.h | 7 | ||||
-rw-r--r-- | gdbserver/linux-x86-low.cc | 44 | ||||
-rw-r--r-- | gdbserver/server.cc | 2 |
11 files changed, 156 insertions, 278 deletions
diff --git a/gdbserver/configure b/gdbserver/configure index b45b55f..1554296 100755 --- a/gdbserver/configure +++ b/gdbserver/configure @@ -7531,119 +7531,6 @@ $as_echo "#define HAVE_CXX17 1" >>confdefs.h -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ctype.h> -#include <stdlib.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - - ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : @@ -7920,118 +7807,6 @@ fi # Set the 'development' global. . $srcdir/../bfd/development.sh - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ctype.h> -#include <stdlib.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 diff --git a/gdbserver/configure.ac b/gdbserver/configure.ac index bd2cac8..f5a669a 100644 --- a/gdbserver/configure.ac +++ b/gdbserver/configure.ac @@ -50,8 +50,6 @@ AC_ARG_PROGRAM # necessary, set CXX_DIALECT to some -std=xxx switch. AX_CXX_COMPILE_STDCXX(17, , mandatory) -AC_HEADER_STDC - GDB_AC_COMMON # This is set by GDB_AC_COMMON. AC_SUBST(WIN32APILIBS) diff --git a/gdbserver/gdbreplay.cc b/gdbserver/gdbreplay.cc index 44aa2fb..a517031 100644 --- a/gdbserver/gdbreplay.cc +++ b/gdbserver/gdbreplay.cc @@ -462,7 +462,7 @@ static void gdbreplay_version (void) { printf ("GNU gdbreplay %s%s\n" - "Copyright (C) 2024 Free Software Foundation, Inc.\n" + "Copyright (C) 2025 Free Software Foundation, Inc.\n" "gdbreplay is free software, covered by " "the GNU General Public License.\n" "This gdbreplay was configured as \"%s\"\n", diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc index 4be0083..90824bd 100644 --- a/gdbserver/i387-fp.cc +++ b/gdbserver/i387-fp.cc @@ -21,7 +21,7 @@ #include "nat/x86-xstate.h" /* Default to SSE. */ -static uint64_t x86_xcr0 = X86_XSTATE_SSE_MASK; +static uint64_t x86_xstate_bv = X86_XSTATE_SSE_MASK; static const int num_avx512_k_registers = 8; static const int num_pkeys_registers = 1; @@ -265,7 +265,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) /* The supported bits in `xstat_bv' are 8 bytes. Clear part in vector registers if its bit in xstat_bv is zero. */ - clear_bv = (~fp->xstate_bv) & x86_xcr0; + clear_bv = (~fp->xstate_bv) & x86_xstate_bv; /* Clear part in x87 and vector registers if its bit in xstat_bv is zero. */ @@ -315,7 +315,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any x87 registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_X87)) + if ((x86_xstate_bv & X86_XSTATE_X87)) { int st0_regnum = find_regno (regcache->tdesc, "st0"); @@ -332,7 +332,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any SSE registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_SSE)) + if ((x86_xstate_bv & X86_XSTATE_SSE)) { int xmm0_regnum = find_regno (regcache->tdesc, "xmm0"); @@ -349,7 +349,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any AVX registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_AVX)) + if ((x86_xstate_bv & X86_XSTATE_AVX)) { int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h"); @@ -366,7 +366,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any K registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_K)) + if ((x86_xstate_bv & X86_XSTATE_K)) { int k0_regnum = find_regno (regcache->tdesc, "k0"); @@ -383,7 +383,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any of ZMM0H-ZMM15H registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_ZMM_H)) + if ((x86_xstate_bv & X86_XSTATE_ZMM_H)) { int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h"); @@ -400,7 +400,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any of ZMM16-ZMM31 registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0) + if ((x86_xstate_bv & X86_XSTATE_ZMM) && num_zmm_high_registers != 0) { int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h"); int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h"); @@ -437,7 +437,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any PKEYS registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_PKRU)) + if ((x86_xstate_bv & X86_XSTATE_PKRU)) { int pkru_regnum = find_regno (regcache->tdesc, "pkru"); @@ -453,7 +453,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } } - if ((x86_xcr0 & X86_XSTATE_SSE) || (x86_xcr0 & X86_XSTATE_AVX)) + if ((x86_xstate_bv & X86_XSTATE_SSE) || (x86_xstate_bv & X86_XSTATE_AVX)) { collect_register_by_name (regcache, "mxcsr", raw); if (memcmp (raw, &fp->mxcsr, 4) != 0) @@ -465,7 +465,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } } - if (x86_xcr0 & X86_XSTATE_X87) + if (x86_xstate_bv & X86_XSTATE_X87) { collect_register_by_name (regcache, "fioff", raw); if (memcmp (raw, &fp->fioff, 4) != 0) @@ -658,10 +658,10 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) /* The supported bits in `xstat_bv' are 8 bytes. Clear part in vector registers if its bit in xstat_bv is zero. */ - clear_bv = (~fp->xstate_bv) & x86_xcr0; + clear_bv = (~fp->xstate_bv) & x86_xstate_bv; /* Check if any x87 registers are changed. */ - if ((x86_xcr0 & X86_XSTATE_X87) != 0) + if ((x86_xstate_bv & X86_XSTATE_X87) != 0) { int st0_regnum = find_regno (regcache->tdesc, "st0"); @@ -678,7 +678,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_SSE) != 0) + if ((x86_xstate_bv & X86_XSTATE_SSE) != 0) { int xmm0_regnum = find_regno (regcache->tdesc, "xmm0"); @@ -695,7 +695,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_AVX) != 0) + if ((x86_xstate_bv & X86_XSTATE_AVX) != 0) { int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h"); @@ -712,7 +712,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_K) != 0) + if ((x86_xstate_bv & X86_XSTATE_K) != 0) { int k0_regnum = find_regno (regcache->tdesc, "k0"); @@ -729,7 +729,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_ZMM_H) != 0) + if ((x86_xstate_bv & X86_XSTATE_ZMM_H) != 0) { int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h"); @@ -746,7 +746,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0) + if ((x86_xstate_bv & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0) { int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h"); int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h"); @@ -773,7 +773,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & X86_XSTATE_PKRU) != 0) + if ((x86_xstate_bv & X86_XSTATE_PKRU) != 0) { int pkru_regnum = find_regno (regcache->tdesc, "pkru"); @@ -858,5 +858,5 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) std::pair<uint64_t *, x86_xsave_layout *> i387_get_xsave_storage () { - return { &x86_xcr0, &xsave_layout }; + return { &x86_xstate_bv, &xsave_layout }; } diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 2eb3af6..9d3ac80 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -39,6 +39,7 @@ #include "gdb_proc_service.h" #include "arch/aarch64.h" +#include "arch/aarch64-gcs-linux.h" #include "arch/aarch64-mte-linux.h" #include "arch/aarch64-scalable-linux.h" #include "linux-aarch32-tdesc.h" @@ -321,6 +322,42 @@ aarch64_store_tlsregset (struct regcache *regcache, const void *buf) supply_register (regcache, *regnum, tls_buf + sizeof (uint64_t)); } +/* Fill BUF with the GCS registers from REGCACHE. */ + +static void +aarch64_fill_gcsregset (regcache *regcache, void *buf) +{ + user_gcs *regset = (user_gcs *) buf; + int gcspr_regnum = find_regno (regcache->tdesc, "gcspr"); + int features_enabled_regnum = find_regno (regcache->tdesc, + "gcs_features_enabled"); + int features_locked_regnum = find_regno (regcache->tdesc, + "gcs_features_locked"); + + collect_register (regcache, gcspr_regnum, ®set->gcspr_el0); + collect_register (regcache, features_enabled_regnum, + ®set->features_enabled); + collect_register (regcache, features_locked_regnum, ®set->features_locked); +} + +/* Store the GCS registers in BUF to REGCACHE. */ + +static void +aarch64_store_gcsregset (regcache *regcache, const void *buf) +{ + const user_gcs *regset = (const user_gcs *) buf; + int gcspr_regnum = find_regno (regcache->tdesc, "gcspr"); + int features_enabled_regnum = find_regno (regcache->tdesc, + "gcs_features_enabled"); + int features_locked_regnum = find_regno (regcache->tdesc, + "gcs_features_locked"); + + supply_register (regcache, gcspr_regnum, ®set->gcspr_el0); + supply_register (regcache, features_enabled_regnum, + ®set->features_enabled); + supply_register (regcache, features_locked_regnum, ®set->features_locked); +} + bool aarch64_target::low_supports_breakpoints () { @@ -846,6 +883,10 @@ static struct regset_info aarch64_regsets[] = { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS, 0, OPTIONAL_REGS, aarch64_fill_tlsregset, aarch64_store_tlsregset }, + /* Guarded Control Stack registers. */ + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_GCS, + 0, OPTIONAL_REGS, + aarch64_fill_gcsregset, aarch64_store_gcsregset }, NULL_REGSET }; @@ -909,6 +950,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features) if (features.sme2) regset->size = AARCH64_SME2_ZT0_SIZE; break; + case NT_ARM_GCS: + if (features.gcs_linux) + regset->size = sizeof (user_gcs); + break; default: gdb_assert_not_reached ("Unknown register set found."); } @@ -940,6 +985,7 @@ aarch64_target::low_arch_setup () /* A-profile MTE is 64-bit only. */ features.mte = linux_get_hwcap2 (pid, 8) & HWCAP2_MTE; features.tls = aarch64_tls_register_count (tid); + features.gcs = features.gcs_linux = linux_get_hwcap (pid, 8) & HWCAP_GCS; /* Scalable Matrix Extension feature and size check. */ if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME) diff --git a/gdbserver/linux-amd64-ipa.cc b/gdbserver/linux-amd64-ipa.cc index af4eb03..ec66367 100644 --- a/gdbserver/linux-amd64-ipa.cc +++ b/gdbserver/linux-amd64-ipa.cc @@ -82,7 +82,7 @@ get_raw_reg (const unsigned char *raw_regs, int regnum) const struct target_desc * get_ipa_tdesc (int idx) { - uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx); + uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx); #if defined __ILP32__ bool is_x32 = true; @@ -90,7 +90,7 @@ get_ipa_tdesc (int idx) bool is_x32 = false; #endif - return amd64_linux_read_description (xcr0, is_x32); + return amd64_linux_read_description (xstate_bv, is_x32); } /* Allocate buffer for the jump pads. The branch instruction has a @@ -159,9 +159,11 @@ initialize_low_tracepoint (void) { #if defined __ILP32__ for (int i = 0; i < x86_linux_x32_tdesc_count (); i++) - amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), true); + amd64_linux_read_description + (x86_linux_tdesc_idx_to_xstate_bv (i), true); #else for (int i = 0; i < x86_linux_amd64_tdesc_count (); i++) - amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), false); + amd64_linux_read_description + (x86_linux_tdesc_idx_to_xstate_bv (i), false); #endif } diff --git a/gdbserver/linux-i386-ipa.cc b/gdbserver/linux-i386-ipa.cc index 17af6eb..4f8398d 100644 --- a/gdbserver/linux-i386-ipa.cc +++ b/gdbserver/linux-i386-ipa.cc @@ -174,9 +174,9 @@ initialize_fast_tracepoint_trampoline_buffer (void) const struct target_desc * get_ipa_tdesc (int idx) { - uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx); + uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx); - return i386_linux_read_description (xcr0); + return i386_linux_read_description (xstate_bv); } /* Allocate buffer for the jump pads. On i386, we can reach an arbitrary @@ -199,5 +199,5 @@ initialize_low_tracepoint (void) { initialize_fast_tracepoint_trampoline_buffer (); for (int i = 0; i < x86_linux_i386_tdesc_count (); i++) - i386_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i)); + i386_linux_read_description (x86_linux_tdesc_idx_to_xstate_bv (i)); } diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index 3964270..e8c4eb8 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -5006,23 +5006,31 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info, if (res < 0) { if (errno == EIO - || (errno == EINVAL && regset->type == OPTIONAL_REGS)) + || (errno == EINVAL + && (regset->type == OPTIONAL_REGS + || regset->type == OPTIONAL_RUNTIME_REGS))) { /* If we get EIO on a regset, or an EINVAL and the regset is - optional, do not try it again for this process mode. */ + optional, do not try it again for this process mode. + Even if the regset can be enabled at runtime it is safe + to deactivate the regset in case of EINVAL, as we know + the regset itself was the invalid argument of the ptrace + call which means that it's unsupported by the kernel. */ disable_regset (regsets_info, regset); } - else if (errno == ENODATA) + else if (errno == ENODATA + || (errno == ENODEV + && regset->type == OPTIONAL_RUNTIME_REGS) + || errno == ESRCH) { - /* ENODATA may be returned if the regset is currently - not "active". This can happen in normal operation, - so suppress the warning in this case. */ - } - else if (errno == ESRCH) - { - /* At this point, ESRCH should mean the process is - already gone, in which case we simply ignore attempts - to read its registers. */ + /* ENODATA or ENODEV may be returned if the regset is + currently not "active". For ENODEV we additionally check + if the register set is of type OPTIONAL_RUNTIME_REGS. + This can happen in normal operation, so suppress the + warning in this case. + ESRCH should mean the process is already gone at this + point, in which case we simply ignore attempts to read + its registers. */ } else { @@ -5104,12 +5112,26 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info, if (res < 0) { if (errno == EIO - || (errno == EINVAL && regset->type == OPTIONAL_REGS)) + || (errno == EINVAL + && (regset->type == OPTIONAL_REGS + || regset->type == OPTIONAL_RUNTIME_REGS))) { /* If we get EIO on a regset, or an EINVAL and the regset is - optional, do not try it again for this process mode. */ + optional, do not try it again for this process mode. + Even if the regset can be enabled at runtime it is safe + to deactivate the regset in case of EINVAL, as we know + the regset itself was the invalid argument of the ptrace + call which means that it's unsupported by the kernel. */ disable_regset (regsets_info, regset); } + else if (errno == ENODEV + && regset->type == OPTIONAL_RUNTIME_REGS) + { + /* If we get ENODEV on a regset and the regset can be + enabled at runtime try it again for this process mode. + This can happen in normal operation, so suppress the + warning in this case. */ + } else if (errno == ESRCH) { /* At this point, ESRCH should mean the process is diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h index e1c88ee..5710e49 100644 --- a/gdbserver/linux-low.h +++ b/gdbserver/linux-low.h @@ -42,7 +42,12 @@ enum regset_type { GENERAL_REGS, FP_REGS, EXTENDED_REGS, - OPTIONAL_REGS, /* Do not error if the regset cannot be accessed. */ + OPTIONAL_REGS, /* Do not error if the regset cannot be accessed. + Disable the regset instead. */ + OPTIONAL_RUNTIME_REGS, /* Some optional regsets can only be accessed + dependent on the execution flow. For such + access errors don't show a warning and don't + disable the regset. */ }; /* The arch's regsets array initializer must be terminated with a NULL diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc index 918630d..44257d5 100644 --- a/gdbserver/linux-x86-low.cc +++ b/gdbserver/linux-x86-low.cc @@ -253,7 +253,8 @@ static const int x86_64_regmap[] = -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 /* pkru */ + -1, /* pkru */ + -1 /* CET user mode register PL3_SSP. */ }; #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0])) @@ -406,6 +407,18 @@ x86_target::low_cannot_fetch_register (int regno) } static void +x86_fill_ssp_reg (regcache *regcache, void *buf) +{ + collect_register_by_name (regcache, "pl3_ssp", buf); +} + +static void +x86_store_ssp_reg (regcache *regcache, const void *buf) +{ + supply_register_by_name (regcache, "pl3_ssp", buf); +} + +static void collect_register_i386 (struct regcache *regcache, int regno, void *buf) { collect_register (regcache, regno, buf); @@ -544,6 +557,8 @@ static struct regset_info x86_regsets[] = x86_fill_gregset, x86_store_gregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_X86_XSTATE, 0, EXTENDED_REGS, x86_fill_xstateregset, x86_store_xstateregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_X86_SHSTK, 0, + OPTIONAL_RUNTIME_REGS, x86_fill_ssp_reg, x86_store_ssp_reg }, # ifndef __x86_64__ # ifdef HAVE_PTRACE_GETFPXREGS { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, 0, sizeof (elf_fpxregset_t), @@ -873,7 +888,7 @@ x86_linux_read_description () bool have_ptrace_getregset_was_unknown = have_ptrace_getregset == TRIBOOL_UNKNOWN; - /* Get pointers to where we should store the xcr0 and xsave_layout + /* Get pointers to where we should store the xstate_bv and xsave_layout values. These will be filled in by x86_linux_tdesc_for_tid the first time that the function is called. Subsequent calls will not modify the stored values. */ @@ -894,7 +909,23 @@ x86_linux_read_description () regset++) { if (regset->get_request == PTRACE_GETREGSET) - regset->size = xsave_len; + { + if (regset->nt_type == NT_X86_XSTATE) + regset->size = xsave_len; + else if (regset->nt_type == NT_X86_SHSTK) + { + /* We must configure the size of the NT_X86_SHSTK regset + from non-zero value to it's appropriate size, even though + the ptrace call is only tested for NT_X86_XSTATE request, + because the NT_X86_SHSTK regset is of type + OPTIONAL_RUNTIME_REGS. A ptrace call with NT_X86_SHSTK + request may only be successful later on, once shadow + stack is enabled for the current thread. */ + regset->size = sizeof (CORE_ADDR); + } + else + gdb_assert_not_reached ("invalid regset type."); + } else if (regset->type != GENERAL_REGS) regset->size = 0; } @@ -2887,17 +2918,16 @@ x86_target::get_ipa_tdesc_idx () || tdesc == tdesc_amd64_linux_no_xml.get () #endif /* __x86_64__ */ ); - return x86_linux_xcr0_to_tdesc_idx (X86_XSTATE_SSE_MASK); + return x86_linux_xstate_bv_to_tdesc_idx (X86_XSTATE_SSE_MASK); } - /* The xcr0 value and xsave layout value are cached when the target + /* The xstate_bv value and xsave layout value are cached when the target description is read. Grab their cache location, and use the cached value to calculate a tdesc index. */ std::pair<uint64_t *, x86_xsave_layout *> storage = i387_get_xsave_storage (); - uint64_t xcr0 = *storage.first; - return x86_linux_xcr0_to_tdesc_idx (xcr0); + return x86_linux_xstate_bv_to_tdesc_idx (*storage.first); } /* The linux target ops object. */ diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 673b784..669c761 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -3812,7 +3812,7 @@ static void gdbserver_version (void) { printf ("GNU gdbserver %s%s\n" - "Copyright (C) 2024 Free Software Foundation, Inc.\n" + "Copyright (C) 2025 Free Software Foundation, Inc.\n" "gdbserver is free software, covered by the " "GNU General Public License.\n" "This gdbserver was configured as \"%s\"\n", |