diff options
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/aarch64-hw-point.c | 6 | ||||
-rw-r--r-- | gdb/nat/linux-osdata.c | 15 | ||||
-rw-r--r-- | gdb/nat/linux-ptrace.c | 41 | ||||
-rw-r--r-- | gdb/nat/x86-gcc-cpuid.h | 153 | ||||
-rw-r--r-- | gdb/nat/x86-linux-tdesc.c | 20 | ||||
-rw-r--r-- | gdb/nat/x86-linux-tdesc.h | 7 | ||||
-rw-r--r-- | gdb/nat/x86-linux.c | 59 | ||||
-rw-r--r-- | gdb/nat/x86-linux.h | 4 |
8 files changed, 251 insertions, 54 deletions
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c index 6d8dce8..8c0854b 100644 --- a/gdb/nat/aarch64-hw-point.c +++ b/gdb/nat/aarch64-hw-point.c @@ -710,10 +710,8 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state, itself. For instance, the access size of an stp instruction is 16. So, if we use stp to store to address p, and set a watchpoint on address p + 8, the reported ADDR_TRAP can be p + 8 (observed on - RK3399 SOC). But it also can be p (observed on M1 SOC). Checking - for this situation introduces the possibility of false positives, - so we only do this for hw_write watchpoints. */ - const CORE_ADDR max_access_size = type == hw_write ? 16 : 8; + RK3399 SOC). But it also can be p (observed on M1 SOC). */ + const CORE_ADDR max_access_size = 16; const CORE_ADDR addr_watch_base = addr_watch_aligned - (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG); if (!(addr_trap >= addr_watch_base diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c index b52a8ed..0a309b8 100644 --- a/gdb/nat/linux-osdata.c +++ b/gdb/nat/linux-osdata.c @@ -21,7 +21,6 @@ #include <sys/types.h> #include <sys/sysinfo.h> -#include <ctype.h> #include <utmp.h> #include <time.h> #include <unistd.h> @@ -205,7 +204,7 @@ get_cores_used_by_process (PID_T pid, int *cores, const int num_cores) PID_T tid; int core; - if (!isdigit (dp->d_name[0]) + if (!c_isdigit (dp->d_name[0]) || NAMELEN (dp) > MAX_PID_T_STRLEN) continue; @@ -310,7 +309,7 @@ linux_xfer_osdata_processes () std::string cores_str; int i; - if (!isdigit (dp->d_name[0]) + if (!c_isdigit (dp->d_name[0]) || NAMELEN (dp) > MAX_PID_T_STRLEN) continue; @@ -419,7 +418,7 @@ linux_xfer_osdata_processgroups () { PID_T pid, pgid; - if (!isdigit (dp->d_name[0]) + if (!c_isdigit (dp->d_name[0]) || NAMELEN (dp) > MAX_PID_T_STRLEN) continue; @@ -483,7 +482,7 @@ linux_xfer_osdata_threads () struct stat statbuf; char procentry[sizeof ("/proc/4294967295")]; - if (!isdigit (dp->d_name[0]) + if (!c_isdigit (dp->d_name[0]) || NAMELEN (dp) > sizeof ("4294967295") - 1) continue; @@ -513,7 +512,7 @@ linux_xfer_osdata_threads () PID_T tid; int core; - if (!isdigit (dp2->d_name[0]) + if (!c_isdigit (dp2->d_name[0]) || NAMELEN (dp2) > sizeof ("4294967295") - 1) continue; @@ -633,7 +632,7 @@ linux_xfer_osdata_fds () struct stat statbuf; char procentry[sizeof ("/proc/4294967295")]; - if (!isdigit (dp->d_name[0]) + if (!c_isdigit (dp->d_name[0]) || NAMELEN (dp) > sizeof ("4294967295") - 1) continue; @@ -662,7 +661,7 @@ linux_xfer_osdata_fds () char buf[1000]; ssize_t rslt; - if (!isdigit (dp2->d_name[0])) + if (!c_isdigit (dp2->d_name[0])) continue; std::string fdname diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index f73058b..7df85c1 100644 --- a/gdb/nat/linux-ptrace.c +++ b/gdb/nat/linux-ptrace.c @@ -24,12 +24,46 @@ #endif #include "gdbsupport/eintr.h" #include "gdbsupport/signals-state-save-restore.h" +#include "gdbsupport/gdb_file.h" /* Stores the ptrace options supported by the running kernel. A value of -1 means we did not check for features yet. A value of 0 means there are no supported features. */ static int supported_ptrace_options = -1; +/* The file from which the kernel.yama.ptrace_scope setting is read. */ + +static constexpr char ptrace_scope_filename[] + = "/proc/sys/kernel/yama/ptrace_scope"; + +/* Reads the yama ptrace_scope value from /proc. Returns the integer value + of ptrace_scope (0, 1, 2, or 3) or -1 if the file cannot be read (e.g., + yama is not enabled). */ + +static int +get_ptrace_scope () +{ + int ptrace_scope = -1; + + /* The /proc file that contains the system-wide ptrace scope setting. */ + gdb_file_up fp (fopen (ptrace_scope_filename, "r")); + if (fp != nullptr) + { + if (fscanf (fp.get (), "%d", &ptrace_scope) != 1) + { + /* If fscanf fails then we couldn't parse the number. But just + to be safe, set the scope back to -1 to indicate no value is + available. */ + ptrace_scope = -1; + } + } + + /* If fp is NULL, it's likely because the yama security module is not + active. In this case, we return -1 to indicate that the scope is + unknown or not applicable. */ + return ptrace_scope; +} + /* Find all possible reasons we could fail to attach PID and return these as a string. An empty string is returned if we didn't find any reason. */ @@ -44,6 +78,13 @@ linux_ptrace_attach_fail_reason (pid_t pid) _("process %d is already traced by process %d"), (int) pid, (int) tracerpid); + int ptrace_scope = get_ptrace_scope (); + if (ptrace_scope > 0) + string_appendf (result, + _("the %s setting of %d might prevent attaching, " + "see 'man 2 ptrace'"), + ptrace_scope_filename, ptrace_scope); + if (linux_proc_pid_is_zombie_nowarn (pid)) string_appendf (result, _("process %d is a zombie - the process has already " diff --git a/gdb/nat/x86-gcc-cpuid.h b/gdb/nat/x86-gcc-cpuid.h index 1498100..9e27fd8 100644 --- a/gdb/nat/x86-gcc-cpuid.h +++ b/gdb/nat/x86-gcc-cpuid.h @@ -1,5 +1,5 @@ /* - * Helper cpuid.h file copied from gcc-6.0.0. Code in gdb should not + * Helper cpuid.h file copied from gcc-14.2.0. Code in gdb should not * include this directly, but pull in x86-cpuid.h and use that func. */ @@ -55,7 +55,7 @@ #define bit_SSE (1 << 25) #define bit_SSE2 (1 << 26) -/* Extended Features */ +/* Extended Features (%eax == 0x80000001) */ /* %ecx */ #define bit_LAHF_LM (1 << 0) #define bit_ABM (1 << 5) @@ -68,29 +68,28 @@ #define bit_MWAITX (1 << 29) /* %edx */ -#define bit_AVX5124VNNIW (1 << 2) -#define bit_AVX5124FMAPS (1 << 3) #define bit_MMXEXT (1 << 22) #define bit_LM (1 << 29) #define bit_3DNOWP (1 << 30) -#define bit_3DNOW (1 << 31) +#define bit_3DNOW (1u << 31) -/* %ebx. */ +/* %ebx */ #define bit_CLZERO (1 << 0) +#define bit_WBNOINVD (1 << 9) -/* Extended Features (%eax == 7) */ +/* Extended Features Leaf (%eax == 7, %ecx == 0) */ /* %ebx */ #define bit_FSGSBASE (1 << 0) -#define bit_BMI (1 << 3) -#define bit_HLE (1 << 4) +#define bit_SGX (1 << 2) +#define bit_BMI (1 << 3) +#define bit_HLE (1 << 4) #define bit_AVX2 (1 << 5) #define bit_BMI2 (1 << 8) -#define bit_RTM (1 << 11) -#define bit_MPX (1 << 14) +#define bit_RTM (1 << 11) #define bit_AVX512F (1 << 16) #define bit_AVX512DQ (1 << 17) #define bit_RDSEED (1 << 18) -#define bit_ADX (1 << 19) +#define bit_ADX (1 << 19) #define bit_AVX512IFMA (1 << 21) #define bit_CLFLUSHOPT (1 << 23) #define bit_CLWB (1 << 24) @@ -99,23 +98,85 @@ #define bit_AVX512CD (1 << 28) #define bit_SHA (1 << 29) #define bit_AVX512BW (1 << 30) -#define bit_AVX512VL (1 << 31) +#define bit_AVX512VL (1u << 31) /* %ecx */ -#define bit_PREFETCHWT1 (1 << 0) +#define bit_PREFETCHWT1 (1 << 0) #define bit_AVX512VBMI (1 << 1) -#define bit_PKU (1 << 3) +#define bit_PKU (1 << 3) #define bit_OSPKE (1 << 4) +#define bit_WAITPKG (1 << 5) +#define bit_AVX512VBMI2 (1 << 6) +#define bit_SHSTK (1 << 7) +#define bit_GFNI (1 << 8) +#define bit_VAES (1 << 9) +#define bit_VPCLMULQDQ (1 << 10) +#define bit_AVX512VNNI (1 << 11) +#define bit_AVX512BITALG (1 << 12) +#define bit_AVX512VPOPCNTDQ (1 << 14) +#define bit_RDPID (1 << 22) +#define bit_KL (1 << 23) +#define bit_CLDEMOTE (1 << 25) +#define bit_MOVDIRI (1 << 27) +#define bit_MOVDIR64B (1 << 28) +#define bit_ENQCMD (1 << 29) -/* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */ -#define bit_BNDREGS (1 << 3) -#define bit_BNDCSR (1 << 4) +/* %edx */ +#define bit_AVX5124VNNIW (1 << 2) +#define bit_AVX5124FMAPS (1 << 3) +#define bit_UINTR (1 << 5) +#define bit_AVX512VP2INTERSECT (1 << 8) +#define bit_SERIALIZE (1 << 14) +#define bit_TSXLDTRK (1 << 16) +#define bit_PCONFIG (1 << 18) +#define bit_IBT (1 << 20) +#define bit_AMX_BF16 (1 << 22) +#define bit_AVX512FP16 (1 << 23) +#define bit_AMX_TILE (1 << 24) +#define bit_AMX_INT8 (1 << 25) + +/* Extended Features Sub-leaf (%eax == 7, %ecx == 1) */ +/* %eax */ +#define bit_SHA512 (1 << 0) +#define bit_SM3 (1 << 1) +#define bit_SM4 (1 << 2) +#define bit_RAOINT (1 << 3) +#define bit_AVXVNNI (1 << 4) +#define bit_AVX512BF16 (1 << 5) +#define bit_CMPCCXADD (1 << 7) +#define bit_AMX_COMPLEX (1 << 8) +#define bit_AMX_FP16 (1 << 21) +#define bit_HRESET (1 << 22) +#define bit_AVXIFMA (1 << 23) -/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */ +/* %edx */ +#define bit_AVXVNNIINT8 (1 << 4) +#define bit_AVXNECONVERT (1 << 5) +#define bit_AVXVNNIINT16 (1 << 10) +#define bit_PREFETCHI (1 << 14) +#define bit_USER_MSR (1 << 15) +#define bit_AVX10 (1 << 19) +#define bit_APX_F (1 << 21) + +/* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */ #define bit_XSAVEOPT (1 << 0) #define bit_XSAVEC (1 << 1) #define bit_XSAVES (1 << 3) +/* PT sub leaf (%eax == 0x14, %ecx == 0) */ +/* %ebx */ +#define bit_PTWRITE (1 << 4) + +/* Keylocker leaf (%eax == 0x19) */ +/* %ebx */ +#define bit_AESKLE ( 1<<0 ) +#define bit_WIDEKL ( 1<<2 ) + +/* AVX10 sub leaf (%eax == 0x24) */ +/* %ebx */ +#define bit_AVX10_256 (1 << 17) +#define bit_AVX10_512 (1 << 18) + /* Signatures for different CPU implementations as returned in uses of cpuid with level 0. */ #define signature_AMD_ebx 0x68747541 @@ -170,19 +231,40 @@ #define signature_VORTEX_ecx 0x436f5320 #define signature_VORTEX_edx 0x36387865 -#define __cpuid(level, a, b, c, d) \ - __asm__ ("cpuid\n\t" \ - : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ - : "0" (level)) +#define signature_SHANGHAI_ebx 0x68532020 +#define signature_SHANGHAI_ecx 0x20206961 +#define signature_SHANGHAI_edx 0x68676e61 -#define __cpuid_count(level, count, a, b, c, d) \ - __asm__ ("cpuid\n\t" \ - : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ - : "0" (level), "2" (count)) +#ifndef __x86_64__ +/* At least one cpu (Winchip 2) does not set %ebx and %ecx + for cpuid leaf 1. Forcibly zero the two registers before + calling cpuid as a precaution. */ +#define __cpuid(level, a, b, c, d) \ + do { \ + if (__builtin_constant_p (level) && (level) != 1) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)); \ + else \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "1" (0), "2" (0)); \ + } while (0) +#else +#define __cpuid(level, a, b, c, d) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) +#endif + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ __volatile__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) /* Return highest supported input value for cpuid instruction. ext can - be either 0x0 or 0x8000000 to return highest supported value for + be either 0x0 or 0x80000000 to return highest supported value for basic or extended cpuid information. Function returns 0 if cpuid is not supported or whatever cpuid returns in eax register. If sig pointer is non-null, then first four bytes of the signature @@ -225,7 +307,7 @@ __get_cpuid_max (unsigned int __ext, unsigned int *__sig) : "i" (0x00200000)); #endif - if (!((__eax ^ __ebx) & 0x00200000)) + if (__builtin_expect (!((__eax ^ __ebx) & 0x00200000), 0)) return 0; #endif @@ -249,8 +331,9 @@ __get_cpuid (unsigned int __leaf, unsigned int *__ecx, unsigned int *__edx) { unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); - if (__get_cpuid_max (__ext, 0) < __leaf) + if (__maxlevel == 0 || __maxlevel < __leaf) return 0; __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx); @@ -265,12 +348,20 @@ __get_cpuid_count (unsigned int __leaf, unsigned int __subleaf, unsigned int *__ecx, unsigned int *__edx) { unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); - if (__get_cpuid_max (__ext, 0) < __leaf) + if (__builtin_expect (__maxlevel == 0, 0) || __maxlevel < __leaf) return 0; __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); return 1; } +static __inline void +__cpuidex (int __cpuid_info[4], int __leaf, int __subleaf) +{ + __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1], + __cpuid_info[2], __cpuid_info[3]); +} + #endif /* GDB_NAT_X86_GCC_CPUID_H */ diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c index 80e4337..5bc36b6 100644 --- a/gdb/nat/x86-linux-tdesc.c +++ b/gdb/nat/x86-linux-tdesc.c @@ -43,7 +43,7 @@ /* See nat/x86-linux-tdesc.h. */ const target_desc * -x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage, +x86_linux_tdesc_for_tid (int tid, uint64_t *xstate_bv_storage, x86_xsave_layout *xsave_layout_storage) { #ifdef __x86_64__ @@ -96,30 +96,34 @@ x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage, these bits being set we generate a completely empty tdesc for i386 which will be rejected by GDB. */ have_ptrace_getregset = TRIBOOL_FALSE; - *xcr0_storage = X86_XSTATE_SSE_MASK; + *xstate_bv_storage = X86_XSTATE_SSE_MASK; } else { have_ptrace_getregset = TRIBOOL_TRUE; /* Get XCR0 from XSAVE extended state. */ - *xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET + uint64_t xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET / sizeof (uint64_t))]; *xsave_layout_storage - = x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ()); + = x86_fetch_xsave_layout (xcr0, x86_xsave_length ()); + + *xstate_bv_storage = xcr0; + if (x86_check_ssp_support (tid)) + *xstate_bv_storage |= X86_XSTATE_CET_U; } } - /* Use cached xcr0 value. */ - uint64_t xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK; + /* Use cached XSTATE_BV_STORAGE value. */ + uint64_t xstate_bv_features_bits = *xstate_bv_storage & X86_XSTATE_ALL_MASK; #ifdef __x86_64__ if (is_64bit) - return amd64_linux_read_description (xcr0_features_bits, is_x32); + return amd64_linux_read_description (xstate_bv_features_bits, is_x32); else #endif - return i386_linux_read_description (xcr0_features_bits); + return i386_linux_read_description (xstate_bv_features_bits); } #endif /* !IN_PROCESS_AGENT */ diff --git a/gdb/nat/x86-linux-tdesc.h b/gdb/nat/x86-linux-tdesc.h index 38c71f1..19aa84f 100644 --- a/gdb/nat/x86-linux-tdesc.h +++ b/gdb/nat/x86-linux-tdesc.h @@ -27,9 +27,9 @@ struct x86_xsave_layout; /* Return the target description for Linux thread TID. - The storage pointed to by XCR0_STORAGE and XSAVE_LAYOUT_STORAGE must + The storage pointed to by XSTATE_BV_STORAGE and XSAVE_LAYOUT_STORAGE must exist until the program (GDB or gdbserver) terminates, this storage is - used to cache the xcr0 and xsave layout values. The values pointed to + used to cache the xstate_bv and xsave layout values. The values pointed to by these arguments are only updated at most once, the first time this function is called if the have_ptrace_getregset global is set to TRIBOOL_UNKNOWN. @@ -45,6 +45,7 @@ struct x86_xsave_layout; returned. */ extern const target_desc *x86_linux_tdesc_for_tid - (int tid, uint64_t *xcr0_storage, x86_xsave_layout *xsave_layout_storage); + (int tid, uint64_t *xstate_bv_storage, + x86_xsave_layout *xsave_layout_storage); #endif /* GDB_NAT_X86_LINUX_TDESC_H */ diff --git a/gdb/nat/x86-linux.c b/gdb/nat/x86-linux.c index 0bdff73..5515826 100644 --- a/gdb/nat/x86-linux.c +++ b/gdb/nat/x86-linux.c @@ -17,6 +17,12 @@ 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 "elf/common.h" +#include "gdbsupport/common-defs.h" +#include "nat/gdb_ptrace.h" +#include "nat/linux-ptrace.h" +#include "nat/x86-cpuid.h" +#include <sys/uio.h> #include "x86-linux.h" #include "x86-linux-dregs.h" #include "nat/gdb_ptrace.h" @@ -126,3 +132,56 @@ x86_linux_ptrace_get_arch_size (int tid) return x86_linux_arch_size (false, false); #endif } + +/* See nat/x86-linux.h. */ + +bool +x86_check_ssp_support (const int tid) +{ + /* It's not enough to check shadow stack support with the ptrace call + below only, as we cannot distinguish between shadow stack not enabled + for the current thread and shadow stack is not supported by HW. In + both scenarios the ptrace call fails with ENODEV. In case shadow + stack is not enabled for the current thread, we still want to return + true. */ + unsigned int eax, ebx, ecx, edx; + eax = ebx = ecx = edx = 0; + + if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx)) + return false; + + if ((ecx & bit_SHSTK) == 0) + return false; + + /* Further check for NT_X86_SHSTK kernel support. */ + uint64_t ssp; + iovec iov {&ssp, sizeof (ssp) }; + + errno = 0; + int res = ptrace (PTRACE_GETREGSET, tid, NT_X86_SHSTK, &iov); + if (res < 0) + { + if (errno == EINVAL) + { + /* The errno EINVAL for a PTRACE_GETREGSET call indicates that + kernel support is not available. */ + return false; + } + else if (errno == ENODEV) + { + /* At this point, since we already checked CPUID, the errno + ENODEV for a PTRACE_GETREGSET call indicates that shadow + stack is not enabled for the current thread. As it could be + enabled later, we still want to return true here. */ + return true; + } + else + { + warning (_("Unknown ptrace error for NT_X86_SHSTK: %s"), + safe_strerror (errno)); + return false; + } + } + + return true; +} diff --git a/gdb/nat/x86-linux.h b/gdb/nat/x86-linux.h index dbdef08..1783aae 100644 --- a/gdb/nat/x86-linux.h +++ b/gdb/nat/x86-linux.h @@ -75,4 +75,8 @@ private: extern x86_linux_arch_size x86_linux_ptrace_get_arch_size (int tid); +/* Check shadow stack hardware and kernel support. */ + +extern bool x86_check_ssp_support (const int tid); + #endif /* GDB_NAT_X86_LINUX_H */ |