diff options
Diffstat (limited to 'sysdeps')
43 files changed, 497 insertions, 300 deletions
diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure index 26a0989..f364e65 100755 --- a/sysdeps/aarch64/configure +++ b/sysdeps/aarch64/configure @@ -194,3 +194,5 @@ if test $build_mathvec = no; then printf "%s\n" "$as_me: WARNING: mathvec is disabled, this results in incomplete ABI." >&2;} fi +libc_cv_support_sframe=yes + diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac index 22fca8b..a9a1b74 100644 --- a/sysdeps/aarch64/configure.ac +++ b/sysdeps/aarch64/configure.ac @@ -31,3 +31,5 @@ fi if test $build_mathvec = no; then AC_MSG_WARN([mathvec is disabled, this results in incomplete ABI.]) fi + +libc_cv_support_sframe=yes diff --git a/sysdeps/generic/Makefile b/sysdeps/generic/Makefile index c48e713..1be63b7 100644 --- a/sysdeps/generic/Makefile +++ b/sysdeps/generic/Makefile @@ -21,7 +21,9 @@ CFLAGS-wordcopy.c += -Wno-uninitialized endif ifeq ($(subdir),elf) +ifeq ($(enable-gsframe),yes) sysdep_routines += sframe-read sframe +endif ifeq (yes:yes,$(build-shared):$(unwind-find-fde)) # This is needed to support g++ v2 and v3. sysdep_routines += framestate unwind-pe diff --git a/sysdeps/generic/sframe-read.c b/sysdeps/generic/sframe-read.c index d536575..a6ebc42 100644 --- a/sysdeps/generic/sframe-read.c +++ b/sysdeps/generic/sframe-read.c @@ -75,11 +75,10 @@ sframe_get_fde_type (sframe_func_desc_entry *fdep) static bool sframe_header_sanity_check_p (sframe_header *hp) { - uint8_t all_flags = SFRAME_F_FDE_SORTED | SFRAME_F_FRAME_POINTER; /* Check preamble is valid. */ if ((hp->sfh_preamble.sfp_magic != SFRAME_MAGIC) || (hp->sfh_preamble.sfp_version != SFRAME_VERSION_2) - || ((hp->sfh_preamble.sfp_flags | all_flags) != all_flags)) + || (hp->sfh_preamble.sfp_flags & ~SFRAME_V2_F_ALL_FLAGS)) return false; /* Check offsets are valid. */ @@ -171,25 +170,103 @@ sframe_fre_entry_size (sframe_frame_row_entry *frep, size_t addr_size) + sframe_fre_offset_bytes_size (fre_info)); } -/* Check whether for the given FDEP, the SFrame Frame Row Entry identified via - the START_IP_OFFSET and the END_IP_OFFSET, provides the stack trace - information for the PC. */ +/* Get SFrame header from the given decoder context DCTX. */ + +static inline sframe_header * +sframe_decoder_get_header (sframe_decoder_ctx *dctx) +{ + sframe_header *hp = NULL; + if (dctx != NULL) + hp = &dctx->sfd_header; + return hp; +} + +/* Get the offset of the sfde_func_start_address field (from the start of the + on-disk layout of the SFrame section) of the FDE at FUNC_IDX in the decoder + context DCTX. */ + +static uint32_t +sframe_decoder_get_offsetof_fde_start_addr (sframe_decoder_ctx *dctx, + uint32_t func_idx, + _Unwind_Reason_Code *errp) +{ + sframe_header *dhp; + + dhp = sframe_decoder_get_header (dctx); + if (dhp == NULL) + { + if (errp != NULL) + *errp = _URC_END_OF_STACK; + return 0; + } + + if (func_idx >= dhp->sfh_num_fdes) + { + if (errp != NULL) + *errp = _URC_END_OF_STACK; + return 0; + } + else if (errp != NULL) + *errp = _URC_NO_REASON; + + return (sframe_get_hdr_size (dhp) + + func_idx * sizeof (sframe_func_desc_entry) + + offsetof (sframe_func_desc_entry, sfde_func_start_address)); +} + + +/* Get the offset of the start PC of the SFrame FDE at FUNC_IDX from + the start of the SFrame section. If the flag + SFRAME_F_FDE_FUNC_START_PCREL is set, sfde_func_start_address is + the offset of the start PC of the function from the field itself. + + If FUNC_IDX is not a valid index in the given decoder object, returns 0. */ + +static int32_t +sframe_decoder_get_secrel_func_start_addr (sframe_decoder_ctx *dctx, + uint32_t func_idx) +{ + int32_t func_start_addr; + _Unwind_Reason_Code err = 0; + int32_t offsetof_fde_in_sec = 0; + + /* Check if we have SFRAME_F_FDE_FUNC_START_PCREL. */ + sframe_header *sh = &dctx->sfd_header; + if ((sh->sfh_preamble.sfp_flags & SFRAME_F_FDE_FUNC_START_PCREL)) + { + offsetof_fde_in_sec = + sframe_decoder_get_offsetof_fde_start_addr (dctx, func_idx, &err); + /* If func_idx is not a valid index, return 0. */ + if (err == _URC_END_OF_STACK) + return 0; + } + + func_start_addr = dctx->sfd_funcdesc[func_idx].sfde_func_start_address; + + return func_start_addr + offsetof_fde_in_sec; +} + +/* Check if the SFrame Frame Row Entry identified via the + START_IP_OFFSET and the END_IP_OFFSET (for SFrame FDE at + FUNC_IDX). */ static bool -sframe_fre_check_range_p (sframe_func_desc_entry *fdep, +sframe_fre_check_range_p (sframe_decoder_ctx *dctx, uint32_t func_idx, uint32_t start_ip_offset, uint32_t end_ip_offset, int32_t pc) { + sframe_func_desc_entry *fdep; int32_t func_start_addr; uint8_t rep_block_size; uint32_t fde_type; uint32_t pc_offset; bool mask_p; + fdep = &dctx->sfd_funcdesc[func_idx]; if (fdep == NULL) return false; - func_start_addr = fdep->sfde_func_start_address; + func_start_addr = sframe_decoder_get_secrel_func_start_addr (dctx, func_idx); fde_type = sframe_get_fde_type (fdep); mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK); rep_block_size = fdep->sfde_func_rep_size; @@ -207,19 +284,6 @@ sframe_fre_check_range_p (sframe_func_desc_entry *fdep, return (start_ip_offset <= pc_offset) && (end_ip_offset >= pc_offset); } -/* The SFrame Decoder. */ - -/* Get SFrame header from the given decoder context DCTX. */ - -static inline sframe_header * -sframe_decoder_get_header (sframe_decoder_ctx *dctx) -{ - sframe_header *hp = NULL; - if (dctx != NULL) - hp = &dctx->sfd_header; - return hp; -} - /* Get IDX'th offset from FRE. Set ERRP as applicable. */ static int32_t @@ -298,7 +362,7 @@ sframe_decode_fre_start_address (const char *fre_buf, static sframe_func_desc_entry * sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr, - int *errp) + int *errp, uint32_t *func_idx) { sframe_header *dhp; sframe_func_desc_entry *fdp; @@ -319,19 +383,23 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr, /* Do the binary search. */ fdp = (sframe_func_desc_entry *) ctx->sfd_funcdesc; low = 0; - high = dhp->sfh_num_fdes; + high = dhp->sfh_num_fdes - 1; while (low <= high) { int mid = low + (high - low) / 2; /* Given sfde_func_start_address <= addr, addr - sfde_func_start_address must be positive. */ - if (fdp[mid].sfde_func_start_address <= addr - && ((uint32_t)(addr - fdp[mid].sfde_func_start_address) + if (sframe_decoder_get_secrel_func_start_addr (ctx, mid) <= addr + && ((uint32_t)(addr - sframe_decoder_get_secrel_func_start_addr (ctx, + mid)) < fdp[mid].sfde_func_size)) - return fdp + mid; + { + *func_idx = mid; + return fdp + mid; + } - if (fdp[mid].sfde_func_start_address < addr) + if (sframe_decoder_get_secrel_func_start_addr (ctx, mid) < addr) low = mid + 1; else high = mid - 1; @@ -510,6 +578,7 @@ __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, sframe_frame_row_entry *frep) { sframe_func_desc_entry *fdep; + uint32_t func_idx; uint32_t fre_type, i; uint32_t start_ip_offset; int32_t func_start_addr; @@ -522,14 +591,14 @@ __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, return _URC_END_OF_STACK; /* Find the FDE which contains the PC, then scan its fre entries. */ - fdep = sframe_get_funcdesc_with_addr_internal (ctx, pc, &err); + fdep = sframe_get_funcdesc_with_addr_internal (ctx, pc, &err, &func_idx); if (fdep == NULL || ctx->sfd_fres == NULL) return _URC_END_OF_STACK; fre_type = sframe_get_fre_type (fdep); fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off; - func_start_addr = fdep->sfde_func_start_address; + func_start_addr = sframe_decoder_get_secrel_func_start_addr (ctx, func_idx); for (i = 0; i < fdep->sfde_func_num_fres; i++) { @@ -553,7 +622,8 @@ __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, if (start_ip_offset > (uint32_t) (pc - func_start_addr)) return _URC_END_OF_STACK; - if (sframe_fre_check_range_p (fdep, start_ip_offset, end_ip_offset, pc)) + if (sframe_fre_check_range_p (ctx, func_idx, start_ip_offset, + end_ip_offset, pc)) { /* Decode last FRE bits: offsets size. */ frep->fre_offsets = fres + addr_size + sizeof (frep->fre_info); diff --git a/sysdeps/generic/sframe-read.h b/sysdeps/generic/sframe-read.h index 1db1886..1461421 100644 --- a/sysdeps/generic/sframe-read.h +++ b/sysdeps/generic/sframe-read.h @@ -99,6 +99,12 @@ __sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx, sframe_frame_row_entry *fre, _Unwind_Reason_Code *errp); +/* Get the offset of the sfde_func_start_address field. */ + +extern uint32_t +__sframe_decoder_get_offsetof_fde_start_addr (sframe_decoder_ctx *dctx, + uint32_t func_idx, + _Unwind_Reason_Code *errp); #ifdef __cplusplus } #endif diff --git a/sysdeps/generic/sframe.h b/sysdeps/generic/sframe.h index 3f8ff1c..e38adcf 100644 --- a/sysdeps/generic/sframe.h +++ b/sysdeps/generic/sframe.h @@ -80,9 +80,20 @@ extern "C" /* Various flags for SFrame. */ /* Function Descriptor Entries are sorted on PC. */ -#define SFRAME_F_FDE_SORTED 0x1 +#define SFRAME_F_FDE_SORTED 0x1 /* Functions preserve frame pointer. */ -#define SFRAME_F_FRAME_POINTER 0x2 +#define SFRAME_F_FRAME_POINTER 0x2 +/* Function start address in SFrame FDE is encoded as the distance from the + location of the sfde_func_start_address to the start PC of the function. + If absent, the function start address in SFrame FDE is encoded as the + distance from the start of the SFrame FDE section to the start PC of the + function. */ +#define SFRAME_F_FDE_FUNC_START_PCREL 0x4 + +/* Set of all defined flags in SFrame V2. */ +#define SFRAME_V2_F_ALL_FLAGS \ + (SFRAME_F_FDE_SORTED | SFRAME_F_FRAME_POINTER \ + | SFRAME_F_FDE_FUNC_START_PCREL) #define SFRAME_CFA_FIXED_FP_INVALID 0 #define SFRAME_CFA_FIXED_RA_INVALID 0 diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile index ee6470d..74068ea 100644 --- a/sysdeps/i386/Makefile +++ b/sysdeps/i386/Makefile @@ -17,19 +17,22 @@ ifeq ($(subdir),gmon) sysdep_routines += i386-mcount endif -ifeq ($(subdir),elf) -CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused -CFLAGS-dl-load.c += -Wno-unused -CFLAGS-dl-reloc.c += -Wno-unused -endif - ifeq ($(subdir),csu) gen-as-const-headers += link-defines.sym +gen-as-const-headers += tlsdesc.sym else stack-align-test-flags += -malign-double endif +# Make sure no code in ld.so uses mm/xmm/ymm/zmm registers on i386 since +# the first 3 mm/xmm/ymm/zmm registers are used to pass vector parameters +# which must be preserved. +# With SSE disabled, ensure -fpmath is not set to use sse either. +rtld-CFLAGS += -mno-sse -mno-mmx -mfpmath=387 ifeq ($(subdir),elf) +CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused +CFLAGS-dl-load.c += -Wno-unused +CFLAGS-dl-reloc.c += -Wno-unused sysdep-dl-routines += \ dl-tls-get-addr \ # sysdep-dl-routines @@ -40,18 +43,6 @@ modules-names += tst-auditmod3a tst-auditmod3b $(objpfx)tst-audit3: $(objpfx)tst-auditmod3a.so $(objpfx)tst-audit3.out: $(objpfx)tst-auditmod3b.so tst-audit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod3b.so -endif - -ifeq ($(subdir),csu) -gen-as-const-headers += tlsdesc.sym -endif - -# Make sure no code in ld.so uses mm/xmm/ymm/zmm registers on i386 since -# the first 3 mm/xmm/ymm/zmm registers are used to pass vector parameters -# which must be preserved. -# With SSE disabled, ensure -fpmath is not set to use sse either. -rtld-CFLAGS += -mno-sse -mno-mmx -mfpmath=387 -ifeq ($(subdir),elf) CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ $(rtld-CFLAGS)) diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index de146dd..7572f62 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -62,7 +62,6 @@ tests += \ tst-abstime \ tst-atfork1 \ tst-attr1 \ - tst-backtrace1 \ tst-bad-schedattr \ tst-barrier1 \ tst-barrier2 \ diff --git a/sysdeps/pthread/tst-backtrace1.c b/sysdeps/pthread/tst-backtrace1.c deleted file mode 100644 index 01b8a0c..0000000 --- a/sysdeps/pthread/tst-backtrace1.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2004-2025 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#include <execinfo.h> -#include <pthread.h> -#include <stdio.h> - -#define BT_SIZE 64 -void *bt_array[BT_SIZE]; -int bt_cnt; - -int -do_bt (void) -{ - bt_cnt = backtrace (bt_array, BT_SIZE); - return 56; -} - -int -call_do_bt (void) -{ - return do_bt () + 1; -} - -void * -tf (void *arg) -{ - if (call_do_bt () != 57) - return (void *) 1L; - return NULL; -} - -int -do_test (void) -{ - pthread_t th; - if (pthread_create (&th, NULL, tf, NULL)) - { - puts ("create failed"); - return 1; - } - - void *res; - if (pthread_join (th, &res)) - { - puts ("join failed"); - return 1; - } - - if (res != NULL) - { - puts ("thread failed"); - return 1; - } - - char **text = backtrace_symbols (bt_array, bt_cnt); - if (text == NULL) - { - puts ("backtrace_symbols failed"); - return 1; - } - - for (int i = 0; i < bt_cnt; ++i) - puts (text[i]); - - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cond23.c b/sysdeps/pthread/tst-cond23.c index 0a68472..a338397 100644 --- a/sysdeps/pthread/tst-cond23.c +++ b/sysdeps/pthread/tst-cond23.c @@ -151,7 +151,7 @@ do_test (void) #if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1 puts ("_POSIX_CLOCK_SELECTION not supported, test skipped"); - return 0; + return EXIT_UNSUPPORTED; #else diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 0aec783..c47cbdf 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -425,8 +425,6 @@ sysdep_headers += \ bits/termios-tcflow.h \ # sysdep_headers -gen-as-const-headers += termios-kernel-consts.sym - tests += \ tst-termios-linux \ # tests diff --git a/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h b/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h index 3a77c23..9d5d345 100644 --- a/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h +++ b/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h @@ -24,7 +24,7 @@ #include <sys/ucontext.h> #include <kernel_rt_sigframe.h> -#if __AARCH64EL__ +#ifdef __AARCH64EL__ #define MOVZ_X8_8B 0xd2801168 #define SVC_0 0xd4000001 #else diff --git a/sysdeps/unix/sysv/linux/alpha/bits/ioctls.h b/sysdeps/unix/sysv/linux/alpha/bits/ioctls.h new file mode 100644 index 0000000..77dc0c1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/bits/ioctls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1996-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_IOCTL_H +# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include <asm/ioctls.h> + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('t', 19, char[44]) +#define TCSETS _IOW ('t', 20, char[44]) +#define TCSETSW _IOW ('t', 21, char[44]) +#define TCSETSF _IOW ('t', 22, char[44]) + +#include <linux/sockios.h> diff --git a/sysdeps/unix/sysv/linux/alpha/termios_arch.h b/sysdeps/unix/sysv/linux/alpha/termios_arch.h new file mode 100644 index 0000000..20025f2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/termios_arch.h @@ -0,0 +1,26 @@ +/* Architectural parameters for Linux termios - Alpha/PowerPC version + + Copyright (C) 1997-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef TERMIOS_INTERNALS_H +# error "<termios_arch.h> should only be included from <termios_internals.h>" +#endif + +#define _TERMIOS2_NCCS 19 +#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 1 +#define _HAVE_STRUCT_OLD_TERMIOS 0 diff --git a/sysdeps/unix/sysv/linux/bits/ioctls.h b/sysdeps/unix/sysv/linux/bits/ioctls.h index f340a4f..1ddcd4f 100644 --- a/sysdeps/unix/sysv/linux/bits/ioctls.h +++ b/sysdeps/unix/sysv/linux/bits/ioctls.h @@ -22,18 +22,4 @@ /* Use the definitions from the kernel header files. */ #include <asm/ioctls.h> -/* The GNU C library has a different definition of struct termios, - incompatible with what the ioctl interface expects. The existence - of the termios2 ioctls is considered an implementation detail. - Undefine all related ioctl constants. */ -#undef TCGETS -#undef TCSETS -#undef TCSETSF -#undef TCSETSW -#undef TCGETS2 -#undef TCSETS2 -#undef TCSETSF2 -#undef TCSETSW2 - - #include <linux/sockios.h> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/ioctls.h b/sysdeps/unix/sysv/linux/hppa/bits/ioctls.h new file mode 100644 index 0000000..6563be8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/hppa/bits/ioctls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1996-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_IOCTL_H +# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include <asm/ioctls.h> + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('T', 16, char[36]) +#define TCSETS _IOW ('T', 17, char[36]) +#define TCSETSW _IOW ('T', 18, char[36]) +#define TCSETSF _IOW ('T', 19, char[36]) + +#include <linux/sockios.h> diff --git a/sysdeps/unix/sysv/linux/isatty.c b/sysdeps/unix/sysv/linux/isatty.c index e7e98f8..3faaec5 100644 --- a/sysdeps/unix/sysv/linux/isatty.c +++ b/sysdeps/unix/sysv/linux/isatty.c @@ -24,6 +24,6 @@ int __isatty (int fd) { struct termios2 k_termios; - return INLINE_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios) == 0; + return INLINE_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios) == 0; } weak_alias (__isatty, isatty) diff --git a/sysdeps/unix/sysv/linux/isatty_nostatus.c b/sysdeps/unix/sysv/linux/isatty_nostatus.c index 9970442..406decb 100644 --- a/sysdeps/unix/sysv/linux/isatty_nostatus.c +++ b/sysdeps/unix/sysv/linux/isatty_nostatus.c @@ -22,5 +22,5 @@ int __isatty_nostatus (int fd) { struct termios2 k_termios; - return INTERNAL_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios) == 0; + return INTERNAL_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios) == 0; } diff --git a/sysdeps/unix/sysv/linux/mips/old_termios.h b/sysdeps/unix/sysv/linux/mips/termios_arch.h index 8164742..392d9aa 100644 --- a/sysdeps/unix/sysv/linux/mips/old_termios.h +++ b/sysdeps/unix/sysv/linux/mips/termios_arch.h @@ -1,6 +1,6 @@ -/* old_termios.h for MIPS. +/* Architectural parameters for Linux termios - MIPS version - Copyright (C) 2025 Free Software Foundation, Inc. + Copyright (C) 1991-2025 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,15 +17,18 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ +#define _TERMIOS2_NCCS 23 +#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0 + #define _HAVE_STRUCT_OLD_TERMIOS 1 #define OLD_NCCS 32 -typedef struct old_termios +struct old_termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[OLD_NCCS]; /* control characters */ -} old_termios_t; + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[OLD_NCCS]; /* control characters */ +}; diff --git a/sysdeps/unix/sysv/linux/powerpc/internal-ioctl.h b/sysdeps/unix/sysv/linux/powerpc/internal-ioctl.h index 94cfd71..6c21357 100644 --- a/sysdeps/unix/sysv/linux/powerpc/internal-ioctl.h +++ b/sysdeps/unix/sysv/linux/powerpc/internal-ioctl.h @@ -1,4 +1,4 @@ -/* Linux internal definitions for ioctl. powerpc version. +/* Linux internal definitions for ioctl. Copyright (C) 2021-2025 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,40 +17,27 @@ <https://www.gnu.org/licenses/>. */ #include <termios.h> -#include <termios_internals.h> -#include <assert.h> - -/* PowerPC quirk: on PowerPC only, ioctl() emulates the TCGETS/TCSETS* - ioctls with tcgetattr/tcsetattr using the glibc struct termios. - As struct termios2 is the same as the kernel struct termios on PowerPC, - simply consider the kernel ones as the termios2 interface, even - though the kernel doesn't call it that. */ - -#define GLIBC_TCGETS _IOR ('t', 19, struct termios) -#define GLIBC_TCSETS _IOW ('t', 20, struct termios) -#define GLIBC_TCSETSW _IOW ('t', 21, struct termios) -#define GLIBC_TCSETSF _IOW ('t', 22, struct termios) +/* The user-visible size of struct termios has changed. Catch ioctl calls + using the new-style struct termios, and translate them to old-style. */ static inline bool __ioctl_arch (int *r, int fd, unsigned long request, void *arg) { - static_assert (GLIBC_TCGETS != KERNEL_TCGETS2, - "emulation not possible due to matching ioctl constants"); switch (request) { - case GLIBC_TCGETS: + case TCGETS: *r = __tcgetattr (fd, (struct termios *) arg); break; - case GLIBC_TCSETS: + case TCSETS: *r = __tcsetattr (fd, TCSANOW, (struct termios *) arg); break; - case GLIBC_TCSETSW: + case TCSETSW: *r = __tcsetattr (fd, TCSADRAIN, (struct termios *) arg); break; - case GLIBC_TCSETSF: + case TCSETSF: *r = __tcsetattr (fd, TCSAFLUSH, (struct termios *) arg); break; diff --git a/sysdeps/unix/sysv/linux/powerpc/termios_arch.h b/sysdeps/unix/sysv/linux/powerpc/termios_arch.h new file mode 100644 index 0000000..919b437 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/termios_arch.h @@ -0,0 +1,33 @@ +/* Architectural parameters for Linux termios - PowerPC version + + Copyright (C) 1997-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#define _TERMIOS2_NCCS 19 +#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 1 +#define _HAVE_STRUCT_OLD_TERMIOS 0 + +/* PowerPC quirk: on PowerPC only, ioctl() emulates the TCGETS/TCSETS* + ioctls with tcgetattr/tcsetattr using the glibc struct termios. + As struct termios2 is the same as the kernel struct termios on PowerPC, + simply consider the kernel ones as the termios2 interface, even + though the kernel doesn't call it that. */ + +#define TCGETS2 _IOR ('t', 19, struct termios2) +#define TCSETS2 _IOW ('t', 20, struct termios2) +#define TCSETSW2 _IOW ('t', 21, struct termios2) +#define TCSETSF2 _IOW ('t', 22, struct termios2) diff --git a/sysdeps/unix/sysv/linux/sparc/bits/ioctls.h b/sysdeps/unix/sysv/linux/sparc/bits/ioctls.h new file mode 100644 index 0000000..1a95466 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/bits/ioctls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1996-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_IOCTL_H +# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include <asm/ioctls.h> + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('T', 8, char[36]) +#define TCSETS _IOW ('T', 9, char[36]) +#define TCSETSW _IOW ('T', 10, char[36]) +#define TCSETSF _IOW ('T', 11, char[36]) + +#include <linux/sockios.h> diff --git a/sysdeps/unix/sysv/linux/sparc/old_termios.h b/sysdeps/unix/sysv/linux/sparc/termios_arch.h index d7af589..f3b3f65 100644 --- a/sysdeps/unix/sysv/linux/sparc/old_termios.h +++ b/sysdeps/unix/sysv/linux/sparc/termios_arch.h @@ -1,6 +1,6 @@ -/* old_termios.h for SPARC. +/* Architectural parameters for Linux termios - SPARC version - Copyright (C) 2025 Free Software Foundation, Inc. + Copyright (C) 1991-2025 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,15 +17,18 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ +#define _TERMIOS2_NCCS 19 +#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0 + #define _HAVE_STRUCT_OLD_TERMIOS 1 #define OLD_NCCS 17 -typedef struct old_termios +struct old_termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[OLD_NCCS]; /* control characters */ -} old_termios_t; + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[OLD_NCCS]; /* control characters */ +}; diff --git a/sysdeps/unix/sysv/linux/tcgetattr.c b/sysdeps/unix/sysv/linux/tcgetattr.c index 36f68a7..ca17569 100644 --- a/sysdeps/unix/sysv/linux/tcgetattr.c +++ b/sysdeps/unix/sysv/linux/tcgetattr.c @@ -22,7 +22,7 @@ int __tcgetattr (int fd, struct termios *termios_p) { struct termios2 k_termios; - long int retval = INLINE_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios); + long int retval = INLINE_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios); if (__glibc_likely (retval != -1)) { diff --git a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c index ad8f2df..4f07a03 100644 --- a/sysdeps/unix/sysv/linux/tcsetattr.c +++ b/sysdeps/unix/sysv/linux/tcsetattr.c @@ -19,12 +19,6 @@ #define static_assert_equal(x,y) _Static_assert ((x) == (y), #x " != " #y) -static_assert_equal (sizeof (struct termios2), KERNEL_TERMIOS2_SIZE); -static_assert_equal (offsetof (struct termios2, c_cc), - KERNEL_TERMIOS2_CC_OFFSET); -static_assert_equal (offsetof (struct termios2, c_line), - KERNEL_TERMIOS2_LINE_OFFSET); - /* Set the state of FD to *TERMIOS_P. */ int __tcsetattr (int fd, int optional_actions, const struct termios *termios_p) @@ -59,10 +53,10 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p) */ static_assert_equal(TCSADRAIN, TCSANOW + 1); static_assert_equal(TCSAFLUSH, TCSANOW + 2); - static_assert_equal(KERNEL_TCSETSW2, KERNEL_TCSETS2 + 1); - static_assert_equal(KERNEL_TCSETSF2, KERNEL_TCSETS2 + 2); - static_assert_equal(KERNEL_TCSETSW, KERNEL_TCSETS + 1); - static_assert_equal(KERNEL_TCSETSF, KERNEL_TCSETS + 2); + static_assert_equal(TCSETSW2, TCSETS2 + 1); + static_assert_equal(TCSETSF2, TCSETS2 + 2); + static_assert_equal(TCSETSW, TCSETS + 1); + static_assert_equal(TCSETSF, TCSETS + 2); cmd = (long)optional_actions - TCSANOW; if (cmd > 2) @@ -72,11 +66,11 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p) k_termios.c_ospeed != k_termios.c_ispeed || cbaud (k_termios.c_cflag) == __BOTHER) { - cmd += KERNEL_TCSETS2; + cmd += TCSETS2; } else { - cmd += KERNEL_TCSETS; + cmd += TCSETS; k_termios.c_cflag &= ~CIBAUD; } diff --git a/sysdeps/unix/sysv/linux/termios-kernel-consts.sym b/sysdeps/unix/sysv/linux/termios-kernel-consts.sym deleted file mode 100644 index 3856a8c..0000000 --- a/sysdeps/unix/sysv/linux/termios-kernel-consts.sym +++ /dev/null @@ -1,26 +0,0 @@ -#include <linux/termios.h> -#include <stddef.h> - -#ifdef TCGETS2 -# define STRUCT_TERMIOS struct termios2 -#else -# define TCGETS2 TCGETS -# define TCSETS2 TCSETS -# define TCSETSW2 TCSETSW -# define TCSETSF2 TCSETSF -# define STRUCT_TERMIOS struct termios -#endif - --- -KERNEL_TCGETS TCGETS -KERNEL_TCSETS TCSETS -KERNEL_TCSETSF TCSETSF -KERNEL_TCSETSW TCSETSW -KERNEL_TCGETS2 TCGETS2 -KERNEL_TCSETS2 TCSETS2 -KERNEL_TCSETSF2 TCSETSF2 -KERNEL_TCSETSW2 TCSETSW2 -KERNEL_TERMIOS2_SIZE sizeof (STRUCT_TERMIOS) -KERNEL_TERMIOS2_CC_OFFSET offsetof (STRUCT_TERMIOS, c_cc) -KERNEL_TERMIOS2_LINE_OFFSET offsetof (STRUCT_TERMIOS, c_line) -_TERMIOS2_NCCS sizeof ((STRUCT_TERMIOS) { 0 }.c_cc) / sizeof (cc_t) diff --git a/sysdeps/unix/sysv/linux/termios_arch.h b/sysdeps/unix/sysv/linux/termios_arch.h new file mode 100644 index 0000000..8dbf420 --- /dev/null +++ b/sysdeps/unix/sysv/linux/termios_arch.h @@ -0,0 +1,23 @@ +/* Architectural parameters for Linux termios - generic version + + Copyright (C) 1997-2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#define _TERMIOS2_NCCS 19 +#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0 + +#define _HAVE_STRUCT_OLD_TERMIOS 0 diff --git a/sysdeps/unix/sysv/linux/termios_internals.h b/sysdeps/unix/sysv/linux/termios_internals.h index b2f3f1b..e8dbfe7 100644 --- a/sysdeps/unix/sysv/linux/termios_internals.h +++ b/sysdeps/unix/sysv/linux/termios_internals.h @@ -30,18 +30,7 @@ #include <sysdep.h> #include <shlib-compat.h> -#include <termios-kernel-consts.h> - -/* Alpha got termios2 late, but TCGETS has exactly the same structure - format and function as TCGETS2. On all other platforms, the termios2 - interface exists as far back as this version of glibc supports. - - For TCSETS* it is more complicated; this is handled in tcsetattr.c. */ -#ifdef __ASSUME_TERMIOS2 -# define ARCH_TCGETS KERNEL_TCGETS2 -#else -# define ARCH_TCGETS KERNEL_TCGETS -#endif +#include <termios_arch.h> /* ---- Kernel interface definitions ---- */ @@ -55,7 +44,7 @@ struct termios2 tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ -#if KERNEL_TERMIOS2_CC_OFFSET < KERNEL_TERMIOS2_LINE_OFFSET +#if _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE cc_t c_cc[_TERMIOS2_NCCS]; /* control characters */ cc_t c_line; /* line discipline */ #else @@ -66,6 +55,26 @@ struct termios2 speed_t c_ospeed; /* output speed */ }; +/* Alpha got termios2 late, but TCGETS has exactly the same structure + format and function as TCGETS2. On all other platforms, the termios2 + interface exists as far back as this version of glibc supports. + + For TCSETS* it is more complicated; this is handled in tcsetattr.c. + + Some other architectures only have the equivalent of the termios2 + interface, in which case the old ioctl names are the only ones + presented, but are equivalent to the new ones. */ +#ifndef TCGETS2 +# define TCGETS2 TCGETS +# define TCSETS2 TCSETS +# define TCSETSW2 TCSETSW +# define TCSETSF2 TCSETSF +#elif !__ASSUME_TERMIOS2 +/* Hack for Alpha */ +# undef TCGETS2 +# define TCGETS2 TCGETS +#endif + /* ---- Application interface definitions ---- */ /* @@ -82,7 +91,12 @@ struct termios2 * This only applies to SPARC and MIPS; for other architectures the * new and old speed_t interfaces both use the same struct termios. */ -#include <old_termios.h> +#if _HAVE_STRUCT_OLD_TERMIOS +typedef struct old_termios old_termios_t; +#else +# define OLD_NCCS NCCS +typedef struct termios old_termios_t; +#endif /* ---- Internal function definitions ---- */ diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure index c7ea9ac..dff26e9 100644 --- a/sysdeps/x86/configure +++ b/sysdeps/x86/configure @@ -171,8 +171,12 @@ fi config_vars="$config_vars have-x86-isa-level = $libc_cv_have_x86_isa_level" config_vars="$config_vars +x86-isa-level-2-or-above = 2 3 4" +config_vars="$config_vars x86-isa-level-3-or-above = 3 4" config_vars="$config_vars +x86-isa-level-4-or-above = 4" +config_vars="$config_vars enable-x86-isa-level = $libc_cv_include_x86_isa_level" diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac index 031f917..54960a7 100644 --- a/sysdeps/x86/configure.ac +++ b/sysdeps/x86/configure.ac @@ -117,7 +117,9 @@ else AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, $libc_cv_have_x86_isa_level) fi LIBC_CONFIG_VAR([have-x86-isa-level], [$libc_cv_have_x86_isa_level]) +LIBC_CONFIG_VAR([x86-isa-level-2-or-above], [2 3 4]) LIBC_CONFIG_VAR([x86-isa-level-3-or-above], [3 4]) +LIBC_CONFIG_VAR([x86-isa-level-4-or-above], [4]) LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level]) dnl Check if TEST_CC supports -mfpmath=387 diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile index c3e1065..8cace35 100644 --- a/sysdeps/x86_64/Makefile +++ b/sysdeps/x86_64/Makefile @@ -11,6 +11,7 @@ endif ifeq ($(subdir),csu) gen-as-const-headers += link-defines.sym +gen-as-const-headers += tlsdesc.sym rtld-offsets.sym endif ifeq ($(subdir),gmon) @@ -235,10 +236,6 @@ $(objpfx)check-rtld.out: $(objpfx)rtld.reloc generated += check-rtld.out endif # $(subdir) == elf -ifeq ($(subdir),csu) -gen-as-const-headers += tlsdesc.sym rtld-offsets.sym -endif - ifeq ($(subdir),wcsmbs) sysdep_routines += \ @@ -269,6 +266,15 @@ endif ifneq ($(enable-cet),no) +# Add -fcf-protection to CFLAGS when CET is enabled. +CFLAGS-.o += -fcf-protection +CFLAGS-.os += -fcf-protection +CFLAGS-.op += -fcf-protection +CFLAGS-.oS += -fcf-protection + +# Compile assembly codes with <cet.h> when CET is enabled. +asm-CPPFLAGS += -fcf-protection -include cet.h + ifeq ($(subdir),elf) sysdep-dl-routines += dl-cet @@ -461,18 +467,7 @@ $(objpfx)tst-shstk-legacy-1g.out: \ $(..)/sysdeps/x86_64/tst-shstk-legacy-1g.sh $(objpfx)tst-shstk-legacy-1g $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' 2> $@; \ $(evaluate-test) -endif - -# Add -fcf-protection to CFLAGS when CET is enabled. -CFLAGS-.o += -fcf-protection -CFLAGS-.os += -fcf-protection -CFLAGS-.op += -fcf-protection -CFLAGS-.oS += -fcf-protection - -# Compile assembly codes with <cet.h> when CET is enabled. -asm-CPPFLAGS += -fcf-protection -include cet.h -ifeq ($(subdir),elf) ifeq (yes,$(build-shared)) tests-special += $(objpfx)check-cet.out endif diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index bbf520b..32324f6 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -289,6 +289,8 @@ fi config_vars="$config_vars have-x86-apx = $libc_cv_x86_have_apx" +libc_cv_support_sframe=yes + test -n "$critic_missing" && as_fn_error $? " *** $critic_missing" "$LINENO" 5 diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index 4a3f7f4..a00958e 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -104,5 +104,7 @@ if test $libc_cv_x86_have_apx = yes; then fi LIBC_CONFIG_VAR([have-x86-apx], [$libc_cv_x86_have_apx]) +libc_cv_support_sframe=yes + test -n "$critic_missing" && AC_MSG_ERROR([ *** $critic_missing]) diff --git a/sysdeps/x86_64/fpu/multiarch/Makefile b/sysdeps/x86_64/fpu/multiarch/Makefile index 5fe872b..708b142 100644 --- a/sysdeps/x86_64/fpu/multiarch/Makefile +++ b/sysdeps/x86_64/fpu/multiarch/Makefile @@ -26,19 +26,21 @@ CFLAGS-s_sinf-fma.c = -mfma -mavx2 CFLAGS-s_cosf-fma.c = -mfma -mavx2 CFLAGS-s_sincosf-fma.c = -mfma -mavx2 +# Check if ISA level is 2 or above. +ifeq (,$(filter $(have-x86-isa-level),$(x86-isa-level-2-or-above))) +sysdep_calls += \ + s_modf-sse4_1 \ + s_modff-sse4_1 \ +# sysdep_calls +endif + # Check if ISA level is 3 or above. ifneq (,$(filter $(have-x86-isa-level),$(x86-isa-level-3-or-above))) -sysdep_routines += \ - s_modf-avx \ - s_modff-avx \ -# sysdep_routines libm-sysdep_routines += \ s_ceil-avx \ s_ceilf-avx \ s_floor-avx \ s_floorf-avx \ - s_modf-avx \ - s_modff-avx \ s_nearbyint-avx \ s_nearbyintf-avx \ s_rint-avx \ @@ -49,6 +51,10 @@ libm-sysdep_routines += \ s_truncf-avx \ # libm-sysdep_routines else +sysdep_calls += \ + s_modf-avx \ + s_modff-avx \ +# sysdep_calls ifeq (no,$(have-x86-apx)) libm-sysdep_routines += \ e_asin-fma4 \ @@ -62,10 +68,6 @@ libm-sysdep_routines += \ s_tan-fma4 \ # libm-sysdep_routines endif -sysdep_routines += \ - s_modf-sse4_1 \ - s_modff-sse4_1 \ -# sysdep_routines libm-sysdep_routines += \ e_asin-fma \ e_atan2-avx \ @@ -95,8 +97,6 @@ libm-sysdep_routines += \ s_floor-sse4_1 \ s_floorf-sse4_1 \ s_log1p-fma \ - s_modf-sse4_1 \ - s_modff-sse4_1 \ s_nearbyint-sse4_1 \ s_nearbyintf-sse4_1 \ s_rint-sse4_1 \ @@ -118,17 +118,11 @@ libm-sysdep_routines += \ s_truncf-sse4_1 \ # libm-sysdep_routines ifeq ($(have-x86-isa-level),baseline) -sysdep_routines += \ - s_modf-c \ - s_modff-c \ -# sysdep-routines libm-sysdep_routines += \ s_ceil-c \ s_ceilf-c \ s_floor-c \ s_floorf-c \ - s_modf-c \ - s_modff-c \ s_nearbyint-c \ s_nearbyintf-c \ s_rint-c \ @@ -139,6 +133,11 @@ libm-sysdep_routines += \ s_truncf-c \ # libm-sysdep_routines endif + +# $(sysdep_calls) functions are built both for libc and libm. While the +# libc objects have the prefix s_, the libm ones are prefixed with m_. +sysdep_routines += $(sysdep_calls) +libm-sysdep_routines += $(sysdep_calls:s_%=m_%) endif CFLAGS-e_asin-fma4.c = -mfma4 @@ -162,8 +161,8 @@ CFLAGS-s_sincos-avx.c = -msse2avx -DSSE2AVX CFLAGS-s_modf-sse4_1.c = -msse4.1 -fno-builtin-modff32x -fno-builtin-modff64 CFLAGS-s_modff-sse4_1.c = -msse4.1 -fno-builtin-modff32 -CFLAGS-s_modf-avx.c = -msse2avx -DSSE2AVX -fno-builtin-modff32x -fno-builtin-modff64 -CFLAGS-s_modff-avx.c = -msse2avx -DSSE2AVX -fno-builtin-modff32 +CFLAGS-s_modf-avx.c = -mavx -fno-builtin-modff32x -fno-builtin-modff64 +CFLAGS-s_modff-avx.c = -mavx -fno-builtin-modff32 endif ifeq ($(subdir),mathvec) diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h new file mode 100644 index 0000000..071595f --- /dev/null +++ b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1-avx.h @@ -0,0 +1,41 @@ +/* Common definition for ifunc selections optimized with SSE4.1 and AVX. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <init-arch.h> + +extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden; +extern __typeof (REDIRECT_NAME) OPTIMIZE (sse41) attribute_hidden; +extern __typeof (REDIRECT_NAME) OPTIMIZE (avx) attribute_hidden; + +static inline void * +IFUNC_SELECTOR (void) +{ + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX)) + return OPTIMIZE (avx); + +#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL + return OPTIMIZE (sse41); +#else + if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)) + return OPTIMIZE (sse41); + + return OPTIMIZE (sse2); +#endif +} diff --git a/sysdeps/x86_64/fpu/multiarch/s_modf-avx.c b/sysdeps/x86_64/fpu/multiarch/s_modf-avx.c index db32398..ab4f03d 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modf-avx.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modf-avx.c @@ -1 +1,3 @@ +#define __modf __modf_avx + #include <sysdeps/ieee754/dbl-64/s_modf.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modf-c.c b/sysdeps/x86_64/fpu/multiarch/s_modf-c.c deleted file mode 100644 index 6679d32..0000000 --- a/sysdeps/x86_64/fpu/multiarch/s_modf-c.c +++ /dev/null @@ -1,2 +0,0 @@ -#define __modf __modf_c -#include <sysdeps/ieee754/dbl-64/s_modf.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modf-sse4_1.c b/sysdeps/x86_64/fpu/multiarch/s_modf-sse4_1.c index 6ef4c19..00aa8cd 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modf-sse4_1.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modf-sse4_1.c @@ -1,7 +1,3 @@ -#include <sysdeps/x86/isa-level.h> - -#if MINIMUM_X86_ISA_LEVEL != SSE4_1_X86_ISA_LEVEL -# define __modf __modf_sse41 -#endif +#define __modf __modf_sse41 #include <sysdeps/ieee754/dbl-64/s_modf.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modf.c b/sysdeps/x86_64/fpu/multiarch/s_modf.c index d65977d..e365bfc 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modf.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modf.c @@ -17,7 +17,7 @@ <https://www.gnu.org/licenses/>. */ #include <sysdeps/x86/isa-level.h> -#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL +#if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL # define NO_MATH_REDIRECT # include <libm-alias-double.h> @@ -28,8 +28,14 @@ # undef __modf # define SYMBOL_NAME modf -# include "ifunc-sse4_1.h" +# include "ifunc-sse4_1-avx.h" libc_ifunc_redirected (__redirect_modf, __modf, IFUNC_SELECTOR ()); libm_alias_double (__modf, modf) +# if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL +# define __modf __modf_sse41 +# else +# define __modf __modf_sse2 +# endif #endif +#include <sysdeps/ieee754/dbl-64/s_modf.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modff-avx.c b/sysdeps/x86_64/fpu/multiarch/s_modff-avx.c index 804b042..07cb9c1 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modff-avx.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modff-avx.c @@ -1 +1,3 @@ +#define __modff __modff_avx + #include <sysdeps/ieee754/flt-32/s_modff.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modff-c.c b/sysdeps/x86_64/fpu/multiarch/s_modff-c.c deleted file mode 100644 index f54f8ea..0000000 --- a/sysdeps/x86_64/fpu/multiarch/s_modff-c.c +++ /dev/null @@ -1,2 +0,0 @@ -#define __modff __modff_c -#include <sysdeps/ieee754/flt-32/s_modff.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modff-sse4_1.c b/sysdeps/x86_64/fpu/multiarch/s_modff-sse4_1.c index 0437e04..060c5e3 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modff-sse4_1.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modff-sse4_1.c @@ -1,7 +1,3 @@ -#include <sysdeps/x86/isa-level.h> - -#if MINIMUM_X86_ISA_LEVEL != SSE4_1_X86_ISA_LEVEL -# define __modff __modff_sse41 -#endif +#define __modff __modff_sse41 #include <sysdeps/ieee754/flt-32/s_modff.c> diff --git a/sysdeps/x86_64/fpu/multiarch/s_modff.c b/sysdeps/x86_64/fpu/multiarch/s_modff.c index 89d0a32..a4b5429 100644 --- a/sysdeps/x86_64/fpu/multiarch/s_modff.c +++ b/sysdeps/x86_64/fpu/multiarch/s_modff.c @@ -17,7 +17,7 @@ <https://www.gnu.org/licenses/>. */ #include <sysdeps/x86/isa-level.h> -#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL +#if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL # define NO_MATH_REDIRECT # include <libm-alias-float.h> @@ -28,8 +28,14 @@ # undef __modff # define SYMBOL_NAME modff -# include "ifunc-sse4_1.h" +# include "ifunc-sse4_1-avx.h" libc_ifunc_redirected (__redirect_modff, __modff, IFUNC_SELECTOR ()); libm_alias_float (__modf, modf) +# if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL +# define __modff __modff_sse41 +# else +# define __modff __modff_sse2 +# endif #endif +#include <sysdeps/ieee754/flt-32/s_modff.c> |