From 3d2ae374acf034670097ae572597eef1eaf42053 Mon Sep 17 00:00:00 2001 From: GNU Libc Maintainers Date: Thu, 17 Mar 2022 21:37:00 +0000 Subject: [PATCH] git-updates GIT update of https://sourceware.org/git/glibc.git/release/2.31/master from glibc-2.31 GIT update of https://sourceware.org/git/glibc.git/release/2.31/master from glibc-2.31 Gbp-Pq: Name git-updates.diff --- NEWS | 72 ++++ Rules | 19 +- configure | 2 +- configure.ac | 2 +- debug/backtrace.c | 5 + elf/Makefile | 4 +- elf/dl-tunables.c | 56 ++- elf/ifuncmain6pie.c | 14 +- elf/ifuncmod6.c | 8 +- elf/tst-env-setuid-tunables.c | 118 ++++-- elf/tst-env-setuid.c | 197 +--------- iconv/Makefile | 17 +- iconv/Versions | 3 + iconv/gconv_charset.c | 228 ++++++++++++ iconv/gconv_charset.h | 34 +- iconv/gconv_int.h | 40 +- iconv/gconv_open.c | 64 +--- iconv/gconv_simple.c | 16 +- iconv/iconv_open.c | 46 +-- iconv/iconv_prog.c | 63 ++-- iconv/tst-iconv-opt.c | 347 ++++++++++++++++++ iconv/tst-iconv8.c | 50 +++ iconv/tst-iconv_prog.sh | 284 ++++++++++++++ iconvdata/Makefile | 8 +- iconvdata/bug-iconv13.c | 53 +++ iconvdata/bug-iconv14.c | 127 +++++++ iconvdata/bug-iconv15.c | 60 +++ iconvdata/euc-kr.c | 6 +- iconvdata/ibm1364.c | 14 +- iconvdata/iso-2022-jp-3.c | 77 +++- iconvdata/ksc5601.h | 6 +- include/libc-symbols.h | 26 +- include/sys/prctl.h | 1 + include/sys/un.h | 12 + intl/dcigettext.c | 16 +- intl/tst-codeset.c | 34 +- localedata/locales/oc_FR | 6 +- malloc/Makefile | 20 + malloc/tst-mallocfork2.c | 39 +- math/Makefile | 122 ++++++ misc/Makefile | 2 +- misc/tst-syscalls.c | 167 +++++++++ nptl/Makefile | 2 +- nptl/descr.h | 8 +- nptl/tst-setgroups.c | 79 ++++ nscd/netgroupcache.c | 4 +- nscd/selinux.c | 15 + nss/makedb.c | 9 + nss/nss_compat/compat-grp.c | 15 +- nss/nss_compat/compat-initgroups.c | 13 +- nss/nss_compat/compat-pwd.c | 15 +- nss/nss_compat/compat-spwd.c | 14 +- posix/glob.c | 25 +- posix/wordexp-test.c | 1 + posix/wordexp.c | 2 +- socket/Makefile | 6 +- socket/sockaddr_un_set.c | 41 +++ socket/tst-sockaddr_un_set.c | 62 ++++ stdlib/Makefile | 3 +- stdlib/tst-secure-getenv.c | 199 +--------- stdlib/tst-system.c | 124 ++++++- sunrpc/Makefile | 5 +- sunrpc/clnt_gen.c | 10 +- sunrpc/svc_unix.c | 11 +- sunrpc/tst-bug22542.c | 44 +++ sunrpc/tst-bug28768.c | 42 +++ support/capture_subprocess.h | 6 + support/shell-container.c | 40 +- support/subprocess.h | 5 + support/support_capture_subprocess.c | 128 ++++++- support/support_subprocess.c | 21 +- sysdeps/aarch64/dl-machine.h | 12 +- sysdeps/aarch64/memcpy.S | 197 +++++----- sysdeps/aarch64/multiarch/Makefile | 2 +- sysdeps/aarch64/multiarch/ifunc-impl-list.c | 2 + sysdeps/aarch64/multiarch/memcpy.c | 8 +- sysdeps/aarch64/multiarch/memcpy_advsimd.S | 248 +++++++++++++ sysdeps/aarch64/multiarch/memmove.c | 6 +- sysdeps/aarch64/strcpy.S | 5 + sysdeps/aarch64/strnlen.S | 5 + sysdeps/aarch64/sysdep.h | 2 +- sysdeps/arm/armv7/multiarch/memcpy_impl.S | 22 +- sysdeps/arm/be/nofpu/Implies | 1 + sysdeps/arm/le/nofpu/Implies | 1 + sysdeps/arm/memcpy.S | 24 +- sysdeps/arm/memmove.S | 24 +- .../unwind-arch.h} | 18 +- sysdeps/hppa/dl-fptr.c | 26 +- sysdeps/hppa/dl-machine.h | 36 +- sysdeps/hppa/dl-runtime.c | 58 +++ sysdeps/hppa/dl-trampoline.S | 74 +++- sysdeps/i386/dl-machine.h | 16 +- sysdeps/i386/sysdep.h | 5 +- sysdeps/ieee754/ldbl-96/Makefile | 5 +- sysdeps/ieee754/ldbl-96/e_rem_pio2l.c | 12 + sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c | 41 +++ sysdeps/posix/system.c | 18 +- sysdeps/powerpc/powerpc32/sysdep.h | 4 +- sysdeps/powerpc/powerpc64/backtrace.c | 13 +- sysdeps/s390/configure | 8 +- sysdeps/s390/configure.ac | 8 +- sysdeps/s390/memmove.c | 2 +- sysdeps/s390/multiarch/ifunc-impl-list.c | 3 +- sysdeps/sh/be/sh4/fpu/Implies | 1 + sysdeps/sh/le/sh4/fpu/Implies | 1 + sysdeps/unix/make-syscalls.sh | 24 ++ sysdeps/unix/syscall-template.S | 49 ++- sysdeps/unix/syscalls.list | 22 +- sysdeps/unix/sysv/linux/Makefile | 4 +- .../unix/sysv/linux/aarch64/arch-syscall.h | 1 + .../unix/sysv/linux/aarch64/cpu-features.h | 8 +- sysdeps/unix/sysv/linux/aarch64/localplt.data | 3 + sysdeps/unix/sysv/linux/hppa/atomic-machine.h | 28 ++ sysdeps/unix/sysv/linux/microblaze/sysdep.h | 91 +++-- .../sysv/linux/mips/mips32/mips-syscall5.S | 6 +- .../sysv/linux/mips/mips32/mips-syscall6.S | 6 +- .../sysv/linux/mips/mips32/mips-syscall7.S | 7 +- .../linux/mips/mips32/mips16/mips16-syscall.h | 64 ++-- .../mips/mips32/mips16/mips16-syscall0.c | 4 +- .../mips/mips32/mips16/mips16-syscall1.c | 6 +- .../mips/mips32/mips16/mips16-syscall2.c | 6 +- .../mips/mips32/mips16/mips16-syscall3.c | 6 +- .../mips/mips32/mips16/mips16-syscall4.c | 6 +- sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 145 ++++---- .../unix/sysv/linux/mips/mips64/n32/sysdep.h | 121 +++--- .../unix/sysv/linux/mips/mips64/n64/sysdep.h | 119 +++--- sysdeps/unix/sysv/linux/mips/mips64/syscall.S | 2 +- sysdeps/unix/sysv/linux/mips/sysdep.h | 4 +- sysdeps/unix/sysv/linux/mips/unwind-arch.h | 67 ++++ sysdeps/unix/sysv/linux/msgctl.c | 10 +- .../sysv/linux/powerpc/powerpc32/sysdep.h | 24 +- .../sysv/linux/powerpc/powerpc64/sysdep.h | 24 +- sysdeps/unix/sysv/linux/prctl.c | 42 +++ sysdeps/unix/sysv/linux/process_vm_readv.c | 32 ++ sysdeps/unix/sysv/linux/process_vm_writev.c | 32 ++ sysdeps/unix/sysv/linux/riscv/sysdep.h | 84 +++-- sysdeps/unix/sysv/linux/semctl.c | 10 +- sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies | 1 + sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies | 1 + sysdeps/unix/sysv/linux/shmctl.c | 10 +- sysdeps/unix/sysv/linux/sparc/Makefile | 8 +- .../unix/sysv/linux/sparc/sparc32/sigaction.c | 26 +- .../sysv/linux/sparc/sparc32/sigreturn_stub.S | 34 ++ .../unix/sysv/linux/sparc/sparc64/sigaction.c | 14 +- .../sysv/linux/sparc/sparc64/sigreturn_stub.S | 29 ++ sysdeps/unix/sysv/linux/syscall-names.list | 4 +- sysdeps/unix/sysv/linux/syscalls.list | 41 +-- sysdeps/unix/sysv/linux/x86_64/sysdep.h | 86 ++++- sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 35 ++ sysdeps/x86/Makefile | 6 + sysdeps/x86/cacheinfo.c | 36 +- sysdeps/x86/dl-cet.c | 6 +- sysdeps/x86/tst-setjmp-cet.c | 1 + sysdeps/x86_64/configure | 33 -- sysdeps/x86_64/configure.ac | 25 -- sysdeps/x86_64/dl-machine.h | 16 +- .../multiarch/memmove-vec-unaligned-erms.S | 27 +- sysdeps/x86_64/multiarch/strcmp-avx2.S | 15 + 158 files changed, 4439 insertions(+), 1414 deletions(-) create mode 100644 iconv/gconv_charset.c create mode 100644 iconv/tst-iconv-opt.c create mode 100644 iconv/tst-iconv8.c create mode 100644 iconv/tst-iconv_prog.sh create mode 100644 iconvdata/bug-iconv13.c create mode 100644 iconvdata/bug-iconv14.c create mode 100644 iconvdata/bug-iconv15.c create mode 100644 misc/tst-syscalls.c create mode 100644 nptl/tst-setgroups.c create mode 100644 socket/sockaddr_un_set.c create mode 100644 socket/tst-sockaddr_un_set.c create mode 100644 sunrpc/tst-bug22542.c create mode 100644 sunrpc/tst-bug28768.c create mode 100644 sysdeps/aarch64/multiarch/memcpy_advsimd.S create mode 100644 sysdeps/arm/be/nofpu/Implies create mode 100644 sysdeps/arm/le/nofpu/Implies rename sysdeps/{unix/sysv/linux/nios2/kernel-features.h => generic/unwind-arch.h} (72%) create mode 100644 sysdeps/hppa/dl-runtime.c create mode 100644 sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c create mode 100644 sysdeps/sh/be/sh4/fpu/Implies create mode 100644 sysdeps/sh/le/sh4/fpu/Implies create mode 100644 sysdeps/unix/sysv/linux/mips/unwind-arch.h create mode 100644 sysdeps/unix/sysv/linux/prctl.c create mode 100644 sysdeps/unix/sysv/linux/process_vm_readv.c create mode 100644 sysdeps/unix/sysv/linux/process_vm_writev.c create mode 100644 sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies create mode 100644 sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/sigreturn_stub.S create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/sigreturn_stub.S create mode 100644 sysdeps/x86/tst-setjmp-cet.c mode change 100644 => 100755 sysdeps/x86_64/configure diff --git a/NEWS b/NEWS index 292fbc595..440286763 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,78 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. +Version 2.31.1 + +The following bugs are resolved with this release: + [19519] iconv(1) with -c option hangs on illegal multi-byte sequences + (CVE-2016-10228) + [20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT + [20543] Please move from .gnu.linkonce to comdat + [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" + [23296] Data race in setting function descriptor during lazy binding + [24973] iconv encounters segmentation fault when converting 0x00 0xfe in + EUC-KR to UTF-8 (CVE-2019-25013) + [25487] sinl() stack corruption from crafted input (CVE-2020-10029) + [25523] MIPS/Linux inline syscall template is miscompiled + [25623] test-sysvmsg, test-sysvsem, test-sysvshm fail with 2.31 on 32 bit and + old kernel + [25635] arm: Wrong sysdep order selection for soft-fp + [25639] localedata: Some names of days and months wrongly spelt in + Occitan + [25715] system() returns wrong errors when posix_spawn fails + [25810] x32: Incorrect syscall entries with pointer, off_t and size_t + [25896] Incorrect prctl + [25902] Bad LOADARGS_N + [25933] Off by one error in __strncmp_avx2 + [25966] Incorrect access of __x86_shared_non_temporal_threshold for x32 + [25976] nss_compat: internal_end*ent may clobber errno, hiding ERANGE + [26224] iconv hangs when converting some invalid inputs from several IBM + character sets (CVE-2020-27618) + [26248] Incorrect argument types for INLINE_SETXID_SYSCALL + [26332] Incorrect cache line size load causes memory corruption in memset + [26383] bind_textdomain_codeset doesn't accept //TRANSLIT anymore + [26923] Assertion failure in iconv when converting invalid UCS4 (CVE-2020-29562) + [26932] libc: sh: Multiple floating point functions defined as stubs only + [27130] "rep movsb" performance issue + [27177] GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on doesn't work + [28524] Conversion from ISO-2022-JP-3 with iconv may emit spurious NULs + [28768] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create + +Security related changes: + + CVE-2016-10228: An infinite loop has been fixed in the iconv program when + invoked with the -c option and when processing invalid multi-byte input + sequences. Reported by Jan Engelhardt. + + CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack + corruption when they were passed a pseudo-zero argument. Reported by Guido + Vranken / ForAllSecure Mayhem. + + CVE-2020-1751: A defect in the PowerPC backtrace function could cause an + out-of-bounds write when executed in a signal frame context. + + CVE-2020-1752: A use-after-free vulnerability in the glob function when + expanding ~user has been fixed. + + CVE-2020-6096: A signed comparison vulnerability in the ARMv7 memcpy and + memmove functions has been fixed. Discovered by Jason Royes and Samual + Dytrych of the Cisco Security Assessment and Penetration Team (See + TALOS-2020-1019). + + CVE-2020-27618: An infinite loop has been fixed in the iconv program when + invoked with input containing redundant shift sequences in the IBM1364, + IBM1371, IBM1388, IBM1390, or IBM1399 character sets. + + CVE-2020-29562: An assertion failure has been fixed in the iconv function + when invoked with UCS4 input containing an invalid character. + + CVE-2022-23219: Passing an overlong file name to the clnt_create + legacy function could result in a stack-based buffer overflow when + using the "unix" protocol. Reported by Martin Sebor. + + CVE-2022-23218: Passing an overlong file name to the svcunix_create + legacy function could result in a stack-based buffer overflow. + Version 2.31 Major new features: diff --git a/Rules b/Rules index 8b771f609..beab969fd 100644 --- a/Rules +++ b/Rules @@ -155,6 +155,7 @@ xtests: tests $(xtests-special) else tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \ $(tests-container:%=$(objpfx)%.out) \ + $(tests-mcheck:%=$(objpfx)%-mcheck.out) \ $(tests-special) $(tests-printers-out) xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) endif @@ -165,7 +166,7 @@ ifeq ($(run-built-tests),no) tests-expected = else tests-expected = $(tests) $(tests-internal) $(tests-printers) \ - $(tests-container) + $(tests-container) $(tests-mcheck:%=%-mcheck) endif tests: $(..)scripts/merge-test-results.sh -s $(objpfx) $(subdir) \ @@ -191,6 +192,7 @@ else binaries-pie-tests = binaries-pie-notests = endif +binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck) else binaries-all-notests = binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) @@ -200,6 +202,7 @@ binaries-static-tests = binaries-static = binaries-pie-tests = binaries-pie-notests = +binaries-mcheck-tests = endif binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests) @@ -223,6 +226,14 @@ $(addprefix $(objpfx),$(binaries-shared-tests)): %: %.o \ $(+link-tests) endif +ifneq "$(strip $(binaries-mcheck-tests))" "" +$(addprefix $(objpfx),$(binaries-mcheck-tests)): %-mcheck: %.o \ + $(link-extra-libs-tests) \ + $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \ + $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) + $(+link-tests) +endif + ifneq "$(strip $(binaries-pie-tests))" "" $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \ $(link-extra-libs-tests) \ @@ -253,6 +264,12 @@ $(addprefix $(objpfx),$(binaries-static-tests)): %: %.o \ $(+link-static-tests) endif +# All mcheck tests will be run with MALLOC_CHECK_=3 +define mcheck-ENVS +$(1)-mcheck-ENV = MALLOC_CHECK_=3 +endef +$(foreach t,$(tests-mcheck),$(eval $(call mcheck-ENVS,$(t)))) + ifneq "$(strip $(tests) $(tests-internal) $(xtests) $(test-srcs))" "" # These are the implicit rules for making test outputs # from the test programs and whatever input files are present. diff --git a/configure b/configure index b959d2d98..3b98ec312 100755 --- a/configure +++ b/configure @@ -4035,7 +4035,7 @@ if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \ -o conftest conftest.S 1>&5 2>&5; then # Do a link to see if the backend supports IFUNC relocs. $READELF -r conftest 1>&5 - LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || { + LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && { libc_cv_ld_gnu_indirect_function=yes } fi diff --git a/configure.ac b/configure.ac index 49b900c1e..e20034f30 100644 --- a/configure.ac +++ b/configure.ac @@ -649,7 +649,7 @@ if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \ -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then # Do a link to see if the backend supports IFUNC relocs. $READELF -r conftest 1>&AS_MESSAGE_LOG_FD - LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || { + LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && { libc_cv_ld_gnu_indirect_function=yes } fi diff --git a/debug/backtrace.c b/debug/backtrace.c index cc4b9a5c9..69cf4c23c 100644 --- a/debug/backtrace.c +++ b/debug/backtrace.c @@ -23,6 +23,7 @@ #include #include #include +#include struct trace_arg { @@ -78,6 +79,10 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a) if (arg->cnt != -1) { arg->array[arg->cnt] = (void *) unwind_getip (ctx); + if (arg->cnt > 0) + arg->array[arg->cnt] + = unwind_arch_adjustment (arg->array[arg->cnt - 1], + arg->array[arg->cnt]); /* Check whether we make any progress. */ _Unwind_Word cfa = unwind_getcfa (ctx); diff --git a/elf/Makefile b/elf/Makefile index 632a4d8b0..f9646f9c8 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1348,6 +1348,8 @@ CFLAGS-ifuncmain7pie.c += $(pie-ccflag) CFLAGS-ifuncmain9pie.c += $(pie-ccflag) CFLAGS-tst-ifunc-textrel.c += $(pic-ccflag) +LDFLAGS-ifuncmain6pie = -Wl,-z,lazy + $(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so $(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o $(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so @@ -1581,8 +1583,6 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \ tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \ LD_HWCAP_MASK=0x1 -tst-env-setuid-tunables-ENV = \ - GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096 $(objpfx)tst-debug1: $(libdl) $(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index 44d06665b..2296ad387 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -177,6 +177,7 @@ parse_tunables (char *tunestr, char *valstring) return; char *p = tunestr; + size_t off = 0; while (true) { @@ -190,7 +191,11 @@ parse_tunables (char *tunestr, char *valstring) /* If we reach the end of the string before getting a valid name-value pair, bail out. */ if (p[len] == '\0') - return; + { + if (__libc_enable_secure) + tunestr[off] = '\0'; + return; + } /* We did not find a valid name-value pair before encountering the colon. */ @@ -216,35 +221,28 @@ parse_tunables (char *tunestr, char *valstring) if (tunable_is_name (cur->name, name)) { - /* If we are in a secure context (AT_SECURE) then ignore the tunable - unless it is explicitly marked as secure. Tunable values take - precendence over their envvar aliases. */ + /* If we are in a secure context (AT_SECURE) then ignore the + tunable unless it is explicitly marked as secure. Tunable + values take precedence over their envvar aliases. We write + the tunables that are not SXID_ERASE back to TUNESTR, thus + dropping all SXID_ERASE tunables and any invalid or + unrecognized tunables. */ if (__libc_enable_secure) { - if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE) + if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE) { - if (p[len] == '\0') - { - /* Last tunable in the valstring. Null-terminate and - return. */ - *name = '\0'; - return; - } - else - { - /* Remove the current tunable from the string. We do - this by overwriting the string starting from NAME - (which is where the current tunable begins) with - the remainder of the string. We then have P point - to NAME so that we continue in the correct - position in the valstring. */ - char *q = &p[len + 1]; - p = name; - while (*q != '\0') - *name++ = *q++; - name[0] = '\0'; - len = 0; - } + if (off > 0) + tunestr[off++] = ':'; + + const char *n = cur->name; + + while (*n != '\0') + tunestr[off++] = *n++; + + tunestr[off++] = '='; + + for (size_t j = 0; j < len; j++) + tunestr[off++] = value[j]; } if (cur->security_level != TUNABLE_SECLEVEL_NONE) @@ -257,9 +255,7 @@ parse_tunables (char *tunestr, char *valstring) } } - if (p[len] == '\0') - return; - else + if (p[len] != '\0') p += len + 1; } } diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c index 04faeb86e..4a0190683 100644 --- a/elf/ifuncmain6pie.c +++ b/elf/ifuncmain6pie.c @@ -9,7 +9,6 @@ #include "ifunc-sel.h" typedef int (*foo_p) (void); -extern foo_p foo_ptr; static int one (void) @@ -28,20 +27,17 @@ foo_ifunc (void) } extern int foo (void); -extern foo_p get_foo (void); +extern int call_foo (void); extern foo_p get_foo_p (void); -foo_p my_foo_ptr = foo; +foo_p foo_ptr = foo; int main (void) { foo_p p; - p = get_foo (); - if (p != foo) - abort (); - if ((*p) () != -30) + if (call_foo () != -30) abort (); p = get_foo_p (); @@ -52,12 +48,8 @@ main (void) if (foo_ptr != foo) abort (); - if (my_foo_ptr != foo) - abort (); if ((*foo_ptr) () != -30) abort (); - if ((*my_foo_ptr) () != -30) - abort (); if (foo () != -30) abort (); diff --git a/elf/ifuncmod6.c b/elf/ifuncmod6.c index 2e16c1d06..2f6d0715e 100644 --- a/elf/ifuncmod6.c +++ b/elf/ifuncmod6.c @@ -4,7 +4,7 @@ extern int foo (void); typedef int (*foo_p) (void); -foo_p foo_ptr = foo; +extern foo_p foo_ptr; foo_p get_foo_p (void) @@ -12,8 +12,8 @@ get_foo_p (void) return foo_ptr; } -foo_p -get_foo (void) +int +call_foo (void) { - return foo; + return foo (); } diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c index 971d5892b..ca0c8c245 100644 --- a/elf/tst-env-setuid-tunables.c +++ b/elf/tst-env-setuid-tunables.c @@ -25,35 +25,76 @@ #include "config.h" #undef _LIBC -#define test_parent test_parent_tunables -#define test_child test_child_tunables - -static int test_child_tunables (void); -static int test_parent_tunables (void); - -#include "tst-env-setuid.c" - -#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096" -#define PARENT_VALSTRING_VALUE \ - "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +const char *teststrings[] = +{ + "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.check=2:glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096:glibc.malloc.check=2", + "glibc.malloc.perturb=0x800", + "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", + "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096", + "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2", + "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096", + ":glibc.malloc.garbage=2:glibc.malloc.check=1", + "glibc.malloc.check=1:glibc.malloc.check=2", + "not_valid.malloc.check=2", + "glibc.not_valid.check=2", +}; + +const char *resultstrings[] = +{ + "glibc.malloc.mmap_threshold=4096", + "glibc.malloc.mmap_threshold=4096", + "glibc.malloc.mmap_threshold=4096", + "glibc.malloc.perturb=0x800", + "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", + "glibc.malloc.mmap_threshold=4096", + "glibc.malloc.mmap_threshold=4096", + "", + "", + "", + "", + "", + "", +}; static int -test_child_tunables (void) +test_child (int off) { const char *val = getenv ("GLIBC_TUNABLES"); #if HAVE_TUNABLES - if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0) + if (val != NULL && strcmp (val, resultstrings[off]) == 0) return 0; if (val != NULL) - printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); + printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val); return 1; #else if (val != NULL) { - printf ("GLIBC_TUNABLES not cleared\n"); + printf ("[%d] GLIBC_TUNABLES not cleared\n", off); return 1; } return 0; @@ -61,15 +102,48 @@ test_child_tunables (void) } static int -test_parent_tunables (void) +do_test (int argc, char **argv) { - const char *val = getenv ("GLIBC_TUNABLES"); + /* Setgid child process. */ + if (argc == 2) + { + if (getgid () == getegid ()) + /* This can happen if the file system is mounted nosuid. */ + FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", + (intmax_t) getgid ()); - if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0) - return 0; + int ret = test_child (atoi (argv[1])); - if (val != NULL) - printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); + if (ret != 0) + exit (1); - return 1; + exit (EXIT_SUCCESS); + } + else + { + int ret = 0; + + /* Spawn tests. */ + for (int i = 0; i < array_length (teststrings); i++) + { + char buf[INT_BUFSIZE_BOUND (int)]; + + printf ("Spawned test for %s (%d)\n", teststrings[i], i); + snprintf (buf, sizeof (buf), "%d\n", i); + if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0) + exit (1); + + int status = support_capture_subprogram_self_sgid (buf); + + /* Bail out early if unsupported. */ + if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) + return EXIT_UNSUPPORTED; + + ret |= status; + } + return ret; + } } + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c index 41dc79e83..2dbccdb69 100644 --- a/elf/tst-env-setuid.c +++ b/elf/tst-env-setuid.c @@ -29,173 +29,12 @@ #include #include +#include #include #include +#include static char SETGID_CHILD[] = "setgid-child"; -#define CHILD_STATUS 42 - -/* Return a GID which is not our current GID, but is present in the - supplementary group list. */ -static gid_t -choose_gid (void) -{ - const int count = 64; - gid_t groups[count]; - int ret = getgroups (count, groups); - if (ret < 0) - { - printf ("getgroups: %m\n"); - exit (1); - } - gid_t current = getgid (); - for (int i = 0; i < ret; ++i) - { - if (groups[i] != current) - return groups[i]; - } - return 0; -} - -/* Spawn and execute a program and verify that it returns the CHILD_STATUS. */ -static pid_t -do_execve (char **args) -{ - pid_t kid = vfork (); - - if (kid < 0) - { - printf ("vfork: %m\n"); - return -1; - } - - if (kid == 0) - { - /* Child process. */ - execve (args[0], args, environ); - _exit (-errno); - } - - if (kid < 0) - return 1; - - int status; - - if (waitpid (kid, &status, 0) < 0) - { - printf ("waitpid: %m\n"); - return 1; - } - - if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) - return EXIT_UNSUPPORTED; - - if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS) - { - printf ("Unexpected exit status %d from child process\n", - WEXITSTATUS (status)); - return 1; - } - return 0; -} - -/* Copies the executable into a restricted directory, so that we can - safely make it SGID with the TARGET group ID. Then runs the - executable. */ -static int -run_executable_sgid (gid_t target) -{ - char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", - test_dir, (intmax_t) getpid ()); - char *execname = xasprintf ("%s/bin", dirname); - int infd = -1; - int outfd = -1; - int ret = 0; - if (mkdir (dirname, 0700) < 0) - { - printf ("mkdir: %m\n"); - goto err; - } - infd = open ("/proc/self/exe", O_RDONLY); - if (infd < 0) - { - printf ("open (/proc/self/exe): %m\n"); - goto err; - } - outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); - if (outfd < 0) - { - printf ("open (%s): %m\n", execname); - goto err; - } - char buf[4096]; - for (;;) - { - ssize_t rdcount = read (infd, buf, sizeof (buf)); - if (rdcount < 0) - { - printf ("read: %m\n"); - goto err; - } - if (rdcount == 0) - break; - char *p = buf; - char *end = buf + rdcount; - while (p != end) - { - ssize_t wrcount = write (outfd, buf, end - p); - if (wrcount == 0) - errno = ENOSPC; - if (wrcount <= 0) - { - printf ("write: %m\n"); - goto err; - } - p += wrcount; - } - } - if (fchown (outfd, getuid (), target) < 0) - { - printf ("fchown (%s): %m\n", execname); - goto err; - } - if (fchmod (outfd, 02750) < 0) - { - printf ("fchmod (%s): %m\n", execname); - goto err; - } - if (close (outfd) < 0) - { - printf ("close (outfd): %m\n"); - goto err; - } - if (close (infd) < 0) - { - printf ("close (infd): %m\n"); - goto err; - } - - char *args[] = {execname, SETGID_CHILD, NULL}; - - ret = do_execve (args); - -err: - if (outfd >= 0) - close (outfd); - if (infd >= 0) - close (infd); - if (execname) - { - unlink (execname); - free (execname); - } - if (dirname) - { - rmdir (dirname); - free (dirname); - } - return ret; -} #ifndef test_child static int @@ -256,40 +95,32 @@ do_test (int argc, char **argv) if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0) { if (getgid () == getegid ()) - { - /* This can happen if the file system is mounted nosuid. */ - fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n", - (intmax_t) getgid ()); - exit (EXIT_UNSUPPORTED); - } + /* This can happen if the file system is mounted nosuid. */ + FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", + (intmax_t) getgid ()); int ret = test_child (); if (ret != 0) exit (1); - exit (CHILD_STATUS); + exit (EXIT_SUCCESS); } else { if (test_parent () != 0) exit (1); - /* Try running a setgid program. */ - gid_t target = choose_gid (); - if (target == 0) - { - fprintf (stderr, - "Could not find a suitable GID for user %jd, skipping test\n", - (intmax_t) getuid ()); - exit (0); - } + int status = support_capture_subprogram_self_sgid (SETGID_CHILD); - return run_executable_sgid (target); - } + if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) + return EXIT_UNSUPPORTED; + + if (!WIFEXITED (status)) + FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); - /* Something went wrong and our argv was corrupted. */ - _exit (1); + return 0; + } } #define TEST_FUNCTION_ARGV do_test diff --git a/iconv/Makefile b/iconv/Makefile index b8fe8c47d..f9b51e23e 100644 --- a/iconv/Makefile +++ b/iconv/Makefile @@ -26,7 +26,7 @@ headers = iconv.h gconv.h routines = iconv_open iconv iconv_close \ gconv_open gconv gconv_close gconv_db gconv_conf \ gconv_builtin gconv_simple gconv_trans gconv_cache -routines += gconv_dl +routines += gconv_dl gconv_charset vpath %.c ../locale/programs ../intl @@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION CFLAGS-simple-hash.c += -I../locale tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ - tst-iconv7 tst-iconv-mt + tst-iconv7 tst-iconv8 tst-iconv-mt tst-iconv-opt others = iconv_prog iconvconfig install-others-programs = $(inst_bindir)/iconv @@ -61,6 +61,7 @@ include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) ifeq ($(run-built-tests),yes) xtests-special += $(objpfx)test-iconvconfig.out +tests-special += $(objpfx)tst-iconv_prog.out endif # Make a copy of the file because gconv module names are constructed @@ -81,6 +82,13 @@ endif include ../Rules +ifeq ($(run-built-tests),yes) +LOCALES := en_US.UTF-8 +include ../gen-locales.mk + +$(objpfx)tst-iconv-opt.out: $(gen-locales) +endif + $(inst_bindir)/iconv: $(objpfx)iconv_prog $(+force) $(do-install-program) @@ -95,3 +103,8 @@ $(objpfx)test-iconvconfig.out: /dev/null $(objpfx)iconvconfig cmp $$tmp $(inst_gconvdir)/gconv-modules.cache; \ rm -f $$tmp) > $@; \ $(evaluate-test) + +$(objpfx)tst-iconv_prog.out: tst-iconv_prog.sh $(objpfx)iconv_prog + $(BASH) $< $(common-objdir) '$(test-wrapper-env)' \ + '$(run-program-env)' > $@; \ + $(evaluate-test) diff --git a/iconv/Versions b/iconv/Versions index 60ab10a27..d51af52fa 100644 --- a/iconv/Versions +++ b/iconv/Versions @@ -7,6 +7,9 @@ libc { # functions shared with iconv program __gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db; + # functions used elsewhere in glibc + __gconv_open; __gconv_create_spec; __gconv_destroy_spec; + # function used by the gconv modules __gconv_transliterate; } diff --git a/iconv/gconv_charset.c b/iconv/gconv_charset.c new file mode 100644 index 000000000..4ba0aa99f --- /dev/null +++ b/iconv/gconv_charset.c @@ -0,0 +1,228 @@ +/* Charset name normalization. + Copyright (C) 2020 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 + . */ + + +#include +#include +#include +#include +#include +#include +#include "gconv_int.h" +#include "gconv_charset.h" + + +/* This function returns a pointer to the last suffix in a conversion code + string. Valid suffixes matched by this function are of the form: '/' or ',' + followed by arbitrary text that doesn't contain '/' or ','. It does not + edit the string in any way. The caller is expected to parse the suffix and + remove it (by e.g. truncating the string) before the next call. */ +static char * +find_suffix (char *s) +{ + /* The conversion code is in the form of a triplet, separated by '/' chars. + The third component of the triplet contains suffixes. If we don't have two + slashes, we don't have a suffix. */ + + int slash_count = 0; + char *suffix_term = NULL; + + for (int i = 0; s[i] != '\0'; i++) + switch (s[i]) + { + case '/': + slash_count++; + /* Fallthrough */ + case ',': + suffix_term = &s[i]; + } + + if (slash_count >= 2) + return suffix_term; + + return NULL; +} + + +struct gconv_parsed_code +{ + char *code; + bool translit; + bool ignore; +}; + + +/* This function parses an iconv_open encoding PC.CODE, strips any suffixes + (such as TRANSLIT or IGNORE) from it and sets corresponding flags in it. */ +static void +gconv_parse_code (struct gconv_parsed_code *pc) +{ + pc->translit = false; + pc->ignore = false; + + while (1) + { + /* First drop any trailing whitespaces and separators. */ + size_t len = strlen (pc->code); + while ((len > 0) + && (isspace (pc->code[len - 1]) + || pc->code[len - 1] == ',' + || pc->code[len - 1] == '/')) + len--; + + pc->code[len] = '\0'; + + if (len == 0) + return; + + char * suffix = find_suffix (pc->code); + if (suffix == NULL) + { + /* At this point, we have processed and removed all suffixes from the + code and what remains of the code is suffix free. */ + return; + } + else + { + /* A suffix is processed from the end of the code array going + backwards, one suffix at a time. The suffix is an index into the + code character array and points to: one past the end of the code + and any unprocessed suffixes, and to the beginning of the suffix + currently being processed during this iteration. We must process + this suffix and then drop it from the code by terminating the + preceding text with NULL. + + We want to allow and recognize suffixes such as: + + "/TRANSLIT" i.e. single suffix + "//TRANSLIT" i.e. single suffix and multiple separators + "//TRANSLIT/IGNORE" i.e. suffixes separated by "/" + "/TRANSLIT//IGNORE" i.e. suffixes separated by "//" + "//IGNORE,TRANSLIT" i.e. suffixes separated by "," + "//IGNORE," i.e. trailing "," + "//TRANSLIT/" i.e. trailing "/" + "//TRANSLIT//" i.e. trailing "//" + "/" i.e. empty suffix. + + Unknown suffixes are silently discarded and ignored. */ + + if ((__strcasecmp_l (suffix, + GCONV_TRIPLE_SEPARATOR + GCONV_TRANSLIT_SUFFIX, + _nl_C_locobj_ptr) == 0) + || (__strcasecmp_l (suffix, + GCONV_SUFFIX_SEPARATOR + GCONV_TRANSLIT_SUFFIX, + _nl_C_locobj_ptr) == 0)) + pc->translit = true; + + if ((__strcasecmp_l (suffix, + GCONV_TRIPLE_SEPARATOR + GCONV_IGNORE_ERRORS_SUFFIX, + _nl_C_locobj_ptr) == 0) + || (__strcasecmp_l (suffix, + GCONV_SUFFIX_SEPARATOR + GCONV_IGNORE_ERRORS_SUFFIX, + _nl_C_locobj_ptr) == 0)) + pc->ignore = true; + + /* We just processed this suffix. We can now drop it from the + code string by truncating it at the suffix's position. */ + suffix[0] = '\0'; + } + } +} + + +/* This function accepts the charset names of the source and destination of the + conversion and populates *conv_spec with an equivalent conversion + specification that may later be used by __gconv_open. The charset names + might contain options in the form of suffixes that alter the conversion, + e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring + and truncating any suffix options in fromcode, and processing and truncating + any suffix options in tocode. Supported suffix options ("TRANSLIT" or + "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec + to be set to true. Unrecognized suffix options are silently discarded. If + the function succeeds, it returns conv_spec back to the caller. It returns + NULL upon failure. conv_spec must be allocated and freed by the caller. */ +struct gconv_spec * +__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, + const char *tocode) +{ + struct gconv_parsed_code pfc, ptc; + struct gconv_spec *ret = NULL; + + pfc.code = __strdup (fromcode); + ptc.code = __strdup (tocode); + + if ((pfc.code == NULL) + || (ptc.code == NULL)) + goto out; + + gconv_parse_code (&pfc); + gconv_parse_code (&ptc); + + /* We ignore suffixes in the fromcode because that is how the current + implementation has always handled them. Only suffixes in the tocode are + processed and handled. The reality is that invalid input in the input + character set should only be ignored if the fromcode specifies IGNORE. + The current implementation ignores invalid intput in the input character + set if the tocode contains IGNORE. We preserve this behavior for + backwards compatibility. In the future we may split the handling of + IGNORE to allow a finer grained specification of ignorning invalid input + and/or ignoring invalid output. */ + conv_spec->translit = ptc.translit; + conv_spec->ignore = ptc.ignore; + + /* 3 extra bytes because 1 extra for '\0', and 2 extra so strip might + be able to add one or two trailing '/' characters if necessary. */ + conv_spec->fromcode = malloc (strlen (fromcode) + 3); + if (conv_spec->fromcode == NULL) + goto out; + + conv_spec->tocode = malloc (strlen (tocode) + 3); + if (conv_spec->tocode == NULL) + { + free (conv_spec->fromcode); + conv_spec->fromcode = NULL; + goto out; + } + + /* Strip unrecognized characters and ensure that the code has two '/' + characters as per conversion code triplet specification. */ + strip (conv_spec->fromcode, pfc.code); + strip (conv_spec->tocode, ptc.code); + ret = conv_spec; + +out: + free (pfc.code); + free (ptc.code); + + return ret; +} +libc_hidden_def (__gconv_create_spec) + + +void +__gconv_destroy_spec (struct gconv_spec *conv_spec) +{ + free (conv_spec->fromcode); + free (conv_spec->tocode); + return; +} +libc_hidden_def (__gconv_destroy_spec) diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h index 348acc089..e9c122cf7 100644 --- a/iconv/gconv_charset.h +++ b/iconv/gconv_charset.h @@ -19,9 +19,41 @@ #include #include +#include +#include +#include +#include +#include "gconv_int.h" -static void +/* An iconv encoding is in the form of a triplet, with parts separated by + a '/' character. The first part is the standard name, the second part is + the character set, and the third part is the error handler. If the first + part is sufficient to identify both the standard and the character set + then the second part can be empty e.g. UTF-8//. If the first part is not + sufficient to identify both the standard and the character set then the + second part is required e.g. ISO-10646/UTF8/. If neither the first or + second parts are provided e.g. //, then the current locale is used. + The actual values used in the first and second parts are not entirely + relevant to the implementation. The values themselves are used in a hash + table to lookup modules and so the naming convention of the first two parts + is somewhat arbitrary and only helps locate the entries in the cache. + The third part is the error handler and is comprised of a ',' or '/' + separated list of suffixes. Currently, we support "TRANSLIT" for + transliteration and "IGNORE" for ignoring conversion errors due to + unrecognized input characters. */ +#define GCONV_TRIPLE_SEPARATOR "/" +#define GCONV_SUFFIX_SEPARATOR "," +#define GCONV_TRANSLIT_SUFFIX "TRANSLIT" +#define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE" + + +/* This function copies in-order, characters from the source 's' that are + either alpha-numeric or one in one of these: "_-.,:/" - into the destination + 'wp' while dropping all other characters. In the process, it converts all + alphabetical characters to upper case. It then appends up to two '/' + characters so that the total number of '/'es in the destination is 2. */ +static inline void __attribute__ ((unused, always_inline)) strip (char *wp, const char *s) { int slash_count = 0; diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h index fbaf12cee..f721ce30f 100644 --- a/iconv/gconv_int.h +++ b/iconv/gconv_int.h @@ -75,6 +75,15 @@ struct gconv_module }; +/* The specification of the conversion that needs to be performed. */ +struct gconv_spec +{ + char *fromcode; + char *tocode; + bool translit; + bool ignore; +}; + /* Flags for `gconv_open'. */ enum { @@ -136,10 +145,33 @@ __libc_lock_define (extern, __gconv_lock attribute_hidden) }) -/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */ -extern int __gconv_open (const char *toset, const char *fromset, - __gconv_t *handle, int flags) - attribute_hidden; +/* Return in *HANDLE, a decriptor for the transformation. The function expects + the specification of the transformation in the structure pointed to by + CONV_SPEC. It only reads *CONV_SPEC and does not take ownership of it. */ +extern int __gconv_open (struct gconv_spec *conv_spec, + __gconv_t *handle, int flags); +libc_hidden_proto (__gconv_open) + +/* This function accepts the charset names of the source and destination of the + conversion and populates *conv_spec with an equivalent conversion + specification that may later be used by __gconv_open. The charset names + might contain options in the form of suffixes that alter the conversion, + e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring + and truncating any suffix options in fromcode, and processing and truncating + any suffix options in tocode. Supported suffix options ("TRANSLIT" or + "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec + to be set to true. Unrecognized suffix options are silently discarded. If + the function succeeds, it returns conv_spec back to the caller. It returns + NULL upon failure. */ +extern struct gconv_spec * +__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, + const char *tocode); +libc_hidden_proto (__gconv_create_spec) + +/* This function frees all heap memory allocated by __gconv_create_spec. */ +extern void +__gconv_destroy_spec (struct gconv_spec *conv_spec); +libc_hidden_proto (__gconv_destroy_spec) /* Free resources associated with transformation descriptor CD. */ extern int __gconv_close (__gconv_t cd) diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c index b39626d25..287862095 100644 --- a/iconv/gconv_open.c +++ b/iconv/gconv_open.c @@ -31,7 +31,7 @@ int -__gconv_open (const char *toset, const char *fromset, __gconv_t *handle, +__gconv_open (struct gconv_spec *conv_spec, __gconv_t *handle, int flags) { struct __gconv_step *steps; @@ -40,77 +40,38 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle, size_t cnt = 0; int res; int conv_flags = 0; - const char *errhand; - const char *ignore; bool translit = false; + char *tocode, *fromcode; /* Find out whether any error handling method is specified. */ - errhand = strchr (toset, '/'); - if (errhand != NULL) - errhand = strchr (errhand + 1, '/'); - if (__glibc_likely (errhand != NULL)) - { - if (*++errhand == '\0') - errhand = NULL; - else - { - /* Make copy without the error handling description. */ - char *newtoset = (char *) alloca (errhand - toset + 1); - char *tok; - char *ptr = NULL /* Work around a bogus warning */; - - newtoset[errhand - toset] = '\0'; - toset = memcpy (newtoset, toset, errhand - toset); + translit = conv_spec->translit; - /* Find the appropriate transliteration handlers. */ - tok = strdupa (errhand); + if (conv_spec->ignore) + conv_flags |= __GCONV_IGNORE_ERRORS; - tok = __strtok_r (tok, ",", &ptr); - while (tok != NULL) - { - if (__strcasecmp_l (tok, "TRANSLIT", _nl_C_locobj_ptr) == 0) - translit = true; - else if (__strcasecmp_l (tok, "IGNORE", _nl_C_locobj_ptr) == 0) - /* Set the flag to ignore all errors. */ - conv_flags |= __GCONV_IGNORE_ERRORS; - - tok = __strtok_r (NULL, ",", &ptr); - } - } - } - - /* For the source character set we ignore the error handler specification. - XXX Is this really always the best? */ - ignore = strchr (fromset, '/'); - if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL - && *++ignore != '\0') - { - char *newfromset = (char *) alloca (ignore - fromset + 1); - - newfromset[ignore - fromset] = '\0'; - fromset = memcpy (newfromset, fromset, ignore - fromset); - } + tocode = conv_spec->tocode; + fromcode = conv_spec->fromcode; /* If the string is empty define this to mean the charset of the currently selected locale. */ - if (strcmp (toset, "//") == 0) + if (strcmp (tocode, "//") == 0) { const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); size_t len = strlen (codeset); char *dest; - toset = dest = (char *) alloca (len + 3); + tocode = dest = (char *) alloca (len + 3); memcpy (__mempcpy (dest, codeset, len), "//", 3); } - if (strcmp (fromset, "//") == 0) + if (strcmp (fromcode, "//") == 0) { const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); size_t len = strlen (codeset); char *dest; - fromset = dest = (char *) alloca (len + 3); + fromcode = dest = (char *) alloca (len + 3); memcpy (__mempcpy (dest, codeset, len), "//", 3); } - res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags); + res = __gconv_find_transform (tocode, fromcode, &steps, &nsteps, flags); if (res == __GCONV_OK) { /* Allocate room for handle. */ @@ -209,3 +170,4 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle, *handle = result; return res; } +libc_hidden_def (__gconv_open) diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index d4797fba1..963b29f24 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step, int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; - size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { uint32_t inval; @@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step, int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; - size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { if (__glibc_unlikely (inptr[0] > 0x80)) { @@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step, int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; - size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { uint32_t inval; @@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step, int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; - size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { if (__glibc_unlikely (inptr[3] > 0x80)) { diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c index 687067070..5b30055c0 100644 --- a/iconv/iconv_open.c +++ b/iconv/iconv_open.c @@ -31,49 +31,15 @@ iconv_t iconv_open (const char *tocode, const char *fromcode) { - /* Normalize the name. We remove all characters beside alpha-numeric, - '_', '-', '/', '.', and ':'. */ - size_t tocode_len = strlen (tocode) + 3; - char *tocode_conv; - bool tocode_usealloca = __libc_use_alloca (tocode_len); - if (tocode_usealloca) - tocode_conv = (char *) alloca (tocode_len); - else - { - tocode_conv = (char *) malloc (tocode_len); - if (tocode_conv == NULL) - return (iconv_t) -1; - } - strip (tocode_conv, tocode); - tocode = (tocode_conv[2] == '\0' && tocode[0] != '\0' - ? upstr (tocode_conv, tocode) : tocode_conv); + __gconv_t cd; + struct gconv_spec conv_spec; - size_t fromcode_len = strlen (fromcode) + 3; - char *fromcode_conv; - bool fromcode_usealloca = __libc_use_alloca (fromcode_len); - if (fromcode_usealloca) - fromcode_conv = (char *) alloca (fromcode_len); - else - { - fromcode_conv = (char *) malloc (fromcode_len); - if (fromcode_conv == NULL) - { - if (! tocode_usealloca) - free (tocode_conv); - return (iconv_t) -1; - } - } - strip (fromcode_conv, fromcode); - fromcode = (fromcode_conv[2] == '\0' && fromcode[0] != '\0' - ? upstr (fromcode_conv, fromcode) : fromcode_conv); + if (__gconv_create_spec (&conv_spec, fromcode, tocode) == NULL) + return (iconv_t) -1; - __gconv_t cd; - int res = __gconv_open (tocode, fromcode, &cd, 0); + int res = __gconv_open (&conv_spec, &cd, 0); - if (! fromcode_usealloca) - free (fromcode_conv); - if (! tocode_usealloca) - free (tocode_conv); + __gconv_destroy_spec (&conv_spec); if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) { diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c index 9709e4a70..d59979759 100644 --- a/iconv/iconv_prog.c +++ b/iconv/iconv_prog.c @@ -39,6 +39,7 @@ #include #include "iconv_prog.h" #include "iconvconfig.h" +#include "gconv_charset.h" /* Get libc version number. */ #include "../version.h" @@ -118,8 +119,7 @@ main (int argc, char *argv[]) { int status = EXIT_SUCCESS; int remaining; - iconv_t cd; - const char *orig_to_code; + __gconv_t cd; struct charmap_t *from_charmap = NULL; struct charmap_t *to_charmap = NULL; @@ -139,39 +139,6 @@ main (int argc, char *argv[]) exit (EXIT_SUCCESS); } - /* If we have to ignore errors make sure we use the appropriate name for - the to-character-set. */ - orig_to_code = to_code; - if (omit_invalid) - { - const char *errhand = strchrnul (to_code, '/'); - int nslash = 2; - char *newp; - char *cp; - - if (*errhand == '/') - { - --nslash; - errhand = strchrnul (errhand + 1, '/'); - - if (*errhand == '/') - { - --nslash; - errhand = strchr (errhand, '\0'); - } - } - - newp = (char *) alloca (errhand - to_code + nslash + 7 + 1); - cp = mempcpy (newp, to_code, errhand - to_code); - while (nslash-- > 0) - *cp++ = '/'; - if (cp[-1] != '/') - *cp++ = ','; - memcpy (cp, "IGNORE", sizeof ("IGNORE")); - - to_code = newp; - } - /* POSIX 1003.2b introduces a silly thing: the arguments to -t anf -f can be file names of charmaps. In this case iconv will have to read those charmaps and use them to do the conversion. But there are @@ -184,10 +151,10 @@ main (int argc, char *argv[]) file. */ from_charmap = charmap_read (from_code, /*0, 1*/1, 0, 0, 0); - if (strchr (orig_to_code, '/') != NULL) + if (strchr (to_code, '/') != NULL) /* The to-name might be a charmap file name. Try reading the file. */ - to_charmap = charmap_read (orig_to_code, /*0, 1,*/1, 0, 0, 0); + to_charmap = charmap_read (to_code, /*0, 1,*/1, 0, 0, 0); /* At this point we have to handle two cases. The first one is @@ -201,9 +168,25 @@ main (int argc, char *argv[]) argc, remaining, argv, output_file); else { + struct gconv_spec conv_spec; + int res; + + if (__gconv_create_spec (&conv_spec, from_code, to_code) == NULL) + { + error (EXIT_FAILURE, errno, + _("failed to start conversion processing")); + exit (1); + } + + if (omit_invalid) + conv_spec.ignore = true; + /* Let's see whether we have these coded character sets. */ - cd = iconv_open (to_code, from_code); - if (cd == (iconv_t) -1) + res = __gconv_open (&conv_spec, &cd, 0); + + __gconv_destroy_spec (&conv_spec); + + if (res != __GCONV_OK) { if (errno == EINVAL) { @@ -221,7 +204,7 @@ main (int argc, char *argv[]) const char *from_pretty = (from_code[0] ? from_code : nl_langinfo (CODESET)); const char *to_pretty = - (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET)); + (to_code[0] ? to_code : nl_langinfo (CODESET)); if (from_wrong) { diff --git a/iconv/tst-iconv-opt.c b/iconv/tst-iconv-opt.c new file mode 100644 index 000000000..669d812a6 --- /dev/null +++ b/iconv/tst-iconv-opt.c @@ -0,0 +1,347 @@ +/* Test iconv's TRANSLIT and IGNORE option handling + + Copyright (C) 2020 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 + . */ + + +#include +#include +#include +#include +#include +#include + + +/* Run one iconv test. Arguments: + to: destination character set and options + from: source character set + input: input string to be converted + exp_in: expected number of bytes consumed + exp_ret: expected return value (error or number of irreversible conversions) + exp_out: expected output string + exp_err: expected value of `errno' after iconv returns. */ +static void +test_iconv (const char *to, const char *from, char *input, size_t exp_in, + size_t exp_ret, const char *exp_out, int exp_err) +{ + iconv_t cd; + char outbuf[500]; + size_t inlen, outlen; + char *inptr, *outptr; + size_t n; + + cd = iconv_open (to, from); + TEST_VERIFY (cd != (iconv_t) -1); + + inlen = strlen (input); + outlen = sizeof (outbuf); + inptr = input; + outptr = outbuf; + + errno = 0; + n = iconv (cd, &inptr, &inlen, &outptr, &outlen); + + TEST_COMPARE (n, exp_ret); + TEST_VERIFY (inptr == input + exp_in); + TEST_COMPARE (errno, exp_err); + TEST_COMPARE_BLOB (outbuf, outptr - outbuf, exp_out, strlen (exp_out)); + TEST_VERIFY (iconv_close (cd) == 0); +} + + +/* We test option parsing by converting UTF-8 inputs to ASCII under various + option combinations. The UTF-8 inputs fall into three categories: + - ASCII-only, + - non-ASCII, + - non-ASCII with invalid UTF-8 characters. */ + +/* 1. */ +char ascii[] = "Just some ASCII text"; + +/* 2. Valid UTF-8 input and some corresponding expected outputs with various + options. The two non-ASCII characters below are accented alphabets: + an `a' then an `o'. */ +char utf8[] = "UTF-8 text with \u00E1 couple \u00F3f non-ASCII characters"; +char u2a[] = "UTF-8 text with "; +char u2a_translit[] = "UTF-8 text with a couple of non-ASCII characters"; +char u2a_ignore[] = "UTF-8 text with couple f non-ASCII characters"; + +/* 3. Invalid UTF-8 input and some corresponding expected outputs. \xff is + invalid UTF-8. It's followed by some valid but non-ASCII UTF-8. */ +char iutf8[] = "Invalid UTF-8 \xff\u27E6text\u27E7"; +char iu2a[] = "Invalid UTF-8 "; +char iu2a_ignore[] = "Invalid UTF-8 text"; +char iu2a_both[] = "Invalid UTF-8 [|text|]"; + +/* 4. Another invalid UTF-8 input and corresponding expected outputs. This time + the valid non-ASCII UTF-8 characters appear before the invalid \xff. */ +char jutf8[] = "Invalid \u27E6UTF-8\u27E7 \xfftext"; +char ju2a[] = "Invalid "; +char ju2a_translit[] = "Invalid [|UTF-8|] "; +char ju2a_ignore[] = "Invalid UTF-8 text"; +char ju2a_both[] = "Invalid [|UTF-8|] text"; + +/* We also test option handling for character set names that have the form + "A/B". In this test, we test conversions "ISO-10646/UTF-8", and either + ISO-8859-1 or ASCII. */ + +/* 5. Accented 'A' and 'a' characters in ISO-8859-1 and UTF-8, and an + equivalent ASCII transliteration. */ +char iso8859_1_a[] = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, /* Accented A's. */ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, /* Accented a's. */ + 0x00}; +char utf8_a[] = "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5" + "\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5"; +char ascii_a[] = "AAAAAAaaaaaa"; + +/* 6. An invalid ASCII string where [0] is invalid and [1] is '~'. */ +char iascii [] = {0x80, '~', '\0'}; +char empty[] = ""; +char ia2u_ignore[] = "~"; + +static int +do_test (void) +{ + xsetlocale (LC_ALL, "en_US.UTF-8"); + + + /* 0. iconv_open should gracefully fail for invalid character sets. */ + + TEST_VERIFY (iconv_open ("INVALID", "UTF-8") == (iconv_t) -1); + TEST_VERIFY (iconv_open ("UTF-8", "INVALID") == (iconv_t) -1); + TEST_VERIFY (iconv_open ("INVALID", "INVALID") == (iconv_t) -1); + + + /* 1. ASCII-only UTF-8 input should convert to ASCII with no changes: */ + + test_iconv ("ASCII", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); + test_iconv ("ASCII//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); + test_iconv ("ASCII//TRANSLIT", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); + test_iconv ("ASCII//TRANSLIT//", "UTF-8", ascii, strlen (ascii), 0, ascii, + 0); + test_iconv ("ASCII//IGNORE", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); + test_iconv ("ASCII//IGNORE//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); + + + /* 2. Valid UTF-8 input with non-ASCII characters: */ + + /* EILSEQ when converted to ASCII. */ + test_iconv ("ASCII", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, EILSEQ); + + /* Converted without error with TRANSLIT enabled. */ + test_iconv ("ASCII//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, u2a_translit, + 0); + + /* EILSEQ with IGNORE enabled. Non-ASCII chars dropped from output. */ + test_iconv ("ASCII//IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1, + u2a_ignore, EILSEQ); + + /* With TRANSLIT and IGNORE enabled, transliterated without error. We test + four combinations. */ + + test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ + test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + + /* Misspellings of TRANSLIT and IGNORE are ignored, but conversion still + works while respecting any other correctly spelled options. */ + + test_iconv ("ASCII//T", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, + EILSEQ); + test_iconv ("ASCII//TRANSLITERATE", "UTF-8", utf8, strlen (u2a), (size_t) -1, + u2a, EILSEQ); + test_iconv ("ASCII//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, + EILSEQ); + test_iconv ("ASCII//IGNORED", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, + EILSEQ); + test_iconv ("ASCII//TRANSLITERATE//IGNORED", "UTF-8", utf8, strlen (u2a), + (size_t) -1, u2a, EILSEQ); + test_iconv ("ASCII//IGNORED,TRANSLITERATE", "UTF-8", utf8, strlen (u2a), + (size_t) -1, u2a, EILSEQ); + test_iconv ("ASCII//T//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, + EILSEQ); + + test_iconv ("ASCII//TRANSLIT//I", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ + test_iconv ("ASCII//I//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + test_iconv ("ASCII//IGNORED,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + test_iconv ("ASCII//TRANSLIT,IGNORED", "UTF-8", utf8, strlen (utf8), 2, + u2a_translit, 0); + + test_iconv ("ASCII//IGNORE,T", "UTF-8", utf8, strlen (utf8), (size_t) -1, + u2a_ignore, EILSEQ); + test_iconv ("ASCII//T,IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1, + u2a_ignore, EILSEQ); + /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ + test_iconv ("ASCII//TRANSLITERATE//IGNORE", "UTF-8", utf8, strlen (utf8), + (size_t) -1, u2a_ignore, EILSEQ); + test_iconv ("ASCII//IGNORE//TRANSLITERATE", "UTF-8", utf8, strlen (utf8), + (size_t) -1, u2a_ignore, EILSEQ); + + + /* 3. Invalid UTF-8 followed by some valid non-ASCII UTF-8 characters: */ + + /* EILSEQ; output is truncated at the first invalid UTF-8 character. */ + test_iconv ("ASCII", "UTF-8", iutf8, strlen (iu2a), (size_t) -1, iu2a, + EILSEQ); + + /* With TRANSLIT enabled: EILSEQ; output still truncated at the first invalid + UTF-8 character. */ + test_iconv ("ASCII//TRANSLIT", "UTF-8", iutf8, strlen (iu2a), (size_t) -1, + iu2a, EILSEQ); + + /* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and + valid UTF-8 non-ASCII characters. */ + test_iconv ("ASCII//IGNORE", "UTF-8", iutf8, strlen (iutf8), (size_t) -1, + iu2a_ignore, EILSEQ); + + /* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8 + characters and transliterates valid non-ASCII UTF-8 characters. We test + four combinations. */ + + test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", iutf8, strlen (iutf8), 2, + iu2a_both, 0); + /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ + test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", iutf8, strlen (iutf8), 2, + iu2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2, + iu2a_both, 0); + /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ + test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2, + iu2a_both, 0); + + + /* 4. Invalid UTF-8 with valid non-ASCII UTF-8 chars appearing first: */ + + /* EILSEQ; output is truncated at the first non-ASCII character. */ + test_iconv ("ASCII", "UTF-8", jutf8, strlen (ju2a), (size_t) -1, ju2a, + EILSEQ); + + /* With TRANSLIT enabled: EILSEQ; output now truncated at the first invalid + UTF-8 character. */ + test_iconv ("ASCII//TRANSLIT", "UTF-8", jutf8, strlen (jutf8) - 5, + (size_t) -1, ju2a_translit, EILSEQ); + test_iconv ("ASCII//translit", "UTF-8", jutf8, strlen (jutf8) - 5, + (size_t) -1, ju2a_translit, EILSEQ); + + /* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and + valid UTF-8 non-ASCII characters. */ + test_iconv ("ASCII//IGNORE", "UTF-8", jutf8, strlen (jutf8), (size_t) -1, + ju2a_ignore, EILSEQ); + test_iconv ("ASCII//ignore", "UTF-8", jutf8, strlen (jutf8), (size_t) -1, + ju2a_ignore, EILSEQ); + + /* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8 + characters and transliterates valid non-ASCII UTF-8 characters. We test + several combinations. */ + + test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ + test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ + test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//translit,ignore", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + /* Trailing whitespace and separators should be ignored. */ + test_iconv ("ASCII//IGNORE,TRANSLIT ", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT/", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT//", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT,", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT,,", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + test_iconv ("ASCII//IGNORE,TRANSLIT /,", "UTF-8", jutf8, strlen (jutf8), 2, + ju2a_both, 0); + + /* TRANSLIT or IGNORE suffixes in fromcode should be ignored. */ + test_iconv ("ASCII", "UTF-8//TRANSLIT", jutf8, strlen (ju2a), (size_t) -1, + ju2a, EILSEQ); + test_iconv ("ASCII", "UTF-8//IGNORE", jutf8, strlen (ju2a), (size_t) -1, + ju2a, EILSEQ); + test_iconv ("ASCII", "UTF-8//TRANSLIT,IGNORE", jutf8, strlen (ju2a), + (size_t) -1, ju2a, EILSEQ); + + + /* 5. Charset names of the form "A/B/": */ + + /* ISO-8859-1 is converted to UTF-8 without needing transliteration. */ + test_iconv ("ISO-10646/UTF-8", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8/", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8/IGNORE", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8//IGNORE", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8//TRANSLIT", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8//TRANSLIT/IGNORE", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ISO-8859-1", iso8859_1_a, + strlen (iso8859_1_a), 0, utf8_a, 0); + + /* UTF-8 with accented A's is converted to ASCII with transliteration. */ + test_iconv ("ASCII", "ISO-10646/UTF-8", utf8_a, + 0, (size_t) -1, empty, EILSEQ); + test_iconv ("ASCII//IGNORE", "ISO-10646/UTF-8", utf8_a, + strlen (utf8_a), (size_t) -1, empty, EILSEQ); + test_iconv ("ASCII//TRANSLIT", "ISO-10646/UTF-8", utf8_a, + strlen (utf8_a), 12, ascii_a, 0); + + /* Invalid ASCII is converted to UTF-8 only with IGNORE. */ + test_iconv ("ISO-10646/UTF-8", "ASCII", iascii, strlen (empty), (size_t) -1, + empty, EILSEQ); + test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ASCII", iascii, strlen (empty), + (size_t) -1, empty, EILSEQ); + test_iconv ("ISO-10646/UTF-8/IGNORE", "ASCII", iascii, strlen (iascii), + (size_t) -1, ia2u_ignore, EILSEQ); + test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ASCII", iascii, + strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); + /* Due to bug 19519, iconv was ignoring IGNORE for the following three + inputs: */ + test_iconv ("ISO-10646/UTF-8/TRANSLIT/IGNORE", "ASCII", iascii, + strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); + test_iconv ("ISO-10646/UTF-8//TRANSLIT,IGNORE", "ASCII", iascii, + strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); + test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ASCII", iascii, + strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); + + return 0; +} + +#include diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c new file mode 100644 index 000000000..0b92b19f6 --- /dev/null +++ b/iconv/tst-iconv8.c @@ -0,0 +1,50 @@ +/* Test iconv behavior on UCS4 conversions with //IGNORE. + Copyright (C) 2020 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 + . */ + +/* Derived from BZ #26923 */ +#include +#include +#include +#include + +static int +do_test (void) +{ + iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/"); + TEST_VERIFY_EXIT (cd != (iconv_t) -1); + + /* + * Convert sequence beginning with an irreversible character into buffer that + * is too small. + */ + char input[12] = "\xe1\x80\xa1" "AAAAAAAAA"; + char *inptr = input; + size_t insize = sizeof (input); + char output[6]; + char *outptr = output; + size_t outsize = sizeof (output); + + TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1); + TEST_VERIFY (errno == E2BIG); + + TEST_VERIFY_EXIT (iconv_close (cd) != -1); + + return 0; +} + +#include diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh new file mode 100644 index 000000000..d8db7b335 --- /dev/null +++ b/iconv/tst-iconv_prog.sh @@ -0,0 +1,284 @@ +#!/bin/bash +# Test for some known iconv(1) hangs from bug 19519, and miscellaneous +# iconv(1) program error conditions. +# Copyright (C) 2020 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 +# . + +codir=$1 +test_wrapper_env="$2" +run_program_env="$3" + +# We have to have some directories in the library path. +LIBPATH=$codir:$codir/iconvdata + +# How the start the iconv(1) program. $from is not defined/expanded yet. +ICONV=' +$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so +$codir/iconv/iconv_prog +' +ICONV="$test_wrapper_env $run_program_env $ICONV" + +# List of known hangs; +# Gathered by running an exhaustive 2 byte input search against glibc-2.28 +hangarray=( +"\x00\x23;-c;ANSI_X3.110;UTF-8//TRANSLIT//IGNORE" +"\x00\xa1;-c;ARMSCII-8;UTF-8//TRANSLIT//IGNORE" +"\x00\xa1;-c;ASMO_449;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;BIG5;UTF-8//TRANSLIT//IGNORE" +"\x00\xff;-c;BIG5HKSCS;UTF-8//TRANSLIT//IGNORE" +"\x00\xff;-c;BRF;UTF-8//TRANSLIT//IGNORE" +"\x00\xff;-c;BS_4730;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1250;UTF-8//TRANSLIT//IGNORE" +"\x00\x98;-c;CP1251;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1252;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1253;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1254;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1255;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1257;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;CP1258;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;CP932;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;CSA_Z243.4-1985-1;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;CSA_Z243.4-1985-2;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;DEC-MCS;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;DIN_66003;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;DS_2089;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-AT-DE;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-AT-DE-A;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-CA-FR;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-DK-NO;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-DK-NO-A;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-ES;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-ES-A;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-ES-S;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-FI-SE;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-FI-SE-A;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-FR;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-IS-FRISS;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-IT;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-PT;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-UK;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;EBCDIC-US;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ES;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ES2;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-CN;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-JISX0213;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-JP;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-JP-MS;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-KR;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;EUC-TW;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GB18030;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GB_1988-80;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GBK;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GOST_19768-74;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GREEK7;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GREEK7-OLD;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;GREEK-CCITT;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;HP-GREEK8;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;HP-ROMAN8;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;HP-ROMAN9;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;HP-THAI8;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;HP-TURKISH8;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM038;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM1004;UTF-8//TRANSLIT//IGNORE" +"\x00\xff;-c;IBM1008;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;IBM1046;UTF-8//TRANSLIT//IGNORE" +"\x00\x51;-c;IBM1132;UTF-8//TRANSLIT//IGNORE" +"\x00\xa0;-c;IBM1133;UTF-8//TRANSLIT//IGNORE" +"\x00\xce;-c;IBM1137;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE" +"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE" +"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE" +"\x00\x0f;-c;IBM1364;UTF-8" +"\x0e\x0e;-c;IBM1364;UTF-8" +"\x00\x0f;-c;IBM1371;UTF-8" +"\x0e\x0e;-c;IBM1371;UTF-8" +"\x00\x0f;-c;IBM1388;UTF-8" +"\x0e\x0e;-c;IBM1388;UTF-8" +"\x00\x0f;-c;IBM1390;UTF-8" +"\x0e\x0e;-c;IBM1390;UTF-8" +"\x00\x0f;-c;IBM1399;UTF-8" +"\x0e\x0e;-c;IBM1399;UTF-8" +"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM281;UTF-8//TRANSLIT//IGNORE" +"\x00\x57;-c;IBM290;UTF-8//TRANSLIT//IGNORE" +"\x00\x45;-c;IBM420;UTF-8//TRANSLIT//IGNORE" +"\x00\x68;-c;IBM423;UTF-8//TRANSLIT//IGNORE" +"\x00\x70;-c;IBM424;UTF-8//TRANSLIT//IGNORE" +"\x00\x53;-c;IBM4517;UTF-8//TRANSLIT//IGNORE" +"\x00\x53;-c;IBM4899;UTF-8//TRANSLIT//IGNORE" +"\x00\xa5;-c;IBM4909;UTF-8//TRANSLIT//IGNORE" +"\x00\xdc;-c;IBM4971;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM803;UTF-8//TRANSLIT//IGNORE" +"\x00\x91;-c;IBM851;UTF-8//TRANSLIT//IGNORE" +"\x00\x9b;-c;IBM856;UTF-8//TRANSLIT//IGNORE" +"\x00\xd5;-c;IBM857;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;IBM864;UTF-8//TRANSLIT//IGNORE" +"\x00\x94;-c;IBM868;UTF-8//TRANSLIT//IGNORE" +"\x00\x94;-c;IBM869;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;IBM874;UTF-8//TRANSLIT//IGNORE" +"\x00\x6a;-c;IBM875;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM880;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM891;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;IBM903;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;IBM904;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM905;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM9066;UTF-8//TRANSLIT//IGNORE" +"\x00\x48;-c;IBM918;UTF-8//TRANSLIT//IGNORE" +"\x00\x57;-c;IBM930;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM932;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM933;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM935;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM937;UTF-8//TRANSLIT//IGNORE" +"\x00\x41;-c;IBM939;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IBM943;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;INIS;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;INIS-8;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;INIS-CYRILLIC;UTF-8//TRANSLIT//IGNORE" +"\x00\xec;-c;ISIRI-3342;UTF-8//TRANSLIT//IGNORE" +"\x00\xec;-c;ISO_10367-BOX;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-CN;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-CN-EXT;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-JP;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-JP-2;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-JP-3;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-2022-KR;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO_2033;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO_5427;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO_5427-EXT;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO_5428;UTF-8//TRANSLIT//IGNORE" +"\x00\xa4;-c;ISO_6937;UTF-8//TRANSLIT//IGNORE" +"\x00\xa0;-c;ISO_6937-2;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-8859-11;UTF-8//TRANSLIT//IGNORE" +"\x00\xa5;-c;ISO-8859-3;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-8859-6;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-8859-7;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;ISO-8859-8;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;ISO-IR-197;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;ISO-IR-209;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;IT;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;JIS_C6220-1969-RO;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;JIS_C6229-1984-B;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;JOHAB;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;JUS_I.B1.002;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;KOI-8;UTF-8//TRANSLIT//IGNORE" +"\x00\x88;-c;KOI8-T;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;KSC5636;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;LATIN-GREEK;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;LATIN-GREEK-1;UTF-8//TRANSLIT//IGNORE" +"\x00\xf6;-c;MAC-IS;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;MSZ_7795.3;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NATS-DANO;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NATS-SEFI;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NC_NC00-10;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NF_Z_62-010;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NF_Z_62-010_1973;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NS_4551-1;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;NS_4551-2;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;PT;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;PT2;UTF-8//TRANSLIT//IGNORE" +"\x00\x98;-c;RK1048;UTF-8//TRANSLIT//IGNORE" +"\x00\x98;-c;SEN_850200_B;UTF-8//TRANSLIT//IGNORE" +"\x00\x98;-c;SEN_850200_C;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;Shift_JISX0213;UTF-8//TRANSLIT//IGNORE" +"\x00\x80;-c;SJIS;UTF-8//TRANSLIT//IGNORE" +"\x00\x23;-c;T.61-8BIT;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;TIS-620;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;TSCII;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;UHC;UTF-8//TRANSLIT//IGNORE" +"\x00\xd8;-c;UNICODE;UTF-8//TRANSLIT//IGNORE" +"\x00\xdc;-c;UTF-16;UTF-8//TRANSLIT//IGNORE" +"\xdc\x00;-c;UTF-16BE;UTF-8//TRANSLIT//IGNORE" +"\x00\xdc;-c;UTF-16LE;UTF-8//TRANSLIT//IGNORE" +"\xff\xff;-c;UTF-7;UTF-8//TRANSLIT//IGNORE" +"\x00\x81;-c;WIN-SAMI-2;UTF-8//TRANSLIT//IGNORE" +) + +# List of option combinations that *should* lead to an error +errorarray=( +# Converting from/to invalid character sets should cause error +"\x00\x00;;INVALID;INVALID" +"\x00\x00;;INVALID;UTF-8" +"\x00\x00;;UTF-8;INVALID" +) + +# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret +execute_test () +{ + eval PROG=\"$ICONV\" + echo -en "$twobyte" \ + | timeout -k 4 3 $PROG $c -f $from -t "$to" &>/dev/null + ret=$? +} + +check_hangtest_result () +{ + if [ "$ret" -eq "124" ] || [ "$ret" -eq "137" ]; then # timeout/hang + result="HANG" + else + if [ "$ret" -eq "139" ]; then # segfault + result="SEGFAULT" + else + if [ "$ret" -gt "127" ]; then # unexpected error + result="UNEXPECTED" + else + result="OK" + fi + fi + fi + + echo -n "$result: from: \"$from\", to: \"$to\"," + echo " input \"$twobyte\", flags \"$c\"" + + if [ "$result" != "OK" ]; then + exit 1 + fi +} + +for hangcommand in "${hangarray[@]}"; do + twobyte="$(echo "$hangcommand" | cut -d";" -f 1)" + c="$(echo "$hangcommand" | cut -d";" -f 2)" + from="$(echo "$hangcommand" | cut -d";" -f 3)" + to="$(echo "$hangcommand" | cut -d";" -f 4)" + execute_test + check_hangtest_result +done + +check_errtest_result () +{ + if [ "$ret" -eq "1" ]; then # we errored out as expected + result="PASS" + else + result="FAIL" + fi + echo -n "$result: from: \"$from\", to: \"$to\"," + echo " input \"$twobyte\", flags \"$c\", return code $ret" + + if [ "$result" != "PASS" ]; then + exit 1 + fi +} + +for errorcommand in "${errorarray[@]}"; do + twobyte="$(echo "$errorcommand" | cut -d";" -f 1)" + c="$(echo "$errorcommand" | cut -d";" -f 2)" + from="$(echo "$errorcommand" | cut -d";" -f 3)" + to="$(echo "$errorcommand" | cut -d";" -f 4)" + execute_test + check_errtest_result +done diff --git a/iconvdata/Makefile b/iconvdata/Makefile index c83962f35..8fbb67a52 100644 --- a/iconvdata/Makefile +++ b/iconvdata/Makefile @@ -1,4 +1,5 @@ # Copyright (C) 1997-2020 Free Software Foundation, Inc. +# Copyright (C) The GNU Toolchain Authors. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -73,7 +74,8 @@ modules.so := $(addsuffix .so, $(modules)) ifeq (yes,$(build-shared)) tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ - bug-iconv10 bug-iconv11 bug-iconv12 + bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \ + bug-iconv15 ifeq ($(have-thread-library),yes) tests += bug-iconv3 endif @@ -316,6 +318,10 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) $(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) +$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) +$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ + $(addprefix $(objpfx),$(modules.so)) $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) \ diff --git a/iconvdata/bug-iconv13.c b/iconvdata/bug-iconv13.c new file mode 100644 index 000000000..87aaff398 --- /dev/null +++ b/iconvdata/bug-iconv13.c @@ -0,0 +1,53 @@ +/* bug 24973: Test EUC-KR module + Copyright (C) 2020 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 + . */ + +#include +#include +#include +#include + +static int +do_test (void) +{ + iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR"); + TEST_VERIFY_EXIT (cd != (iconv_t) -1); + + /* 0xfe (->0x7e : row 94) and 0xc9 (->0x49 : row 41) are user-defined + areas, which are not allowed and should be skipped over due to + //IGNORE. The trailing 0xfe also is an incomplete sequence, which + should be checked first. */ + char input[4] = { '\xc9', '\xa1', '\0', '\xfe' }; + char *inptr = input; + size_t insize = sizeof (input); + char output[4]; + char *outptr = output; + size_t outsize = sizeof (output); + + /* This used to crash due to buffer overrun. */ + TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); + TEST_VERIFY (errno == EINVAL); + /* The conversion should produce one character, the converted null + character. */ + TEST_VERIFY (sizeof (output) - outsize == 1); + + TEST_VERIFY_EXIT (iconv_close (cd) != -1); + + return 0; +} + +#include diff --git a/iconvdata/bug-iconv14.c b/iconvdata/bug-iconv14.c new file mode 100644 index 000000000..902f140fa --- /dev/null +++ b/iconvdata/bug-iconv14.c @@ -0,0 +1,127 @@ +/* Assertion in ISO-2022-JP-3 due to two-character sequence (bug 27256). + Copyright (C) 2021 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 + . */ + +#include +#include +#include +#include + +/* Use an escape sequence to return to the initial state. */ +static void +with_escape_sequence (void) +{ + iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); + TEST_VERIFY_EXIT (c != (iconv_t) -1); + + char in[] = "\e$(O+D\e(B"; + char *inbuf = in; + size_t inleft = strlen (in); + char out[3]; /* Space for one output character. */ + char *outbuf; + size_t outleft; + + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); + TEST_COMPARE (errno, E2BIG); + TEST_COMPARE (inleft, 3); + TEST_COMPARE (inbuf - in, strlen (in) - 3); + TEST_COMPARE (outleft, sizeof (out) - 2); + TEST_COMPARE (outbuf - out, 2); + TEST_COMPARE (out[0] & 0xff, 0xc3); + TEST_COMPARE (out[1] & 0xff, 0xa6); + + /* Return to the initial shift state, producing the pending + character. */ + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), 0); + TEST_COMPARE (inleft, 0); + TEST_COMPARE (inbuf - in, strlen (in)); + TEST_COMPARE (outleft, sizeof (out) - 2); + TEST_COMPARE (outbuf - out, 2); + TEST_COMPARE (out[0] & 0xff, 0xcc); + TEST_COMPARE (out[1] & 0xff, 0x80); + + /* Nothing should be flushed the second time. */ + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); + TEST_COMPARE (outleft, sizeof (out)); + TEST_COMPARE (outbuf - out, 0); + TEST_COMPARE (out[0] & 0xff, 0xcc); + TEST_COMPARE (out[1] & 0xff, 0x80); + + TEST_COMPARE (iconv_close (c), 0); +} + +/* Use an explicit flush to return to the initial state. */ +static void +with_flush (void) +{ + iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); + TEST_VERIFY_EXIT (c != (iconv_t) -1); + + char in[] = "\e$(O+D"; + char *inbuf = in; + size_t inleft = strlen (in); + char out[3]; /* Space for one output character. */ + char *outbuf; + size_t outleft; + + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); + TEST_COMPARE (errno, E2BIG); + TEST_COMPARE (inleft, 0); + TEST_COMPARE (inbuf - in, strlen (in)); + TEST_COMPARE (outleft, sizeof (out) - 2); + TEST_COMPARE (outbuf - out, 2); + TEST_COMPARE (out[0] & 0xff, 0xc3); + TEST_COMPARE (out[1] & 0xff, 0xa6); + + /* Flush the pending character. */ + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); + TEST_COMPARE (outleft, sizeof (out) - 2); + TEST_COMPARE (outbuf - out, 2); + TEST_COMPARE (out[0] & 0xff, 0xcc); + TEST_COMPARE (out[1] & 0xff, 0x80); + + /* Nothing should be flushed the second time. */ + outbuf = out; + outleft = sizeof (out); + TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); + TEST_COMPARE (outleft, sizeof (out)); + TEST_COMPARE (outbuf - out, 0); + TEST_COMPARE (out[0] & 0xff, 0xcc); + TEST_COMPARE (out[1] & 0xff, 0x80); + + TEST_COMPARE (iconv_close (c), 0); +} + +static int +do_test (void) +{ + with_escape_sequence (); + with_flush (); + return 0; +} + +#include diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c new file mode 100644 index 000000000..cc04bd031 --- /dev/null +++ b/iconvdata/bug-iconv15.c @@ -0,0 +1,60 @@ +/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv + may emit spurious NUL character on state reset. + Copyright (C) The GNU Toolchain Authors. + 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 + . */ + +#include +#include +#include + +static int +do_test (void) +{ + char in[] = "\x1b(I"; + char *inbuf = in; + size_t inleft = sizeof (in) - 1; + char out[1]; + char *outbuf = out; + size_t outleft = sizeof (out); + iconv_t cd; + + cd = iconv_open ("UTF8", "ISO-2022-JP-3"); + TEST_VERIFY_EXIT (cd != (iconv_t) -1); + + /* First call to iconv should alter internal state. + Now, JISX0201_Kana_set is selected and + state value != ASCII_set. */ + TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1); + + /* No bytes should have been added to + the output buffer at this point. */ + TEST_VERIFY (outbuf == out); + TEST_VERIFY (outleft == sizeof (out)); + + /* Second call shall emit spurious NUL character in unpatched glibc. */ + TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1); + + /* No characters are expected to be produced. */ + TEST_VERIFY (outbuf == out); + TEST_VERIFY (outleft == sizeof (out)); + + TEST_VERIFY_EXIT (iconv_close (cd) != -1); + + return 0; +} + +#include diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c index b0d56cf3e..1045bae92 100644 --- a/iconvdata/euc-kr.c +++ b/iconvdata/euc-kr.c @@ -80,11 +80,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp) \ if (ch <= 0x9f) \ ++inptr; \ - /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ - user-defined areas. */ \ - else if (__builtin_expect (ch == 0xa0, 0) \ - || __builtin_expect (ch > 0xfe, 0) \ - || __builtin_expect (ch == 0xc9, 0)) \ + else if (__glibc_unlikely (ch == 0xa0)) \ { \ /* This is illegal. */ \ STANDARD_FROM_LOOP_ERR_HANDLER (1); \ diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c index 49e7267ab..521f0825b 100644 --- a/iconvdata/ibm1364.c +++ b/iconvdata/ibm1364.c @@ -158,24 +158,14 @@ enum \ if (__builtin_expect (ch, 0) == SO) \ { \ - /* Shift OUT, change to DBCS converter. */ \ - if (curcs == db) \ - { \ - result = __GCONV_ILLEGAL_INPUT; \ - break; \ - } \ + /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ curcs = db; \ ++inptr; \ continue; \ } \ if (__builtin_expect (ch, 0) == SI) \ { \ - /* Shift IN, change to SBCS converter. */ \ - if (curcs == sb) \ - { \ - result = __GCONV_ILLEGAL_INPUT; \ - break; \ - } \ + /* Shift IN, change to SBCS converter (redundant escape okay). */ \ curcs = sb; \ ++inptr; \ continue; \ diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c index 8c3b7e627..c7b470db6 100644 --- a/iconvdata/iso-2022-jp-3.c +++ b/iconvdata/iso-2022-jp-3.c @@ -1,5 +1,6 @@ /* Conversion module for ISO-2022-JP-3. Copyright (C) 1998-2020 Free Software Foundation, Inc. + Copyright (C) The GNU Toolchain Authors. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998, and Bruno Haible , 2002. @@ -67,10 +68,15 @@ enum CURRENT_SEL_MASK = 7 << 3 }; -/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the state - also contains the last two bytes to be output, shifted by 6 bits, and a - one-bit indicator whether they must be preceded by the shift sequence, - in bit 22. */ +/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the + state also contains the last two bytes to be output, shifted by 6 + bits, and a one-bit indicator whether they must be preceded by the + shift sequence, in bit 22. During ISO-2022-JP-3 to UCS-4 + conversion, COUNT may also contain a non-zero pending wide + character, shifted by six bits. This happens for certain inputs in + JISX0213_1_2004_set and JISX0213_2_set if the second wide character + in a combining sequence cannot be written because the buffer is + full. */ /* Since this is a stateful encoding we have to provide code which resets the output state to the initial state. This has to be done during the @@ -80,10 +86,27 @@ enum { \ if (FROM_DIRECTION) \ { \ - /* It's easy, we don't have to emit anything, we just reset the \ - state for the input. */ \ - data->__statep->__count &= 7; \ - data->__statep->__count |= ASCII_set; \ + uint32_t ch = data->__statep->__count >> 6; \ + \ + if (__glibc_unlikely (ch != 0)) \ + { \ + if (__glibc_likely (outbuf + 4 <= outend)) \ + { \ + /* Write out the last character. */ \ + put32u (outbuf, ch); \ + outbuf += 4; \ + data->__statep->__count &= 7; \ + data->__statep->__count |= ASCII_set; \ + } \ + else \ + /* We don't have enough room in the output buffer. */ \ + status = __GCONV_FULL_OUTPUT; \ + } \ + else \ + { \ + data->__statep->__count &= 7; \ + data->__statep->__count |= ASCII_set; \ + } \ } \ else \ { \ @@ -151,7 +174,21 @@ enum #define LOOPFCT FROM_LOOP #define BODY \ { \ - uint32_t ch = *inptr; \ + uint32_t ch; \ + \ + /* Output any pending character. */ \ + ch = set >> 6; \ + if (__glibc_unlikely (ch != 0)) \ + { \ + put32 (outptr, ch); \ + outptr += 4; \ + /* Remove the pending character, but preserve state bits. */ \ + set &= (1 << 6) - 1; \ + continue; \ + } \ + \ + /* Otherwise read the next input byte. */ \ + ch = *inptr; \ \ /* Recognize escape sequences. */ \ if (__glibc_unlikely (ch == ESC)) \ @@ -297,21 +334,25 @@ enum uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0]; \ uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1]; \ \ + inptr += 2; \ + \ + put32 (outptr, u1); \ + outptr += 4; \ + \ /* See whether we have room for two characters. */ \ - if (outptr + 8 <= outend) \ + if (outptr + 4 <= outend) \ { \ - inptr += 2; \ - put32 (outptr, u1); \ - outptr += 4; \ put32 (outptr, u2); \ outptr += 4; \ continue; \ } \ - else \ - { \ - result = __GCONV_FULL_OUTPUT; \ - break; \ - } \ + \ + /* Otherwise store only the first character now, and \ + put the second one into the queue. */ \ + set |= u2 << 6; \ + /* Tell the caller why we terminate the loop. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ } \ \ inptr += 2; \ diff --git a/iconvdata/ksc5601.h b/iconvdata/ksc5601.h index d3eb3a4ff..f5cdc7279 100644 --- a/iconvdata/ksc5601.h +++ b/iconvdata/ksc5601.h @@ -50,15 +50,15 @@ ksc5601_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset) unsigned char ch2; int idx; + if (avail < 2) + return 0; + /* row 94(0x7e) and row 41(0x49) are user-defined area in KS C 5601 */ if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e || (ch - offset) == 0x49) return __UNKNOWN_10646_CHAR; - if (avail < 2) - return 0; - ch2 = (*s)[1]; if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f) return __UNKNOWN_10646_CHAR; diff --git a/include/libc-symbols.h b/include/libc-symbols.h index 685e20fdc..68fc79805 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -59,6 +59,19 @@ # define IN_MODULE (-1) #endif +/* Use symbol_version_reference to specify the version a symbol + reference should link to. Use symbol_version or + default_symbol_version for the definition of a versioned symbol. + The difference is that the latter is a no-op in non-shared + builds. */ +#ifdef __ASSEMBLER__ +# define symbol_version_reference(real, name, version) \ + .symver real, name##@##version +#else /* !__ASSEMBLER__ */ +# define symbol_version_reference(real, name, version) \ + __asm__ (".symver " #real "," #name "@" #version) +#endif + #ifndef _ISOMAC /* This is defined for the compilation of all C library code. features.h @@ -396,19 +409,6 @@ for linking") past the last element in SET. */ #define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set) -/* Use symbol_version_reference to specify the version a symbol - reference should link to. Use symbol_version or - default_symbol_version for the definition of a versioned symbol. - The difference is that the latter is a no-op in non-shared - builds. */ -#ifdef __ASSEMBLER__ -# define symbol_version_reference(real, name, version) \ - .symver real, name##@##version -#else /* !__ASSEMBLER__ */ -# define symbol_version_reference(real, name, version) \ - __asm__ (".symver " #real "," #name "@" #version) -#endif - #ifdef SHARED # define symbol_version(real, name, version) \ symbol_version_reference(real, name, version) diff --git a/include/sys/prctl.h b/include/sys/prctl.h index 0920ed642..d33f3a290 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -4,6 +4,7 @@ # ifndef _ISOMAC extern int __prctl (int __option, ...); +libc_hidden_proto (__prctl) # endif /* !_ISOMAC */ #endif diff --git a/include/sys/un.h b/include/sys/un.h index bdbee9998..152afd9fc 100644 --- a/include/sys/un.h +++ b/include/sys/un.h @@ -1 +1,13 @@ #include + +#ifndef _ISOMAC + +/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME. + Return 0 on success or -1 on failure (due to overlong PATHNAME). + The caller should always use sizeof (struct sockaddr_un) as the + socket address length, disregaring the length of PATHNAME. + Only concrete (non-abstract) pathnames are supported. */ +int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) + attribute_hidden; + +#endif /* _ISOMAC */ diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 465c8df34..bd332e71d 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -1119,11 +1119,19 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, outcharset = encoding; # ifdef _LIBC + + struct gconv_spec conv_spec; + + __gconv_create_spec (&conv_spec, charset, outcharset); + /* We always want to use transliteration. */ - outcharset = norm_add_slashes (outcharset, "TRANSLIT"); - charset = norm_add_slashes (charset, ""); - int r = __gconv_open (outcharset, charset, &convd->conv, - GCONV_AVOID_NOCONV); + conv_spec.translit = true; + + int r = __gconv_open (&conv_spec, &convd->conv, + GCONV_AVOID_NOCONV); + + __gconv_destroy_spec (&conv_spec); + if (__builtin_expect (r != __GCONV_OK, 0)) { /* If the output encoding is the same there is diff --git a/intl/tst-codeset.c b/intl/tst-codeset.c index fd70432ec..e9f6e5e09 100644 --- a/intl/tst-codeset.c +++ b/intl/tst-codeset.c @@ -22,13 +22,11 @@ #include #include #include +#include static int do_test (void) { - char *s; - int result = 0; - unsetenv ("LANGUAGE"); unsetenv ("OUTPUT_CHARSET"); setlocale (LC_ALL, "de_DE.ISO-8859-1"); @@ -36,25 +34,21 @@ do_test (void) bindtextdomain ("codeset", OBJPFX "domaindir"); /* Here we expect output in ISO-8859-1. */ - s = gettext ("cheese"); - if (strcmp (s, "K\344se")) - { - printf ("call 1 returned: %s\n", s); - result = 1; - } + TEST_COMPARE_STRING (gettext ("cheese"), "K\344se"); + /* Here we expect output in UTF-8. */ bind_textdomain_codeset ("codeset", "UTF-8"); + TEST_COMPARE_STRING (gettext ("cheese"), "K\303\244se"); - /* Here we expect output in UTF-8. */ - s = gettext ("cheese"); - if (strcmp (s, "K\303\244se")) - { - printf ("call 2 returned: %s\n", s); - result = 1; - } - - return result; + /* `a with umlaut' is transliterated to `ae'. */ + bind_textdomain_codeset ("codeset", "ASCII//TRANSLIT"); + TEST_COMPARE_STRING (gettext ("cheese"), "Kaese"); + + /* Transliteration also works by default even if not set. */ + bind_textdomain_codeset ("codeset", "ASCII"); + TEST_COMPARE_STRING (gettext ("cheese"), "Kaese"); + + return 0; } -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include diff --git a/localedata/locales/oc_FR b/localedata/locales/oc_FR index d0d89a149..ba9377ed4 100644 --- a/localedata/locales/oc_FR +++ b/localedata/locales/oc_FR @@ -92,7 +92,7 @@ day "dimenge";/ "diluns";/ "dimars";/ "dimcres";/ - "dijus";/ + "dijus";/ "divendres";/ "dissabte" abmon "gen.";/ @@ -110,7 +110,7 @@ abmon "gen.";/ alt_mon "genir";/ "febrir";/ "mar";/ - "abrial";/ + "abril";/ "mai";/ "junh";/ "julhet";/ @@ -122,7 +122,7 @@ alt_mon "genir";/ mon "de genir";/ "de febrir";/ "de mar";/ - "dabrial";/ + "dabril";/ "de mai";/ "de junh";/ "de julhet";/ diff --git a/malloc/Makefile b/malloc/Makefile index 984045b5b..8edeb3d62 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -61,6 +61,16 @@ endif tests += $(tests-static) test-srcs = tst-mtrace +# These tests either are run with MALLOC_CHECK_=3 by default or do not work +# with MALLOC_CHECK_=3 because they expect a specific failure. +tests-exclude-mcheck = tst-mcheck tst-malloc-usable \ + tst-interpose-nothread tst-interpose-static-nothread \ + tst-interpose-static-thread tst-malloc-too-large \ + tst-mxfast tst-safe-linking + +# Run all tests with MALLOC_CHECK_=3 +tests-mcheck = $(filter-out $(tests-exclude-mcheck),$(tests)) + routines = malloc morecore mcheck mtrace obstack reallocarray \ scratch_buffer_grow scratch_buffer_grow_preserve \ scratch_buffer_set_array_size \ @@ -99,6 +109,11 @@ $(objpfx)tst-malloc-thread-exit: $(shared-thread-library) $(objpfx)tst-malloc-thread-fail: $(shared-thread-library) $(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library) $(objpfx)tst-malloc-stats-cancellation: $(shared-thread-library) +$(objpfx)tst-malloc-backtrace-mcheck: $(shared-thread-library) +$(objpfx)tst-malloc-thread-exit-mcheck: $(shared-thread-library) +$(objpfx)tst-malloc-thread-fail-mcheck: $(shared-thread-library) +$(objpfx)tst-malloc-fork-deadlock-mcheck: $(shared-thread-library) +$(objpfx)tst-malloc-stats-cancellation-mcheck: $(shared-thread-library) # Export the __malloc_initialize_hook variable to libc.so. LDFLAGS-tst-mallocstate = -rdynamic @@ -238,6 +253,8 @@ $(tests:%=$(objpfx)%.o): CPPFLAGS += -DTEST_NO_MALLOPT $(objpfx)tst-interpose-nothread: $(objpfx)tst-interpose-aux-nothread.o $(objpfx)tst-interpose-thread: \ $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library) +$(objpfx)tst-interpose-thread-mcheck: \ + $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library) $(objpfx)tst-interpose-static-nothread: $(objpfx)tst-interpose-aux-nothread.o $(objpfx)tst-interpose-static-thread: \ $(objpfx)tst-interpose-aux-thread.o $(static-thread-library) @@ -255,3 +272,6 @@ $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out $(objpfx)tst-malloc-tcache-leak: $(shared-thread-library) $(objpfx)tst-malloc_info: $(shared-thread-library) $(objpfx)tst-mallocfork2: $(shared-thread-library) +$(objpfx)tst-malloc-tcache-leak-mcheck: $(shared-thread-library) +$(objpfx)tst-malloc_info-mcheck: $(shared-thread-library) +$(objpfx)tst-mallocfork2-mcheck: $(shared-thread-library) diff --git a/malloc/tst-mallocfork2.c b/malloc/tst-mallocfork2.c index 0602a9489..fc1fd64b2 100644 --- a/malloc/tst-mallocfork2.c +++ b/malloc/tst-mallocfork2.c @@ -62,6 +62,9 @@ static volatile sig_atomic_t sigusr1_received; progress. Checked by liveness_signal_handler. */ static volatile sig_atomic_t progress_indicator = 1; +/* Set to 1 if an error occurs in the signal handler. */ +static volatile sig_atomic_t error_indicator = 0; + static void sigusr1_handler (int signo) { @@ -72,7 +75,8 @@ sigusr1_handler (int signo) if (pid == -1) { write_message ("error: fork\n"); - abort (); + error_indicator = 1; + return; } if (pid == 0) _exit (0); @@ -81,12 +85,14 @@ sigusr1_handler (int signo) if (ret < 0) { write_message ("error: waitpid\n"); - abort (); + error_indicator = 1; + return; } if (status != 0) { write_message ("error: unexpected exit status from subprocess\n"); - abort (); + error_indicator = 1; + return; } } @@ -122,9 +128,25 @@ signal_sender (int signo, bool sleep) } } +/* Children processes. */ +static pid_t sigusr1_sender_pids[5] = { 0 }; +static pid_t sigusr2_sender_pid = 0; + +static void +kill_children (void) +{ + for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i) + if (sigusr1_sender_pids[i] > 0) + kill (sigusr1_sender_pids[i], SIGKILL); + if (sigusr2_sender_pid > 0) + kill (sigusr2_sender_pid, SIGKILL); +} + static int do_test (void) { + atexit (kill_children); + /* shared->barrier is intialized along with sigusr1_sender_pids below. */ shared = support_shared_allocate (sizeof (*shared)); @@ -148,14 +170,13 @@ do_test (void) return 1; } - pid_t sigusr2_sender_pid = xfork (); + sigusr2_sender_pid = xfork (); if (sigusr2_sender_pid == 0) signal_sender (SIGUSR2, true); /* Send SIGUSR1 signals from several processes. Hopefully, one signal will hit one of the ciritical functions. Use a barrier to avoid sending signals while not running fork/free/malloc. */ - pid_t sigusr1_sender_pids[5]; { pthread_barrierattr_t attr; xpthread_barrierattr_init (&attr); @@ -166,7 +187,7 @@ do_test (void) } for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i) { - sigusr1_sender_pids[i] = fork (); + sigusr1_sender_pids[i] = xfork (); if (sigusr1_sender_pids[i] == 0) signal_sender (SIGUSR1, false); } @@ -211,7 +232,7 @@ do_test (void) ++malloc_signals; xpthread_barrier_wait (&shared->barrier); - if (objects[slot] == NULL) + if (objects[slot] == NULL || error_indicator != 0) { printf ("error: malloc: %m\n"); for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i) @@ -225,10 +246,6 @@ do_test (void) for (int slot = 0; slot < malloc_objects; ++slot) free (objects[slot]); - for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i) - kill (sigusr1_sender_pids[i], SIGKILL); - kill (sigusr2_sender_pid, SIGKILL); - printf ("info: signals received during fork: %u\n", fork_signals); printf ("info: signals received during free: %u\n", free_signals); printf ("info: signals received during malloc: %u\n", malloc_signals); diff --git a/math/Makefile b/math/Makefile index 5985b6744..3496af404 100644 --- a/math/Makefile +++ b/math/Makefile @@ -644,6 +644,128 @@ ifneq ($(long-double-fcts),yes) # We won't compile the `long double' code at all. Tell the `double' code # to define aliases for the `FUNCl' names. math-CPPFLAGS += -DNO_LONG_DOUBLE +# GCC 10 diagnoses aliases with types conflicting with built-in +# functions. +CFLAGS-w_acos.c += -fno-builtin-acosl +CFLAGS-w_acosh.c += -fno-builtin-acoshl +CFLAGS-w_asin.c += -fno-builtin-asinl +CFLAGS-s_asinh.c += -fno-builtin-asinhl +CFLAGS-s_atan.c += -fno-builtin-atanl +CFLAGS-w_atan2.c += -fno-builtin-atan2l +CFLAGS-w_atanh.c += -fno-builtin-atanhl +CFLAGS-s_cabs.c += -fno-builtin-cabsl +CFLAGS-s_cacos.c += -fno-builtin-cacosl +CFLAGS-s_cacosh.c += -fno-builtin-cacoshl +CFLAGS-s_canonicalize.c += -fno-builtin-canonicalizel +CFLAGS-s_carg.c += -fno-builtin-cargl +CFLAGS-s_casin.c += -fno-builtin-casinl +CFLAGS-s_casinh.c += -fno-builtin-casinhl +CFLAGS-s_catan.c += -fno-builtin-catanl +CFLAGS-s_catanh.c += -fno-builtin-catanhl +CFLAGS-s_cbrt.c += -fno-builtin-cbrtl +CFLAGS-s_ccos.c += -fno-builtin-ccosl +CFLAGS-s_ccosh.c += -fno-builtin-ccoshl +CFLAGS-s_ceil.c += -fno-builtin-ceill +CFLAGS-s_cexp.c += -fno-builtin-cexpl +CFLAGS-s_cimag.c += -fno-builtin-cimagl +CFLAGS-s_clog.c += -fno-builtin-clogl +CFLAGS-s_clog10.c += -fno-builtin-clog10l +CFLAGS-s_conj.c += -fno-builtin-conjl +CFLAGS-s_copysign.c += -fno-builtin-copysignl +CFLAGS-s_cos.c += -fno-builtin-cosl +CFLAGS-w_cosh.c += -fno-builtin-coshl +CFLAGS-s_cpow.c += -fno-builtin-cpowl +CFLAGS-s_cproj.c += -fno-builtin-cprojl +CFLAGS-s_creal.c += -fno-builtin-creall +CFLAGS-s_csin.c += -fno-builtin-csinl +CFLAGS-s_csinh.c += -fno-builtin-csinhl +CFLAGS-s_csqrt.c += -fno-builtin-csqrtl +CFLAGS-s_ctan.c += -fno-builtin-ctanl +CFLAGS-s_ctanh.c += -fno-builtin-ctanhl +CFLAGS-s_dadd.c += -fno-builtin-daddl +CFLAGS-s_ddiv.c += -fno-builtin-ddivl +CFLAGS-s_dmul.c += -fno-builtin-dmull +CFLAGS-s_dsub.c += -fno-builtin-dsubl +CFLAGS-s_erf.c += -fno-builtin-erfl +CFLAGS-s_erfc.c += -fno-builtin-erfcl +CFLAGS-e_exp.c += -fno-builtin-expl +CFLAGS-w_exp10.c += -fno-builtin-exp10l +CFLAGS-e_exp2.c += -fno-builtin-exp2l +CFLAGS-s_expm1.c += -fno-builtin-expm1l +CFLAGS-s_fabs.c += -fno-builtin-fabsl +CFLAGS-s_fadd.c += -fno-builtin-faddl +CFLAGS-s_fdim.c += -fno-builtin-fdiml +CFLAGS-s_fdiv.c += -fno-builtin-fdivl +CFLAGS-s_finite.c += -fno-builtin-finitel +CFLAGS-s_floor.c += -fno-builtin-floorl +CFLAGS-s_fma.c += -fno-builtin-fmal +CFLAGS-s_fmax.c += -fno-builtin-fmaxl +CFLAGS-s_fmaxmag.c += -fno-builtin-fmaxmagl +CFLAGS-s_fmin.c += -fno-builtin-fminl +CFLAGS-s_fminmag.c += -fno-builtin-fminmagl +CFLAGS-w_fmod.c += -fno-builtin-fmodl +CFLAGS-s_fmul.c += -fno-builtin-fmull +CFLAGS-s_frexp.c += -fno-builtin-frexpl +CFLAGS-s_fromfp.c += -fno-builtin-fromfpl +CFLAGS-s_fromfpx.c += -fno-builtin-fromfpxl +CFLAGS-s_fsub.c += -fno-builtin-fsubl +CFLAGS-s_gamma.c += -fno-builtin-gammal +CFLAGS-s_getpayload.c += -fno-builtin-getpayloadl +CFLAGS-w_hypot.c += -fno-builtin-hypotl +CFLAGS-w_ilogb.c += -fno-builtin-ilogbl +CFLAGS-s_isinf.c += -fno-builtin-isinfl +CFLAGS-s_isnan.c += -fno-builtin-isnanl +CFLAGS-w_j0.c += -fno-builtin-j0l +CFLAGS-w_j1.c += -fno-builtin-j1l +CFLAGS-w_jn.c += -fno-builtin-jnl +CFLAGS-s_ldexp.c += -fno-builtin-ldexpl +CFLAGS-w_lgamma.c += -fno-builtin-lgammal +CFLAGS-w_lgamma_r.c += -fno-builtin-lgammal_r +CFLAGS-w_llogb.c += -fno-builtin-llogbl +CFLAGS-s_llrint.c += -fno-builtin-llrintl +CFLAGS-s_llround.c += -fno-builtin-llroundl +CFLAGS-e_log.c += -fno-builtin-logl +CFLAGS-w_log10.c += -fno-builtin-log10l +CFLAGS-w_log1p.c += -fno-builtin-log1pl +CFLAGS-e_log2.c += -fno-builtin-log2l +CFLAGS-s_logb.c += -fno-builtin-logbl +CFLAGS-s_lrint.c += -fno-builtin-lrintl +CFLAGS-s_lround.c += -fno-builtin-lroundl +CFLAGS-s_modf.c += -fno-builtin-modfl +CFLAGS-s_nan.c += -fno-builtin-nanl +CFLAGS-s_nearbyint.c += -fno-builtin-nearbyintl +CFLAGS-s_nextafter.c += -fno-builtin-nextafterl +CFLAGS-s_nextdown.c += -fno-builtin-nextdownl +CFLAGS-s_nexttoward.c += -fno-builtin-nexttoward -fno-builtin-nexttowardl +CFLAGS-s_nexttowardf.c += -fno-builtin-nexttowardf +CFLAGS-s_nextup.c += -fno-builtin-nextupl +CFLAGS-e_pow.c += -fno-builtin-powl +CFLAGS-w_remainder.c += -fno-builtin-remainderl -fno-builtin-dreml +CFLAGS-s_remquo.c += -fno-builtin-remquol +CFLAGS-s_rint.c += -fno-builtin-rintl +CFLAGS-s_round.c += -fno-builtin-roundl +CFLAGS-s_roundeven.c += -fno-builtin-roundevenl +CFLAGS-w_scalb.c += -fno-builtin-scalbl +CFLAGS-w_scalbln.c += -fno-builtin-scalblnl +CFLAGS-s_scalbn.c += -fno-builtin-scalbnl +CFLAGS-s_setpayload.c += -fno-builtin-setpayloadl +CFLAGS-s_setpayloadsig.c += -fno-builtin-setpayloadsigl +CFLAGS-s_significand.c += -fno-builtin-significandl +CFLAGS-s_sin.c += -fno-builtin-sinl +CFLAGS-s_sincos.c += -fno-builtin-sincosl +CFLAGS-w_sinh.c += -fno-builtin-sinhl +CFLAGS-w_sqrt.c += -fno-builtin-sqrtl +CFLAGS-s_tan.c += -fno-builtin-tanl +CFLAGS-s_tanh.c += -fno-builtin-tanhl +CFLAGS-w_tgamma.c += -fno-builtin-tgammal +CFLAGS-s_totalorder.c += -fno-builtin-totalorderl +CFLAGS-s_totalordermag.c += -fno-builtin-totalordermagl +CFLAGS-s_trunc.c += -fno-builtin-truncl +CFLAGS-s_ufromfp.c += -fno-builtin-ufromfpl +CFLAGS-s_ufromfpx.c += -fno-builtin-ufromfpxl +CFLAGS-s_y0.c += -fno-builtin-y0l +CFLAGS-s_y1.c += -fno-builtin-y1l +CFLAGS-s_yn.c += -fno-builtin-ynl endif # These files quiet sNaNs in a way that is optimized away without diff --git a/misc/Makefile b/misc/Makefile index e0465980c..e167e199e 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -87,7 +87,7 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \ tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \ tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \ - tst-mntent-autofs + tst-mntent-autofs tst-syscalls # Tests which need libdl. ifeq (yes,$(build-shared)) diff --git a/misc/tst-syscalls.c b/misc/tst-syscalls.c new file mode 100644 index 000000000..cfcd38232 --- /dev/null +++ b/misc/tst-syscalls.c @@ -0,0 +1,167 @@ +/* Test for syscall interfaces. + Copyright (C) 2020 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 + . */ + +/* This test verifies that the x32 system call handling zero-extends + unsigned 32-bit arguments to the 64-bit argument registers for + system calls (bug 25810). The bug is specific to x32, but the test + should pass on all architectures. */ + +#include +#include +#include +#include +#include +#include + +/* On x32, this can be passed in a single 64-bit integer register. */ +struct Array +{ + size_t length; + void *ptr; +}; + +static int error_count; + +__attribute__ ((noclone, noinline)) +struct Array +allocate (size_t bytes) +{ + if (!bytes) + return __extension__ (struct Array) {0, 0}; + + void *p = mmap (0x0, bytes, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (p == MAP_FAILED) + return __extension__ (struct Array) {0, 0}; + + return __extension__ (struct Array) {bytes, p}; +} + +__attribute__ ((noclone, noinline)) +void +deallocate (struct Array b) +{ + /* On x32, the 64-bit integer register containing `b' may be copied + to another 64-bit integer register to pass the second argument to + munmap. */ + if (b.length && munmap (b.ptr, b.length)) + { + printf ("munmap error: %m\n"); + error_count++; + } +} + +__attribute__ ((noclone, noinline)) +void * +do_mmap (void *addr, size_t length) +{ + return mmap (addr, length, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); +} + +__attribute__ ((noclone, noinline)) +void * +reallocate (struct Array b) +{ + /* On x32, the 64-bit integer register containing `b' may be copied + to another 64-bit integer register to pass the second argument to + do_mmap. */ + if (b.length) + return do_mmap (b.ptr, b.length); + return NULL; +} + +__attribute__ ((noclone, noinline)) +void +protect (struct Array b) +{ + if (b.length) + { + /* On x32, the 64-bit integer register containing `b' may be copied + to another 64-bit integer register to pass the second argument + to mprotect. */ + if (mprotect (b.ptr, b.length, + PROT_READ | PROT_WRITE | PROT_EXEC)) + { + printf ("mprotect error: %m\n"); + error_count++; + } + } +} + +__attribute__ ((noclone, noinline)) +ssize_t +do_read (int fd, void *ptr, struct Array b) +{ + /* On x32, the 64-bit integer register containing `b' may be copied + to another 64-bit integer register to pass the second argument to + read. */ + if (b.length) + return read (fd, ptr, b.length); + return 0; +} + +__attribute__ ((noclone, noinline)) +ssize_t +do_write (int fd, void *ptr, struct Array b) +{ + /* On x32, the 64-bit integer register containing `b' may be copied + to another 64-bit integer register to pass the second argument to + write. */ + if (b.length) + return write (fd, ptr, b.length); + return 0; +} + +static int +do_test (void) +{ + struct Array array; + + array = allocate (1); + protect (array); + deallocate (array); + void *p = reallocate (array); + if (p == MAP_FAILED) + { + printf ("mmap error: %m\n"); + error_count++; + } + array.ptr = p; + protect (array); + deallocate (array); + + int fd = xopen ("/dev/null", O_RDWR, 0); + char buf[2]; + array.ptr = buf; + if (do_read (fd, array.ptr, array) == -1) + { + printf ("read error: %m\n"); + error_count++; + } + if (do_write (fd, array.ptr, array) == -1) + { + printf ("write error: %m\n"); + error_count++; + } + xclose (fd); + + return error_count ? EXIT_FAILURE : EXIT_SUCCESS; +} + +#include diff --git a/nptl/Makefile b/nptl/Makefile index 584e0ffd9..2df4c9098 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -332,7 +332,7 @@ tests-internal := tst-rwlock19 tst-rwlock20 \ tst-mutexpi8 tst-mutexpi8-static tst-cancel25 xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ - tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 + tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 tst-setgroups # This test can run into task limits because of a linux kernel bug # and then cause the make process to fail too, see bug 24537. diff --git a/nptl/descr.h b/nptl/descr.h index 9dcf480bd..5f1f35e9a 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -94,7 +94,13 @@ struct pthread_unwind_buf struct xid_command { int syscall_no; - long int id[3]; + /* Enforce zero-extension for the pointer argument in + + int setgroups (size_t size, const gid_t *list); + + The kernel XID arguments are unsigned and do not require sign + extension. */ + unsigned long int id[3]; volatile int cntr; volatile int error; /* -1: no call yet, 0: success seen, >0: error seen. */ }; diff --git a/nptl/tst-setgroups.c b/nptl/tst-setgroups.c new file mode 100644 index 000000000..ae3c1b1ba --- /dev/null +++ b/nptl/tst-setgroups.c @@ -0,0 +1,79 @@ +/* Test setgroups as root and in the presence of threads (Bug 26248) + Copyright (C) 2020 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The purpose of this test is to test the setgroups API as root and in + the presence of threads. Once we create a thread the setgroups + implementation must ensure that all threads are set to the same + group and this operation should not fail. Lastly we test setgroups + with a zero sized group and a bad address and verify we get EPERM. */ + +static void * +start_routine (void *args) +{ + return NULL; +} + +static int +do_test (void) +{ + int size; + /* NB: Stack address can be at 0xfffXXXXX on 32-bit OSes. */ + gid_t list[NGROUPS_MAX]; + int status = EXIT_SUCCESS; + + pthread_t thread = xpthread_create (NULL, start_routine, NULL); + + size = getgroups (sizeof (list) / sizeof (list[0]), list); + if (size < 0) + { + status = EXIT_FAILURE; + error (0, errno, "getgroups failed"); + } + if (setgroups (size, list) < 0) + { + if (errno == EPERM) + status = EXIT_UNSUPPORTED; + else + { + status = EXIT_FAILURE; + error (0, errno, "setgroups failed"); + } + } + + if (status == EXIT_SUCCESS && setgroups (0, list) < 0) + { + status = EXIT_FAILURE; + error (0, errno, "setgroups failed"); + } + + xpthread_join (thread); + + return status; +} + +#include diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 88c69d1e9..381aa721e 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, : NULL); ndomain = (ndomain ? newbuf + ndomaindiff : NULL); - buffer = newbuf; + *tofreep = buffer = newbuf; } nhost = memcpy (buffer + bufused, @@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) { buflen *= 2; - buffer = xrealloc (buffer, buflen); + *tofreep = buffer = xrealloc (buffer, buflen); } else if (status == NSS_STATUS_RETURN || status == NSS_STATUS_NOTFOUND diff --git a/nscd/selinux.c b/nscd/selinux.c index a4ea8008e..1ebf92482 100644 --- a/nscd/selinux.c +++ b/nscd/selinux.c @@ -33,6 +33,7 @@ #ifdef HAVE_LIBAUDIT # include #endif +#include #include "dbg_log.h" #include "selinux.h" @@ -320,6 +321,12 @@ avc_free_lock (void *lock) } +/* avc_init (along with several other symbols) was marked as deprecated by the + SELinux API starting from version 3.1. We use it here, but should + eventually switch to the newer API. */ +DIAG_PUSH_NEEDS_COMMENT +DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); + /* Initialize the user space access vector cache (AVC) for NSCD along with log/thread/lock callbacks. */ void @@ -335,7 +342,14 @@ nscd_avc_init (void) audit_init (); #endif } +DIAG_POP_NEEDS_COMMENT + +/* security_context_t and sidput (along with several other symbols) were marked + as deprecated by the SELinux API starting from version 3.1. We use them + here, but should eventually switch to the newer API. */ +DIAG_PUSH_NEEDS_COMMENT +DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); /* Check the permission from the caller (via getpeercon) to nscd. Returns 0 if access is allowed, 1 if denied, and -1 on error. @@ -422,6 +436,7 @@ out: return rc; } +DIAG_POP_NEEDS_COMMENT /* Wrapper to get AVC statistics. */ diff --git a/nss/makedb.c b/nss/makedb.c index 8e389a168..8e1e8ec9a 100644 --- a/nss/makedb.c +++ b/nss/makedb.c @@ -38,6 +38,7 @@ #include #include #include "nss_db/nss_db.h" +#include /* Get libc version number. */ #include "../version.h" @@ -841,6 +842,13 @@ print_database (int fd) #ifdef HAVE_SELINUX + +/* security_context_t and matchpathcon (along with several other symbols) were + marked as deprecated by the SELinux API starting from version 3.1. We use + them here, but should eventually switch to the newer API. */ +DIAG_PUSH_NEEDS_COMMENT +DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); + static void set_file_creation_context (const char *outname, mode_t mode) { @@ -870,6 +878,7 @@ set_file_creation_context (const char *outname, mode_t mode) freecon (ctx); } } +DIAG_POP_NEEDS_COMMENT static void reset_file_creation_context (void) diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c index a8de1e03b..f8b19a5cf 100644 --- a/nss/nss_compat/compat-grp.c +++ b/nss/nss_compat/compat-grp.c @@ -142,7 +142,7 @@ _nss_compat_setgrent (int stayopen) } -static enum nss_status +static enum nss_status __attribute_warn_unused_result__ internal_endgrent (ent_t *ent) { if (ent->stream != NULL) @@ -163,6 +163,15 @@ internal_endgrent (ent_t *ent) return NSS_STATUS_SUCCESS; } +/* Like internal_endgrent, but preserve errno in all cases. */ +static void +internal_endgrent_noerror (ent_t *ent) +{ + int saved_errno = errno; + enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent); + __set_errno (saved_errno); +} + enum nss_status _nss_compat_endgrent (void) { @@ -483,7 +492,7 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp, if (result == NSS_STATUS_SUCCESS) result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop); - internal_endgrent (&ent); + internal_endgrent_noerror (&ent); return result; } @@ -612,7 +621,7 @@ _nss_compat_getgrgid_r (gid_t gid, struct group *grp, if (result == NSS_STATUS_SUCCESS) result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop); - internal_endgrent (&ent); + internal_endgrent_noerror (&ent); return result; } diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c index 939b25b33..7591442ff 100644 --- a/nss/nss_compat/compat-initgroups.c +++ b/nss/nss_compat/compat-initgroups.c @@ -133,7 +133,7 @@ internal_setgrent (ent_t *ent) } -static enum nss_status +static enum nss_status __attribute_warn_unused_result__ internal_endgrent (ent_t *ent) { if (ent->stream != NULL) @@ -157,6 +157,15 @@ internal_endgrent (ent_t *ent) return NSS_STATUS_SUCCESS; } +/* Like internal_endgrent, but preserve errno in all cases. */ +static void +internal_endgrent_noerror (ent_t *ent) +{ + int saved_errno = errno; + enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent); + __set_errno (saved_errno); +} + /* Add new group record. */ static void add_group (long int *start, long int *size, gid_t **groupsp, long int limit, @@ -501,7 +510,7 @@ _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, done: scratch_buffer_free (&tmpbuf); - internal_endgrent (&intern); + internal_endgrent_noerror (&intern); return status; } diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c index ec3f35c59..bd5e707da 100644 --- a/nss/nss_compat/compat-pwd.c +++ b/nss/nss_compat/compat-pwd.c @@ -259,7 +259,7 @@ _nss_compat_setpwent (int stayopen) } -static enum nss_status +static enum nss_status __attribute_warn_unused_result__ internal_endpwent (ent_t *ent) { if (ent->stream != NULL) @@ -287,6 +287,15 @@ internal_endpwent (ent_t *ent) return NSS_STATUS_SUCCESS; } +/* Like internal_endpwent, but preserve errno in all cases. */ +static void +internal_endpwent_noerror (ent_t *ent) +{ + int saved_errno = errno; + enum nss_status unused __attribute__ ((unused)) = internal_endpwent (ent); + __set_errno (saved_errno); +} + enum nss_status _nss_compat_endpwent (void) { @@ -822,7 +831,7 @@ _nss_compat_getpwnam_r (const char *name, struct passwd *pwd, if (result == NSS_STATUS_SUCCESS) result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop); - internal_endpwent (&ent); + internal_endpwent_noerror (&ent); return result; } @@ -1061,7 +1070,7 @@ _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, if (result == NSS_STATUS_SUCCESS) result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop); - internal_endpwent (&ent); + internal_endpwent_noerror (&ent); return result; } diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c index f6b7a1ef1..d0e3c51b4 100644 --- a/nss/nss_compat/compat-spwd.c +++ b/nss/nss_compat/compat-spwd.c @@ -215,7 +215,7 @@ _nss_compat_setspent (int stayopen) } -static enum nss_status +static enum nss_status __attribute_warn_unused_result__ internal_endspent (ent_t *ent) { if (ent->stream != NULL) @@ -244,6 +244,15 @@ internal_endspent (ent_t *ent) return NSS_STATUS_SUCCESS; } +/* Like internal_endspent, but preserve errno in all cases. */ +static void +internal_endspent_noerror (ent_t *ent) +{ + int saved_errno = errno; + enum nss_status unused __attribute__ ((unused)) = internal_endspent (ent); + __set_errno (saved_errno); +} + enum nss_status _nss_compat_endspent (void) { @@ -261,7 +270,6 @@ _nss_compat_endspent (void) return result; } - static enum nss_status getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent, char *group, char *buffer, size_t buflen, @@ -786,7 +794,7 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd, if (result == NSS_STATUS_SUCCESS) result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); - internal_endspent (&ent); + internal_endspent_noerror (&ent); return result; } diff --git a/posix/glob.c b/posix/glob.c index cba9cd181..4580cefb9 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -827,31 +827,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { size_t home_len = strlen (p->pw_dir); size_t rest_len = end_name == NULL ? 0 : strlen (end_name); - char *d; + char *d, *newp; + bool use_alloca = glob_use_alloca (alloca_used, + home_len + rest_len + 1); - if (__glibc_unlikely (malloc_dirname)) - free (dirname); - malloc_dirname = 0; - - if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) - dirname = alloca_account (home_len + rest_len + 1, - alloca_used); + if (use_alloca) + newp = alloca_account (home_len + rest_len + 1, alloca_used); else { - dirname = malloc (home_len + rest_len + 1); - if (dirname == NULL) + newp = malloc (home_len + rest_len + 1); + if (newp == NULL) { scratch_buffer_free (&pwtmpbuf); retval = GLOB_NOSPACE; goto out; } - malloc_dirname = 1; } - d = mempcpy (dirname, p->pw_dir, home_len); + d = mempcpy (newp, p->pw_dir, home_len); if (end_name != NULL) d = mempcpy (d, end_name, rest_len); *d = '\0'; + if (__glibc_unlikely (malloc_dirname)) + free (dirname); + dirname = newp; + malloc_dirname = !use_alloca; + dirlen = home_len + rest_len; dirname_modified = 1; } diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c index ed1b22308..cb3f989cb 100644 --- a/posix/wordexp-test.c +++ b/posix/wordexp-test.c @@ -183,6 +183,7 @@ struct test_case_struct { 0, NULL, "$var", 0, 0, { NULL, }, IFS }, { 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS }, { 0, NULL, "", 0, 0, { NULL, }, IFS }, + { 0, NULL, "${1234567890123456789012}", 0, 0, { NULL, }, IFS }, /* Flags not already covered (testit() has special handling for these) */ { 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS }, diff --git a/posix/wordexp.c b/posix/wordexp.c index e082d9489..56289503a 100644 --- a/posix/wordexp.c +++ b/posix/wordexp.c @@ -1399,7 +1399,7 @@ envsubst: /* Is it a numeric parameter? */ else if (isdigit (env[0])) { - int n = atoi (env); + unsigned long n = strtoul (env, NULL, 10); if (n >= __libc_argc) /* Substitute NULL. */ diff --git a/socket/Makefile b/socket/Makefile index 125c042ca..19fc6ab41 100644 --- a/socket/Makefile +++ b/socket/Makefile @@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \ routines := accept bind connect getpeername getsockname getsockopt \ listen recv recvfrom recvmsg send sendmsg sendto \ setsockopt shutdown socket socketpair isfdtype opensock \ - sockatmark accept4 recvmmsg sendmmsg + sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set tests := tst-accept4 +tests-internal := \ + tst-sockaddr_un_set \ + # tests-internal + aux := sa_len include ../Rules diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c new file mode 100644 index 000000000..0bd40dc34 --- /dev/null +++ b/socket/sockaddr_un_set.c @@ -0,0 +1,41 @@ +/* Set the sun_path member of struct sockaddr_un. + Copyright (C) 2022 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 + . */ + +#include +#include +#include +#include + +int +__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) +{ + size_t name_length = strlen (pathname); + + /* The kernel supports names of exactly sizeof (addr->sun_path) + bytes, without a null terminator, but userspace does not; see the + SUN_LEN macro. */ + if (name_length >= sizeof (addr->sun_path)) + { + __set_errno (EINVAL); /* Error code used by the kernel. */ + return -1; + } + + addr->sun_family = AF_UNIX; + memcpy (addr->sun_path, pathname, name_length + 1); + return 0; +} diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c new file mode 100644 index 000000000..29c2a81af --- /dev/null +++ b/socket/tst-sockaddr_un_set.c @@ -0,0 +1,62 @@ +/* Test the __sockaddr_un_set function. + Copyright (C) 2022 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 + . */ + +/* Re-compile the function because the version in libc is not + exported. */ +#include "sockaddr_un_set.c" + +#include + +static int +do_test (void) +{ + struct sockaddr_un sun; + + memset (&sun, 0xcc, sizeof (sun)); + __sockaddr_un_set (&sun, ""); + TEST_COMPARE (sun.sun_family, AF_UNIX); + TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0); + + memset (&sun, 0xcc, sizeof (sun)); + TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0); + TEST_COMPARE_STRING (sun.sun_path, "/example"); + + { + char pathname[108]; /* Length of sun_path (ABI constant). */ + memset (pathname, 'x', sizeof (pathname)); + pathname[sizeof (pathname) - 1] = '\0'; + memset (&sun, 0xcc, sizeof (sun)); + TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0); + TEST_COMPARE (sun.sun_family, AF_UNIX); + TEST_COMPARE_STRING (sun.sun_path, pathname); + } + + { + char pathname[109]; + memset (pathname, 'x', sizeof (pathname)); + pathname[sizeof (pathname) - 1] = '\0'; + memset (&sun, 0xcc, sizeof (sun)); + errno = 0; + TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1); + TEST_COMPARE (errno, EINVAL); + } + + return 0; +} + +#include diff --git a/stdlib/Makefile b/stdlib/Makefile index 45214b59e..4615f6dfe 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -70,7 +70,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ test-canon test-canon2 tst-strtoll tst-environ \ tst-xpg-basename tst-random tst-random2 tst-bsearch \ tst-limits tst-rand48 bug-strtod tst-setcontext \ - tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \ + tst-setcontext2 test-a64l tst-qsort testmb2 \ bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \ tst-rand48-2 tst-makecontext tst-strtod5 \ tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ @@ -92,6 +92,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ tst-tls-atexit tst-tls-atexit-nodelete tests-static := tst-secure-getenv +tests-container := tst-system ifeq ($(build-hardcoded-path-in-tests),yes) tests += tst-empty-env diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c index 3cfe9a05c..d4b1139c5 100644 --- a/stdlib/tst-secure-getenv.c +++ b/stdlib/tst-secure-getenv.c @@ -30,167 +30,12 @@ #include #include +#include #include +#include #include static char MAGIC_ARGUMENT[] = "run-actual-test"; -#define MAGIC_STATUS 19 - -/* Return a GID which is not our current GID, but is present in the - supplementary group list. */ -static gid_t -choose_gid (void) -{ - int count = getgroups (0, NULL); - if (count < 0) - { - printf ("getgroups: %m\n"); - exit (1); - } - gid_t *groups; - groups = xcalloc (count, sizeof (*groups)); - int ret = getgroups (count, groups); - if (ret < 0) - { - printf ("getgroups: %m\n"); - exit (1); - } - gid_t current = getgid (); - gid_t not_current = 0; - for (int i = 0; i < ret; ++i) - { - if (groups[i] != current) - { - not_current = groups[i]; - break; - } - } - free (groups); - return not_current; -} - - -/* Copies the executable into a restricted directory, so that we can - safely make it SGID with the TARGET group ID. Then runs the - executable. */ -static int -run_executable_sgid (gid_t target) -{ - char *dirname = xasprintf ("%s/secure-getenv.%jd", - test_dir, (intmax_t) getpid ()); - char *execname = xasprintf ("%s/bin", dirname); - int infd = -1; - int outfd = -1; - int ret = -1; - if (mkdir (dirname, 0700) < 0) - { - printf ("mkdir: %m\n"); - goto err; - } - infd = open ("/proc/self/exe", O_RDONLY); - if (infd < 0) - { - printf ("open (/proc/self/exe): %m\n"); - goto err; - } - outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); - if (outfd < 0) - { - printf ("open (%s): %m\n", execname); - goto err; - } - char buf[4096]; - for (;;) - { - ssize_t rdcount = read (infd, buf, sizeof (buf)); - if (rdcount < 0) - { - printf ("read: %m\n"); - goto err; - } - if (rdcount == 0) - break; - char *p = buf; - char *end = buf + rdcount; - while (p != end) - { - ssize_t wrcount = write (outfd, buf, end - p); - if (wrcount == 0) - errno = ENOSPC; - if (wrcount <= 0) - { - printf ("write: %m\n"); - goto err; - } - p += wrcount; - } - } - if (fchown (outfd, getuid (), target) < 0) - { - printf ("fchown (%s): %m\n", execname); - goto err; - } - if (fchmod (outfd, 02750) < 0) - { - printf ("fchmod (%s): %m\n", execname); - goto err; - } - if (close (outfd) < 0) - { - printf ("close (outfd): %m\n"); - goto err; - } - if (close (infd) < 0) - { - printf ("close (infd): %m\n"); - goto err; - } - - int kid = fork (); - if (kid < 0) - { - printf ("fork: %m\n"); - goto err; - } - if (kid == 0) - { - /* Child process. */ - char *args[] = { execname, MAGIC_ARGUMENT, NULL }; - execve (execname, args, environ); - printf ("execve (%s): %m\n", execname); - _exit (1); - } - int status; - if (waitpid (kid, &status, 0) < 0) - { - printf ("waitpid: %m\n"); - goto err; - } - if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS) - { - printf ("Unexpected exit status %d from child process\n", - status); - goto err; - } - ret = 0; - -err: - if (outfd >= 0) - close (outfd); - if (infd >= 0) - close (infd); - if (execname) - { - unlink (execname); - free (execname); - } - if (dirname) - { - rmdir (dirname); - free (dirname); - } - return ret; -} static int do_test (void) @@ -212,15 +57,15 @@ do_test (void) exit (1); } - gid_t target = choose_gid (); - if (target == 0) - { - fprintf (stderr, - "Could not find a suitable GID for user %jd, skipping test\n", - (intmax_t) getuid ()); - exit (0); - } - return run_executable_sgid (target); + int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT); + + if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) + return EXIT_UNSUPPORTED; + + if (!WIFEXITED (status)) + FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); + + return 0; } static void @@ -229,23 +74,15 @@ alternative_main (int argc, char **argv) if (argc == 2 && strcmp (argv[1], MAGIC_ARGUMENT) == 0) { if (getgid () == getegid ()) - { - /* This can happen if the file system is mounted nosuid. */ - fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n", - (intmax_t) getgid ()); - exit (MAGIC_STATUS); - } + /* This can happen if the file system is mounted nosuid. */ + FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", + (intmax_t) getgid ()); if (getenv ("PATH") == NULL) - { - printf ("PATH variable not present\n"); - exit (3); - } + FAIL_EXIT (3, "PATH variable not present\n"); if (secure_getenv ("PATH") != NULL) - { - printf ("PATH variable not filtered out\n"); - exit (4); - } - exit (MAGIC_STATUS); + FAIL_EXIT (4, "PATH variable not filtered out\n"); + + exit (EXIT_SUCCESS); } } diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c index b6c5aea08..eddea33f4 100644 --- a/stdlib/tst-system.c +++ b/stdlib/tst-system.c @@ -17,14 +17,130 @@ . */ #include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *tmpdir; +static long int namemax; + +static void +do_prepare (int argc, char *argv[]) +{ + tmpdir = support_create_temp_directory ("tst-system-"); + /* Include the last '/0'. */ + namemax = pathconf (tmpdir, _PC_NAME_MAX) + 1; + TEST_VERIFY_EXIT (namemax != -1); +} +#define PREPARE do_prepare + +struct args +{ + const char *command; + int exit_status; + int term_sig; + const char *path; +}; + +static void +call_system (void *closure) +{ + struct args *args = (struct args *) closure; + int ret; + + if (args->path != NULL) + TEST_COMPARE (setenv ("PATH", args->path, 1), 0); + ret = system (args->command); + if (args->term_sig == 0) + { + /* Expect regular termination. */ + TEST_VERIFY (WIFEXITED (ret) != 0); + TEST_COMPARE (WEXITSTATUS (ret), args->exit_status); + } + else + { + /* status_or_signal < 0. Expect termination by signal. */ + TEST_VERIFY (WIFSIGNALED (ret) != 0); + TEST_COMPARE (WTERMSIG (ret), args->term_sig); + } +} static int do_test (void) { - return system (":"); -} + TEST_VERIFY (system (NULL) != 0); + { + char cmd[namemax]; + memset (cmd, 'a', sizeof(cmd)); + cmd[sizeof(cmd) - 1] = '\0'; + + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { + cmd, 127, 0, tmpdir + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); + + char *returnerr = xasprintf ("%s: execing %s failed: " + "No such file or directory", + basename(_PATH_BSHELL), cmd); + TEST_COMPARE_STRING (result.err.buffer, returnerr); + free (returnerr); + } + + { + char cmd[namemax + 1]; + memset (cmd, 'a', sizeof(cmd)); + cmd[sizeof(cmd) - 1] = '\0'; + + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { + cmd, 127, 0, tmpdir + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); + + char *returnerr = xasprintf ("%s: execing %s failed: " + "File name too long", + basename(_PATH_BSHELL), cmd); + TEST_COMPARE_STRING (result.err.buffer, returnerr); + free (returnerr); + } + + { + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { + "kill $$", 0, SIGTERM + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_none); + } + + { + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { "echo ...", 0 }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_stdout); + TEST_COMPARE_STRING (result.out.buffer, "...\n"); + } + + { + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { "exit 1", 1 }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_none); + } + + TEST_COMPARE (system (""), 0); + + return 0; +} -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include diff --git a/sunrpc/Makefile b/sunrpc/Makefile index d5840d077..162a5cef5 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -95,7 +95,8 @@ others += rpcgen endif tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ - tst-udp-nonblocking + tst-udp-nonblocking tst-bug22542 tst-bug28768 + xtests := tst-getmyaddr ifeq ($(have-thread-library),yes) @@ -246,3 +247,5 @@ $(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so $(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so $(objpfx)tst-udp-garbage: \ $(common-objpfx)linkobj/libc.so $(shared-thread-library) + +$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c index 13ced8994..b44357cd8 100644 --- a/sunrpc/clnt_gen.c +++ b/sunrpc/clnt_gen.c @@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers, if (strcmp (proto, "unix") == 0) { - memset ((char *)&sun, 0, sizeof (sun)); - sun.sun_family = AF_UNIX; - strcpy (sun.sun_path, hostname); + if (__sockaddr_un_set (&sun, hostname) < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + return NULL; + } sock = RPC_ANYSOCK; client = clntunix_create (&sun, prog, vers, &sock, 0, 0); if (client == NULL) diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c index e01afeabe..b065d6063 100644 --- a/sunrpc/svc_unix.c +++ b/sunrpc/svc_unix.c @@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) SVCXPRT *xprt; struct unix_rendezvous *r; struct sockaddr_un addr; - socklen_t len = sizeof (struct sockaddr_in); + socklen_t len = sizeof (addr); + + if (__sockaddr_un_set (&addr, path) < 0) + return NULL; if (sock == RPC_ANYSOCK) { @@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) } madesock = TRUE; } - memset (&addr, '\0', sizeof (addr)); - addr.sun_family = AF_UNIX; - len = strlen (path) + 1; - memcpy (addr.sun_path, path, len); - len += sizeof (addr.sun_family); - __bind (sock, (struct sockaddr *) &addr, len); if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c new file mode 100644 index 000000000..d6cd79787 --- /dev/null +++ b/sunrpc/tst-bug22542.c @@ -0,0 +1,44 @@ +/* Test to verify that overlong hostname is rejected by clnt_create + and doesn't cause a buffer overflow (bug 22542). + + Copyright (C) 2022 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 + . */ + +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + /* Create an arbitrary hostname that's longer than fits in sun_path. */ + char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2]; + memset (name, 'x', sizeof name - 1); + name [sizeof name - 1] = '\0'; + + errno = 0; + CLIENT *clnt = clnt_create (name, 0, 0, "unix"); + + TEST_VERIFY (clnt == NULL); + TEST_COMPARE (errno, EINVAL); + return 0; +} + +#include diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c new file mode 100644 index 000000000..35a4b7b0b --- /dev/null +++ b/sunrpc/tst-bug28768.c @@ -0,0 +1,42 @@ +/* Test to verify that long path is rejected by svcunix_create (bug 28768). + Copyright (C) 2022 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 + . */ + +#include +#include +#include +#include +#include + +/* svcunix_create does not have a default version in linkobj/libc.so. */ +compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1); + +static int +do_test (void) +{ + char pathname[109]; + memset (pathname, 'x', sizeof (pathname)); + pathname[sizeof (pathname) - 1] = '\0'; + + errno = 0; + TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL); + TEST_COMPARE (errno, EINVAL); + + return 0; +} + +#include diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h index 9808750f8..421f65767 100644 --- a/support/capture_subprocess.h +++ b/support/capture_subprocess.h @@ -41,6 +41,12 @@ struct support_capture_subprocess support_capture_subprocess struct support_capture_subprocess support_capture_subprogram (const char *file, char *const argv[]); +/* Copy the running program into a setgid binary and run it with CHILD_ID + argument. If execution is successful, return the exit status of the child + program, otherwise return a non-zero failure exit code. */ +int support_capture_subprogram_self_sgid + (char *child_id); + /* Deallocate the subprocess data captured by support_capture_subprocess. */ void support_capture_subprocess_free (struct support_capture_subprocess *); diff --git a/support/shell-container.c b/support/shell-container.c index 509e0d69b..201536d24 100644 --- a/support/shell-container.c +++ b/support/shell-container.c @@ -135,6 +135,37 @@ copy_func (char **argv) } +/* Emulate the 'exit' builtin. The exit value is optional. */ +static int +exit_func (char **argv) +{ + int exit_val = 0; + + if (argv[0] != 0) + exit_val = atoi (argv[0]) & 0xff; + exit (exit_val); + return 0; +} + +/* Emulate the "/bin/kill" command. Options are ignored. */ +static int +kill_func (char **argv) +{ + int signum = SIGTERM; + int i; + + for (i = 0; argv[i]; i++) + { + pid_t pid; + if (strcmp (argv[i], "$$") == 0) + pid = getpid (); + else + pid = atoi (argv[i]); + kill (pid, signum); + } + return 0; +} + /* This is a list of all the built-in commands we understand. */ static struct { const char *name; @@ -143,6 +174,8 @@ static struct { { "true", true_func }, { "echo", echo_func }, { "cp", copy_func }, + { "exit", exit_func }, + { "kill", kill_func }, { NULL, NULL } }; @@ -238,7 +271,7 @@ run_command_array (char **argv) fprintf (stderr, "sh: execing %s failed: %s", argv[0], strerror (errno)); - exit (1); + exit (127); } waitpid (pid, &status, 0); @@ -251,6 +284,11 @@ run_command_array (char **argv) if (rv) exit (rv); } + else if (WIFSIGNALED (status)) + { + int sig = WTERMSIG (status); + raise (sig); + } else exit (1); } diff --git a/support/subprocess.h b/support/subprocess.h index 8b442fd5c..34ffd02e8 100644 --- a/support/subprocess.h +++ b/support/subprocess.h @@ -38,6 +38,11 @@ struct support_subprocess support_subprocess struct support_subprocess support_subprogram (const char *file, char *const argv[]); +/* Invoke program FILE with ARGV arguments by using posix_spawn and wait for it + to complete. Return program exit status. */ +int support_subprogram_wait + (const char *file, char *const argv[]); + /* Wait for the subprocess indicated by PROC::PID. Return the status indicate by waitpid call. */ int support_process_wait (struct support_subprocess *proc); diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c index eeed676e3..28a37df67 100644 --- a/support/support_capture_subprocess.c +++ b/support/support_capture_subprocess.c @@ -20,11 +20,14 @@ #include #include +#include #include #include #include #include #include +#include +#include static void transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) @@ -36,7 +39,7 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) if (ret < 0) { support_record_failure (); - printf ("error: reading from subprocess %s: %m", what); + printf ("error: reading from subprocess %s: %m\n", what); pfd->events = 0; pfd->revents = 0; } @@ -102,6 +105,129 @@ support_capture_subprogram (const char *file, char *const argv[]) return result; } +/* Copies the executable into a restricted directory, so that we can + safely make it SGID with the TARGET group ID. Then runs the + executable. */ +static int +copy_and_spawn_sgid (char *child_id, gid_t gid) +{ + char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", + test_dir, (intmax_t) getpid ()); + char *execname = xasprintf ("%s/bin", dirname); + int infd = -1; + int outfd = -1; + int ret = 1, status = 1; + + TEST_VERIFY (mkdir (dirname, 0700) == 0); + if (support_record_failure_is_failed ()) + goto err; + + infd = open ("/proc/self/exe", O_RDONLY); + if (infd < 0) + FAIL_UNSUPPORTED ("unsupported: Cannot read binary from procfs\n"); + + outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); + TEST_VERIFY (outfd >= 0); + if (support_record_failure_is_failed ()) + goto err; + + char buf[4096]; + for (;;) + { + ssize_t rdcount = read (infd, buf, sizeof (buf)); + TEST_VERIFY (rdcount >= 0); + if (support_record_failure_is_failed ()) + goto err; + if (rdcount == 0) + break; + char *p = buf; + char *end = buf + rdcount; + while (p != end) + { + ssize_t wrcount = write (outfd, buf, end - p); + if (wrcount == 0) + errno = ENOSPC; + TEST_VERIFY (wrcount > 0); + if (support_record_failure_is_failed ()) + goto err; + p += wrcount; + } + } + TEST_VERIFY (fchown (outfd, getuid (), gid) == 0); + if (support_record_failure_is_failed ()) + goto err; + TEST_VERIFY (fchmod (outfd, 02750) == 0); + if (support_record_failure_is_failed ()) + goto err; + TEST_VERIFY (close (outfd) == 0); + if (support_record_failure_is_failed ()) + goto err; + TEST_VERIFY (close (infd) == 0); + if (support_record_failure_is_failed ()) + goto err; + + /* We have the binary, now spawn the subprocess. Avoid using + support_subprogram because we only want the program exit status, not the + contents. */ + ret = 0; + + char * const args[] = {execname, child_id, NULL}; + + status = support_subprogram_wait (args[0], args); + +err: + if (outfd >= 0) + close (outfd); + if (infd >= 0) + close (infd); + if (execname != NULL) + { + unlink (execname); + free (execname); + } + if (dirname != NULL) + { + rmdir (dirname); + free (dirname); + } + + if (ret != 0) + FAIL_EXIT1("Failed to make sgid executable for test\n"); + + return status; +} + +int +support_capture_subprogram_self_sgid (char *child_id) +{ + gid_t target = 0; + const int count = 64; + gid_t groups[count]; + + /* Get a GID which is not our current GID, but is present in the + supplementary group list. */ + int ret = getgroups (count, groups); + if (ret < 0) + FAIL_UNSUPPORTED("Could not get group list for user %jd\n", + (intmax_t) getuid ()); + + gid_t current = getgid (); + for (int i = 0; i < ret; ++i) + { + if (groups[i] != current) + { + target = groups[i]; + break; + } + } + + if (target == 0) + FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n", + (intmax_t) getuid ()); + + return copy_and_spawn_sgid (child_id, target); +} + void support_capture_subprocess_free (struct support_capture_subprocess *p) { diff --git a/support/support_subprocess.c b/support/support_subprocess.c index 36e3a77af..4a2582811 100644 --- a/support/support_subprocess.c +++ b/support/support_subprocess.c @@ -27,7 +27,7 @@ #include static struct support_subprocess -support_suprocess_init (void) +support_subprocess_init (void) { struct support_subprocess result; @@ -48,7 +48,7 @@ support_suprocess_init (void) struct support_subprocess support_subprocess (void (*callback) (void *), void *closure) { - struct support_subprocess result = support_suprocess_init (); + struct support_subprocess result = support_subprocess_init (); result.pid = xfork (); if (result.pid == 0) @@ -71,7 +71,7 @@ support_subprocess (void (*callback) (void *), void *closure) struct support_subprocess support_subprogram (const char *file, char *const argv[]) { - struct support_subprocess result = support_suprocess_init (); + struct support_subprocess result = support_subprocess_init (); posix_spawn_file_actions_t fa; /* posix_spawn_file_actions_init does not fail. */ @@ -84,7 +84,7 @@ support_subprogram (const char *file, char *const argv[]) xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]); xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]); - result.pid = xposix_spawn (file, &fa, NULL, argv, NULL); + result.pid = xposix_spawn (file, &fa, NULL, argv, environ); xclose (result.stdout_pipe[1]); xclose (result.stderr_pipe[1]); @@ -92,6 +92,19 @@ support_subprogram (const char *file, char *const argv[]) return result; } +int +support_subprogram_wait (const char *file, char *const argv[]) +{ + posix_spawn_file_actions_t fa; + + posix_spawn_file_actions_init (&fa); + struct support_subprocess res = support_subprocess_init (); + + res.pid = xposix_spawn (file, &fa, NULL, argv, environ); + + return support_process_wait (&res); +} + int support_process_wait (struct support_subprocess *proc) { diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h index db3335e5a..8ffa0d1c5 100644 --- a/sysdeps/aarch64/dl-machine.h +++ b/sysdeps/aarch64/dl-machine.h @@ -392,13 +392,6 @@ elf_machine_lazy_rel (struct link_map *map, /* Check for unexpected PLT reloc type. */ if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1)) { - if (map->l_mach.plt == 0) - { - /* Prelinking. */ - *reloc_addr += l_addr; - return; - } - if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL)) { /* Check the symbol table for variant PCS symbols. */ @@ -422,7 +415,10 @@ elf_machine_lazy_rel (struct link_map *map, } } - *reloc_addr = map->l_mach.plt; + if (map->l_mach.plt == 0) + *reloc_addr += l_addr; + else + *reloc_addr = map->l_mach.plt; } else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1)) { diff --git a/sysdeps/aarch64/memcpy.S b/sysdeps/aarch64/memcpy.S index d0d47e90b..e0b4c4502 100644 --- a/sysdeps/aarch64/memcpy.S +++ b/sysdeps/aarch64/memcpy.S @@ -33,11 +33,11 @@ #define A_l x6 #define A_lw w6 #define A_h x7 -#define A_hw w7 #define B_l x8 #define B_lw w8 #define B_h x9 #define C_l x10 +#define C_lw w10 #define C_h x11 #define D_l x12 #define D_h x13 @@ -51,16 +51,6 @@ #define H_h srcend #define tmp1 x14 -/* Copies are split into 3 main cases: small copies of up to 32 bytes, - medium copies of 33..128 bytes which are fully unrolled. Large copies - of more than 128 bytes align the destination and use an unrolled loop - processing 64 bytes per iteration. - In order to share code with memmove, small and medium copies read all - data before writing, allowing any kind of overlap. So small, medium - and large backwards memmoves are handled by falling through into memcpy. - Overlapping large forward memmoves use a loop that copies backwards. -*/ - #ifndef MEMMOVE # define MEMMOVE memmove #endif @@ -68,118 +58,115 @@ # define MEMCPY memcpy #endif -ENTRY_ALIGN (MEMMOVE, 6) +/* This implementation supports both memcpy and memmove and shares most code. + It uses unaligned accesses and branchless sequences to keep the code small, + simple and improve performance. - DELOUSE (0) - DELOUSE (1) - DELOUSE (2) + Copies are split into 3 main cases: small copies of up to 32 bytes, medium + copies of up to 128 bytes, and large copies. The overhead of the overlap + check in memmove is negligible since it is only required for large copies. - sub tmp1, dstin, src - cmp count, 128 - ccmp tmp1, count, 2, hi - b.lo L(move_long) - - /* Common case falls through into memcpy. */ -END (MEMMOVE) -libc_hidden_builtin_def (MEMMOVE) -ENTRY (MEMCPY) + Large copies use a software pipelined loop processing 64 bytes per + iteration. The destination pointer is 16-byte aligned to minimize + unaligned accesses. The loop tail is handled by always copying 64 bytes + from the end. +*/ +ENTRY_ALIGN (MEMCPY, 6) DELOUSE (0) DELOUSE (1) DELOUSE (2) - prfm PLDL1KEEP, [src] add srcend, src, count add dstend, dstin, count - cmp count, 32 - b.ls L(copy32) cmp count, 128 b.hi L(copy_long) + cmp count, 32 + b.hi L(copy32_128) - /* Medium copies: 33..128 bytes. */ + /* Small copies: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) ldp A_l, A_h, [src] - ldp B_l, B_h, [src, 16] - ldp C_l, C_h, [srcend, -32] ldp D_l, D_h, [srcend, -16] - cmp count, 64 - b.hi L(copy128) stp A_l, A_h, [dstin] - stp B_l, B_h, [dstin, 16] - stp C_l, C_h, [dstend, -32] stp D_l, D_h, [dstend, -16] ret - .p2align 4 - /* Small copies: 0..32 bytes. */ -L(copy32): - /* 16-32 bytes. */ - cmp count, 16 - b.lo 1f - ldp A_l, A_h, [src] - ldp B_l, B_h, [srcend, -16] - stp A_l, A_h, [dstin] - stp B_l, B_h, [dstend, -16] - ret - .p2align 4 -1: - /* 8-15 bytes. */ - tbz count, 3, 1f + /* Copy 8-15 bytes. */ +L(copy16): + tbz count, 3, L(copy8) ldr A_l, [src] ldr A_h, [srcend, -8] str A_l, [dstin] str A_h, [dstend, -8] ret - .p2align 4 -1: - /* 4-7 bytes. */ - tbz count, 2, 1f + + .p2align 3 + /* Copy 4-7 bytes. */ +L(copy8): + tbz count, 2, L(copy4) ldr A_lw, [src] - ldr A_hw, [srcend, -4] + ldr B_lw, [srcend, -4] str A_lw, [dstin] - str A_hw, [dstend, -4] + str B_lw, [dstend, -4] ret - /* Copy 0..3 bytes. Use a branchless sequence that copies the same - byte 3 times if count==1, or the 2nd byte twice if count==2. */ -1: - cbz count, 2f + /* Copy 0..3 bytes using a branchless sequence. */ +L(copy4): + cbz count, L(copy0) lsr tmp1, count, 1 ldrb A_lw, [src] - ldrb A_hw, [srcend, -1] + ldrb C_lw, [srcend, -1] ldrb B_lw, [src, tmp1] strb A_lw, [dstin] strb B_lw, [dstin, tmp1] - strb A_hw, [dstend, -1] -2: ret + strb C_lw, [dstend, -1] +L(copy0): + ret + + .p2align 4 + /* Medium copies: 33..128 bytes. */ +L(copy32_128): + ldp A_l, A_h, [src] + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [srcend, -32] + ldp D_l, D_h, [srcend, -16] + cmp count, 64 + b.hi L(copy128) + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstend, -32] + stp D_l, D_h, [dstend, -16] + ret .p2align 4 - /* Copy 65..128 bytes. Copy 64 bytes from the start and - 64 bytes from the end. */ + /* Copy 65..128 bytes. */ L(copy128): ldp E_l, E_h, [src, 32] ldp F_l, F_h, [src, 48] + cmp count, 96 + b.ls L(copy96) ldp G_l, G_h, [srcend, -64] ldp H_l, H_h, [srcend, -48] + stp G_l, G_h, [dstend, -64] + stp H_l, H_h, [dstend, -48] +L(copy96): stp A_l, A_h, [dstin] stp B_l, B_h, [dstin, 16] stp E_l, E_h, [dstin, 32] stp F_l, F_h, [dstin, 48] - stp G_l, G_h, [dstend, -64] - stp H_l, H_h, [dstend, -48] stp C_l, C_h, [dstend, -32] stp D_l, D_h, [dstend, -16] ret - /* Align DST to 16 byte alignment so that we don't cross cache line - boundaries on both loads and stores. There are at least 128 bytes - to copy, so copy 16 bytes unaligned and then align. The loop - copies 64 bytes per iteration and prefetches one iteration ahead. */ - .p2align 4 + /* Copy more than 128 bytes. */ L(copy_long): + /* Copy 16 bytes and then align dst to 16-byte alignment. */ + ldp D_l, D_h, [src] and tmp1, dstin, 15 bic dst, dstin, 15 - ldp D_l, D_h, [src] sub src, src, tmp1 add count, count, tmp1 /* Count is now 16 too large. */ ldp A_l, A_h, [src, 16] @@ -188,7 +175,8 @@ L(copy_long): ldp C_l, C_h, [src, 48] ldp D_l, D_h, [src, 64]! subs count, count, 128 + 16 /* Test and readjust count. */ - b.ls L(last64) + b.ls L(copy64_from_end) + L(loop64): stp A_l, A_h, [dst, 16] ldp A_l, A_h, [src, 16] @@ -201,10 +189,8 @@ L(loop64): subs count, count, 64 b.hi L(loop64) - /* Write the last full set of 64 bytes. The remainder is at most 64 - bytes, so it is safe to always copy 64 bytes from the end even if - there is just 1 byte left. */ -L(last64): + /* Write the last iteration and copy 64 bytes from the end. */ +L(copy64_from_end): ldp E_l, E_h, [srcend, -64] stp A_l, A_h, [dst, 16] ldp A_l, A_h, [srcend, -48] @@ -219,20 +205,42 @@ L(last64): stp C_l, C_h, [dstend, -16] ret - .p2align 4 -L(move_long): - cbz tmp1, 3f +END (MEMCPY) +libc_hidden_builtin_def (MEMCPY) + +ENTRY_ALIGN (MEMMOVE, 4) + DELOUSE (0) + DELOUSE (1) + DELOUSE (2) add srcend, src, count add dstend, dstin, count + cmp count, 128 + b.hi L(move_long) + cmp count, 32 + b.hi L(copy32_128) - /* Align dstend to 16 byte alignment so that we don't cross cache line - boundaries on both loads and stores. There are at least 128 bytes - to copy, so copy 16 bytes unaligned and then align. The loop - copies 64 bytes per iteration and prefetches one iteration ahead. */ + /* Small copies: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) + ldp A_l, A_h, [src] + ldp D_l, D_h, [srcend, -16] + stp A_l, A_h, [dstin] + stp D_l, D_h, [dstend, -16] + ret - and tmp1, dstend, 15 + .p2align 4 +L(move_long): + /* Only use backward copy if there is an overlap. */ + sub tmp1, dstin, src + cbz tmp1, L(copy0) + cmp tmp1, count + b.hs L(copy_long) + + /* Large backwards copy for overlapping copies. + Copy 16 bytes and then align dst to 16-byte alignment. */ ldp D_l, D_h, [srcend, -16] + and tmp1, dstend, 15 sub srcend, srcend, tmp1 sub count, count, tmp1 ldp A_l, A_h, [srcend, -16] @@ -242,10 +250,9 @@ L(move_long): ldp D_l, D_h, [srcend, -64]! sub dstend, dstend, tmp1 subs count, count, 128 - b.ls 2f + b.ls L(copy64_from_start) - nop -1: +L(loop64_backwards): stp A_l, A_h, [dstend, -16] ldp A_l, A_h, [srcend, -16] stp B_l, B_h, [dstend, -32] @@ -255,12 +262,10 @@ L(move_long): stp D_l, D_h, [dstend, -64]! ldp D_l, D_h, [srcend, -64]! subs count, count, 64 - b.hi 1b + b.hi L(loop64_backwards) - /* Write the last full set of 64 bytes. The remainder is at most 64 - bytes, so it is safe to always copy 64 bytes from the start even if - there is just 1 byte left. */ -2: + /* Write the last iteration and copy 64 bytes from the start. */ +L(copy64_from_start): ldp G_l, G_h, [src, 48] stp A_l, A_h, [dstend, -16] ldp A_l, A_h, [src, 32] @@ -273,7 +278,7 @@ L(move_long): stp A_l, A_h, [dstin, 32] stp B_l, B_h, [dstin, 16] stp C_l, C_h, [dstin] -3: ret + ret -END (MEMCPY) -libc_hidden_builtin_def (MEMCPY) +END (MEMMOVE) +libc_hidden_builtin_def (MEMMOVE) diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile index 8378107c7..3c5292d1a 100644 --- a/sysdeps/aarch64/multiarch/Makefile +++ b/sysdeps/aarch64/multiarch/Makefile @@ -1,5 +1,5 @@ ifeq ($(subdir),string) -sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \ +sysdep_routines += memcpy_generic memcpy_advsimd memcpy_thunderx memcpy_thunderx2 \ memcpy_falkor memmove_falkor \ memset_generic memset_falkor memset_emag memset_kunpeng \ memchr_generic memchr_nosimd \ diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c index b7da62c3b..4b004ac47 100644 --- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c +++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c @@ -42,11 +42,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2) IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor) + IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_simd) IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic)) IFUNC_IMPL (i, name, memmove, IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx) IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx2) IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor) + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_simd) IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic)) IFUNC_IMPL (i, name, memset, /* Enable this on non-falkor processors too so that other cores diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c index 2fafefd5d..799d60c98 100644 --- a/sysdeps/aarch64/multiarch/memcpy.c +++ b/sysdeps/aarch64/multiarch/memcpy.c @@ -29,6 +29,7 @@ extern __typeof (__redirect_memcpy) __libc_memcpy; extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden; +extern __typeof (__redirect_memcpy) __memcpy_simd attribute_hidden; extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden; extern __typeof (__redirect_memcpy) __memcpy_thunderx2 attribute_hidden; extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; @@ -36,11 +37,14 @@ extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; libc_ifunc (__libc_memcpy, (IS_THUNDERX (midr) ? __memcpy_thunderx - : (IS_FALKOR (midr) || IS_PHECDA (midr) || IS_ARES (midr) || IS_KUNPENG920 (midr) + : (IS_FALKOR (midr) || IS_PHECDA (midr) || IS_KUNPENG920 (midr) ? __memcpy_falkor : (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr) ? __memcpy_thunderx2 - : __memcpy_generic)))); + : (IS_NEOVERSE_N1 (midr) || IS_NEOVERSE_N2 (midr) + || IS_NEOVERSE_V1 (midr) + ? __memcpy_simd + : __memcpy_generic))))); # undef memcpy strong_alias (__libc_memcpy, memcpy); diff --git a/sysdeps/aarch64/multiarch/memcpy_advsimd.S b/sysdeps/aarch64/multiarch/memcpy_advsimd.S new file mode 100644 index 000000000..48bb6d7ca --- /dev/null +++ b/sysdeps/aarch64/multiarch/memcpy_advsimd.S @@ -0,0 +1,248 @@ +/* Generic optimized memcpy using SIMD. + Copyright (C) 2020 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 + . */ + +#include + +/* Assumptions: + * + * ARMv8-a, AArch64, Advanced SIMD, unaligned accesses. + * + */ + +#define dstin x0 +#define src x1 +#define count x2 +#define dst x3 +#define srcend x4 +#define dstend x5 +#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define B_l x8 +#define B_lw w8 +#define B_h x9 +#define C_lw w10 +#define tmp1 x14 + +#define A_q q0 +#define B_q q1 +#define C_q q2 +#define D_q q3 +#define E_q q4 +#define F_q q5 +#define G_q q6 +#define H_q q7 + + +/* This implementation supports both memcpy and memmove and shares most code. + It uses unaligned accesses and branchless sequences to keep the code small, + simple and improve performance. + + Copies are split into 3 main cases: small copies of up to 32 bytes, medium + copies of up to 128 bytes, and large copies. The overhead of the overlap + check in memmove is negligible since it is only required for large copies. + + Large copies use a software pipelined loop processing 64 bytes per + iteration. The destination pointer is 16-byte aligned to minimize + unaligned accesses. The loop tail is handled by always copying 64 bytes + from the end. */ + +ENTRY (__memcpy_simd) + DELOUSE (0) + DELOUSE (1) + DELOUSE (2) + + add srcend, src, count + add dstend, dstin, count + cmp count, 128 + b.hi L(copy_long) + cmp count, 32 + b.hi L(copy32_128) + + /* Small copies: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) + ldr A_q, [src] + ldr B_q, [srcend, -16] + str A_q, [dstin] + str B_q, [dstend, -16] + ret + + /* Copy 8-15 bytes. */ +L(copy16): + tbz count, 3, L(copy8) + ldr A_l, [src] + ldr A_h, [srcend, -8] + str A_l, [dstin] + str A_h, [dstend, -8] + ret + + /* Copy 4-7 bytes. */ +L(copy8): + tbz count, 2, L(copy4) + ldr A_lw, [src] + ldr B_lw, [srcend, -4] + str A_lw, [dstin] + str B_lw, [dstend, -4] + ret + + /* Copy 0..3 bytes using a branchless sequence. */ +L(copy4): + cbz count, L(copy0) + lsr tmp1, count, 1 + ldrb A_lw, [src] + ldrb C_lw, [srcend, -1] + ldrb B_lw, [src, tmp1] + strb A_lw, [dstin] + strb B_lw, [dstin, tmp1] + strb C_lw, [dstend, -1] +L(copy0): + ret + + .p2align 4 + /* Medium copies: 33..128 bytes. */ +L(copy32_128): + ldp A_q, B_q, [src] + ldp C_q, D_q, [srcend, -32] + cmp count, 64 + b.hi L(copy128) + stp A_q, B_q, [dstin] + stp C_q, D_q, [dstend, -32] + ret + + .p2align 4 + /* Copy 65..128 bytes. */ +L(copy128): + ldp E_q, F_q, [src, 32] + cmp count, 96 + b.ls L(copy96) + ldp G_q, H_q, [srcend, -64] + stp G_q, H_q, [dstend, -64] +L(copy96): + stp A_q, B_q, [dstin] + stp E_q, F_q, [dstin, 32] + stp C_q, D_q, [dstend, -32] + ret + + /* Align loop64 below to 16 bytes. */ + nop + + /* Copy more than 128 bytes. */ +L(copy_long): + /* Copy 16 bytes and then align src to 16-byte alignment. */ + ldr D_q, [src] + and tmp1, src, 15 + bic src, src, 15 + sub dst, dstin, tmp1 + add count, count, tmp1 /* Count is now 16 too large. */ + ldp A_q, B_q, [src, 16] + str D_q, [dstin] + ldp C_q, D_q, [src, 48] + subs count, count, 128 + 16 /* Test and readjust count. */ + b.ls L(copy64_from_end) +L(loop64): + stp A_q, B_q, [dst, 16] + ldp A_q, B_q, [src, 80] + stp C_q, D_q, [dst, 48] + ldp C_q, D_q, [src, 112] + add src, src, 64 + add dst, dst, 64 + subs count, count, 64 + b.hi L(loop64) + + /* Write the last iteration and copy 64 bytes from the end. */ +L(copy64_from_end): + ldp E_q, F_q, [srcend, -64] + stp A_q, B_q, [dst, 16] + ldp A_q, B_q, [srcend, -32] + stp C_q, D_q, [dst, 48] + stp E_q, F_q, [dstend, -64] + stp A_q, B_q, [dstend, -32] + ret + +END (__memcpy_simd) +libc_hidden_builtin_def (__memcpy_simd) + + +ENTRY (__memmove_simd) + DELOUSE (0) + DELOUSE (1) + DELOUSE (2) + + add srcend, src, count + add dstend, dstin, count + cmp count, 128 + b.hi L(move_long) + cmp count, 32 + b.hi L(copy32_128) + + /* Small moves: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) + ldr A_q, [src] + ldr B_q, [srcend, -16] + str A_q, [dstin] + str B_q, [dstend, -16] + ret + +L(move_long): + /* Only use backward copy if there is an overlap. */ + sub tmp1, dstin, src + cbz tmp1, L(move0) + cmp tmp1, count + b.hs L(copy_long) + + /* Large backwards copy for overlapping copies. + Copy 16 bytes and then align srcend to 16-byte alignment. */ +L(copy_long_backwards): + ldr D_q, [srcend, -16] + and tmp1, srcend, 15 + bic srcend, srcend, 15 + sub count, count, tmp1 + ldp A_q, B_q, [srcend, -32] + str D_q, [dstend, -16] + ldp C_q, D_q, [srcend, -64] + sub dstend, dstend, tmp1 + subs count, count, 128 + b.ls L(copy64_from_start) + +L(loop64_backwards): + str B_q, [dstend, -16] + str A_q, [dstend, -32] + ldp A_q, B_q, [srcend, -96] + str D_q, [dstend, -48] + str C_q, [dstend, -64]! + ldp C_q, D_q, [srcend, -128] + sub srcend, srcend, 64 + subs count, count, 64 + b.hi L(loop64_backwards) + + /* Write the last iteration and copy 64 bytes from the start. */ +L(copy64_from_start): + ldp E_q, F_q, [src, 32] + stp A_q, B_q, [dstend, -32] + ldp A_q, B_q, [src] + stp C_q, D_q, [dstend, -64] + stp E_q, F_q, [dstin, 32] + stp A_q, B_q, [dstin] +L(move0): + ret + +END (__memmove_simd) +libc_hidden_builtin_def (__memmove_simd) diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c index ed5a47f6f..46a4cb3a5 100644 --- a/sysdeps/aarch64/multiarch/memmove.c +++ b/sysdeps/aarch64/multiarch/memmove.c @@ -29,6 +29,7 @@ extern __typeof (__redirect_memmove) __libc_memmove; extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden; +extern __typeof (__redirect_memmove) __memmove_simd attribute_hidden; extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden; extern __typeof (__redirect_memmove) __memmove_thunderx2 attribute_hidden; extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden; @@ -40,7 +41,10 @@ libc_ifunc (__libc_memmove, ? __memmove_falkor : (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr) ? __memmove_thunderx2 - : __memmove_generic)))); + : (IS_NEOVERSE_N1 (midr) || IS_NEOVERSE_N2 (midr) + || IS_NEOVERSE_V1 (midr) + ? __memmove_simd + : __memmove_generic))))); # undef memmove strong_alias (__libc_memmove, memmove); diff --git a/sysdeps/aarch64/strcpy.S b/sysdeps/aarch64/strcpy.S index 548130e41..a8ff52c07 100644 --- a/sysdeps/aarch64/strcpy.S +++ b/sysdeps/aarch64/strcpy.S @@ -234,8 +234,13 @@ L(entry_no_page_cross): #endif /* calculate the loc value */ cmeq datav.16b, datav.16b, #0 +#ifdef __AARCH64EB__ + mov data1, datav.d[1] + mov data2, datav.d[0] +#else mov data1, datav.d[0] mov data2, datav.d[1] +#endif cmp data1, 0 csel data1, data1, data2, ne mov pos, 8 diff --git a/sysdeps/aarch64/strnlen.S b/sysdeps/aarch64/strnlen.S index 5981247dd..086a5c7e9 100644 --- a/sysdeps/aarch64/strnlen.S +++ b/sysdeps/aarch64/strnlen.S @@ -154,8 +154,13 @@ L(loop_end): byte. */ cmeq datav.16b, datav.16b, #0 +#ifdef __AARCH64EB__ + mov data1, datav.d[1] + mov data2, datav.d[0] +#else mov data1, datav.d[0] mov data2, datav.d[1] +#endif cmp data1, 0 csel data1, data1, data2, ne sub len, src, srcin diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h index 604c48917..f1feb19dc 100644 --- a/sysdeps/aarch64/sysdep.h +++ b/sysdeps/aarch64/sysdep.h @@ -45,7 +45,7 @@ #define ENTRY(name) \ .globl C_SYMBOL_NAME(name); \ .type C_SYMBOL_NAME(name),%function; \ - .align 4; \ + .p2align 6; \ C_LABEL(name) \ cfi_startproc; \ CALL_MCOUNT diff --git a/sysdeps/arm/armv7/multiarch/memcpy_impl.S b/sysdeps/arm/armv7/multiarch/memcpy_impl.S index bf4ac7077..379bb56fc 100644 --- a/sysdeps/arm/armv7/multiarch/memcpy_impl.S +++ b/sysdeps/arm/armv7/multiarch/memcpy_impl.S @@ -268,7 +268,7 @@ ENTRY(memcpy) mov dst, dstin /* Preserve dstin, we need to return it. */ cmp count, #64 - bge .Lcpy_not_short + bhs .Lcpy_not_short /* Deal with small copies quickly by dropping straight into the exit block. */ @@ -351,10 +351,10 @@ ENTRY(memcpy) 1: subs tmp2, count, #64 /* Use tmp2 for count. */ - blt .Ltail63aligned + blo .Ltail63aligned cmp tmp2, #512 - bge .Lcpy_body_long + bhs .Lcpy_body_long .Lcpy_body_medium: /* Count in tmp2. */ #ifdef USE_VFP @@ -378,7 +378,7 @@ ENTRY(memcpy) add src, src, #64 vstr d1, [dst, #56] add dst, dst, #64 - bge 1b + bhs 1b tst tmp2, #0x3f beq .Ldone @@ -412,7 +412,7 @@ ENTRY(memcpy) ldrd A_l, A_h, [src, #64]! strd A_l, A_h, [dst, #64]! subs tmp2, tmp2, #64 - bge 1b + bhs 1b tst tmp2, #0x3f bne 1f ldr tmp2,[sp], #FRAME_SIZE @@ -482,7 +482,7 @@ ENTRY(memcpy) add src, src, #32 subs tmp2, tmp2, #prefetch_lines * 64 * 2 - blt 2f + blo 2f 1: cpy_line_vfp d3, 0 cpy_line_vfp d4, 64 @@ -494,7 +494,7 @@ ENTRY(memcpy) add dst, dst, #2 * 64 add src, src, #2 * 64 subs tmp2, tmp2, #prefetch_lines * 64 - bge 1b + bhs 1b 2: cpy_tail_vfp d3, 0 @@ -615,8 +615,8 @@ ENTRY(memcpy) 1: pld [src, #(3 * 64)] subs count, count, #64 - ldrmi tmp2, [sp], #FRAME_SIZE - bmi .Ltail63unaligned + ldrlo tmp2, [sp], #FRAME_SIZE + blo .Ltail63unaligned pld [src, #(4 * 64)] #ifdef USE_NEON @@ -633,7 +633,7 @@ ENTRY(memcpy) neon_load_multi d0-d3, src neon_load_multi d4-d7, src subs count, count, #64 - bmi 2f + blo 2f 1: pld [src, #(4 * 64)] neon_store_multi d0-d3, dst @@ -641,7 +641,7 @@ ENTRY(memcpy) neon_store_multi d4-d7, dst neon_load_multi d4-d7, src subs count, count, #64 - bpl 1b + bhs 1b 2: neon_store_multi d0-d3, dst neon_store_multi d4-d7, dst diff --git a/sysdeps/arm/be/nofpu/Implies b/sysdeps/arm/be/nofpu/Implies new file mode 100644 index 000000000..c90dd7fd5 --- /dev/null +++ b/sysdeps/arm/be/nofpu/Implies @@ -0,0 +1 @@ +arm/nofpu diff --git a/sysdeps/arm/le/nofpu/Implies b/sysdeps/arm/le/nofpu/Implies new file mode 100644 index 000000000..c90dd7fd5 --- /dev/null +++ b/sysdeps/arm/le/nofpu/Implies @@ -0,0 +1 @@ +arm/nofpu diff --git a/sysdeps/arm/memcpy.S b/sysdeps/arm/memcpy.S index 510e8adaf..bcfbc51d9 100644 --- a/sysdeps/arm/memcpy.S +++ b/sysdeps/arm/memcpy.S @@ -68,7 +68,7 @@ ENTRY(memcpy) cfi_remember_state subs r2, r2, #4 - blt 8f + blo 8f ands ip, r0, #3 PLD( pld [r1, #0] ) bne 9f @@ -82,7 +82,7 @@ ENTRY(memcpy) cfi_rel_offset (r6, 4) cfi_rel_offset (r7, 8) cfi_rel_offset (r8, 12) - blt 5f + blo 5f CALGN( ands ip, r1, #31 ) CALGN( rsb r3, ip, #32 ) @@ -98,9 +98,9 @@ ENTRY(memcpy) #endif PLD( pld [r1, #0] ) -2: PLD( subs r2, r2, #96 ) +2: PLD( cmp r2, #96 ) PLD( pld [r1, #28] ) - PLD( blt 4f ) + PLD( blo 4f ) PLD( pld [r1, #60] ) PLD( pld [r1, #92] ) @@ -108,9 +108,7 @@ ENTRY(memcpy) 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} subs r2, r2, #32 stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} - bge 3b - PLD( cmn r2, #96 ) - PLD( bge 4b ) + bhs 3b 5: ands ip, r2, #28 rsb ip, ip, #32 @@ -222,7 +220,7 @@ ENTRY(memcpy) strbge r4, [r0], #1 subs r2, r2, ip strb lr, [r0], #1 - blt 8b + blo 8b ands ip, r1, #3 beq 1b @@ -236,7 +234,7 @@ ENTRY(memcpy) .macro forward_copy_shift pull push subs r2, r2, #28 - blt 14f + blo 14f CALGN( ands ip, r1, #31 ) CALGN( rsb ip, ip, #32 ) @@ -253,9 +251,9 @@ ENTRY(memcpy) cfi_rel_offset (r10, 16) PLD( pld [r1, #0] ) - PLD( subs r2, r2, #96 ) + PLD( cmp r2, #96 ) PLD( pld [r1, #28] ) - PLD( blt 13f ) + PLD( blo 13f ) PLD( pld [r1, #60] ) PLD( pld [r1, #92] ) @@ -280,9 +278,7 @@ ENTRY(memcpy) mov ip, ip, PULL #\pull orr ip, ip, lr, PUSH #\push stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip} - bge 12b - PLD( cmn r2, #96 ) - PLD( bge 13b ) + bhs 12b pop {r5 - r8, r10} cfi_adjust_cfa_offset (-20) diff --git a/sysdeps/arm/memmove.S b/sysdeps/arm/memmove.S index 954037ef3..0d07b76ee 100644 --- a/sysdeps/arm/memmove.S +++ b/sysdeps/arm/memmove.S @@ -85,7 +85,7 @@ ENTRY(memmove) add r1, r1, r2 add r0, r0, r2 subs r2, r2, #4 - blt 8f + blo 8f ands ip, r0, #3 PLD( pld [r1, #-4] ) bne 9f @@ -99,7 +99,7 @@ ENTRY(memmove) cfi_rel_offset (r6, 4) cfi_rel_offset (r7, 8) cfi_rel_offset (r8, 12) - blt 5f + blo 5f CALGN( ands ip, r1, #31 ) CALGN( sbcsne r4, ip, r2 ) @ C is always set here @@ -114,9 +114,9 @@ ENTRY(memmove) #endif PLD( pld [r1, #-4] ) -2: PLD( subs r2, r2, #96 ) +2: PLD( cmp r2, #96 ) PLD( pld [r1, #-32] ) - PLD( blt 4f ) + PLD( blo 4f ) PLD( pld [r1, #-64] ) PLD( pld [r1, #-96] ) @@ -124,9 +124,7 @@ ENTRY(memmove) 4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} subs r2, r2, #32 stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} - bge 3b - PLD( cmn r2, #96 ) - PLD( bge 4b ) + bhs 3b 5: ands ip, r2, #28 rsb ip, ip, #32 @@ -237,7 +235,7 @@ ENTRY(memmove) strbge r4, [r0, #-1]! subs r2, r2, ip strb lr, [r0, #-1]! - blt 8b + blo 8b ands ip, r1, #3 beq 1b @@ -251,7 +249,7 @@ ENTRY(memmove) .macro backward_copy_shift push pull subs r2, r2, #28 - blt 14f + blo 14f CALGN( ands ip, r1, #31 ) CALGN( rsb ip, ip, #32 ) @@ -268,9 +266,9 @@ ENTRY(memmove) cfi_rel_offset (r10, 16) PLD( pld [r1, #-4] ) - PLD( subs r2, r2, #96 ) + PLD( cmp r2, #96 ) PLD( pld [r1, #-32] ) - PLD( blt 13f ) + PLD( blo 13f ) PLD( pld [r1, #-64] ) PLD( pld [r1, #-96] ) @@ -295,9 +293,7 @@ ENTRY(memmove) mov r4, r4, PUSH #\push orr r4, r4, r3, PULL #\pull stmdb r0!, {r4 - r8, r10, ip, lr} - bge 12b - PLD( cmn r2, #96 ) - PLD( bge 13b ) + bhs 12b pop {r5 - r8, r10} cfi_adjust_cfa_offset (-20) diff --git a/sysdeps/unix/sysv/linux/nios2/kernel-features.h b/sysdeps/generic/unwind-arch.h similarity index 72% rename from sysdeps/unix/sysv/linux/nios2/kernel-features.h rename to sysdeps/generic/unwind-arch.h index d68d11498..d712e5e11 100644 --- a/sysdeps/unix/sysv/linux/nios2/kernel-features.h +++ b/sysdeps/generic/unwind-arch.h @@ -1,6 +1,5 @@ -/* Set flags signalling availability of kernel features based on given - kernel version number. NIOS2 version. - Copyright (C) 2019-2020 Free Software Foundation, Inc. +/* Return backtrace of current program state. Arch-specific bits. + Copyright (C) 2020 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,6 +16,15 @@ License along with the GNU C Library; if not, see . */ -#include_next +#ifndef _UNWIND_ARCH_H +#define _UNWIND_ARCH_H -#undef __ASSUME_SYSVIPC_DEFAULT_IPC_64 +#include + +static inline void * +unwind_arch_adjustment (void *prev, void *addr) +{ + return addr; +} + +#endif diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c index 0a3739728..25ca8f846 100644 --- a/sysdeps/hppa/dl-fptr.c +++ b/sysdeps/hppa/dl-fptr.c @@ -172,8 +172,8 @@ make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp) } install: - fdesc->ip = ip; fdesc->gp = gp; + fdesc->ip = ip; return (ElfW(Addr)) fdesc; } @@ -350,7 +350,9 @@ ElfW(Addr) _dl_lookup_address (const void *address) { ElfW(Addr) addr = (ElfW(Addr)) address; - unsigned int *desc, *gptr; + ElfW(Word) reloc_arg; + volatile unsigned int *desc; + unsigned int *gptr; /* Return ADDR if the least-significant two bits of ADDR are not consistent with ADDR being a linker defined function pointer. The normal value for @@ -367,7 +369,11 @@ _dl_lookup_address (const void *address) if (!_dl_read_access_allowed (desc)) return addr; - /* Load first word of candidate descriptor. It should be a pointer + /* First load the relocation offset. */ + reloc_arg = (ElfW(Word)) desc[1]; + atomic_full_barrier(); + + /* Then load first word of candidate descriptor. It should be a pointer with word alignment and point to memory that can be read. */ gptr = (unsigned int *) desc[0]; if (((unsigned int) gptr & 3) != 0 @@ -377,8 +383,8 @@ _dl_lookup_address (const void *address) /* See if descriptor requires resolution. The following trampoline is used in each global offset table for function resolution: - ldw 0(r20),r22 - bv r0(r22) + ldw 0(r20),r21 + bv r0(r21) ldw 4(r20),r21 tramp: b,l .-12,r20 depwi 0,31,2,r20 @@ -389,7 +395,15 @@ _dl_lookup_address (const void *address) if (gptr[0] == 0xea9f1fdd /* b,l .-12,r20 */ && gptr[1] == 0xd6801c1e /* depwi 0,31,2,r20 */ && (ElfW(Addr)) gptr[2] == elf_machine_resolve ()) - _dl_fixup ((struct link_map *) gptr[5], (ElfW(Word)) desc[1]); + { + struct link_map *l = (struct link_map *) gptr[5]; + + /* If gp has been resolved, we need to hunt for relocation offset. */ + if (!(reloc_arg & PA_GP_RELOC)) + reloc_arg = _dl_fix_reloc_arg (addr, l); + + _dl_fixup (l, reloc_arg); + } return (ElfW(Addr)) desc[0]; } diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h index 9e98366ea..8ecff9770 100644 --- a/sysdeps/hppa/dl-machine.h +++ b/sysdeps/hppa/dl-machine.h @@ -48,6 +48,14 @@ #define GOT_FROM_PLT_STUB (4*4) #define PLT_ENTRY_SIZE (2*4) +/* The gp slot in the function descriptor contains the relocation offset + before resolution. To distinguish between a resolved gp value and an + unresolved relocation offset we set an unused bit in the relocation + offset. This would allow us to do a synchronzied two word update + using this bit (interlocked update), but instead of waiting for the + update we simply recompute the gp value given that we know the ip. */ +#define PA_GP_RELOC 1 + /* Initialize the function descriptor table before relocations */ static inline void __hppa_init_bootstrap_fdesc_table (struct link_map *map) @@ -117,10 +125,28 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t, volatile Elf32_Addr *rfdesc = reloc_addr; /* map is the link_map for the caller, t is the link_map for the object being called */ - rfdesc[1] = value.gp; - /* Need to ensure that the gp is visible before the code - entry point is updated */ - rfdesc[0] = value.ip; + + /* We would like the function descriptor to be double word aligned. This + helps performance (ip and gp then reside on the same cache line) and + we can update the pair atomically with a single store. The linker + now ensures this alignment but we still have to handle old code. */ + if ((unsigned int)reloc_addr & 7) + { + /* Need to ensure that the gp is visible before the code + entry point is updated */ + rfdesc[1] = value.gp; + atomic_full_barrier(); + rfdesc[0] = value.ip; + } + else + { + /* Update pair atomically with floating point store. */ + union { ElfW(Word) v[2]; double d; } u; + + u.v[0] = value.ip; + u.v[1] = value.gp; + *(volatile double *)rfdesc = u.d; + } return value; } @@ -265,7 +291,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) here. The trampoline code will load the proper LTP and pass the reloc offset to the fixup function. */ - fptr->gp = iplt - jmprel; + fptr->gp = (iplt - jmprel) | PA_GP_RELOC; } /* r_sym != 0 */ else { diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c new file mode 100644 index 000000000..885a3f183 --- /dev/null +++ b/sysdeps/hppa/dl-runtime.c @@ -0,0 +1,58 @@ +/* On-demand PLT fixup for shared objects. HPPA version. + Copyright (C) 2019 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Clear PA_GP_RELOC bit in relocation offset. */ +#define reloc_offset (reloc_arg & ~PA_GP_RELOC) +#define reloc_index (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL) + +#include + +/* The caller has encountered a partially relocated function descriptor. + The gp of the descriptor has been updated, but not the ip. We find + the function descriptor again and compute the relocation offset and + return that to the caller. The caller will continue on to call + _dl_fixup with the relocation offset. */ + +ElfW(Word) +attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE +_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) +{ + Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type; + const Elf32_Rela *reloc; + + l_addr = l->l_addr; + jmprel = D_PTR(l, l_info[DT_JMPREL]); + end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val; + + /* Look for the entry... */ + for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela)) + { + reloc = (const Elf32_Rela *) iplt; + r_type = ELF32_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_PARISC_IPLT, 1) + && fptr == (struct fdesc *) (reloc->r_offset + l_addr)) + /* Found entry. Return the reloc offset. */ + return iplt - jmprel; + } + + /* Crash if we weren't passed a valid function pointer. */ + ABORT_INSTRUCTION; + return 0; +} diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S index 0114ca8b1..d0804b30c 100644 --- a/sysdeps/hppa/dl-trampoline.S +++ b/sysdeps/hppa/dl-trampoline.S @@ -31,7 +31,7 @@ slow down __cffc when it attempts to call fixup to resolve function descriptor references. Please refer to gcc/gcc/config/pa/fptr.c - Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */ + Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp, r22 = fp. */ /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ .text @@ -61,17 +61,20 @@ _dl_runtime_resolve: copy %sp, %r1 /* Copy previous sp */ /* Save function result address (on entry) */ stwm %r28,128(%sp) - /* Fillin some frame info to follow ABI */ + /* Fill in some frame info to follow ABI */ stw %r1,-4(%sp) /* Previous sp */ stw %r21,-32(%sp) /* PIC register value */ /* Save input floating point registers. This must be done in the new frame since the previous frame doesn't have enough space */ - ldo -56(%sp),%r1 + ldo -64(%sp),%r1 fstd,ma %fr4,-8(%r1) fstd,ma %fr5,-8(%r1) fstd,ma %fr6,-8(%r1) + + /* Test PA_GP_RELOC bit. */ + bb,>= %r19,31,2f /* branch if not reloc offset */ fstd,ma %fr7,-8(%r1) /* Set up args to fixup func, needs only two arguments */ @@ -79,7 +82,7 @@ _dl_runtime_resolve: copy %r19,%r25 /* (2) reloc offset */ /* Call the real address resolver. */ - bl _dl_fixup,%rp +3: bl _dl_fixup,%rp copy %r21,%r19 /* set fixup func ltp */ /* While the linker will set a function pointer to NULL when it @@ -102,7 +105,7 @@ _dl_runtime_resolve: copy %r29, %r19 /* Reload arguments fp args */ - ldo -56(%sp),%r1 + ldo -64(%sp),%r1 fldd,ma -8(%r1),%fr4 fldd,ma -8(%r1),%fr5 fldd,ma -8(%r1),%fr6 @@ -129,6 +132,25 @@ _dl_runtime_resolve: bv %r0(%rp) ldo -128(%sp),%sp +2: + /* Set up args for _dl_fix_reloc_arg. */ + copy %r22,%r26 /* (1) function pointer */ + depi 0,31,2,%r26 /* clear least significant bits */ + ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ + + /* Save ltp and link map arg for _dl_fixup. */ + stw %r21,-56(%sp) /* ltp */ + stw %r25,-60(%sp) /* struct link map */ + + /* Find reloc offset. */ + bl _dl_fix_reloc_arg,%rp + copy %r21,%r19 /* set func ltp */ + + /* Set up args for _dl_fixup. */ + ldw -56(%sp),%r21 /* ltp */ + ldw -60(%sp),%r26 /* (1) struct link map */ + b 3b + copy %ret0,%r25 /* (2) reloc offset */ .EXIT .PROCEND cfi_endproc @@ -153,7 +175,7 @@ _dl_runtime_profile: copy %sp, %r1 /* Copy previous sp */ /* Save function result address (on entry) */ stwm %r28,192(%sp) - /* Fillin some frame info to follow ABI */ + /* Fill in some frame info to follow ABI */ stw %r1,-4(%sp) /* Previous sp */ stw %r21,-32(%sp) /* PIC register value */ @@ -181,10 +203,11 @@ _dl_runtime_profile: fstd,ma %fr5,8(%r1) fstd,ma %fr6,8(%r1) fstd,ma %fr7,8(%r1) - /* 32-bit stack pointer and return register */ - stw %sp,-56(%sp) - stw %r2,-52(%sp) + /* Test PA_GP_RELOC bit. */ + bb,>= %r19,31,2f /* branch if not reloc offset */ + /* 32-bit stack pointer */ + stw %sp,-56(%sp) /* Set up args to fixup func, needs five arguments */ ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ @@ -197,7 +220,7 @@ _dl_runtime_profile: stw %r1, -52(%sp) /* (5) long int *framesizep */ /* Call the real address resolver. */ - bl _dl_profile_fixup,%rp +3: bl _dl_profile_fixup,%rp copy %r21,%r19 /* set fixup func ltp */ /* Load up the returned function descriptor */ @@ -215,7 +238,9 @@ _dl_runtime_profile: fldd,ma 8(%r1),%fr5 fldd,ma 8(%r1),%fr6 fldd,ma 8(%r1),%fr7 - ldw -52(%sp),%rp + + /* Reload rp register -(192+20) without adjusting stack */ + ldw -212(%sp),%rp /* Reload static link register -(192+16) without adjusting stack */ ldw -208(%sp),%r29 @@ -303,6 +328,33 @@ L(cont): ldw -20(%sp),%rp /* Return */ bv,n 0(%r2) + +2: + /* Set up args for _dl_fix_reloc_arg. */ + copy %r22,%r26 /* (1) function pointer */ + depi 0,31,2,%r26 /* clear least significant bits */ + ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ + + /* Save ltp and link map arg for _dl_fixup. */ + stw %r21,-92(%sp) /* ltp */ + stw %r25,-116(%sp) /* struct link map */ + + /* Find reloc offset. */ + bl _dl_fix_reloc_arg,%rp + copy %r21,%r19 /* set func ltp */ + + /* Restore fixup ltp. */ + ldw -92(%sp),%r21 /* ltp */ + + /* Set up args to fixup func, needs five arguments */ + ldw -116(%sp),%r26 /* (1) struct link map */ + copy %ret0,%r25 /* (2) reloc offset */ + stw %r25,-120(%sp) /* Save reloc offset */ + ldw -212(%sp),%r24 /* (3) profile_fixup needs rp */ + ldo -56(%sp),%r23 /* (4) La_hppa_regs */ + ldo -112(%sp), %r1 + b 3b + stw %r1, -52(%sp) /* (5) long int *framesizep */ .EXIT .PROCEND cfi_endproc diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 8af0789a9..4334ade2a 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -338,16 +338,22 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, { # ifndef RTLD_BOOTSTRAP if (sym_map != map - && sym_map->l_type != lt_executable && !sym_map->l_relocated) { const char *strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ + if (sym_map->l_type == lt_executable) + _dl_fatal_printf ("\ +%s: IFUNC symbol '%s' referenced in '%s' is defined in the executable \ +and creates an unsatisfiable circular dependency.\n", + RTLD_PROGNAME, strtab + refsym->st_name, + map->l_name); + else + _dl_error_printf ("\ %s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", - RTLD_PROGNAME, map->l_name, - sym_map->l_name, - strtab + refsym->st_name); + RTLD_PROGNAME, map->l_name, + sym_map->l_name, + strtab + refsym->st_name); } # endif value = ((Elf32_Addr (*) (void)) value) (); diff --git a/sysdeps/i386/sysdep.h b/sysdeps/i386/sysdep.h index b4bcd8fb6..6094af8fe 100644 --- a/sysdeps/i386/sysdep.h +++ b/sysdeps/i386/sysdep.h @@ -61,7 +61,7 @@ lose: SYSCALL_PIC_SETUP \ # define SETUP_PIC_REG(reg) \ .ifndef GET_PC_THUNK(reg); \ - .section .gnu.linkonce.t.GET_PC_THUNK(reg),"ax",@progbits; \ + .section .text.GET_PC_THUNK(reg),"axG",@progbits,GET_PC_THUNK(reg),comdat; \ .globl GET_PC_THUNK(reg); \ .hidden GET_PC_THUNK(reg); \ .p2align 4; \ @@ -97,7 +97,8 @@ GET_PC_THUNK(reg): \ # define SETUP_PIC_REG_STR(reg) \ ".ifndef " GET_PC_THUNK_STR (reg) "\n" \ - ".section .gnu.linkonce.t." GET_PC_THUNK_STR (reg) ",\"ax\",@progbits\n" \ + ".section .text." GET_PC_THUNK_STR (reg) ",\"axG\",@progbits," \ + GET_PC_THUNK_STR (reg) ",comdat\n" \ ".globl " GET_PC_THUNK_STR (reg) "\n" \ ".hidden " GET_PC_THUNK_STR (reg) "\n" \ ".p2align 4\n" \ diff --git a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile index 995e90d6d..6030adf7e 100644 --- a/sysdeps/ieee754/ldbl-96/Makefile +++ b/sysdeps/ieee754/ldbl-96/Makefile @@ -17,5 +17,8 @@ # . ifeq ($(subdir),math) -tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 +tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo +ifeq ($(have-ssp),yes) +CFLAGS-test-sinl-pseudo.c += -fstack-protector-all endif +endif # $(subdir) == math diff --git a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c index 5f742321a..bcdf20179 100644 --- a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +++ b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c @@ -210,6 +210,18 @@ __ieee754_rem_pio2l (long double x, long double *y) return 0; } + if ((i0 & 0x80000000) == 0) + { + /* Pseudo-zero and unnormal representations are not valid + representations of long double. We need to avoid stack + corruption in __kernel_rem_pio2, which expects input in a + particular normal form, but those representations do not need + to be consistently handled like any particular floating-point + value. */ + y[1] = y[0] = __builtin_nanl (""); + return 0; + } + /* Split the 64 bits of the mantissa into three 24-bit integers stored in a double array. */ exp = j0 - 23; diff --git a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c new file mode 100644 index 000000000..f59b97769 --- /dev/null +++ b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c @@ -0,0 +1,41 @@ +/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487). + Copyright (C) 2020 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 + . */ + +#include +#include +#include + +static int +do_test (void) +{ + for (int i = 0; i < 64; i++) + { + uint64_t sig = i == 63 ? 0 : 1ULL << i; + long double ld; + SET_LDOUBLE_WORDS (ld, 0x4141, + sig >> 32, sig & 0xffffffffULL); + /* The requirement is that no stack overflow occurs when the + pseudo-zero or unnormal goes through range reduction. */ + volatile long double ldr; + ldr = sinl (ld); + (void) ldr; + } + return 0; +} + +#include diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c index e613e6a34..a03f478fc 100644 --- a/sysdeps/posix/system.c +++ b/sysdeps/posix/system.c @@ -101,7 +101,8 @@ cancel_handler (void *arg) static int do_system (const char *line) { - int status; + int status = -1; + int ret; pid_t pid; struct sigaction sa; #ifndef _LIBC_REENTRANT @@ -144,14 +145,14 @@ do_system (const char *line) __posix_spawnattr_setflags (&spawn_attr, POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK); - status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr, - (char *const[]){ (char*) SHELL_NAME, - (char*) "-c", - (char *) line, NULL }, - __environ); + ret = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr, + (char *const[]){ (char *) SHELL_NAME, + (char *) "-c", + (char *) line, NULL }, + __environ); __posix_spawnattr_destroy (&spawn_attr); - if (status == 0) + if (ret == 0) { /* Cancellation results in cleanup handlers running as exceptions in the block where they were installed, so it is safe to reference @@ -186,6 +187,9 @@ do_system (const char *line) } DO_UNLOCK (); + if (ret != 0) + __set_errno (ret); + return status; } diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h index 2ba009e91..829eec266 100644 --- a/sysdeps/powerpc/powerpc32/sysdep.h +++ b/sysdeps/powerpc/powerpc32/sysdep.h @@ -179,8 +179,8 @@ GOT_LABEL: ; \ #else /* Position-dependent code does not require access to the GOT. */ # define __GLRO(rOUT, rGOT, member, offset) \ - lis rOUT,(member+LOWORD)@ha; \ - lwz rOUT,(member+LOWORD)@l(rOUT) + lis rOUT,(member)@ha; \ + lwz rOUT,(member)@l(rOUT) #endif /* PIC */ #endif /* __ASSEMBLER__ */ diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c index 8a53a1088..362a2b713 100644 --- a/sysdeps/powerpc/powerpc64/backtrace.c +++ b/sysdeps/powerpc/powerpc64/backtrace.c @@ -54,11 +54,22 @@ struct signal_frame_64 { /* We don't care about the rest, since the IP value is at 'uc' field. */ }; +/* Test if the address match to the inside the trampoline code. + Up to and including kernel 5.8, returning from an interrupt or syscall to a + signal handler starts execution directly at the handler's entry point, with + LR set to address of the sigreturn trampoline (the vDSO symbol). + Newer kernels will branch to signal handler from the trampoline instead, so + checking the stacktrace against the vDSO entrypoint does not work in such + case. + The vDSO branches with a 'bctrl' instruction, so checking either the + vDSO address itself and the next instruction should cover all kernel + versions. */ static inline bool is_sigtramp_address (void *nip) { #ifdef HAVE_SIGTRAMP_RT64 - if (nip == GLRO (dl_vdso_sigtramp_rt64)) + if (nip == GLRO (dl_vdso_sigtramp_rt64) || + nip == GLRO (dl_vdso_sigtramp_rt64) + 4) return true; #endif return false; diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure index fa46e9e35..e7f576338 100644 --- a/sysdeps/s390/configure +++ b/sysdeps/s390/configure @@ -123,7 +123,9 @@ void testinsn (char *buf) __asm__ (".machine \"arch13\" \n\t" ".machinemode \"zarch_nohighgprs\" \n\t" "lghi %%r0,16 \n\t" - "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); + "mvcrl 0(%0),32(%0) \n\t" + "vstrs %%v20,%%v20,%%v20,%%v20,0,2" + : : "a" (buf) : "memory", "r0"); } EOF if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c @@ -271,7 +273,9 @@ else void testinsn (char *buf) { __asm__ ("lghi %%r0,16 \n\t" - "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); + "mvcrl 0(%0),32(%0) \n\t" + "vstrs %%v20,%%v20,%%v20,%%v20,0,2" + : : "a" (buf) : "memory", "r0"); } EOF if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac index 3ed5a8ef8..5c3479e8c 100644 --- a/sysdeps/s390/configure.ac +++ b/sysdeps/s390/configure.ac @@ -88,7 +88,9 @@ void testinsn (char *buf) __asm__ (".machine \"arch13\" \n\t" ".machinemode \"zarch_nohighgprs\" \n\t" "lghi %%r0,16 \n\t" - "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); + "mvcrl 0(%0),32(%0) \n\t" + "vstrs %%v20,%%v20,%%v20,%%v20,0,2" + : : "a" (buf) : "memory", "r0"); } EOF dnl test, if assembler supports S390 arch13 instructions @@ -195,7 +197,9 @@ cat > conftest.c <<\EOF void testinsn (char *buf) { __asm__ ("lghi %%r0,16 \n\t" - "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); + "mvcrl 0(%0),32(%0) \n\t" + "vstrs %%v20,%%v20,%%v20,%%v20,0,2" + : : "a" (buf) : "memory", "r0"); } EOF dnl test, if assembler supports S390 arch13 zarch instructions as default diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c index 5fc85e129..ee59b5de1 100644 --- a/sysdeps/s390/memmove.c +++ b/sysdeps/s390/memmove.c @@ -43,7 +43,7 @@ extern __typeof (__redirect_memmove) MEMMOVE_ARCH13 attribute_hidden; s390_libc_ifunc_expr (__redirect_memmove, memmove, ({ s390_libc_ifunc_expr_stfle_init (); - (HAVE_MEMMOVE_ARCH13 + (HAVE_MEMMOVE_ARCH13 && (hwcap & HWCAP_S390_VXRS_EXT2) && S390_IS_ARCH13_MIE3 (stfle_bits)) ? MEMMOVE_ARCH13 : (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX)) diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c index e6195c6e2..17c0cc395 100644 --- a/sysdeps/s390/multiarch/ifunc-impl-list.c +++ b/sysdeps/s390/multiarch/ifunc-impl-list.c @@ -171,7 +171,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, IFUNC_IMPL (i, name, memmove, # if HAVE_MEMMOVE_ARCH13 IFUNC_IMPL_ADD (array, i, memmove, - S390_IS_ARCH13_MIE3 (stfle_bits), + ((dl_hwcap & HWCAP_S390_VXRS_EXT2) + && S390_IS_ARCH13_MIE3 (stfle_bits)), MEMMOVE_ARCH13) # endif # if HAVE_MEMMOVE_Z13 diff --git a/sysdeps/sh/be/sh4/fpu/Implies b/sysdeps/sh/be/sh4/fpu/Implies new file mode 100644 index 000000000..71b28ee1a --- /dev/null +++ b/sysdeps/sh/be/sh4/fpu/Implies @@ -0,0 +1 @@ +sh/sh4/fpu diff --git a/sysdeps/sh/le/sh4/fpu/Implies b/sysdeps/sh/le/sh4/fpu/Implies new file mode 100644 index 000000000..71b28ee1a --- /dev/null +++ b/sysdeps/sh/le/sh4/fpu/Implies @@ -0,0 +1 @@ +sh/sh4/fpu diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh index c07626677..4f6c3490a 100644 --- a/sysdeps/unix/make-syscalls.sh +++ b/sysdeps/unix/make-syscalls.sh @@ -30,6 +30,7 @@ # P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction) # s: non-NULL string (e.g., 1st arg to open) # S: optionally-NULL string (e.g., 1st arg to acct) +# U: unsigned long int (32-bit types are zero-extended to 64-bit types) # v: vararg scalar (e.g., optional 3rd arg to open) # V: byte-per-page vector (3rd arg to mincore) # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4) @@ -184,6 +185,27 @@ while read file srcfile caller syscall args strong weak; do ?:?????????) nargs=9;; esac + # Derive the unsigned long int arguments from the argument signature + ulong_arg_1=0 + ulong_arg_2=0 + ulong_count=0 + for U in $(echo $args | sed -e "s/.*:/:/" | grep -ob U) + do + ulong_count=$(expr $ulong_count + 1) + ulong_arg=$(echo $U | sed -e "s/:U//") + case $ulong_count in + 1) + ulong_arg_1=$ulong_arg + ;; + 2) + ulong_arg_2=$ulong_arg + ;; + *) + echo >&2 "$0: Too many unsigned long int arguments for syscall ($strong $weak)" + exit 2 + esac + done + # Make sure only the first syscall rule is used, if multiple dirs # define the same syscall. echo '' @@ -245,6 +267,8 @@ while read file srcfile caller syscall args strong weak; do \$(make-target-directory) (echo '#define SYSCALL_NAME $syscall'; \\ echo '#define SYSCALL_NARGS $nargs'; \\ + echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\ + echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\ echo '#define SYSCALL_SYMBOL $strong'; \\ echo '#define SYSCALL_NOERRNO $noerrno'; \\ echo '#define SYSCALL_ERRVAL $errval'; \\ diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S index cf6c7a58f..f807a8603 100644 --- a/sysdeps/unix/syscall-template.S +++ b/sysdeps/unix/syscall-template.S @@ -25,6 +25,12 @@ defining a few macros: SYSCALL_NAME syscall name SYSCALL_NARGS number of arguments this call takes + SYSCALL_ULONG_ARG_1 the first unsigned long int argument this + call takes. 0 means that there are no + unsigned long int arguments. + SYSCALL_ULONG_ARG_2 the second unsigned long int argument this + call takes. 0 means that there is at most + one unsigned long int argument. SYSCALL_SYMBOL primary symbol name SYSCALL_NOERRNO 1 to define a no-errno version (see below) SYSCALL_ERRVAL 1 to define an error-value version (see below) @@ -44,9 +50,31 @@ /* This indirection is needed so that SYMBOL gets macro-expanded. */ #define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL) -#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N) -#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N) -#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N) +/* If PSEUDOS_HAVE_ULONG_INDICES is defined, PSEUDO and T_PSEUDO macros + have 2 extra arguments for unsigned long int arguments: + Extra argument 1: Position of the first unsigned long int argument. + Extra argument 2: Position of the second unsigned long int argument. + */ +#ifndef PSEUDOS_HAVE_ULONG_INDICES +# undef SYSCALL_ULONG_ARG_1 +# define SYSCALL_ULONG_ARG_1 0 +#endif + +#if SYSCALL_ULONG_ARG_1 +# define T_PSEUDO(SYMBOL, NAME, N, U1, U2) \ + PSEUDO (SYMBOL, NAME, N, U1, U2) +# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N, U1, U2) \ + PSEUDO_NOERRNO (SYMBOL, NAME, N, U1, U2) +# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N, U1, U2) \ + PSEUDO_ERRVAL (SYMBOL, NAME, N, U1, U2) +#else +# define T_PSEUDO(SYMBOL, NAME, N) \ + PSEUDO (SYMBOL, NAME, N) +# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) \ + PSEUDO_NOERRNO (SYMBOL, NAME, N) +# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) \ + PSEUDO_ERRVAL (SYMBOL, NAME, N) +#endif #define T_PSEUDO_END(SYMBOL) PSEUDO_END (SYMBOL) #define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL) #define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL) @@ -56,7 +84,12 @@ /* This kind of system call stub never returns an error. We return the return value register to the caller unexamined. */ +# if SYSCALL_ULONG_ARG_1 +T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS, + SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2) +# else T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) +# endif ret_NOERRNO T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL) @@ -66,7 +99,12 @@ T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL) value, or zero for success. We may massage the kernel's return value to meet that ABI, but we never set errno here. */ +# if SYSCALL_ULONG_ARG_1 +T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS, + SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2) +# else T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) +# endif ret_ERRVAL T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL) @@ -75,7 +113,12 @@ T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL) /* This is a "normal" system call stub: if there is an error, it returns -1 and sets errno. */ +# if SYSCALL_ULONG_ARG_1 +T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS, + SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2) +# else T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) +# endif ret T_PSEUDO_END (SYSCALL_SYMBOL) diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list index e28e801c7..6b22b2cb4 100644 --- a/sysdeps/unix/syscalls.list +++ b/sysdeps/unix/syscalls.list @@ -39,27 +39,27 @@ kill - kill i:ii __kill kill link - link i:ss __link link listen - listen i:ii __listen listen lseek - lseek i:iii __libc_lseek __lseek lseek -madvise - madvise i:pii __madvise madvise +madvise - madvise i:pUi __madvise madvise mkdir - mkdir i:si __mkdir mkdir -mmap - mmap b:aniiii __mmap mmap -mprotect - mprotect i:aii __mprotect mprotect -munmap - munmap i:ai __munmap munmap +mmap - mmap b:aUiiii __mmap mmap +mprotect - mprotect i:aUi __mprotect mprotect +munmap - munmap i:aU __munmap munmap open - open Ci:siv __libc_open __open open profil - profil i:piii __profil profil ptrace - ptrace i:iiii ptrace -read - read Ci:ibn __libc_read __read read -readlink - readlink i:spi __readlink readlink +read - read Ci:ibU __libc_read __read read +readlink - readlink i:spU __readlink readlink readv - readv Ci:ipi __readv readv reboot - reboot i:i reboot -recv - recv Ci:ibni __libc_recv recv -recvfrom - recvfrom Ci:ibniBN __libc_recvfrom __recvfrom recvfrom +recv - recv Ci:ibUi __libc_recv recv +recvfrom - recvfrom Ci:ibUiBN __libc_recvfrom __recvfrom recvfrom recvmsg - recvmsg Ci:ipi __libc_recvmsg __recvmsg recvmsg rename - rename i:ss rename rmdir - rmdir i:s __rmdir rmdir select - select Ci:iPPPP __select __libc_select select -send - send Ci:ibni __libc_send __send send +send - send Ci:ibUi __libc_send __send send sendmsg - sendmsg Ci:ipi __libc_sendmsg __sendmsg sendmsg -sendto - sendto Ci:ibnibn __libc_sendto __sendto sendto +sendto - sendto Ci:ibUibn __libc_sendto __sendto sendto setdomain - setdomainname i:si setdomainname setegid - setegid i:i __setegid setegid seteuid - seteuid i:i __seteuid seteuid @@ -94,5 +94,5 @@ uname - uname i:p __uname uname unlink - unlink i:s __unlink unlink utimes - utimes i:sp __utimes utimes vhangup - vhangup i:i vhangup -write - write Ci:ibn __libc_write __write write +write - write Ci:ibU __libc_write __write write writev - writev Ci:ipi __writev writev diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index f12b7b1a2..5fbde369c 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -60,7 +60,9 @@ sysdep_routines += adjtimex clone umount umount2 readahead \ setfsuid setfsgid epoll_pwait signalfd \ eventfd eventfd_read eventfd_write prlimit \ personality epoll_wait tee vmsplice splice \ - open_by_handle_at mlock2 pkey_mprotect pkey_set pkey_get + open_by_handle_at mlock2 pkey_mprotect pkey_set pkey_get \ + prctl \ + process_vm_readv process_vm_writev CFLAGS-gethostid.c = -fexceptions CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h index 937838774..c8471947b 100644 --- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h +++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h @@ -17,6 +17,7 @@ #define __NR_clock_nanosleep 115 #define __NR_clock_settime 112 #define __NR_clone 220 +#define __NR_clone3 435 #define __NR_close 57 #define __NR_connect 203 #define __NR_copy_file_range 285 diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h index 1389cea1b..346d045fb 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h @@ -51,8 +51,12 @@ #define IS_PHECDA(midr) (MIDR_IMPLEMENTOR(midr) == 'h' \ && MIDR_PARTNUM(midr) == 0x000) -#define IS_ARES(midr) (MIDR_IMPLEMENTOR(midr) == 'A' \ - && MIDR_PARTNUM(midr) == 0xd0c) +#define IS_NEOVERSE_N1(midr) (MIDR_IMPLEMENTOR(midr) == 'A' \ + && MIDR_PARTNUM(midr) == 0xd0c) +#define IS_NEOVERSE_N2(midr) (MIDR_IMPLEMENTOR(midr) == 'A' \ + && MIDR_PARTNUM(midr) == 0xd49) +#define IS_NEOVERSE_V1(midr) (MIDR_IMPLEMENTOR(midr) == 'A' \ + && MIDR_PARTNUM(midr) == 0xd40) #define IS_EMAG(midr) (MIDR_IMPLEMENTOR(midr) == 'P' \ && MIDR_PARTNUM(midr) == 0x000) diff --git a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data index a60053b91..08af68b5e 100644 --- a/sysdeps/unix/sysv/linux/aarch64/localplt.data +++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data @@ -7,6 +7,9 @@ libc.so: malloc libc.so: memalign libc.so: realloc libm.so: matherr +# If outline atomics are used, libgcc (built outside of glibc) may +# call __getauxval using the PLT. +libc.so: __getauxval ? # The dynamic loader needs __tls_get_addr for TLS. ld.so: __tls_get_addr # The main malloc is interposed into the dynamic linker, for diff --git a/sysdeps/unix/sysv/linux/hppa/atomic-machine.h b/sysdeps/unix/sysv/linux/hppa/atomic-machine.h index 9d8ffbe86..bf61b66b7 100644 --- a/sysdeps/unix/sysv/linux/hppa/atomic-machine.h +++ b/sysdeps/unix/sysv/linux/hppa/atomic-machine.h @@ -36,9 +36,37 @@ typedef uintptr_t uatomicptr_t; typedef intmax_t atomic_max_t; typedef uintmax_t uatomic_max_t; +#define atomic_full_barrier() __sync_synchronize () + #define __HAVE_64B_ATOMICS 0 #define USE_ATOMIC_COMPILER_BUILTINS 0 +/* We use the compiler atomic load and store builtins as the generic + defines are not atomic. In particular, we need to use compare and + exchange for stores as the implementation is synthesized. */ +void __atomic_link_error (void); +#define __atomic_check_size_ls(mem) \ + if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && sizeof (*mem) != 4) \ + __atomic_link_error (); + +#define atomic_load_relaxed(mem) \ + ({ __atomic_check_size_ls((mem)); \ + __atomic_load_n ((mem), __ATOMIC_RELAXED); }) +#define atomic_load_acquire(mem) \ + ({ __atomic_check_size_ls((mem)); \ + __atomic_load_n ((mem), __ATOMIC_ACQUIRE); }) + +#define atomic_store_relaxed(mem, val) \ + do { \ + __atomic_check_size_ls((mem)); \ + __atomic_store_n ((mem), (val), __ATOMIC_RELAXED); \ + } while (0) +#define atomic_store_release(mem, val) \ + do { \ + __atomic_check_size_ls((mem)); \ + __atomic_store_n ((mem), (val), __ATOMIC_RELEASE); \ + } while (0) + /* XXX Is this actually correct? */ #define ATOMIC_EXCHANGE_USES_CAS 1 diff --git a/sysdeps/unix/sysv/linux/microblaze/sysdep.h b/sysdeps/unix/sysv/linux/microblaze/sysdep.h index ed873d9dd..796663a23 100644 --- a/sysdeps/unix/sysv/linux/microblaze/sysdep.h +++ b/sysdeps/unix/sysv/linux/microblaze/sysdep.h @@ -209,8 +209,8 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall0(name,dummy) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r12) \ @@ -219,9 +219,10 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall1(name,arg1) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ + long int __arg1 = (long int) (arg1); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r12) \ @@ -230,10 +231,12 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall2(name,arg1,arg2) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ - register long __r6 __asm__("r6") = (long)(arg2); \ + long int __arg1 = (long int) (arg1); \ + long int __arg2 = (long int) (arg2); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ + register long int __r6 __asm__("r6") = __arg2; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r6), "r"(__r12) \ @@ -243,11 +246,14 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall3(name,arg1,arg2,arg3) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ - register long __r6 __asm__("r6") = (long)(arg2); \ - register long __r7 __asm__("r7") = (long)(arg3); \ + long int __arg1 = (long int) (arg1); \ + long int __arg2 = (long int) (arg2); \ + long int __arg3 = (long int) (arg3); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ + register long int __r6 __asm__("r6") = __arg2; \ + register long int __r7 __asm__("r7") = __arg3; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r12) \ @@ -257,12 +263,16 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall4(name,arg1,arg2,arg3,arg4) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ - register long __r6 __asm__("r6") = (long)(arg2); \ - register long __r7 __asm__("r7") = (long)(arg3); \ - register long __r8 __asm__("r8") = (long)(arg4); \ + long int __arg1 = (long int) (arg1); \ + long int __arg2 = (long int) (arg2); \ + long int __arg3 = (long int) (arg3); \ + long int __arg4 = (long int) (arg4); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ + register long int __r6 __asm__("r6") = __arg2; \ + register long int __r7 __asm__("r7") = __arg3; \ + register long int __r8 __asm__("r8") = __arg4; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r12) \ @@ -272,13 +282,18 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ - register long __r6 __asm__("r6") = (long)(arg2); \ - register long __r7 __asm__("r7") = (long)(arg3); \ - register long __r8 __asm__("r8") = (long)(arg4); \ - register long __r9 __asm__("r9") = (long)(arg5); \ + long int __arg1 = (long int) (arg1); \ + long int __arg2 = (long int) (arg2); \ + long int __arg3 = (long int) (arg3); \ + long int __arg4 = (long int) (arg4); \ + long int __arg5 = (long int) (arg5); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ + register long int __r6 __asm__("r6") = __arg2; \ + register long int __r7 __asm__("r7") = __arg3; \ + register long int __r8 __asm__("r8") = __arg4; \ + register long int __r9 __asm__("r9") = __arg5; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r12) \ @@ -288,14 +303,20 @@ SYSCALL_ERROR_LABEL_DCL: \ # define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ ({ \ - register long __ret __asm__("r3"); \ - register long __r12 __asm__("r12") = name; \ - register long __r5 __asm__("r5") = (long)(arg1); \ - register long __r6 __asm__("r6") = (long)(arg2); \ - register long __r7 __asm__("r7") = (long)(arg3); \ - register long __r8 __asm__("r8") = (long)(arg4); \ - register long __r9 __asm__("r9") = (long)(arg5); \ - register long __r10 __asm__("r10") = (long)(arg6); \ + long int __arg1 = (long int) (arg1); \ + long int __arg2 = (long int) (arg2); \ + long int __arg3 = (long int) (arg3); \ + long int __arg4 = (long int) (arg4); \ + long int __arg5 = (long int) (arg5); \ + long int __arg6 = (long int) (arg6); \ + register long int __ret __asm__("r3"); \ + register long int __r12 __asm__("r12") = name; \ + register long int __r5 __asm__("r5") = __arg1; \ + register long int __r6 __asm__("r6") = __arg2; \ + register long int __r7 __asm__("r7") = __arg3; \ + register long int __r8 __asm__("r8") = __arg4; \ + register long int __r9 __asm__("r9") = __arg5; \ + register long int __r10 __asm__("r10") = __arg6; \ __asm__ __volatile__( "brki r14,8; nop;" \ : "=r"(__ret) \ : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r10), \ diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S index b2bbf1018..ff445a540 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S @@ -22,9 +22,9 @@ .text .set nomips16 -/* long long __mips_syscall5 (long arg1, long arg2, long arg3, long arg4, - long arg5, - long number) */ +/* long long int __mips_syscall5 (long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, + long int number) */ ENTRY(__mips_syscall5) lw v0, 20(sp) diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S index 572d7c113..2b4a3117d 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S @@ -22,9 +22,9 @@ .text .set nomips16 -/* long long __mips_syscall6 (long arg1, long arg2, long arg3, long arg4, - long arg5, long arg6, - long number) */ +/* long long int __mips_syscall6 (long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6, + long int number) */ ENTRY(__mips_syscall6) lw v0, 24(sp) diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S index 05164cb25..2723bbb13 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S @@ -22,9 +22,10 @@ .text .set nomips16 -/* long long __mips_syscall7 (long arg1, long arg2, long arg3, long arg4, - long arg5, long arg6, long arg7, - long number) */ +/* long long int __mips_syscall7 (long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6, + long int arg7, + long int number) */ ENTRY(__mips_syscall7) lw v0, 28(sp) diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h index 9bf551ace..f23ede025 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h @@ -19,51 +19,57 @@ #ifndef MIPS16_SYSCALL_H #define MIPS16_SYSCALL_H 1 -long long __nomips16 __mips16_syscall0 (long number); +long long int __nomips16 __mips16_syscall0 (long int number); #define __mips16_syscall0(dummy, number) \ - __mips16_syscall0 ((long) (number)) + __mips16_syscall0 ((long int) (number)) -long long __nomips16 __mips16_syscall1 (long a0, - long number); +long long int __nomips16 __mips16_syscall1 (long int a0, + long int number); #define __mips16_syscall1(a0, number) \ - __mips16_syscall1 ((long) (a0), \ - (long) (number)) + __mips16_syscall1 ((long int) (a0), \ + (long int) (number)) -long long __nomips16 __mips16_syscall2 (long a0, long a1, - long number); +long long int __nomips16 __mips16_syscall2 (long int a0, long int a1, + long int number); #define __mips16_syscall2(a0, a1, number) \ - __mips16_syscall2 ((long) (a0), (long) (a1), \ - (long) (number)) + __mips16_syscall2 ((long int) (a0), (long int) (a1), \ + (long int) (number)) -long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2, - long number); +long long int __nomips16 __mips16_syscall3 (long int a0, long int a1, + long int a2, + long int number); #define __mips16_syscall3(a0, a1, a2, number) \ - __mips16_syscall3 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (number)) + __mips16_syscall3 ((long int) (a0), (long int) (a1), \ + (long int) (a2), \ + (long int) (number)) -long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3, - long number); +long long int __nomips16 __mips16_syscall4 (long int a0, long int a1, + long int a2, long int a3, + long int number); #define __mips16_syscall4(a0, a1, a2, a3, number) \ - __mips16_syscall4 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), \ - (long) (number)) + __mips16_syscall4 ((long int) (a0), (long int) (a1), \ + (long int) (a2), (long int) (a3), \ + (long int) (number)) /* The remaining ones use regular MIPS wrappers. */ #define __mips16_syscall5(a0, a1, a2, a3, a4, number) \ - __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), \ - (long) (number)) + __mips_syscall5 ((long int) (a0), (long int) (a1), \ + (long int) (a2), (long int) (a3), \ + (long int) (a4), \ + (long int) (number)) #define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number) \ - __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (number)) + __mips_syscall6 ((long int) (a0), (long int) (a1), \ + (long int) (a2), (long int) (a3), \ + (long int) (a4), (long int) (a5), \ + (long int) (number)) #define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number) \ - __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (a6), \ - (long) (number)) + __mips_syscall7 ((long int) (a0), (long int) (a1), \ + (long int) (a2), (long int) (a3), \ + (long int) (a4), (long int) (a5), \ + (long int) (a6), \ + (long int) (number)) #endif diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c index 92f16e272..43c05f805 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c @@ -20,8 +20,8 @@ #undef __mips16_syscall0 -long long __nomips16 -__mips16_syscall0 (long number) +long long int __nomips16 +__mips16_syscall0 (long int number) { union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0); diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c index fa985a96e..16a567e83 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c @@ -20,9 +20,9 @@ #undef __mips16_syscall1 -long long __nomips16 -__mips16_syscall1 (long a0, - long number) +long long int __nomips16 +__mips16_syscall1 (long int a0, + long int number) { union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1, diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c index f042ac815..c0a856c34 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c @@ -20,9 +20,9 @@ #undef __mips16_syscall2 -long long __nomips16 -__mips16_syscall2 (long a0, long a1, - long number) +long long int __nomips16 +__mips16_syscall2 (long int a0, long int a1, + long int number) { union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2, diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c index dfe2f7feb..042768ebf 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c @@ -20,9 +20,9 @@ #undef __mips16_syscall3 -long long __nomips16 -__mips16_syscall3 (long a0, long a1, long a2, - long number) +long long int __nomips16 +__mips16_syscall3 (long int a0, long int a1, long int a2, + long int number) { union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3, diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c index 39de51035..8658d822a 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c +++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c @@ -20,9 +20,9 @@ #undef __mips16_syscall4 -long long __nomips16 -__mips16_syscall4 (long a0, long a1, long a2, long a3, - long number) +long long int __nomips16 +__mips16_syscall4 (long int a0, long int a1, long int a2, long int a3, + long int number) { union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4, diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index beefcf284..0c6a83e9b 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -52,7 +52,7 @@ #undef INLINE_SYSCALL #define INLINE_SYSCALL(name, nr, args...) \ ({ INTERNAL_SYSCALL_DECL (_sc_err); \ - long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ + long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \ { \ __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \ @@ -61,10 +61,10 @@ result_var; }) #undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused)) +#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused)) #undef INTERNAL_SYSCALL_ERROR_P -#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err)) +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err)) #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) @@ -103,11 +103,11 @@ union __mips_syscall_return { - long long val; + long long int val; struct { - long v0; - long v1; + long int v0; + long int v1; } reg; }; @@ -152,13 +152,13 @@ union __mips_syscall_return #define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -175,14 +175,15 @@ union __mips_syscall_return #define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -199,15 +200,17 @@ union __mips_syscall_return #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -225,16 +228,19 @@ union __mips_syscall_return #define internal_syscall3(v0_init, input, number, err, \ arg1, arg2, arg3) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -252,16 +258,20 @@ union __mips_syscall_return #define internal_syscall4(v0_init, input, number, err, \ arg1, arg2, arg3, arg4) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7") = _arg4; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -285,63 +295,66 @@ union __mips_syscall_return compiler specifics required for the stack arguments to be pushed, which would be the case if these syscalls were inlined. */ -long long __nomips16 __mips_syscall5 (long arg1, long arg2, long arg3, - long arg4, long arg5, - long number); +long long int __nomips16 __mips_syscall5 (long int arg1, long int arg2, + long int arg3, long int arg4, + long int arg5, + long int number); libc_hidden_proto (__mips_syscall5, nomips16) #define internal_syscall5(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5) \ ({ \ union __mips_syscall_return _sc_ret; \ - _sc_ret.val = __mips_syscall5 ((long) (arg1), \ - (long) (arg2), \ - (long) (arg3), \ - (long) (arg4), \ - (long) (arg5), \ - (long) (number)); \ + _sc_ret.val = __mips_syscall5 ((long int) (arg1), \ + (long int) (arg2), \ + (long int) (arg3), \ + (long int) (arg4), \ + (long int) (arg5), \ + (long int) (number)); \ err = _sc_ret.reg.v1; \ _sc_ret.reg.v0; \ }) -long long __nomips16 __mips_syscall6 (long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6, - long number); +long long int __nomips16 __mips_syscall6 (long int arg1, long int arg2, + long int arg3, long int arg4, + long int arg5, long int arg6, + long int number); libc_hidden_proto (__mips_syscall6, nomips16) #define internal_syscall6(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ union __mips_syscall_return _sc_ret; \ - _sc_ret.val = __mips_syscall6 ((long) (arg1), \ - (long) (arg2), \ - (long) (arg3), \ - (long) (arg4), \ - (long) (arg5), \ - (long) (arg6), \ - (long) (number)); \ + _sc_ret.val = __mips_syscall6 ((long int) (arg1), \ + (long int) (arg2), \ + (long int) (arg3), \ + (long int) (arg4), \ + (long int) (arg5), \ + (long int) (arg6), \ + (long int) (number)); \ err = _sc_ret.reg.v1; \ _sc_ret.reg.v0; \ }) -long long __nomips16 __mips_syscall7 (long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6, - long arg7, - long number); +long long int __nomips16 __mips_syscall7 (long int arg1, long int arg2, + long int arg3, long int arg4, + long int arg5, long int arg6, + long int arg7, + long int number); libc_hidden_proto (__mips_syscall7, nomips16) #define internal_syscall7(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ ({ \ union __mips_syscall_return _sc_ret; \ - _sc_ret.val = __mips_syscall7 ((long) (arg1), \ - (long) (arg2), \ - (long) (arg3), \ - (long) (arg4), \ - (long) (arg5), \ - (long) (arg6), \ - (long) (arg7), \ - (long) (number)); \ + _sc_ret.val = __mips_syscall7 ((long int) (arg1), \ + (long int) (arg2), \ + (long int) (arg3), \ + (long int) (arg4), \ + (long int) (arg5), \ + (long int) (arg6), \ + (long int) (arg7), \ + (long int) (number)); \ err = _sc_ret.reg.v1; \ _sc_ret.reg.v0; \ }) diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h index f96636538..4a9d7054f 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h @@ -47,14 +47,14 @@ /* Convert X to a long long, without losing any bits if it is one already or warning if it is a 32-bit pointer. */ -#define ARGIFY(X) ((long long) (__typeof__ ((X) - (X))) (X)) +#define ARGIFY(X) ((long long int) (__typeof__ ((X) - (X))) (X)) /* Define a macro which expands into the inline wrapper code for a system call. */ #undef INLINE_SYSCALL #define INLINE_SYSCALL(name, nr, args...) \ ({ INTERNAL_SYSCALL_DECL (_sc_err); \ - long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ + long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \ { \ __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \ @@ -63,10 +63,10 @@ result_var; }) #undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused)) +#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused)) #undef INTERNAL_SYSCALL_ERROR_P -#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err)) +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err)) #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) @@ -112,13 +112,13 @@ #define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a3 asm ("$7"); \ + register long long int __v0 asm ("$2"); \ + register long long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -135,14 +135,15 @@ #define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a3 asm ("$7"); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -159,15 +160,17 @@ #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + long long int _arg2 = ARGIFY (arg2); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a1 asm ("$5") = ARGIFY (arg2); \ - register long long __a3 asm ("$7"); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a1 asm ("$5") = _arg2; \ + register long long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -185,16 +188,19 @@ #define internal_syscall3(v0_init, input, number, err, \ arg1, arg2, arg3) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + long long int _arg2 = ARGIFY (arg2); \ + long long int _arg3 = ARGIFY (arg3); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a1 asm ("$5") = ARGIFY (arg2); \ - register long long __a2 asm ("$6") = ARGIFY (arg3); \ - register long long __a3 asm ("$7"); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a1 asm ("$5") = _arg2; \ + register long long int __a2 asm ("$6") = _arg3; \ + register long long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -212,16 +218,20 @@ #define internal_syscall4(v0_init, input, number, err, \ arg1, arg2, arg3, arg4) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + long long int _arg2 = ARGIFY (arg2); \ + long long int _arg3 = ARGIFY (arg3); \ + long long int _arg4 = ARGIFY (arg4); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a1 asm ("$5") = ARGIFY (arg2); \ - register long long __a2 asm ("$6") = ARGIFY (arg3); \ - register long long __a3 asm ("$7") = ARGIFY (arg4); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a1 asm ("$5") = _arg2; \ + register long long int __a2 asm ("$6") = _arg3; \ + register long long int __a3 asm ("$7") = _arg4; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -239,17 +249,22 @@ #define internal_syscall5(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + long long int _arg2 = ARGIFY (arg2); \ + long long int _arg3 = ARGIFY (arg3); \ + long long int _arg4 = ARGIFY (arg4); \ + long long int _arg5 = ARGIFY (arg5); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a1 asm ("$5") = ARGIFY (arg2); \ - register long long __a2 asm ("$6") = ARGIFY (arg3); \ - register long long __a3 asm ("$7") = ARGIFY (arg4); \ - register long long __a4 asm ("$8") = ARGIFY (arg5); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a1 asm ("$5") = _arg2; \ + register long long int __a2 asm ("$6") = _arg3; \ + register long long int __a3 asm ("$7") = _arg4; \ + register long long int __a4 asm ("$8") = _arg5; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -267,18 +282,24 @@ #define internal_syscall6(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long long __s0 asm ("$16") __attribute__ ((unused)) \ + long long int _arg1 = ARGIFY (arg1); \ + long long int _arg2 = ARGIFY (arg2); \ + long long int _arg3 = ARGIFY (arg3); \ + long long int _arg4 = ARGIFY (arg4); \ + long long int _arg5 = ARGIFY (arg5); \ + long long int _arg6 = ARGIFY (arg6); \ + register long long int __s0 asm ("$16") __attribute__ ((unused))\ = (number); \ - register long long __v0 asm ("$2"); \ - register long long __a0 asm ("$4") = ARGIFY (arg1); \ - register long long __a1 asm ("$5") = ARGIFY (arg2); \ - register long long __a2 asm ("$6") = ARGIFY (arg3); \ - register long long __a3 asm ("$7") = ARGIFY (arg4); \ - register long long __a4 asm ("$8") = ARGIFY (arg5); \ - register long long __a5 asm ("$9") = ARGIFY (arg6); \ + register long long int __v0 asm ("$2"); \ + register long long int __a0 asm ("$4") = _arg1; \ + register long long int __a1 asm ("$5") = _arg2; \ + register long long int __a2 asm ("$6") = _arg3; \ + register long long int __a3 asm ("$7") = _arg4; \ + register long long int __a4 asm ("$8") = _arg5; \ + register long long int __a5 asm ("$9") = _arg6; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h index 9d30291f8..3e1f1cc3c 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h @@ -50,7 +50,7 @@ #undef INLINE_SYSCALL #define INLINE_SYSCALL(name, nr, args...) \ ({ INTERNAL_SYSCALL_DECL (_sc_err); \ - long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ + long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \ { \ __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \ @@ -59,10 +59,10 @@ result_var; }) #undef INTERNAL_SYSCALL_DECL -#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused)) +#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused)) #undef INTERNAL_SYSCALL_ERROR_P -#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err)) +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err)) #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) @@ -108,13 +108,13 @@ #define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -131,14 +131,15 @@ #define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -155,15 +156,17 @@ #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -181,16 +184,19 @@ #define internal_syscall3(v0_init, input, number, err, \ arg1, arg2, arg3) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7"); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -208,16 +214,20 @@ #define internal_syscall4(v0_init, input, number, err, \ arg1, arg2, arg3, arg4) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7") = _arg4; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -235,17 +245,22 @@ #define internal_syscall5(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ - register long __a4 asm ("$8") = (long) (arg5); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7") = _arg4; \ + register long int __a4 asm ("$8") = _arg5; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ @@ -263,18 +278,24 @@ #define internal_syscall6(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ - long _sys_result; \ + long int _sys_result; \ \ { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ + register long int __s0 asm ("$16") __attribute__ ((unused)) \ = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ - register long __a4 asm ("$8") = (long) (arg5); \ - register long __a5 asm ("$9") = (long) (arg6); \ + register long int __v0 asm ("$2"); \ + register long int __a0 asm ("$4") = _arg1; \ + register long int __a1 asm ("$5") = _arg2; \ + register long int __a2 asm ("$6") = _arg3; \ + register long int __a3 asm ("$7") = _arg4; \ + register long int __a4 asm ("$8") = _arg5; \ + register long int __a5 asm ("$9") = _arg6; \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ v0_init \ diff --git a/sysdeps/unix/sysv/linux/mips/mips64/syscall.S b/sysdeps/unix/sysv/linux/mips/mips64/syscall.S index 26adf2cd0..a9baff3c1 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/syscall.S +++ b/sysdeps/unix/sysv/linux/mips/mips64/syscall.S @@ -20,7 +20,7 @@ #include /* Usage: - long syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6, arg7) + long int syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6, arg7) We need to do some arg shifting, syscall_number will be in v0. */ diff --git a/sysdeps/unix/sysv/linux/mips/sysdep.h b/sysdeps/unix/sysv/linux/mips/sysdep.h index cdfc0b1b5..a4cf1540f 100644 --- a/sysdeps/unix/sysv/linux/mips/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/sysdep.h @@ -36,8 +36,8 @@ the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly. */ #define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \ ({ \ - long _ret = funcptr (args); \ - err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \ + long int _ret = funcptr (args); \ + err = ((unsigned long int) (_ret) >= (unsigned long int) -4095L); \ if (err) \ _ret = -_ret; \ _ret; \ diff --git a/sysdeps/unix/sysv/linux/mips/unwind-arch.h b/sysdeps/unix/sysv/linux/mips/unwind-arch.h new file mode 100644 index 000000000..a00989998 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/unwind-arch.h @@ -0,0 +1,67 @@ +/* Return backtrace of current program state. Arch-specific bits. + Copyright (C) 2020 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 + . */ + +#ifndef _UNWIND_ARCH_H +#define _UNWIND_ARCH_H + +#include + +/* MIPS fallback code handle a frame where its FDE can not be obtained + (for instance a signal frame) by reading the kernel allocated signal frame + and adding '2' to the value of 'sc_pc' [1]. The added value is used to + recognize an end of an EH region on mips16 [2]. + + The idea here is to adjust the obtained signal frame ADDR value and remove + the libgcc added value by checking if the previous frame is a signal frame + one. + + [1] libgcc/config/mips/linux-unwind.h from gcc code. + [2] gcc/config/mips/mips.h from gcc code. */ + +static inline void * +unwind_arch_adjustment (void *prev, void *addr) +{ + uint32_t *pc = (uint32_t *) prev; + + if (pc == NULL) + return addr; + + /* For MIPS16 or microMIPS frame libgcc makes no adjustment. */ + if ((uintptr_t) pc & 0x3) + return addr; + + /* The vDSO containes either + + 24021061 li v0, 0x1061 (rt_sigreturn) + 0000000c syscall + or + 24021017 li v0, 0x1017 (sigreturn) + 0000000c syscall */ + if (pc[1] != 0x0000000c) + return addr; +#if _MIPS_SIM == _ABIO32 + if (pc[0] == (0x24020000 | __NR_sigreturn)) + return (void *) ((uintptr_t) addr - 2); +#endif + if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) + return (void *) ((uintptr_t) addr - 2); + + return addr; +} + +#endif diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c index 27879e76c..fd46aec1a 100644 --- a/sysdeps/unix/sysv/linux/msgctl.c +++ b/sysdeps/unix/sysv/linux/msgctl.c @@ -21,6 +21,7 @@ #include #include #include +#include /* For __kernel_mode_t. */ #ifndef DEFAULT_VERSION # ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T @@ -61,7 +62,6 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) int ret = msgctl_syscall (msqid, cmd, buf); -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T if (ret >= 0) { switch (cmd) @@ -69,10 +69,16 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) case IPC_STAT: case MSG_STAT: case MSG_STAT_ANY: +#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T buf->msg_perm.mode >>= 16; +#else + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct msqid_ds){0}.msg_perm.mode) + != sizeof (__kernel_mode_t)) + buf->msg_perm.mode &= 0xFFFF; +#endif } } -#endif return ret; } diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h index 725dfafde..ffc150851 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h @@ -134,47 +134,47 @@ # define LOADARGS_0(name, dummy) \ r0 = name # define LOADARGS_1(name, __arg1) \ - long int arg1 = (long int) (__arg1); \ + long int _arg1 = (long int) (__arg1); \ LOADARGS_0(name, 0); \ extern void __illegally_sized_syscall_arg1 (void); \ if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \ __illegally_sized_syscall_arg1 (); \ - r3 = arg1 + r3 = _arg1 # define LOADARGS_2(name, __arg1, __arg2) \ - long int arg2 = (long int) (__arg2); \ + long int _arg2 = (long int) (__arg2); \ LOADARGS_1(name, __arg1); \ extern void __illegally_sized_syscall_arg2 (void); \ if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \ __illegally_sized_syscall_arg2 (); \ - r4 = arg2 + r4 = _arg2 # define LOADARGS_3(name, __arg1, __arg2, __arg3) \ - long int arg3 = (long int) (__arg3); \ + long int _arg3 = (long int) (__arg3); \ LOADARGS_2(name, __arg1, __arg2); \ extern void __illegally_sized_syscall_arg3 (void); \ if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \ __illegally_sized_syscall_arg3 (); \ - r5 = arg3 + r5 = _arg3 # define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ - long int arg4 = (long int) (__arg4); \ + long int _arg4 = (long int) (__arg4); \ LOADARGS_3(name, __arg1, __arg2, __arg3); \ extern void __illegally_sized_syscall_arg4 (void); \ if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \ __illegally_sized_syscall_arg4 (); \ - r6 = arg4 + r6 = _arg4 # define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ - long int arg5 = (long int) (__arg5); \ + long int _arg5 = (long int) (__arg5); \ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ extern void __illegally_sized_syscall_arg5 (void); \ if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \ __illegally_sized_syscall_arg5 (); \ - r7 = arg5 + r7 = _arg5 # define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ - long int arg6 = (long int) (__arg6); \ + long int _arg6 = (long int) (__arg6); \ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ extern void __illegally_sized_syscall_arg6 (void); \ if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \ __illegally_sized_syscall_arg6 (); \ - r8 = arg6 + r8 = _arg6 # define ASM_INPUT_0 "0" (r0) # define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index ee7f43653..8a3f1c43e 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -139,47 +139,47 @@ #define LOADARGS_0(name, dummy) \ r0 = name #define LOADARGS_1(name, __arg1) \ - long int arg1 = (long int) (__arg1); \ + long int _arg1 = (long int) (__arg1); \ LOADARGS_0(name, 0); \ extern void __illegally_sized_syscall_arg1 (void); \ if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 8) \ __illegally_sized_syscall_arg1 (); \ - r3 = arg1 + r3 = _arg1 #define LOADARGS_2(name, __arg1, __arg2) \ - long int arg2 = (long int) (__arg2); \ + long int _arg2 = (long int) (__arg2); \ LOADARGS_1(name, __arg1); \ extern void __illegally_sized_syscall_arg2 (void); \ if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 8) \ __illegally_sized_syscall_arg2 (); \ - r4 = arg2 + r4 = _arg2 #define LOADARGS_3(name, __arg1, __arg2, __arg3) \ - long int arg3 = (long int) (__arg3); \ + long int _arg3 = (long int) (__arg3); \ LOADARGS_2(name, __arg1, __arg2); \ extern void __illegally_sized_syscall_arg3 (void); \ if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 8) \ __illegally_sized_syscall_arg3 (); \ - r5 = arg3 + r5 = _arg3 #define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ - long int arg4 = (long int) (__arg4); \ + long int _arg4 = (long int) (__arg4); \ LOADARGS_3(name, __arg1, __arg2, __arg3); \ extern void __illegally_sized_syscall_arg4 (void); \ if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 8) \ __illegally_sized_syscall_arg4 (); \ - r6 = arg4 + r6 = _arg4 #define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ - long int arg5 = (long int) (__arg5); \ + long int _arg5 = (long int) (__arg5); \ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ extern void __illegally_sized_syscall_arg5 (void); \ if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 8) \ __illegally_sized_syscall_arg5 (); \ - r7 = arg5 + r7 = _arg5 #define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ - long int arg6 = (long int) (__arg6); \ + long int _arg6 = (long int) (__arg6); \ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ extern void __illegally_sized_syscall_arg6 (void); \ if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 8) \ __illegally_sized_syscall_arg6 (); \ - r8 = arg6 + r8 = _arg6 #define ASM_INPUT_0 "0" (r0) #define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) diff --git a/sysdeps/unix/sysv/linux/prctl.c b/sysdeps/unix/sysv/linux/prctl.c new file mode 100644 index 000000000..d5725f14c --- /dev/null +++ b/sysdeps/unix/sysv/linux/prctl.c @@ -0,0 +1,42 @@ +/* prctl - Linux specific syscall. + Copyright (C) 2020 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 + . */ + +#include +#include +#include + +/* Unconditionally read all potential arguments. This may pass + garbage values to the kernel, but avoids the need for teaching + glibc the argument counts of individual options (including ones + that are added to the kernel in the future). */ + +int +__prctl (int option, ...) +{ + va_list arg; + va_start (arg, option); + unsigned long int arg2 = va_arg (arg, unsigned long int); + unsigned long int arg3 = va_arg (arg, unsigned long int); + unsigned long int arg4 = va_arg (arg, unsigned long int); + unsigned long int arg5 = va_arg (arg, unsigned long int); + va_end (arg); + return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5); +} + +libc_hidden_def (__prctl) +weak_alias (__prctl, prctl) diff --git a/sysdeps/unix/sysv/linux/process_vm_readv.c b/sysdeps/unix/sysv/linux/process_vm_readv.c new file mode 100644 index 000000000..e1377f7e5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/process_vm_readv.c @@ -0,0 +1,32 @@ +/* process_vm_readv - Linux specific syscall. + Copyright (C) 2020 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 + . */ + +#include +#include +#include +#include + +ssize_t +process_vm_readv (pid_t pid, const struct iovec *local_iov, + unsigned long int liovcnt, + const struct iovec *remote_iov, + unsigned long int riovcnt, unsigned long int flags) +{ + return INLINE_SYSCALL_CALL (process_vm_readv, pid, local_iov, + liovcnt, remote_iov, riovcnt, flags); +} diff --git a/sysdeps/unix/sysv/linux/process_vm_writev.c b/sysdeps/unix/sysv/linux/process_vm_writev.c new file mode 100644 index 000000000..944ab9b7f --- /dev/null +++ b/sysdeps/unix/sysv/linux/process_vm_writev.c @@ -0,0 +1,32 @@ +/* process_vm_writev - Linux specific syscall. + Copyright (C) 2020 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 + . */ + +#include +#include +#include +#include + +ssize_t +process_vm_writev (pid_t pid, const struct iovec *local_iov, + unsigned long int liovcnt, + const struct iovec *remote_iov, + unsigned long int riovcnt, unsigned long int flags) +{ + return INLINE_SYSCALL_CALL (process_vm_writev, pid, local_iov, + liovcnt, remote_iov, riovcnt, flags); +} diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h index 201bf9a91..2bd9b16f3 100644 --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h @@ -176,10 +176,11 @@ # define internal_syscall1(number, err, arg0) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a0 asm ("a0") = _arg0; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -193,11 +194,13 @@ # define internal_syscall2(number, err, arg0, arg1) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -211,12 +214,15 @@ # define internal_syscall3(number, err, arg0, arg1, arg2) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ - register long int __a2 asm ("a2") = (long int) (arg2); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ + register long int __a2 asm ("a2") = _arg2; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -230,13 +236,17 @@ # define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ - register long int __a2 asm ("a2") = (long int) (arg2); \ - register long int __a3 asm ("a3") = (long int) (arg3); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ + register long int __a2 asm ("a2") = _arg2; \ + register long int __a3 asm ("a3") = _arg3; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -250,14 +260,19 @@ # define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ - register long int __a2 asm ("a2") = (long int) (arg2); \ - register long int __a3 asm ("a3") = (long int) (arg3); \ - register long int __a4 asm ("a4") = (long int) (arg4); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ + register long int __a2 asm ("a2") = _arg2; \ + register long int __a3 asm ("a3") = _arg3; \ + register long int __a4 asm ("a4") = _arg4; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -271,15 +286,21 @@ # define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ - register long int __a2 asm ("a2") = (long int) (arg2); \ - register long int __a3 asm ("a3") = (long int) (arg3); \ - register long int __a4 asm ("a4") = (long int) (arg4); \ - register long int __a5 asm ("a5") = (long int) (arg5); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ + register long int __a2 asm ("a2") = _arg2; \ + register long int __a3 asm ("a3") = _arg3; \ + register long int __a4 asm ("a4") = _arg4; \ + register long int __a5 asm ("a5") = _arg5; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ @@ -294,16 +315,23 @@ # define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long int _sys_result; \ + long int _arg0 = (long int) (arg0); \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ \ { \ register long int __a7 asm ("a7") = number; \ - register long int __a0 asm ("a0") = (long int) (arg0); \ - register long int __a1 asm ("a1") = (long int) (arg1); \ - register long int __a2 asm ("a2") = (long int) (arg2); \ - register long int __a3 asm ("a3") = (long int) (arg3); \ - register long int __a4 asm ("a4") = (long int) (arg4); \ - register long int __a5 asm ("a5") = (long int) (arg5); \ - register long int __a6 asm ("a6") = (long int) (arg6); \ + register long int __a0 asm ("a0") = _arg0; \ + register long int __a1 asm ("a1") = _arg1; \ + register long int __a2 asm ("a2") = _arg2; \ + register long int __a3 asm ("a3") = _arg3; \ + register long int __a4 asm ("a4") = _arg4; \ + register long int __a5 asm ("a5") = _arg5; \ + register long int __a6 asm ("a6") = _arg6; \ __asm__ volatile ( \ "scall\n\t" \ : "+r" (__a0) \ diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index 0c3eb0932..30571af49 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -22,6 +22,7 @@ #include #include #include +#include /* For __kernel_mode_t. */ /* Define a `union semun' suitable for Linux here. */ union semun @@ -92,7 +93,6 @@ __new_semctl (int semid, int semnum, int cmd, ...) int ret = semctl_syscall (semid, semnum, cmd, arg); -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T if (ret >= 0) { switch (cmd) @@ -100,10 +100,16 @@ __new_semctl (int semid, int semnum, int cmd, ...) case IPC_STAT: case SEM_STAT: case SEM_STAT_ANY: +#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T arg.buf->sem_perm.mode >>= 16; +#else + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct semid_ds){0}.sem_perm.mode) + != sizeof (__kernel_mode_t)) + arg.buf->sem_perm.mode &= 0xFFFF; +#endif } } -#endif return ret; } diff --git a/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies b/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies new file mode 100644 index 000000000..7eeaf15a5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies @@ -0,0 +1 @@ +unix/sysv/linux/sh/sh4/fpu diff --git a/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies b/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies new file mode 100644 index 000000000..7eeaf15a5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies @@ -0,0 +1 @@ +unix/sysv/linux/sh/sh4/fpu diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c index 39fa861e1..f41b359b8 100644 --- a/sysdeps/unix/sysv/linux/shmctl.c +++ b/sysdeps/unix/sysv/linux/shmctl.c @@ -22,6 +22,7 @@ #include #include #include +#include /* For __kernel_mode_t. */ #ifndef DEFAULT_VERSION # ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T @@ -63,7 +64,6 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) int ret = shmctl_syscall (shmid, cmd, buf); -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T if (ret >= 0) { switch (cmd) @@ -71,10 +71,16 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) case IPC_STAT: case SHM_STAT: case SHM_STAT_ANY: +#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T buf->shm_perm.mode >>= 16; +#else + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct shmid_ds){0}.shm_perm.mode) + != sizeof (__kernel_mode_t)) + buf->shm_perm.mode &= 0xFFFF; +#endif } } -#endif return ret; } diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile index b0d182a43..147503967 100644 --- a/sysdeps/unix/sysv/linux/sparc/Makefile +++ b/sysdeps/unix/sysv/linux/sparc/Makefile @@ -11,8 +11,12 @@ ifeq ($(subdir),sysvipc) sysdep_routines += getshmlba endif +ifeq ($(subdir),signal) +sysdep_routines += sigreturn_stub +endif + ifeq ($(subdir),nptl) # pull in __syscall_error routine -libpthread-routines += sysdep -libpthread-shared-only-routines += sysdep +libpthread-routines += sysdep sigreturn_stub +libpthread-shared-only-routines += sysdep sigreturn_stub endif diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c index 6b2f66422..938aa7aa8 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c @@ -24,8 +24,8 @@ #include #include -static void __rt_sigreturn_stub (void); -static void __sigreturn_stub (void); +void __rt_sigreturn_stub (void); +void __sigreturn_stub (void); #define STUB(act, sigsetsize) \ (act) ? ((unsigned long)((act->sa_flags & SA_SIGINFO) \ @@ -35,25 +35,3 @@ static void __sigreturn_stub (void); (sigsetsize) #include - -static -inhibit_stack_protector -void -__rt_sigreturn_stub (void) -{ - __asm__ ("mov %0, %%g1\n\t" - "ta 0x10\n\t" - : /* no outputs */ - : "i" (__NR_rt_sigreturn)); -} - -static -inhibit_stack_protector -void -__sigreturn_stub (void) -{ - __asm__ ("mov %0, %%g1\n\t" - "ta 0x10\n\t" - : /* no outputs */ - : "i" (__NR_sigreturn)); -} diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigreturn_stub.S b/sysdeps/unix/sysv/linux/sparc/sparc32/sigreturn_stub.S new file mode 100644 index 000000000..727cc9473 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigreturn_stub.S @@ -0,0 +1,34 @@ +/* Sigreturn stub function used on sa_restore field. + Copyright (C) 2020 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 + . */ + +#include + +/* These functions must not change the register window or the stack + pointer [1]. + + [1] https://lkml.org/lkml/2016/5/27/465 */ + +ENTRY (__rt_sigreturn_stub) + mov __NR_rt_sigreturn, %g1 + ta 0x10 +END (__rt_sigreturn_stub) + +ENTRY (__sigreturn_stub) + mov __NR_sigreturn, %g1 + ta 0x10 +END (__sigreturn_stub) diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c index 9c0dc2a63..4e2617232 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c @@ -22,21 +22,11 @@ #include #include -static void __rt_sigreturn_stub (void); +/* Defined on sigreturn_stub.S. */ +void __rt_sigreturn_stub (void); #define STUB(act, sigsetsize) \ (((unsigned long) &__rt_sigreturn_stub) - 8), \ (sigsetsize) #include - -static -inhibit_stack_protector -void -__rt_sigreturn_stub (void) -{ - __asm__ ("mov %0, %%g1\n\t" - "ta 0x6d\n\t" - : /* no outputs */ - : "i" (__NR_rt_sigreturn)); -} diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigreturn_stub.S b/sysdeps/unix/sysv/linux/sparc/sparc64/sigreturn_stub.S new file mode 100644 index 000000000..add476683 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigreturn_stub.S @@ -0,0 +1,29 @@ +/* Sigreturn stub function used on sa_restore field. + Copyright (C) 2020 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 + . */ + +#include + +/* This function must not change the register window or the stack + pointer [1]. + + [1] https://lkml.org/lkml/2016/5/27/465 */ + +ENTRY (__rt_sigreturn_stub) + mov __NR_rt_sigreturn, %g1 + ta 0x6d +END (__rt_sigreturn_stub) diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list index 36e087d8f..3d8981400 100644 --- a/sysdeps/unix/sysv/linux/syscall-names.list +++ b/sysdeps/unix/sysv/linux/syscall-names.list @@ -21,8 +21,8 @@ # This file can list all potential system calls. The names are only # used if the installed kernel headers also provide them. -# The list of system calls is current as of Linux 5.4. -kernel 5.4 +# The list of system calls is current as of Linux 5.5. +kernel 5.5 FAST_atomic_update FAST_cmpxchg diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 5f1352ad4..52e6dafc8 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -28,25 +28,24 @@ inotify_add_watch EXTRA inotify_add_watch i:isi inotify_add_watch inotify_init EXTRA inotify_init i: inotify_init inotify_init1 EXTRA inotify_init1 i:I inotify_init1 inotify_rm_watch EXTRA inotify_rm_watch i:ii inotify_rm_watch -ioperm - ioperm i:iii ioperm +ioperm - ioperm i:UUi ioperm iopl - iopl i:i iopl klogctl EXTRA syslog i:isi klogctl lchown - lchown i:sii __lchown lchown -mincore - mincore i:anV mincore -mlock - mlock i:bn mlock +mincore - mincore i:aUV mincore +mlock - mlock i:bU mlock mlockall - mlockall i:i mlockall -mount EXTRA mount i:sssip __mount mount -mremap EXTRA mremap b:ainip __mremap mremap -munlock - munlock i:ai munlock +mount EXTRA mount i:sssUp __mount mount +mremap EXTRA mremap b:aUUip __mremap mremap +munlock - munlock i:aU munlock munlockall - munlockall i: munlockall nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28 pipe - pipe i:f __pipe pipe pipe2 - pipe2 i:fi __pipe2 pipe2 pivot_root EXTRA pivot_root i:ss pivot_root -prctl EXTRA prctl i:iiiii __prctl prctl query_module EXTRA query_module i:sipip __compat_query_module query_module@GLIBC_2.0:GLIBC_2.23 quotactl EXTRA quotactl i:isip quotactl -remap_file_pages - remap_file_pages i:piiii __remap_file_pages remap_file_pages +remap_file_pages - remap_file_pages i:pUiUi __remap_file_pages remap_file_pages sched_getp - sched_getparam i:ip __sched_getparam sched_getparam sched_gets - sched_getscheduler i:i __sched_getscheduler sched_getscheduler sched_primax - sched_get_priority_max i:i __sched_get_priority_max sched_get_priority_max @@ -55,8 +54,8 @@ sched_rr_gi - sched_rr_get_interval i:ip __sched_rr_get_interval sched_rr_get_in sched_setp - sched_setparam i:ip __sched_setparam sched_setparam sched_sets - sched_setscheduler i:iip __sched_setscheduler sched_setscheduler sched_yield - sched_yield i: __sched_yield sched_yield -sendfile - sendfile i:iipi sendfile -sendfile64 - sendfile64 i:iipi sendfile64 +sendfile - sendfile i:iipU sendfile +sendfile64 - sendfile64 i:iipU sendfile64 setfsgid EXTRA setfsgid i:i setfsgid setfsuid EXTRA setfsuid i:i setfsuid setpgid - setpgid i:ii __setpgid setpgid @@ -73,19 +72,19 @@ chown - chown i:sii __libc_chown __chown chown fchownat - fchownat i:isiii fchownat linkat - linkat i:isisi linkat mkdirat - mkdirat i:isi mkdirat -readlinkat - readlinkat i:issi readlinkat +readlinkat - readlinkat i:issU readlinkat symlinkat - symlinkat i:sis symlinkat unlinkat - unlinkat i:isi unlinkat -setxattr - setxattr i:sspii setxattr -lsetxattr - lsetxattr i:sspii lsetxattr -fsetxattr - fsetxattr i:ispii fsetxattr -getxattr - getxattr i:sspi getxattr -lgetxattr - lgetxattr i:sspi lgetxattr -fgetxattr - fgetxattr i:ispi fgetxattr -listxattr - listxattr i:ssi listxattr -llistxattr - llistxattr i:ssi llistxattr -flistxattr - flistxattr i:isi flistxattr +setxattr - setxattr i:sspUi setxattr +lsetxattr - lsetxattr i:sspUi lsetxattr +fsetxattr - fsetxattr i:ispUi fsetxattr +getxattr - getxattr i:sspU getxattr +lgetxattr - lgetxattr i:sspU lgetxattr +fgetxattr - fgetxattr i:ispU fgetxattr +listxattr - listxattr i:ssU listxattr +llistxattr - llistxattr i:ssU llistxattr +flistxattr - flistxattr i:isU flistxattr removexattr - removexattr i:ss removexattr lremovexattr - lremovexattr i:ss lremovexattr fremovexattr - fremovexattr i:is fremovexattr @@ -102,8 +101,6 @@ name_to_handle_at EXTRA name_to_handle_at i:isppi name_to_handle_at setns EXTRA setns i:ii setns -process_vm_readv EXTRA process_vm_readv i:ipipii process_vm_readv -process_vm_writev EXTRA process_vm_writev i:ipipii process_vm_writev memfd_create EXTRA memfd_create i:si memfd_create pkey_alloc EXTRA pkey_alloc i:ii pkey_alloc pkey_free EXTRA pkey_free i:i pkey_free diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index c2eb37e57..c7f740a1d 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -61,13 +61,31 @@ # define SYSCALL_ERROR_LABEL syscall_error # endif +/* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long + int arguments. */ +# define PSEUDOS_HAVE_ULONG_INDICES 1 + +# ifndef SYSCALL_ULONG_ARG_1 +# define SYSCALL_ULONG_ARG_1 0 +# define SYSCALL_ULONG_ARG_2 0 +# endif + # undef PSEUDO -# define PSEUDO(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args); \ - cmpq $-4095, %rax; \ +# if SYSCALL_ULONG_ARG_1 +# define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \ + cmpq $-4095, %rax; \ jae SYSCALL_ERROR_LABEL +# else +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, 0, 0); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL +# endif # undef PSEUDO_END # define PSEUDO_END(name) \ @@ -75,10 +93,17 @@ END (name) # undef PSEUDO_NOERRNO -# define PSEUDO_NOERRNO(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args) +# if SYSCALL_ULONG_ARG_1 +# define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2) +# else +# define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, 0, 0) +# endif # undef PSEUDO_END_NOERRNO # define PSEUDO_END_NOERRNO(name) \ @@ -87,11 +112,19 @@ # define ret_NOERRNO ret # undef PSEUDO_ERRVAL -# define PSEUDO_ERRVAL(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args); \ +# if SYSCALL_ULONG_ARG_1 +# define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \ + negq %rax +# else +# define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args, 0, 0); \ negq %rax +# endif # undef PSEUDO_END_ERRVAL # define PSEUDO_END_ERRVAL(name) \ @@ -163,8 +196,10 @@ Syscalls of more than 6 arguments are not supported. */ # undef DO_CALL -# define DO_CALL(syscall_name, args) \ +# define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \ DOARGS_##args \ + ZERO_EXTEND_##ulong_arg_1 \ + ZERO_EXTEND_##ulong_arg_2 \ movl $SYS_ify (syscall_name), %eax; \ syscall; @@ -176,6 +211,14 @@ # define DOARGS_5 DOARGS_4 # define DOARGS_6 DOARGS_5 +# define ZERO_EXTEND_0 /* nothing */ +# define ZERO_EXTEND_1 /* nothing */ +# define ZERO_EXTEND_2 /* nothing */ +# define ZERO_EXTEND_3 /* nothing */ +# define ZERO_EXTEND_4 /* nothing */ +# define ZERO_EXTEND_5 /* nothing */ +# define ZERO_EXTEND_6 /* nothing */ + #else /* !__ASSEMBLER__ */ /* Define a macro which expands inline into the wrapper code for a system call. */ @@ -210,12 +253,15 @@ /* Registers clobbered by syscall. */ # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx" -/* Create a variable 'name' based on type 'X' to avoid explicit types. - This is mainly used set use 64-bits arguments in x32. */ -#define TYPEFY(X, name) __typeof__ ((X) - (X)) name -/* Explicit cast the argument to avoid integer from pointer warning on - x32. */ -#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) +/* NB: This also works when X is an array. For an array X, type of + (X) - (X) is ptrdiff_t, which is signed, since size of ptrdiff_t + == size of pointer, cast is a NOP. */ +#define TYPEFY1(X) __typeof__ ((X) - (X)) +/* Explicit cast the argument. */ +#define ARGIFY(X) ((TYPEFY1 (X)) (X)) +/* Create a variable 'name' based on type of variable 'X' to avoid + explicit types. */ +#define TYPEFY(X, name) __typeof__ (ARGIFY (X)) name #undef INTERNAL_SYSCALL #define INTERNAL_SYSCALL(name, err, nr, args...) \ diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h index 5bf9eed80..62e6f8fe1 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h @@ -26,4 +26,39 @@ #undef LO_HI_LONG #define LO_HI_LONG(val) (val) +#ifdef __ASSEMBLER__ +/* Zero-extend 32-bit unsigned long int arguments to 64 bits. */ +# undef ZERO_EXTEND_1 +# define ZERO_EXTEND_1 movl %edi, %edi; +# undef ZERO_EXTEND_2 +# define ZERO_EXTEND_2 movl %esi, %esi; +# undef ZERO_EXTEND_3 +# define ZERO_EXTEND_3 movl %edx, %edx; +# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4 +# undef DOARGS_4 +# define DOARGS_4 movl %ecx, %r10d; +# else +# undef ZERO_EXTEND_4 +# define ZERO_EXTEND_4 movl %r10d, %r10d; +# endif +# undef ZERO_EXTEND_5 +# define ZERO_EXTEND_5 movl %r8d, %r8d; +# undef ZERO_EXTEND_6 +# define ZERO_EXTEND_6 movl %r9d, %r9d; +#else /* !__ASSEMBLER__ */ +# undef ARGIFY +/* Enforce zero-extension for pointers and array system call arguments. + For integer types, extend to int64_t (the full register) using a + regular cast, resulting in zero or sign extension based on the + signedness of the original type. */ +# define ARGIFY(X) \ + ({ \ + _Pragma ("GCC diagnostic push"); \ + _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ + (__builtin_classify_type (X) == 5 \ + ? (uintptr_t) (X) : (int64_t) (X)); \ + _Pragma ("GCC diagnostic pop"); \ + }) +#endif /* __ASSEMBLER__ */ + #endif /* linux/x86_64/x32/sysdep.h */ diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile index 95182a508..a5112ef36 100644 --- a/sysdeps/x86/Makefile +++ b/sysdeps/x86/Makefile @@ -12,6 +12,12 @@ endif ifeq ($(subdir),setjmp) gen-as-const-headers += jmp_buf-ssp.sym sysdep_routines += __longjmp_cancel +ifneq ($(enable-cet),no) +ifneq ($(have-tunables),no) +tests += tst-setjmp-cet +tst-setjmp-cet-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on +endif +endif endif ifeq ($(enable-cet),yes) diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c index e3e8ef27b..39c13b719 100644 --- a/sysdeps/x86/cacheinfo.c +++ b/sysdeps/x86/cacheinfo.c @@ -722,7 +722,7 @@ intel_bug_no_cache_info: threads = 1 << ((ecx >> 12) & 0x0f); } - if (threads == 0) + if (threads == 0 || cpu_features->basic.family >= 0x17) { /* If APIC ID width is not available, use logical processor count. */ @@ -737,8 +737,22 @@ intel_bug_no_cache_info: if (threads > 0) shared /= threads; - /* Account for exclusive L2 and L3 caches. */ - shared += core; + /* Get shared cache per ccx for Zen architectures. */ + if (cpu_features->basic.family >= 0x17) + { + unsigned int eax; + + /* Get number of threads share the L3 cache in CCX. */ + __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx); + + unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1; + shared *= threads_per_ccx; + } + else + { + /* Account for exclusive L2 and L3 caches. */ + shared += core; + } } #ifndef DISABLE_PREFETCHW @@ -778,14 +792,20 @@ intel_bug_no_cache_info: __x86_shared_cache_size = shared; } - /* The large memcpy micro benchmark in glibc shows that 6 times of - shared cache size is the approximate value above which non-temporal - store becomes faster on a 8-core processor. This is the 3/4 of the - total shared cache size. */ + /* The default setting for the non_temporal threshold is 3/4 of one + thread's share of the chip's cache. For most Intel and AMD processors + with an initial release date between 2017 and 2020, a thread's typical + share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4 + threshold leaves 125 KBytes to 500 KBytes of the thread's data + in cache after a maximum temporal copy, which will maintain + in cache a reasonable portion of the thread's stack and other + active data. If the threshold is set higher than one thread's + share of the cache, it has a substantial risk of negatively + impacting the performance of other threads running on the chip. */ __x86_shared_non_temporal_threshold = (cpu_features->non_temporal_threshold != 0 ? cpu_features->non_temporal_threshold - : __x86_shared_cache_size * threads * 3 / 4); + : __x86_shared_cache_size * 3 / 4); } #endif diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c index ca3b5849b..8ffaf94a0 100644 --- a/sysdeps/x86/dl-cet.c +++ b/sysdeps/x86/dl-cet.c @@ -105,7 +105,11 @@ dl_cet_check (struct link_map *m, const char *program) /* No legacy object check if both IBT and SHSTK are always on. */ if (enable_ibt_type == CET_ALWAYS_ON && enable_shstk_type == CET_ALWAYS_ON) - return; + { + THREAD_SETMEM (THREAD_SELF, header.feature_1, + GL(dl_x86_feature_1)[0]); + return; + } /* Check if IBT is enabled by kernel. */ bool ibt_enabled diff --git a/sysdeps/x86/tst-setjmp-cet.c b/sysdeps/x86/tst-setjmp-cet.c new file mode 100644 index 000000000..42c795d2a --- /dev/null +++ b/sysdeps/x86/tst-setjmp-cet.c @@ -0,0 +1 @@ +#include diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure old mode 100644 new mode 100755 index 84f82c240..fc1840e23 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -107,39 +107,6 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi -if test "$static_pie" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 -$as_echo_n "checking for linker static PIE support... " >&6; } -if ${libc_cv_ld_static_pie+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat > conftest.s <<\EOF - .text - .global _start - .weak foo -_start: - leaq foo(%rip), %rax -EOF - libc_cv_pie_option="-Wl,-pie" - if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - libc_cv_ld_static_pie=yes - else - libc_cv_ld_static_pie=no - fi -rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 -$as_echo "$libc_cv_ld_static_pie" >&6; } - if test "$libc_cv_ld_static_pie" != yes; then - as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 - fi -fi - $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index cdaba0c07..611a7d9ba 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -53,31 +53,6 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi -dnl Check if linker supports static PIE with the fix for -dnl -dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 -dnl -if test "$static_pie" = yes; then - AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl -cat > conftest.s <<\EOF - .text - .global _start - .weak foo -_start: - leaq foo(%rip), %rax -EOF - libc_cv_pie_option="-Wl,-pie" - if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then - libc_cv_ld_static_pie=yes - else - libc_cv_ld_static_pie=no - fi -rm -f conftest*]) - if test "$libc_cv_ld_static_pie" != yes; then - AC_MSG_ERROR([linker support for static PIE needed]) - fi -fi - dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 8e9baffeb..74029871d 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -315,16 +315,22 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, { # ifndef RTLD_BOOTSTRAP if (sym_map != map - && sym_map->l_type != lt_executable && !sym_map->l_relocated) { const char *strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ + if (sym_map->l_type == lt_executable) + _dl_fatal_printf ("\ +%s: IFUNC symbol '%s' referenced in '%s' is defined in the executable \ +and creates an unsatisfiable circular dependency.\n", + RTLD_PROGNAME, strtab + refsym->st_name, + map->l_name); + else + _dl_error_printf ("\ %s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", - RTLD_PROGNAME, map->l_name, - sym_map->l_name, - strtab + refsym->st_name); + RTLD_PROGNAME, map->l_name, + sym_map->l_name, + strtab + refsym->st_name); } # endif value = ((ElfW(Addr) (*) (void)) value) (); diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S index c763b7d87..06f70eb1b 100644 --- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S @@ -67,6 +67,13 @@ # define REP_MOVSB_THRESHOLD (2048 * (VEC_SIZE / 16)) #endif +/* Avoid short distance rep movsb only with non-SSE vector. */ +#ifndef AVOID_SHORT_DISTANCE_REP_MOVSB +# define AVOID_SHORT_DISTANCE_REP_MOVSB (VEC_SIZE > 16) +#else +# define AVOID_SHORT_DISTANCE_REP_MOVSB 0 +#endif + #ifndef PREFETCH # define PREFETCH(addr) prefetcht0 addr #endif @@ -244,7 +251,7 @@ L(return): ret L(movsb): - cmpq __x86_shared_non_temporal_threshold(%rip), %rdx + cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP jae L(more_8x_vec) cmpq %rsi, %rdi jb 1f @@ -257,7 +264,21 @@ L(movsb): # error Unsupported REP_MOVSB_THRESHOLD and VEC_SIZE! # endif jb L(more_8x_vec_backward) +# if AVOID_SHORT_DISTANCE_REP_MOVSB + movq %rdi, %rcx + subq %rsi, %rcx + jmp 2f +# endif 1: +# if AVOID_SHORT_DISTANCE_REP_MOVSB + movq %rsi, %rcx + subq %rdi, %rcx +2: +/* Avoid "rep movsb" if RCX, the distance between source and destination, + is N*4GB + [1..63] with N >= 0. */ + cmpl $63, %ecx + jbe L(more_2x_vec) /* Avoid "rep movsb" if ECX <= 63. */ +# endif mov %RDX_LP, %RCX_LP rep movsb L(nop): @@ -402,7 +423,7 @@ L(more_8x_vec): addq %r8, %rdx #if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) /* Check non-temporal store threshold. */ - cmpq __x86_shared_non_temporal_threshold(%rip), %rdx + cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP ja L(large_forward) #endif L(loop_4x_vec_forward): @@ -454,7 +475,7 @@ L(more_8x_vec_backward): subq %r8, %rdx #if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) /* Check non-temporal store threshold. */ - cmpq __x86_shared_non_temporal_threshold(%rip), %rdx + cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP ja L(large_backward) #endif L(loop_4x_vec_backward): diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S index 48d03a9f4..ee82fa3e1 100644 --- a/sysdeps/x86_64/multiarch/strcmp-avx2.S +++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S @@ -591,7 +591,14 @@ L(loop_cross_page_2_vec): movl $(PAGE_SIZE / (VEC_SIZE * 4) - 1), %esi testq %rdi, %rdi +# ifdef USE_AS_STRNCMP + /* At this point, if %rdi value is 0, it already tested + VEC_SIZE*4+%r10 byte starting from %rax. This label + checks whether strncmp maximum offset reached or not. */ + je L(string_nbyte_offset_check) +# else je L(back_to_loop) +# endif tzcntq %rdi, %rcx addq %r10, %rcx /* Adjust for number of bytes skipped. */ @@ -627,6 +634,14 @@ L(loop_cross_page_2_vec): VZEROUPPER ret +# ifdef USE_AS_STRNCMP +L(string_nbyte_offset_check): + leaq (VEC_SIZE * 4)(%r10), %r10 + cmpq %r10, %r11 + jbe L(zero) + jmp L(back_to_loop) +# endif + .p2align 4 L(cross_page_loop): /* Check one byte/dword at a time. */ -- 2.30.2