eee78a9dd5
CVE-2017-1000366 and CVE-2015-5180.
14966 lines
488 KiB
Diff
14966 lines
488 KiB
Diff
diff --git a/ChangeLog b/ChangeLog
|
||
index c44c926094..7b8c817b68 100644
|
||
--- a/ChangeLog
|
||
+++ b/ChangeLog
|
||
@@ -1,3 +1,553 @@
|
||
+2017-06-19 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ * elf/rtld.c (audit_list_string): New variable.
|
||
+ (audit_list): Update comment.
|
||
+ (struct audit_list_iter): Define.
|
||
+ (audit_list_iter_init, audit_list_iter_next): New function.
|
||
+ (dl_main): Use struct audit_list_iter to process audit modules.
|
||
+ (process_dl_audit): Call dso_name_valid_for_suid.
|
||
+ (process_envvars): Set audit_list_string instead of calling
|
||
+ process_dl_audit.
|
||
+
|
||
+2017-06-19 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
|
||
+ (dso_name_valid_for_suid): New function.
|
||
+ (handle_ld_preload): Likewise.
|
||
+ (dl_main): Call it. Remove alloca.
|
||
+
|
||
+2017-06-19 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #21624]
|
||
+ CVE-2017-1000366
|
||
+ * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for
|
||
+ __libc_enable_secure.
|
||
+
|
||
+2017-02-01 Andreas Schwab <schwab@linux-m68k.org>
|
||
+
|
||
+ * sysdeps/m68k/m680x0/m68020/atomic-machine.h
|
||
+ (__arch_compare_and_exchange_val_64_acq, atomic_exchange_acq)
|
||
+ (atomic_exchange_and_add, atomic_add): Add casts to 64 bit asm
|
||
+ operands.
|
||
+
|
||
+2017-05-12 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #21386]
|
||
+ * sysdeps/nptl/fork.c (__libc_fork): Remove assertions on the
|
||
+ parent PID. The assertion in the child is incorrect with PID
|
||
+ namespaces.
|
||
+
|
||
+2017-06-07 Arjun Shankar <arjun.is@lostca.se>
|
||
+
|
||
+ * sysdeps/unix/sysv/linux/tst-clone2.c: Do not
|
||
+ include test-skeleton.c.
|
||
+ Include support/check.h and support/test-driver.c.
|
||
+
|
||
+2016-11-24 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||
+
|
||
+ * sysdeps/nptl/fork.c (__libc_fork): Remove pid cache setting.
|
||
+ * nptl/allocatestack.c (allocate_stack): Likewise.
|
||
+ (__reclaim_stacks): Likewise.
|
||
+ (setxid_signal_thread): Obtain pid through syscall.
|
||
+ * nptl/nptl-init.c (sigcancel_handler): Likewise.
|
||
+ (sighandle_setxid): Likewise.
|
||
+ * nptl/pthread_cancel.c (pthread_cancel): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/pthread_sigqueue.c (pthread_sigqueue):
|
||
+ Likewise.
|
||
+ * sysdeps/unix/sysv/linux/createthread.c (create_thread): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/raise.c (raise): Remove old behaviour
|
||
+ comment.
|
||
+ * sysdeps/unix/sysv/linux/getpid.c: Remove file.
|
||
+ * nptl/descr.h (struct pthread): Change comment about pid value.
|
||
+ * nptl/pthread_getattr_np.c (pthread_getattr_np): Remove thread
|
||
+ pid assert.
|
||
+ * sysdeps/unix/sysv/linux/pthread-pids.h (__pthread_initialize_pids):
|
||
+ Do not set pid value.
|
||
+ * nptl_db/td_ta_thr_iter.c (iterate_thread_list): Remove thread
|
||
+ pid cache check.
|
||
+ * nptl_db/td_thr_validate.c (td_thr_validate): Likewise.
|
||
+ * sysdeps/aarch64/nptl/tcb-offsets.sym: Remove pid offset.
|
||
+ * sysdeps/alpha/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/arm/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/hppa/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/i386/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/ia64/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/m68k/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/microblaze/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/mips/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/nios2/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/powerpc/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/s390/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/sh/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/sparc/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/tile/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/x86_64/nptl/tcb-offsets.sym: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/aarch64/clone.S: Remove pid and tid caching.
|
||
+ * sysdeps/unix/sysv/linux/alpha/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/arm/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/hppa/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/i386/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/ia64/clone2.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/mips/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/nios2/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sh/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/tile/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/x86_64/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/aarch64/vfork.S: Remove pid set and reset.
|
||
+ * sysdeps/unix/sysv/linux/alpha/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/arm/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/i386/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/ia64/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/m68k/clone.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/m68k/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/mips/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/nios2/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sh/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/tile/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/x86_64/vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/hppa/pt-vfork.S: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/tst-clone2.c (f): Remove direct pthread
|
||
+ struct access.
|
||
+ (clone_test): Remove function.
|
||
+ (do_test): Rewrite to take in consideration pid is not cached anymore.
|
||
+
|
||
+2016-09-26 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||
+
|
||
+ * sysdeps/unix/sysdep.h (__INTERNAL_SYSCALL0): New macro.
|
||
+ (__INTERNAL_SYSCALL1): Likewise.
|
||
+ (__INTERNAL_SYSCALL2): Likewise.
|
||
+ (__INTERNAL_SYSCALL3): Likewise.
|
||
+ (__INTERNAL_SYSCALL4): Likewise.
|
||
+ (__INTERNAL_SYSCALL5): Likewise.
|
||
+ (__INTERNAL_SYSCALL6): Likewise.
|
||
+ (__INTERNAL_SYSCALL7): Likewise.
|
||
+ (__INTERNAL_SYSCALL_NARGS_X): Likewise.
|
||
+ (__INTERNAL_SYSCALL_NARGS): Likewise.
|
||
+ (__INTERNAL_SYSCALL_DISP): Likewise.
|
||
+ (INTERNAL_SYSCALL_CALL): Likewise.
|
||
+ (__SYSCALL0): Rename to __INLINE_SYSCALL0.
|
||
+ (__SYSCALL1): Rename to __INLINE_SYSCALL1.
|
||
+ (__SYSCALL2): Rename to __INLINE_SYSCALL2.
|
||
+ (__SYSCALL3): Rename to __INLINE_SYSCALL3.
|
||
+ (__SYSCALL4): Rename to __INLINE_SYSCALL4.
|
||
+ (__SYSCALL5): Rename to __INLINE_SYSCALL5.
|
||
+ (__SYSCALL6): Rename to __INLINE_SYSCALL6.
|
||
+ (__SYSCALL7): Rename to __INLINE_SYSCALL7.
|
||
+ (__SYSCALL_NARGS_X): Rename to __INLINE_SYSCALL_NARGS_X.
|
||
+ (__SYSCALL_NARGS): Rename to __INLINE_SYSCALL_NARGS.
|
||
+ (__SYSCALL_DISP): Rename to __INLINE_SYSCALL_DISP.
|
||
+ (__SYSCALL_CALL): Rename to INLINE_SYSCALL_CALL.
|
||
+ (SYSCALL_CANCEL): Replace __SYSCALL_CALL with INLINE_SYSCALL_CALL.
|
||
+
|
||
+2017-04-28 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ [BZ #21396]
|
||
+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set
|
||
+ Prefer_No_AVX512 if AVX512ER isn't available.
|
||
+ * sysdeps/x86/cpu-features.h (bit_arch_Prefer_No_AVX512): New.
|
||
+ (index_arch_Prefer_No_AVX512): Likewise.
|
||
+ * sysdeps/x86_64/multiarch/memcpy.S (__new_memcpy): Don't use
|
||
+ AVX512 version if Prefer_No_AVX512 is set.
|
||
+ * sysdeps/x86_64/multiarch/memcpy_chk.S (__memcpy_chk):
|
||
+ Likewise.
|
||
+ * sysdeps/x86_64/multiarch/memmove.S (__libc_memmove): Likewise.
|
||
+ * sysdeps/x86_64/multiarch/memmove_chk.S (__memmove_chk):
|
||
+ Likewise.
|
||
+ * sysdeps/x86_64/multiarch/mempcpy.S (__mempcpy): Likewise.
|
||
+ * sysdeps/x86_64/multiarch/mempcpy_chk.S (__mempcpy_chk):
|
||
+ Likewise.
|
||
+ * sysdeps/x86_64/multiarch/memset.S (memset): Likewise.
|
||
+ * sysdeps/x86_64/multiarch/memset_chk.S (__memset_chk):
|
||
+ Likewise.
|
||
+
|
||
+2017-04-28 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set
|
||
+ Prefer_No_VZEROUPPER if AVX512ER is available.
|
||
+ * sysdeps/x86/cpu-features.h
|
||
+ (bit_cpu_AVX512PF): New.
|
||
+ (bit_cpu_AVX512ER): Likewise.
|
||
+ (bit_cpu_AVX512CD): Likewise.
|
||
+ (bit_cpu_AVX512BW): Likewise.
|
||
+ (bit_cpu_AVX512VL): Likewise.
|
||
+ (index_cpu_AVX512PF): Likewise.
|
||
+ (index_cpu_AVX512ER): Likewise.
|
||
+ (index_cpu_AVX512CD): Likewise.
|
||
+ (index_cpu_AVX512BW): Likewise.
|
||
+ (index_cpu_AVX512VL): Likewise.
|
||
+ (reg_AVX512PF): Likewise.
|
||
+ (reg_AVX512ER): Likewise.
|
||
+ (reg_AVX512CD): Likewise.
|
||
+ (reg_AVX512BW): Likewise.
|
||
+ (reg_AVX512VL): Likewise.
|
||
+
|
||
+2017-01-05 Joseph Myers <joseph@codesourcery.com>
|
||
+
|
||
+ [BZ #21026]
|
||
+ * sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
|
||
+ (readahead): New syscall entry.
|
||
+
|
||
+2017-04-07 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ [BZ #21258]
|
||
+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve_opt):
|
||
+ Define only if _dl_runtime_resolve is defined to
|
||
+ _dl_runtime_resolve_sse_vex.
|
||
+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_opt):
|
||
+ Fallthrough to _dl_runtime_resolve_sse_vex.
|
||
+
|
||
+2017-04-03 Mike Frysinger <vapier@gentoo.org>
|
||
+
|
||
+ [BZ #21253]
|
||
+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Increase argv_size
|
||
+ slack space by 32KiB.
|
||
+
|
||
+2017-03-31 Slava Barinov <v.barinov@samsung.com>
|
||
+
|
||
+ [BZ #21289]
|
||
+ * io/fts.h (fts_set): Replace __REDIRECT with __REDIRECT_NTH.
|
||
+
|
||
+2017-03-20 Mike Frysinger <vapier@gentoo.org>
|
||
+
|
||
+ [BZ #21275]
|
||
+ * sysdeps/unix/sysv/linux/spawni.c [__ia64__] (CLONE): Rename
|
||
+ __stack to __stackbase.
|
||
+ (STACK): Invert _STACK_GROWS_DOWN and _STACK_GROWS_UP order of
|
||
+ checks so we can include defined(__ia64__) first.
|
||
+
|
||
+2017-03-15 John David Anglin <danglin@gcc.gnu.org>
|
||
+
|
||
+ * sysdeps/hppa/dl-machine.h (DL_STACK_END): Define.
|
||
+ (RTLD_START): Don't record stack end address in _dl_start_user.
|
||
+
|
||
+2017-01-30 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ [BZ #21081]
|
||
+ * sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
|
||
+ (L(stosb)): Add VZEROUPPER before ret.
|
||
+
|
||
+2016-11-28 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ [BZ #20750]
|
||
+ * sysdeps/x86_64/sysdep.h (JUMPTARGET): Check SHARED instead
|
||
+ of PIC.
|
||
+
|
||
+2016-12-31 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #18784]
|
||
+ CVE-2015-5180
|
||
+ * include/arpa/nameser_compat.h (T_QUERY_A_AND_AAAA): Rename from
|
||
+ T_UNSPEC. Adjust value.
|
||
+ * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Use it.
|
||
+ * resolv/res_query.c (__libc_res_nquery): Likewise.
|
||
+ * resolv/res_mkquery.c (res_nmkquery): Check for out-of-range
|
||
+ QTYPEs.
|
||
+ * resolv/tst-resolv-qtypes.c: New file.
|
||
+ * resolv/Makefile (xtests): Add tst-resolv-qtypes.
|
||
+ (tst-resolv-qtypes): Link against libresolv and libpthread.
|
||
+
|
||
+2017-02-02 Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||
+
|
||
+ * sysdeps/generic/unsecvars.h: Add GLIBC_TUNABLES.
|
||
+
|
||
+2017-01-23 Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>
|
||
+ Steven Munroe <sjmunroe@us.ibm.com>
|
||
+ Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||
+
|
||
+ [BZ #20822]
|
||
+ * sysdeps/unix/sysv/linux/powerpc/elision-lock.c
|
||
+ (__lll_lock_elision): Access adapt_count via C11 atomics.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
|
||
+ (__lll_trylock_elision): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
|
||
+ (__lll_unlock_elision): Update adapt_count variable inside the
|
||
+ critical section using C11 atomics.
|
||
+
|
||
+2016-12-24 Carlos O'Donell <carlos@redhat.com>
|
||
+
|
||
+ [BZ #11941]
|
||
+ * elf/dl-close.c (_dl_close): Take dl_load_lock to examine map.
|
||
+ Remove assert (map->l_init_called); if DF_1_NODELETE is set.
|
||
+ * elf/Makefile [ifeq (yes,$(build-shared))] (tests): Add
|
||
+ tst-nodelete-dlclose.
|
||
+ (modules-names): Add tst-nodelete-dlclose-dso and
|
||
+ tst-nodelete-dlclose-plugin.
|
||
+ ($(objpfx)tst-nodelete-dlclose-dso.so): Define.
|
||
+ ($(objpfx)tst-nodelete-dlclose-plugin.so): Define.
|
||
+ ($(objpfx)tst-nodelete-dlclose): Define.
|
||
+ ($(objpfx)tst-nodelete-dlclose.out): Define.
|
||
+
|
||
+2016-08-02 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+2016-08-02 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+ * sysdeps/alpha/fpu/s_ceil.c (__ceil): Add argument with itself
|
||
+ when it is a NaN.
|
||
+ [_IEEE_FP_INEXACT] Remove.
|
||
+ * sysdeps/alpha/fpu/s_ceilf.c (__ceilf): Likewise.
|
||
+ * sysdeps/alpha/fpu/s_floor.c (__floor): Add argument with itself
|
||
+ when it is a NaN.
|
||
+ [_IEEE_FP_INEXACT] Remove.
|
||
+ * sysdeps/alpha/fpu/s_floorf.c (__floorf): Likewise.
|
||
+ * sysdeps/alpha/fpu/s_rint.c (__rint): Add argument with itself
|
||
+ when it is a NaN.
|
||
+ * sysdeps/alpha/fpu/s_rintf.c (__rintf): Likewise.
|
||
+ * sysdeps/alpha/fpu/s_trunc.c (__trunc): Return the input value
|
||
+ when its absolute value is greater than 0x1.0p52.
|
||
+ [_IEEE_FP_INEXACT] Remove.
|
||
+ * sysdeps/alpha/fpu/s_truncf.c (__truncf): Return the input value
|
||
+ when its absolute value is greater than 0x1.0p23.
|
||
+ [_IEEE_FP_INEXACT] Remove.
|
||
+
|
||
+2016-11-30 H.J. Lu <hongjiu.lu@intel.com>
|
||
+
|
||
+ [BZ #20495]
|
||
+ [BZ #20508]
|
||
+ * sysdeps/x86/cpu-features.c (init_cpu_features): For Intel
|
||
+ processors, set Use_dl_runtime_resolve_slow and set
|
||
+ Use_dl_runtime_resolve_opt if XGETBV suports ECX == 1.
|
||
+ * sysdeps/x86/cpu-features.h (bit_arch_Use_dl_runtime_resolve_opt):
|
||
+ New.
|
||
+ (bit_arch_Use_dl_runtime_resolve_slow): Likewise.
|
||
+ (index_arch_Use_dl_runtime_resolve_opt): Likewise.
|
||
+ (index_arch_Use_dl_runtime_resolve_slow): Likewise.
|
||
+ * sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup): Use
|
||
+ _dl_runtime_resolve_avx512_opt and _dl_runtime_resolve_avx_opt
|
||
+ if Use_dl_runtime_resolve_opt is set. Use
|
||
+ _dl_runtime_resolve_slow if Use_dl_runtime_resolve_slow is set.
|
||
+ * sysdeps/x86_64/dl-trampoline.S: Include <cpu-features.h>.
|
||
+ (_dl_runtime_resolve_opt): New. Defined for AVX and AVX512.
|
||
+ (_dl_runtime_resolve): Add one for _dl_runtime_resolve_sse_vex.
|
||
+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_avx_slow):
|
||
+ New.
|
||
+ (_dl_runtime_resolve_opt): Likewise.
|
||
+ (_dl_runtime_profile): Define only if _dl_runtime_profile is
|
||
+ defined.
|
||
+
|
||
+2016-11-24 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+ * sysdeps/x86_64/memcpy_chk.S (__memcpy_chk): Check for SHARED
|
||
+ instead of PIC.
|
||
+
|
||
+2016-11-23 Matthew Fortune <Matthew.Fortune@imgtec.com>
|
||
+ Maciej W. Rozycki <macro@imgtec.com>
|
||
+
|
||
+ * sysdeps/mips/mips32/crti.S (_init): Add `.insn' pseudo-op at
|
||
+ `.Lno_weak_fn' label.
|
||
+ * sysdeps/mips/mips64/n32/crti.S (_init): Likewise.
|
||
+ * sysdeps/mips/mips64/n64/crti.S (_init): Likewise.
|
||
+
|
||
+2016-11-22 Adhemerval Zanella <adhemerva.zanella@linaro.org>
|
||
+
|
||
+ [BZ #20847]
|
||
+ * posix/execvpe.c (maybe_script_execute): Remove write past allocated
|
||
+ array bounds.
|
||
+ (__execvpe): Likewise.
|
||
+
|
||
+2016-11-15 Denis Kaganovich <mahatma@eu.by>
|
||
+ Magnus Granberg <zorry@gentoo.org>
|
||
+ Mike Frysinger <vapier@gentoo.org>
|
||
+
|
||
+ [BZ #20662]
|
||
+ * configure.ac (libc_cv_predef_stack_protector): Also check for
|
||
+ __stack_chk_fail_local symbols.
|
||
+ * configure: Regenerated.
|
||
+
|
||
+2016-11-03 Joseph Myers <joseph@codesourcery.com>
|
||
+
|
||
+ * conform/Makefile ($(linknamespace-header-tests)): Also depend on
|
||
+ $(linknamespace-symlists-tests).
|
||
+
|
||
+2016-11-06 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+ * iconv/gconv.h (__gconv_info): Define __data element using a
|
||
+ zero-length array.
|
||
+
|
||
+2016-10-25 Joseph Myers <joseph@codesourcery.com>
|
||
+
|
||
+ * sysdeps/powerpc/powerpc32/power6/memset.S (memset): Use cmplwi
|
||
+ instead of cmpli.
|
||
+ * sysdeps/powerpc/powerpc64/power6/memset.S (memset): Use cmpldi
|
||
+ instead of cmpli.
|
||
+
|
||
+2016-10-24 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||
+
|
||
+ * sysdeps/unix/sysv/linux/pread.c (__libc_pread): Use SYSCALL_LL_PRW.
|
||
+ * sysdeps/unix/sysv/linux/pwrite.c (__libc_pwrite): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/pread64.c (__libc_pread64): Use
|
||
+ SYSCALL_LL64_PRW.
|
||
+ * sysdeps/unix/sysv/linux/pwrite64.c (__libc_pwrite64): Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sh/kernel-features.h: Define
|
||
+ __ASSUME_PRW_DUMMY_ARG.
|
||
+ * sysdeps/unix/sysv/linux/sh/pread.c: Remove file.
|
||
+ * sysdeps/unix/sysv/linux/sh/pread64.c: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sh/pwrite.c: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sh/pwrite64.c: Likewise.
|
||
+ * sysdeps/unix/sysv/linux/sysdep.h: Define SYSCALL_LL_PRW and
|
||
+ SYSCALL_LL_PRW64 based on __ASSUME_PRW_DUMMY_ARG.
|
||
+
|
||
+2016-10-05 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||
+
|
||
+ * sysdeps/powerpc/fpu/libm-test-ulps: Regenerated.
|
||
+
|
||
+2016-09-20 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||
+
|
||
+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Correctly block and unblock
|
||
+ all signals when executing the clone vfork child.
|
||
+ (SIGALL_SET): Remove macro.
|
||
+
|
||
+ * nptl/Makefile (tests): Add tst-exec5.
|
||
+ * nptl/tst-exec5.c: New file.
|
||
+ * sysdeps/unix/sysv/linux/spawni.c (__spawni): Correctly enable and disable
|
||
+ asynchronous cancellation.
|
||
+
|
||
+2016-09-19 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||
+
|
||
+ [BZ #20615]
|
||
+ * sysdeps/powerpc/powerpc32/power9/multiarch/Implies: Replace
|
||
+ fpu directory by non-fpu.
|
||
+ * sysdeps/powerpc/powerpc64/power9/fpu/Implies: Remove dependency
|
||
+ on non-fpu directory from a fpu directory.
|
||
+
|
||
+2016-09-02 Roland McGrath <roland@hack.frob.com>
|
||
+
|
||
+ * sysdeps/arm/nacl/libc.abilist: Add GLIBC_2.24 A.
|
||
+
|
||
+ * sysdeps/nacl/dup.c: Add libc_hidden_def.
|
||
+
|
||
+2016-09-02 Roland McGrath <roland@hack.frob.com>
|
||
+
|
||
+ * sysdeps/posix/wait3.c: Don't treat STAT_LOC as a union, since it's
|
||
+ not any more.
|
||
+
|
||
+2016-09-02 Roland McGrath <roland@hack.frob.com>
|
||
+
|
||
+ * sysdeps/nacl/clock.c (clock): nacl_abi_clock_t -> nacl_irt_clock_t
|
||
+
|
||
+2016-08-17 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ Reduce time to expected nptl/tst-once5 failure.
|
||
+ * nptl/tst-once5.cc (TIMEOUT): Define.
|
||
+
|
||
+2016-08-18 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #16907]
|
||
+ * argp/argp.h: Switch to __BEGIN_DECLS and __END_DECLS.
|
||
+ (__THROW, __NTH, __attribute__, __restrict): Remove definitions.
|
||
+ * argp/argp-fmtstream.h: Add __BEGIN_DECLS and __END_DECLS.
|
||
+ (__attribute__): Remove definition.
|
||
+
|
||
+2016-08-15 Andreas Schwab <schwab@suse.de>
|
||
+
|
||
+ [BZ #20435]
|
||
+ * sysdeps/unix/sysv/linux/arm/setcontext.S (__startcontext): Mark
|
||
+ as .cantunwind.
|
||
+
|
||
+2016-08-17 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #20452]
|
||
+ Avoid additional copies of objects in libc.a in static libraries.
|
||
+ * sysdeps/ia64/nptl/Makefile (libpthread-shared-only-routines):
|
||
+ Add ptw-sysdep, ptw-sigblock, ptw-sigprocmask.
|
||
+ * sysdeps/mips/Makefile (librt-shared-only-routines): Add
|
||
+ rt-sysdep.
|
||
+ * sysdeps/mips/nptl/Makefile (libpthread-shared-only-routines):
|
||
+ Add nptl-sysdep.
|
||
+ * sysdeps/s390/nptl/Makefile (libpthread-shared-only-routines):
|
||
+ Add ptw-sysdep.
|
||
+ * sysdeps/unix/alpha/Makefile (librt-shared-only-routines): Add
|
||
+ rt-sysdep.
|
||
+ * sysdeps/unix/sysv/linux/alpha/Makefile
|
||
+ (libpthread-shared-only-routines): Add ptw-sysdep,
|
||
+ ptw-sigprocmask, ptw-rt_sigaction.
|
||
+ * sysdeps/unix/sysv/linux/ia64/Makefile
|
||
+ (librt-shared-only-routines): Add rt-sysdep.
|
||
+ * sysdeps/unix/sysv/linux/i386/Makefile
|
||
+ (libpthread-shared-only-routines): Add libc-do-syscall.
|
||
+ * sysdeps/unix/sysv/linux/microblaze/Makefile
|
||
+ (libpthread-shared-only-routines): Add sysdep.
|
||
+ * sysdeps/unix/sysv/linux/powerpc/Makefile
|
||
+ (librt-shared-only-routines): Add rt-sysdep.
|
||
+ (libpthread-shared-only-routines): Add sysdep.
|
||
+ * sysdeps/unix/sysv/linux/s390/Makefile
|
||
+ (librt-shared-only-routines): Add rt-sysdep.
|
||
+ * sysdeps/unix/sysv/linux/sparc/Makefile
|
||
+ (librt-shared-only-routines): Add rt-sysdep.
|
||
+ (libpthread-shared-only-routines): Add sysdep.
|
||
+ * sysdeps/unix/sysv/linux/tile/Makefile
|
||
+ (libpthread-shared-only-routines): Likewise.
|
||
+
|
||
+2016-08-05 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/Makefile
|
||
+ [$(subdir) = math && $(have-as-vis3) = yes] (libm-sysdep_routines):
|
||
+ Remove s_fdimf-vis3, s_fdim-vis3.
|
||
+ * sysdeps/sparc/sparc32/fpu/s_fdim.S: Delete file.
|
||
+ * sysdeps/sparc/sparc32/fpu/s_fdimf.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim-vis3.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf-vis3.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/s_fdim.S: Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/s_fdimf.S: Likewise.
|
||
+ * sysdeps/sparc/sparc64/fpu/s_fdim.S: Likewise.
|
||
+ * sysdeps/sparc/sparc64/fpu/s_fdimf.S: Likewise.
|
||
+
|
||
+2016-08-02 David S. Miller <davem@davemloft.net>
|
||
+
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyint-vis3.S
|
||
+ (__nearbyint_vis3): Don't check for sNaN before float register is
|
||
+ loaded with the incoming argument.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyintf-vis3.S
|
||
+ (__nearbyintf_vis3): Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyint.S (__nearbyint):
|
||
+ Likewise.
|
||
+ * sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyintf.S (__nearbyintf):
|
||
+ Likewise.
|
||
+
|
||
+2016-08-03 Aurelien Jarno <aurelien@aurel32.net>
|
||
+
|
||
+ * sysdeps/powerpc/ifunc-sel.h (ifunc_sel): Replace beqlr instructions
|
||
+ by beq instructions jumping to the end of the function.
|
||
+ * sysdeps/powerpc/ifunc-sel.h (ifunc_sel): Add "11", "12", "cr0" to the
|
||
+ clobber list. Use "i" constraint instead of "X".
|
||
+ (ifunc_one): Add "12" to the clobber list. Use "i" constraint instead
|
||
+ of "X".
|
||
+
|
||
+2016-08-04 Carlos O'Donell <carlos@redhat.com>
|
||
+
|
||
+ * po/de.po: Update from Translation Project.
|
||
+ * po/fi.po: Likewise.
|
||
+ * po/sv.po: Likewise.
|
||
+
|
||
+2016-08-02 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ [BZ #20370]
|
||
+ * malloc/arena.c (get_free_list): Update comment. Assert that
|
||
+ arenas on the free list have no attached threads.
|
||
+ (remove_from_free_list): New function.
|
||
+ (reused_arena): Call it.
|
||
+
|
||
+2016-08-04 Florian Weimer <fweimer@redhat.com>
|
||
+
|
||
+ Use sysdep.o from libc.a in static libraries.
|
||
+ * sysdeps/unix/sysv/linux/i386/Makefile
|
||
+ (libpthread-shared-only-routines): Add sysdep.
|
||
+ (librt-shared-only-routines): Likewise.
|
||
+
|
||
2016-08-01 Carlos O'Donell <carlos@redhat.com>
|
||
|
||
* version.h (RELEASE): Set to "stable"
|
||
diff --git a/Makeconfig b/Makeconfig
|
||
index 03fd89c13e..ee379f5852 100644
|
||
--- a/Makeconfig
|
||
+++ b/Makeconfig
|
||
@@ -394,6 +394,9 @@ ifndef after-link
|
||
after-link =
|
||
endif
|
||
|
||
+# Additional libraries to link into every test.
|
||
+link-extra-libs-tests = $(libsupport)
|
||
+
|
||
# Command for linking PIE programs with the C library.
|
||
ifndef +link-pie
|
||
+link-pie-before-libc = $(CC) -pie -Wl,-O1 -nostdlib -nostartfiles -o $@ \
|
||
@@ -503,7 +506,7 @@ link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib)
|
||
link-libc-tests = $(link-libc-tests-rpath-link) \
|
||
$(link-libc-before-gnulib) $(gnulib-tests)
|
||
# This is how to find at build-time things that will be installed there.
|
||
-rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec
|
||
+rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec support
|
||
rpath-link = \
|
||
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
|
||
else
|
||
@@ -850,7 +853,7 @@ libio-include = -I$(..)libio
|
||
# List of non-library modules that we build.
|
||
built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \
|
||
libSegFault libpcprofile librpcsvc locale-programs \
|
||
- memusagestat nonlib nscd extramodules libnldbl
|
||
+ memusagestat nonlib nscd extramodules libnldbl libsupport
|
||
|
||
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
|
||
$(libof-$(<F)) \
|
||
@@ -1089,6 +1092,12 @@ libm = $(common-objpfx)math/libm.a
|
||
libmvec = $(common-objpfx)mathvec/libmvec.a
|
||
endif
|
||
|
||
+ifeq ($(build-shared),yes)
|
||
+libsupport = $(common-objpfx)support/libsupport_nonshared.a
|
||
+else
|
||
+libsupport = $(common-objpfx)support/libsupport.a
|
||
+endif
|
||
+
|
||
# These are the subdirectories containing the library source. The order
|
||
# is more or less arbitrary. The sorting step will take care of the
|
||
# dependencies.
|
||
@@ -1096,7 +1105,7 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
|
||
stdlib stdio-common libio malloc string wcsmbs time dirent \
|
||
grp pwd posix io termios resource misc socket sysvipc gmon \
|
||
gnulib iconv iconvdata wctype manual shadow gshadow po argp \
|
||
- crypt localedata timezone rt conform debug mathvec \
|
||
+ crypt localedata timezone rt conform debug mathvec support \
|
||
$(add-on-subdirs) dlfcn elf
|
||
|
||
ifndef avoid-generated
|
||
diff --git a/NEWS b/NEWS
|
||
index b0447e7169..d42af91972 100644
|
||
--- a/NEWS
|
||
+++ b/NEWS
|
||
@@ -5,6 +5,28 @@ See the end for copying conditions.
|
||
Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
|
||
using `glibc' in the "product" field.
|
||
|
||
+Version 2.24.1
|
||
+
|
||
+Security related changes:
|
||
+
|
||
+* On ARM EABI (32-bit), generating a backtrace for execution contexts which
|
||
+ have been created with makecontext could fail to terminate due to a
|
||
+ missing .cantunwind annotation. This has been observed to lead to a hang
|
||
+ (denial of service) in some Go applications compiled with gccgo. Reported
|
||
+ by Andreas Schwab. (CVE-2016-6323)
|
||
+
|
||
+* The DNS stub resolver functions would crash due to a NULL pointer
|
||
+ dereference when processing a query with a valid DNS question type which
|
||
+ was used internally in the implementation. The stub resolver now uses a
|
||
+ question type which is outside the range of valid question type values.
|
||
+ (CVE-2015-5180)
|
||
+
|
||
+The following bugs are resolved with this release:
|
||
+
|
||
+ [21289] Fix symbol redirect for fts_set
|
||
+ [21386] Assertion in fork for distinct parent PID is incorrect
|
||
+ [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
|
||
+
|
||
Version 2.24
|
||
|
||
* The minimum Linux kernel version that this version of the GNU C Library
|
||
diff --git a/Rules b/Rules
|
||
index 8306d36a07..a981965d2b 100644
|
||
--- a/Rules
|
||
+++ b/Rules
|
||
@@ -149,6 +149,7 @@ endif
|
||
|
||
ifneq "$(strip $(binaries-shared-tests))" ""
|
||
$(addprefix $(objpfx),$(binaries-shared-tests)): %: %.o \
|
||
+ $(link-extra-libs-tests) \
|
||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||
$(+link-tests)
|
||
@@ -156,6 +157,7 @@ endif
|
||
|
||
ifneq "$(strip $(binaries-pie-tests))" ""
|
||
$(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \
|
||
+ $(link-extra-libs-tests) \
|
||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||
$(+link-pie-tests)
|
||
@@ -177,6 +179,7 @@ endif
|
||
|
||
ifneq "$(strip $(binaries-static-tests))" ""
|
||
$(addprefix $(objpfx),$(binaries-static-tests)): %: %.o \
|
||
+ $(link-extra-libs-tests) \
|
||
$(sort $(filter $(common-objpfx)lib%,$(link-libc-static-tests))) \
|
||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||
$(+link-static-tests)
|
||
diff --git a/argp/argp-fmtstream.h b/argp/argp-fmtstream.h
|
||
index bdeaa54dc2..e8c5797f38 100644
|
||
--- a/argp/argp-fmtstream.h
|
||
+++ b/argp/argp-fmtstream.h
|
||
@@ -29,21 +29,6 @@
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
|
||
-#ifndef __attribute__
|
||
-/* This feature is available in gcc versions 2.5 and later. */
|
||
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || \
|
||
- defined __STRICT_ANSI__
|
||
-# define __attribute__(Spec) /* empty */
|
||
-# endif
|
||
-/* The __-protected variants of `format' and `printf' attributes
|
||
- are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || \
|
||
- defined __STRICT_ANSI__
|
||
-# define __format__ format
|
||
-# define __printf__ printf
|
||
-# endif
|
||
-#endif
|
||
-
|
||
#if defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)
|
||
/* line_wrap_stream is available, so use that. */
|
||
#define ARGP_FMTSTREAM_USE_LINEWRAP
|
||
@@ -111,6 +96,8 @@ struct argp_fmtstream
|
||
|
||
typedef struct argp_fmtstream *argp_fmtstream_t;
|
||
|
||
+__BEGIN_DECLS
|
||
+
|
||
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
|
||
written on it with LMARGIN spaces and limits them to RMARGIN columns
|
||
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
|
||
@@ -297,6 +284,8 @@ __argp_fmtstream_point (argp_fmtstream_t __fs)
|
||
|
||
#endif /* __OPTIMIZE__ */
|
||
|
||
+__END_DECLS
|
||
+
|
||
#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
|
||
|
||
#endif /* argp-fmtstream.h */
|
||
diff --git a/argp/argp.h b/argp/argp.h
|
||
index e67bbef739..7cb5a69f08 100644
|
||
--- a/argp/argp.h
|
||
+++ b/argp/argp.h
|
||
@@ -28,48 +28,12 @@
|
||
#define __need_error_t
|
||
#include <errno.h>
|
||
|
||
-#ifndef __THROW
|
||
-# define __THROW
|
||
-#endif
|
||
-#ifndef __NTH
|
||
-# define __NTH(fct) fct __THROW
|
||
-#endif
|
||
-
|
||
-#ifndef __attribute__
|
||
-/* This feature is available in gcc versions 2.5 and later. */
|
||
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || \
|
||
- defined __STRICT_ANSI__
|
||
-# define __attribute__(Spec) /* empty */
|
||
-# endif
|
||
-/* The __-protected variants of `format' and `printf' attributes
|
||
- are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || \
|
||
- defined __STRICT_ANSI__
|
||
-# define __format__ format
|
||
-# define __printf__ printf
|
||
-# endif
|
||
-#endif
|
||
-
|
||
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
|
||
- "restrict", and "configure" may have defined "restrict". */
|
||
-#ifndef __restrict
|
||
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
|
||
-# if defined restrict || 199901L <= __STDC_VERSION__
|
||
-# define __restrict restrict
|
||
-# else
|
||
-# define __restrict
|
||
-# endif
|
||
-# endif
|
||
-#endif
|
||
-
|
||
#ifndef __error_t_defined
|
||
typedef int error_t;
|
||
# define __error_t_defined
|
||
#endif
|
||
|
||
-#ifdef __cplusplus
|
||
-extern "C" {
|
||
-#endif
|
||
+__BEGIN_DECLS
|
||
|
||
/* A description of a particular option. A pointer to an array of
|
||
these is passed in the OPTIONS field of an argp structure. Each option
|
||
@@ -590,8 +554,6 @@ __NTH (__option_is_end (const struct argp_option *__opt))
|
||
# endif
|
||
#endif /* Use extern inlines. */
|
||
|
||
-#ifdef __cplusplus
|
||
-}
|
||
-#endif
|
||
+__END_DECLS
|
||
|
||
#endif /* argp.h */
|
||
diff --git a/configure b/configure
|
||
index 17625e1041..9b5a486048 100755
|
||
--- a/configure
|
||
+++ b/configure
|
||
@@ -6289,12 +6289,14 @@ echo >&5 "libc_undefs='$libc_undefs'"
|
||
# symbols (resolved by the linker), so filter out unknown symbols.
|
||
# This will fail to produce the correct result if the compiler
|
||
# defaults to -fstack-protector but this produces an undefined symbol
|
||
-# other than __stack_chk_fail. However, compilers like that have not
|
||
-# been encountered in practice.
|
||
-libc_undefs=`echo "$libc_undefs" | egrep '^(foobar|__stack_chk_fail)$'`
|
||
+# other than __stack_chk_fail or __stack_chk_fail_local. However,
|
||
+# compilers like that have not been encountered in practice.
|
||
+libc_undefs=`echo "$libc_undefs" | \
|
||
+ egrep '^(foobar|__stack_chk_fail|__stack_chk_fail_local)$'`
|
||
case "$libc_undefs" in
|
||
foobar) libc_cv_predef_stack_protector=no ;;
|
||
'__stack_chk_fail
|
||
+foobar'|'__stack_chk_fail_local
|
||
foobar') libc_cv_predef_stack_protector=yes ;;
|
||
*) as_fn_error $? "unexpected symbols in test: $libc_undefs" "$LINENO" 5 ;;
|
||
esac
|
||
diff --git a/configure.ac b/configure.ac
|
||
index 33bcd62180..8277d9f727 100644
|
||
--- a/configure.ac
|
||
+++ b/configure.ac
|
||
@@ -1626,12 +1626,14 @@ echo >&AS_MESSAGE_LOG_FD "libc_undefs='$libc_undefs'"
|
||
# symbols (resolved by the linker), so filter out unknown symbols.
|
||
# This will fail to produce the correct result if the compiler
|
||
# defaults to -fstack-protector but this produces an undefined symbol
|
||
-# other than __stack_chk_fail. However, compilers like that have not
|
||
-# been encountered in practice.
|
||
-libc_undefs=`echo "$libc_undefs" | egrep '^(foobar|__stack_chk_fail)$'`
|
||
+# other than __stack_chk_fail or __stack_chk_fail_local. However,
|
||
+# compilers like that have not been encountered in practice.
|
||
+libc_undefs=`echo "$libc_undefs" | \
|
||
+ egrep '^(foobar|__stack_chk_fail|__stack_chk_fail_local)$'`
|
||
case "$libc_undefs" in
|
||
foobar) libc_cv_predef_stack_protector=no ;;
|
||
'__stack_chk_fail
|
||
+foobar'|'__stack_chk_fail_local
|
||
foobar') libc_cv_predef_stack_protector=yes ;;
|
||
*) AC_MSG_ERROR([unexpected symbols in test: $libc_undefs]) ;;
|
||
esac],
|
||
diff --git a/conform/Makefile b/conform/Makefile
|
||
index 32a0937b06..762aac98fc 100644
|
||
--- a/conform/Makefile
|
||
+++ b/conform/Makefile
|
||
@@ -229,6 +229,7 @@ $(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
|
||
|
||
$(linknamespace-header-tests): $(objpfx)%/linknamespace.out: \
|
||
linknamespace.pl \
|
||
+ $(linknamespace-symlists-tests) \
|
||
$(linknamespace-symlist-stdlibs-tests)
|
||
(set -e; std_hdr=$*; std=$${std_hdr%%/*}; hdr=$${std_hdr#*/}; \
|
||
mkdir -p $(@D)/scratch; \
|
||
diff --git a/elf/Makefile b/elf/Makefile
|
||
index 593403c640..847a012f84 100644
|
||
--- a/elf/Makefile
|
||
+++ b/elf/Makefile
|
||
@@ -149,7 +149,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||
tst-nodelete) \
|
||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
||
- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error
|
||
+ tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error \
|
||
+ tst-nodelete-dlclose
|
||
# reldep9
|
||
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||
tests += tst-dlopen-aout
|
||
@@ -223,7 +224,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||
tst-array5dep tst-null-argv-lib \
|
||
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
|
||
tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
|
||
- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12
|
||
+ tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
|
||
+ tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin
|
||
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||
tests += tst-gnu2-tls1
|
||
modules-names += tst-gnu2-tls1mod
|
||
@@ -1267,3 +1269,12 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||
$(evaluate-test)
|
||
|
||
$(objpfx)tst-dlsym-error: $(libdl)
|
||
+
|
||
+# The application depends on the DSO, and the DSO loads the plugin.
|
||
+# The plugin also depends on the DSO. This creates the circular
|
||
+# dependency via dlopen that we're testing to make sure works.
|
||
+$(objpfx)tst-nodelete-dlclose-dso.so: $(libdl)
|
||
+$(objpfx)tst-nodelete-dlclose-plugin.so: $(objpfx)tst-nodelete-dlclose-dso.so
|
||
+$(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so
|
||
+$(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
|
||
+ $(objpfx)tst-nodelete-dlclose-plugin.so
|
||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||
index 687d7de874..9f93ab7628 100644
|
||
--- a/elf/dl-close.c
|
||
+++ b/elf/dl-close.c
|
||
@@ -805,19 +805,37 @@ _dl_close (void *_map)
|
||
{
|
||
struct link_map *map = _map;
|
||
|
||
- /* First see whether we can remove the object at all. */
|
||
+ /* We must take the lock to examine the contents of map and avoid
|
||
+ concurrent dlopens. */
|
||
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||
+
|
||
+ /* At this point we are guaranteed nobody else is touching the list of
|
||
+ loaded maps, but a concurrent dlclose might have freed our map
|
||
+ before we took the lock. There is no way to detect this (see below)
|
||
+ so we proceed assuming this isn't the case. First see whether we
|
||
+ can remove the object at all. */
|
||
if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
|
||
{
|
||
- assert (map->l_init_called);
|
||
/* Nope. Do nothing. */
|
||
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||
return;
|
||
}
|
||
|
||
+ /* At present this is an unreliable check except in the case where the
|
||
+ caller has recursively called dlclose and we are sure the link map
|
||
+ has not been freed. In a non-recursive dlclose the map itself
|
||
+ might have been freed and this access is potentially a data race
|
||
+ with whatever other use this memory might have now, or worse we
|
||
+ might silently corrupt memory if it looks enough like a link map.
|
||
+ POSIX has language in dlclose that appears to guarantee that this
|
||
+ should be a detectable case and given that dlclose should be threadsafe
|
||
+ we need this to be a reliable detection.
|
||
+ This is bug 20990. */
|
||
if (__builtin_expect (map->l_direct_opencount, 1) == 0)
|
||
- GLRO(dl_signal_error) (0, map->l_name, NULL, N_("shared object not open"));
|
||
-
|
||
- /* Acquire the lock. */
|
||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||
+ {
|
||
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||
+ _dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
|
||
+ }
|
||
|
||
_dl_close_worker (map, false);
|
||
|
||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||
index 647661ca45..302bb63620 100644
|
||
--- a/elf/rtld.c
|
||
+++ b/elf/rtld.c
|
||
@@ -99,14 +99,121 @@ uintptr_t __pointer_chk_guard_local
|
||
strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
|
||
#endif
|
||
|
||
+/* Length limits for names and paths, to protect the dynamic linker,
|
||
+ particularly when __libc_enable_secure is active. */
|
||
+#ifdef NAME_MAX
|
||
+# define SECURE_NAME_LIMIT NAME_MAX
|
||
+#else
|
||
+# define SECURE_NAME_LIMIT 255
|
||
+#endif
|
||
+#ifdef PATH_MAX
|
||
+# define SECURE_PATH_LIMIT PATH_MAX
|
||
+#else
|
||
+# define SECURE_PATH_LIMIT 1024
|
||
+#endif
|
||
+
|
||
+/* Check that AT_SECURE=0, or that the passed name does not contain
|
||
+ directories and is not overly long. Reject empty names
|
||
+ unconditionally. */
|
||
+static bool
|
||
+dso_name_valid_for_suid (const char *p)
|
||
+{
|
||
+ if (__glibc_unlikely (__libc_enable_secure))
|
||
+ {
|
||
+ /* Ignore pathnames with directories for AT_SECURE=1
|
||
+ programs, and also skip overlong names. */
|
||
+ size_t len = strlen (p);
|
||
+ if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
|
||
+ return false;
|
||
+ }
|
||
+ return *p != '\0';
|
||
+}
|
||
|
||
-/* List of auditing DSOs. */
|
||
+/* LD_AUDIT variable contents. Must be processed before the
|
||
+ audit_list below. */
|
||
+const char *audit_list_string;
|
||
+
|
||
+/* Cyclic list of auditing DSOs. audit_list->next is the first
|
||
+ element. */
|
||
static struct audit_list
|
||
{
|
||
const char *name;
|
||
struct audit_list *next;
|
||
} *audit_list;
|
||
|
||
+/* Iterator for audit_list_string followed by audit_list. */
|
||
+struct audit_list_iter
|
||
+{
|
||
+ /* Tail of audit_list_string still needing processing, or NULL. */
|
||
+ const char *audit_list_tail;
|
||
+
|
||
+ /* The list element returned in the previous iteration. NULL before
|
||
+ the first element. */
|
||
+ struct audit_list *previous;
|
||
+
|
||
+ /* Scratch buffer for returning a name which is part of
|
||
+ audit_list_string. */
|
||
+ char fname[SECURE_NAME_LIMIT];
|
||
+};
|
||
+
|
||
+/* Initialize an audit list iterator. */
|
||
+static void
|
||
+audit_list_iter_init (struct audit_list_iter *iter)
|
||
+{
|
||
+ iter->audit_list_tail = audit_list_string;
|
||
+ iter->previous = NULL;
|
||
+}
|
||
+
|
||
+/* Iterate through both audit_list_string and audit_list. */
|
||
+static const char *
|
||
+audit_list_iter_next (struct audit_list_iter *iter)
|
||
+{
|
||
+ if (iter->audit_list_tail != NULL)
|
||
+ {
|
||
+ /* First iterate over audit_list_string. */
|
||
+ while (*iter->audit_list_tail != '\0')
|
||
+ {
|
||
+ /* Split audit list at colon. */
|
||
+ size_t len = strcspn (iter->audit_list_tail, ":");
|
||
+ if (len > 0 && len < sizeof (iter->fname))
|
||
+ {
|
||
+ memcpy (iter->fname, iter->audit_list_tail, len);
|
||
+ iter->fname[len] = '\0';
|
||
+ }
|
||
+ else
|
||
+ /* Do not return this name to the caller. */
|
||
+ iter->fname[0] = '\0';
|
||
+
|
||
+ /* Skip over the substring and the following delimiter. */
|
||
+ iter->audit_list_tail += len;
|
||
+ if (*iter->audit_list_tail == ':')
|
||
+ ++iter->audit_list_tail;
|
||
+
|
||
+ /* If the name is valid, return it. */
|
||
+ if (dso_name_valid_for_suid (iter->fname))
|
||
+ return iter->fname;
|
||
+ /* Otherwise, wrap around and try the next name. */
|
||
+ }
|
||
+ /* Fall through to the procesing of audit_list. */
|
||
+ }
|
||
+
|
||
+ if (iter->previous == NULL)
|
||
+ {
|
||
+ if (audit_list == NULL)
|
||
+ /* No pre-parsed audit list. */
|
||
+ return NULL;
|
||
+ /* Start of audit list. The first list element is at
|
||
+ audit_list->next (cyclic list). */
|
||
+ iter->previous = audit_list->next;
|
||
+ return iter->previous->name;
|
||
+ }
|
||
+ if (iter->previous == audit_list)
|
||
+ /* Cyclic list wrap-around. */
|
||
+ return NULL;
|
||
+ iter->previous = iter->previous->next;
|
||
+ return iter->previous->name;
|
||
+}
|
||
+
|
||
#ifndef HAVE_INLINED_SYSCALLS
|
||
/* Set nonzero during loading and initialization of executable and
|
||
libraries, cleared before the executable's entry point runs. This
|
||
@@ -730,6 +837,42 @@ static const char *preloadlist attribute_relro;
|
||
/* Nonzero if information about versions has to be printed. */
|
||
static int version_info attribute_relro;
|
||
|
||
+/* The LD_PRELOAD environment variable gives list of libraries
|
||
+ separated by white space or colons that are loaded before the
|
||
+ executable's dependencies and prepended to the global scope list.
|
||
+ (If the binary is running setuid all elements containing a '/' are
|
||
+ ignored since it is insecure.) Return the number of preloads
|
||
+ performed. */
|
||
+unsigned int
|
||
+handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||
+{
|
||
+ unsigned int npreloads = 0;
|
||
+ const char *p = preloadlist;
|
||
+ char fname[SECURE_PATH_LIMIT];
|
||
+
|
||
+ while (*p != '\0')
|
||
+ {
|
||
+ /* Split preload list at space/colon. */
|
||
+ size_t len = strcspn (p, " :");
|
||
+ if (len > 0 && len < sizeof (fname))
|
||
+ {
|
||
+ memcpy (fname, p, len);
|
||
+ fname[len] = '\0';
|
||
+ }
|
||
+ else
|
||
+ fname[0] = '\0';
|
||
+
|
||
+ /* Skip over the substring and the following delimiter. */
|
||
+ p += len;
|
||
+ if (*p != '\0')
|
||
+ ++p;
|
||
+
|
||
+ if (dso_name_valid_for_suid (fname))
|
||
+ npreloads += do_preload (fname, main_map, "LD_PRELOAD");
|
||
+ }
|
||
+ return npreloads;
|
||
+}
|
||
+
|
||
static void
|
||
dl_main (const ElfW(Phdr) *phdr,
|
||
ElfW(Word) phnum,
|
||
@@ -1257,11 +1400,13 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||
|
||
/* If we have auditing DSOs to load, do it now. */
|
||
- if (__glibc_unlikely (audit_list != NULL))
|
||
+ bool need_security_init = true;
|
||
+ if (__glibc_unlikely (audit_list != NULL)
|
||
+ || __glibc_unlikely (audit_list_string != NULL))
|
||
{
|
||
- /* Iterate over all entries in the list. The order is important. */
|
||
struct audit_ifaces *last_audit = NULL;
|
||
- struct audit_list *al = audit_list->next;
|
||
+ struct audit_list_iter al_iter;
|
||
+ audit_list_iter_init (&al_iter);
|
||
|
||
/* Since we start using the auditing DSOs right away we need to
|
||
initialize the data structures now. */
|
||
@@ -1272,9 +1417,14 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||
use different values (especially the pointer guard) and will
|
||
fail later on. */
|
||
security_init ();
|
||
+ need_security_init = false;
|
||
|
||
- do
|
||
+ while (true)
|
||
{
|
||
+ const char *name = audit_list_iter_next (&al_iter);
|
||
+ if (name == NULL)
|
||
+ break;
|
||
+
|
||
int tls_idx = GL(dl_tls_max_dtv_idx);
|
||
|
||
/* Now it is time to determine the layout of the static TLS
|
||
@@ -1283,7 +1433,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||
no DF_STATIC_TLS bit is set. The reason is that we know
|
||
glibc will use the static model. */
|
||
struct dlmopen_args dlmargs;
|
||
- dlmargs.fname = al->name;
|
||
+ dlmargs.fname = name;
|
||
dlmargs.map = NULL;
|
||
|
||
const char *objname;
|
||
@@ -1296,7 +1446,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||
not_loaded:
|
||
_dl_error_printf ("\
|
||
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||
- al->name, err_str);
|
||
+ name, err_str);
|
||
if (malloced)
|
||
free ((char *) err_str);
|
||
}
|
||
@@ -1400,10 +1550,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||
goto not_loaded;
|
||
}
|
||
}
|
||
-
|
||
- al = al->next;
|
||
}
|
||
- while (al != audit_list->next);
|
||
|
||
/* If we have any auditing modules, announce that we already
|
||
have two objects loaded. */
|
||
@@ -1481,23 +1628,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||
|
||
if (__glibc_unlikely (preloadlist != NULL))
|
||
{
|
||
- /* The LD_PRELOAD environment variable gives list of libraries
|
||
- separated by white space or colons that are loaded before the
|
||
- executable's dependencies and prepended to the global scope
|
||
- list. If the binary is running setuid all elements
|
||
- containing a '/' are ignored since it is insecure. */
|
||
- char *list = strdupa (preloadlist);
|
||
- char *p;
|
||
-
|
||
HP_TIMING_NOW (start);
|
||
-
|
||
- /* Prevent optimizing strsep. Speed is not important here. */
|
||
- while ((p = (strsep) (&list, " :")) != NULL)
|
||
- if (p[0] != '\0'
|
||
- && (__builtin_expect (! __libc_enable_secure, 1)
|
||
- || strchr (p, '/') == NULL))
|
||
- npreloads += do_preload (p, main_map, "LD_PRELOAD");
|
||
-
|
||
+ npreloads += handle_ld_preload (preloadlist, main_map);
|
||
HP_TIMING_NOW (stop);
|
||
HP_TIMING_DIFF (diff, start, stop);
|
||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||
@@ -1682,7 +1814,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||
if (tcbp == NULL)
|
||
tcbp = init_tls ();
|
||
|
||
- if (__glibc_likely (audit_list == NULL))
|
||
+ if (__glibc_likely (need_security_init))
|
||
/* Initialize security features. But only if we have not done it
|
||
earlier. */
|
||
security_init ();
|
||
@@ -2313,9 +2445,7 @@ process_dl_audit (char *str)
|
||
char *p;
|
||
|
||
while ((p = (strsep) (&str, ":")) != NULL)
|
||
- if (p[0] != '\0'
|
||
- && (__builtin_expect (! __libc_enable_secure, 1)
|
||
- || strchr (p, '/') == NULL))
|
||
+ if (dso_name_valid_for_suid (p))
|
||
{
|
||
/* This is using the local malloc, not the system malloc. The
|
||
memory can never be freed. */
|
||
@@ -2379,7 +2509,7 @@ process_envvars (enum mode *modep)
|
||
break;
|
||
}
|
||
if (memcmp (envline, "AUDIT", 5) == 0)
|
||
- process_dl_audit (&envline[6]);
|
||
+ audit_list_string = &envline[6];
|
||
break;
|
||
|
||
case 7:
|
||
@@ -2437,7 +2567,8 @@ process_envvars (enum mode *modep)
|
||
|
||
case 12:
|
||
/* The library search path. */
|
||
- if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
|
||
+ if (!__libc_enable_secure
|
||
+ && memcmp (envline, "LIBRARY_PATH", 12) == 0)
|
||
{
|
||
library_path = &envline[13];
|
||
break;
|
||
diff --git a/elf/tst-nodelete-dlclose-dso.c b/elf/tst-nodelete-dlclose-dso.c
|
||
new file mode 100644
|
||
index 0000000000..dd930f99cc
|
||
--- /dev/null
|
||
+++ b/elf/tst-nodelete-dlclose-dso.c
|
||
@@ -0,0 +1,90 @@
|
||
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||
+ Copyright (C) 2016 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This is the primary DSO that is loaded by the appliation. This DSO
|
||
+ then loads a plugin with RTLD_NODELETE. This plugin depends on this
|
||
+ DSO. This dependency chain means that at application shutdown the
|
||
+ plugin will be destructed first. Thus by the time this DSO is
|
||
+ destructed we will be calling dlclose on an object that has already
|
||
+ been destructed. It is allowed to call dlclose in this way and
|
||
+ should not assert. */
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <dlfcn.h>
|
||
+
|
||
+/* Plugin to load. */
|
||
+static void *plugin_lib = NULL;
|
||
+/* Plugin function. */
|
||
+static void (*plugin_func) (void);
|
||
+#define LIB_PLUGIN "tst-nodelete-dlclose-plugin.so"
|
||
+
|
||
+/* This function is never called but the plugin references it.
|
||
+ We do this to avoid any future --as-needed from removing the
|
||
+ plugin's DT_NEEDED on this DSO (required for the test). */
|
||
+void
|
||
+primary_reference (void)
|
||
+{
|
||
+ printf ("INFO: Called primary_reference function.\n");
|
||
+}
|
||
+
|
||
+void
|
||
+primary (void)
|
||
+{
|
||
+ char *error;
|
||
+
|
||
+ plugin_lib = dlopen (LIB_PLUGIN, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
|
||
+ if (plugin_lib == NULL)
|
||
+ {
|
||
+ printf ("ERROR: Unable to load plugin library.\n");
|
||
+ exit (EXIT_FAILURE);
|
||
+ }
|
||
+ dlerror ();
|
||
+
|
||
+ plugin_func = (void (*) (void)) dlsym (plugin_lib, "plugin_func");
|
||
+ error = dlerror ();
|
||
+ if (error != NULL)
|
||
+ {
|
||
+ printf ("ERROR: Unable to find symbol with error \"%s\".",
|
||
+ error);
|
||
+ exit (EXIT_FAILURE);
|
||
+ }
|
||
+
|
||
+ return;
|
||
+}
|
||
+
|
||
+__attribute__ ((destructor))
|
||
+static void
|
||
+primary_dtor (void)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ printf ("INFO: Calling primary destructor.\n");
|
||
+
|
||
+ /* The destructor runs in the test driver also, which
|
||
+ hasn't called primary, in that case do nothing. */
|
||
+ if (plugin_lib == NULL)
|
||
+ return;
|
||
+
|
||
+ ret = dlclose (plugin_lib);
|
||
+ if (ret != 0)
|
||
+ {
|
||
+ printf ("ERROR: Calling dlclose failed with \"%s\"\n",
|
||
+ dlerror ());
|
||
+ exit (EXIT_FAILURE);
|
||
+ }
|
||
+}
|
||
diff --git a/elf/tst-nodelete-dlclose-plugin.c b/elf/tst-nodelete-dlclose-plugin.c
|
||
new file mode 100644
|
||
index 0000000000..8b295c1718
|
||
--- /dev/null
|
||
+++ b/elf/tst-nodelete-dlclose-plugin.c
|
||
@@ -0,0 +1,40 @@
|
||
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||
+ Copyright (C) 2016 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This DSO simulates a plugin with a dependency on the
|
||
+ primary DSO loaded by the appliation. */
|
||
+#include <stdio.h>
|
||
+
|
||
+extern void primary_reference (void);
|
||
+
|
||
+void
|
||
+plugin_func (void)
|
||
+{
|
||
+ printf ("INFO: Calling plugin function.\n");
|
||
+ /* Need a reference to the DSO to ensure that a potential --as-needed
|
||
+ doesn't remove the DT_NEEDED entry which we rely upon to ensure
|
||
+ destruction ordering. */
|
||
+ primary_reference ();
|
||
+}
|
||
+
|
||
+__attribute__ ((destructor))
|
||
+static void
|
||
+plugin_dtor (void)
|
||
+{
|
||
+ printf ("INFO: Calling plugin destructor.\n");
|
||
+}
|
||
diff --git a/elf/tst-nodelete-dlclose.c b/elf/tst-nodelete-dlclose.c
|
||
new file mode 100644
|
||
index 0000000000..b3d07e1849
|
||
--- /dev/null
|
||
+++ b/elf/tst-nodelete-dlclose.c
|
||
@@ -0,0 +1,36 @@
|
||
+/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||
+ Copyright (C) 2016 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This simulates an application using the primary DSO which loads the
|
||
+ plugin DSO. */
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+extern void primary (void);
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ printf ("INFO: Starting application.\n");
|
||
+ primary ();
|
||
+ printf ("INFO: Exiting application.\n");
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#define TEST_FUNCTION do_test ()
|
||
+#include "../test-skeleton.c"
|
||
diff --git a/extra-lib.mk b/extra-lib.mk
|
||
index b10748d185..2552049135 100644
|
||
--- a/extra-lib.mk
|
||
+++ b/extra-lib.mk
|
||
@@ -5,6 +5,9 @@
|
||
# The variable $($(lib)-routines) defines the list of modules
|
||
# to be included in that library. A sysdep Makefile can add to
|
||
# $(lib)-sysdep_routines to include additional modules.
|
||
+#
|
||
+# Libraries listed in $(extra-libs-noinstall) are built, but not
|
||
+# installed.
|
||
|
||
lib := $(firstword $(extra-libs-left))
|
||
extra-libs-left := $(filter-out $(lib),$(extra-libs-left))
|
||
@@ -28,7 +31,9 @@ extra-objs := $(extra-objs)
|
||
all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines)
|
||
|
||
# Add each flavor of library to the lists of things to build and install.
|
||
+ifeq (,$(filter $(lib), $(extra-libs-noinstall)))
|
||
install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
|
||
+endif
|
||
extra-objs += $(foreach o,$(filter-out .os .oS,$(object-suffixes-$(lib))),\
|
||
$(patsubst %,%$o,$(filter-out \
|
||
$($(lib)-shared-only-routines),\
|
||
diff --git a/iconv/gconv.h b/iconv/gconv.h
|
||
index 8d8ce5813b..a87028047b 100644
|
||
--- a/iconv/gconv.h
|
||
+++ b/iconv/gconv.h
|
||
@@ -139,7 +139,7 @@ typedef struct __gconv_info
|
||
{
|
||
size_t __nsteps;
|
||
struct __gconv_step *__steps;
|
||
- __extension__ struct __gconv_step_data __data __flexarr;
|
||
+ __extension__ struct __gconv_step_data __data[0];
|
||
} *__gconv_t;
|
||
|
||
/* Transliteration using the locale's data. */
|
||
diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
|
||
index 2e735ede4c..7c0deed9ae 100644
|
||
--- a/include/arpa/nameser_compat.h
|
||
+++ b/include/arpa/nameser_compat.h
|
||
@@ -1,8 +1,8 @@
|
||
#ifndef _ARPA_NAMESER_COMPAT_
|
||
#include <resolv/arpa/nameser_compat.h>
|
||
|
||
-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
|
||
- T_A and T_AAAA). */
|
||
-#define T_UNSPEC 62321
|
||
+/* The number is outside the 16-bit RR type range and is used
|
||
+ internally by the implementation. */
|
||
+#define T_QUERY_A_AND_AAAA 439963904
|
||
|
||
#endif
|
||
diff --git a/io/fts.h b/io/fts.h
|
||
index 127a0d2721..b6b45206c8 100644
|
||
--- a/io/fts.h
|
||
+++ b/io/fts.h
|
||
@@ -193,7 +193,7 @@ FTS *__REDIRECT (fts_open, (char * const *, int,
|
||
int (*)(const FTSENT **, const FTSENT **)),
|
||
fts64_open);
|
||
FTSENT *__REDIRECT (fts_read, (FTS *), fts64_read);
|
||
-int __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW;
|
||
+int __REDIRECT_NTH (fts_set, (FTS *, FTSENT *, int), fts64_set);
|
||
# else
|
||
# define fts_children fts64_children
|
||
# define fts_close fts64_close
|
||
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
|
||
index 4be8afc110..a7688e3df6 100644
|
||
--- a/localedata/ChangeLog
|
||
+++ b/localedata/ChangeLog
|
||
@@ -1,3 +1,17 @@
|
||
+2017-06-11 Santhosh Thottingal <santhosh.thottingal@gmail.com>
|
||
+
|
||
+ [BZ #19922]
|
||
+ * locales/iso14651_t1_common: Add collation rules for U+07DA to U+07DF.
|
||
+
|
||
+ [BZ #19919]
|
||
+ * locales/iso14651_t1_common: Correct collation of U+0D36 and U+0D37.
|
||
+
|
||
+2016-12-30 Mike Frysinger <vapier@gentoo.org>
|
||
+
|
||
+ [BZ #20974]
|
||
+ * localedata/bs_BA (LC_MESSAGES): Delete "*." from the end of
|
||
+ yesexpr and noexpr.
|
||
+
|
||
2016-07-07 Aurelien Jarno <aurelien@aurel32.net>
|
||
|
||
* locales/de_LI (postal_fmt): Fix indentation.
|
||
diff --git a/localedata/locales/bs_BA b/localedata/locales/bs_BA
|
||
index a47f87eb37..68c2f9471a 100644
|
||
--- a/localedata/locales/bs_BA
|
||
+++ b/localedata/locales/bs_BA
|
||
@@ -148,8 +148,8 @@ copy "en_DK"
|
||
END LC_CTYPE
|
||
|
||
LC_MESSAGES
|
||
-yesexpr "<U005E><U005B><U002B><U0031><U0064><U0044><U0079><U0059><U005D><U002A><U002E>"
|
||
-noexpr "<U005E><U005B><U002D><U0030><U006E><U004E><U005D><U002A><U002E>"
|
||
+yesexpr "<U005E><U005B><U002B><U0031><U0064><U0044><U0079><U0059><U005D>"
|
||
+noexpr "<U005E><U005B><U002D><U0030><U006E><U004E><U005D>"
|
||
yesstr "<U0064><U0061>"
|
||
nostr "<U006E><U0065>"
|
||
END LC_MESSAGES
|
||
diff --git a/localedata/locales/iso14651_t1_common b/localedata/locales/iso14651_t1_common
|
||
index eef75ba65e..0e64f26a12 100644
|
||
--- a/localedata/locales/iso14651_t1_common
|
||
+++ b/localedata/locales/iso14651_t1_common
|
||
@@ -1042,9 +1042,9 @@ collating-element <ml-bh> from "<U0D2D><U0D4D>"
|
||
collating-element <ml-m> from "<U0D2E><U0D4D>"
|
||
collating-element <ml-y> from "<U0D2F><U0D4D>"
|
||
collating-element <ml-v> from "<U0D35><U0D4D>"
|
||
-collating-element <ml-s> from "<U0D38><U0D4D>"
|
||
collating-element <ml-ss> from "<U0D36><U0D4D>"
|
||
collating-element <ml-sh> from "<U0D37><U0D4D>"
|
||
+collating-element <ml-s> from "<U0D38><U0D4D>"
|
||
collating-element <ml-h> from "<U0D39><U0D4D>"
|
||
collating-element <ml-zh> from "<U0D34><U0D4D>"
|
||
collating-element <ml-rr> from "<U0D31><U0D4D>"
|
||
@@ -1103,8 +1103,8 @@ collating-symbol <ml-rra>
|
||
collating-symbol <ml-la>
|
||
collating-symbol <ml-lla>
|
||
collating-symbol <ml-va>
|
||
-collating-symbol <ml-sha>
|
||
collating-symbol <ml-ssa>
|
||
+collating-symbol <ml-sha>
|
||
collating-symbol <ml-sa>
|
||
collating-symbol <ml-ha>
|
||
collating-symbol <ml-avagrah>
|
||
@@ -1126,6 +1126,12 @@ collating-symbol <mlvs-o>
|
||
collating-symbol <mlvs-au>
|
||
collating-symbol <ml-visarga>
|
||
collating-symbol <ml-virama>
|
||
+collating-symbol <ml-atomic-chillu-k>
|
||
+collating-symbol <ml-atomic-chillu-n>
|
||
+collating-symbol <ml-atomic-chillu-nn>
|
||
+collating-symbol <ml-atomic-chillu-l>
|
||
+collating-symbol <ml-atomic-chillu-ll>
|
||
+collating-symbol <ml-atomic-chillu-r>
|
||
#
|
||
# <BENGALI>
|
||
#
|
||
@@ -4552,6 +4558,12 @@ collating-symbol <TIB-subA>
|
||
<mlvs-o>
|
||
<mlvs-au>
|
||
<ml-visarga>
|
||
+<ml-atomic-chillu-k>
|
||
+<ml-atomic-chillu-n>
|
||
+<ml-atomic-chillu-nn>
|
||
+<ml-atomic-chillu-l>
|
||
+<ml-atomic-chillu-ll>
|
||
+<ml-atomic-chillu-r>
|
||
#
|
||
# <BENGALI>
|
||
#
|
||
@@ -7252,6 +7264,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||
<U0D13> <mlvw-o>;<BAS>;<MIN>;IGNORE
|
||
<U0D14> <mlvw-au>;<BAS>;<MIN>;IGNORE
|
||
<ml-chillu-k> "<ml-ka><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
+<U0D7F> "<ml-ka><ml-virama>";<ml-atomic-chillu-k>;<MIN>;IGNORE
|
||
<U0D15> "<ml-ka><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-kh> "<ml-kha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D16> "<ml-kha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
@@ -7280,6 +7293,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||
<ml-dh> "<ml-dha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D22> "<ml-dha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-chillu-nn> "<ml-nna><ml-virama>";<BAS>;<MIN>;IGNORE # ണ് = ണ + ് + zwj
|
||
+<U0D7A> "<ml-nna><ml-virama>";<ml-atomic-chillu-nn>;<MIN>;IGNORE
|
||
<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ണ = ണ + ് + അ
|
||
<ml-th> "<ml-tha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D24> "<ml-tha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
@@ -7290,6 +7304,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||
<ml-ddh> "<ml-ddha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D27> "<ml-ddha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-chillu-n> "<ml-na><ml-virama>";<BAS>;<MIN>;IGNORE # ന്= ന + ് + zwj
|
||
+<U0D7B> "<ml-na><ml-virama>";<ml-atomic-chillu-n>;<MIN>;IGNORE
|
||
<U0D28> "<ml-na><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE #ന = ന + ് + അ
|
||
<ml-p> "<ml-pa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D2A> "<ml-pa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
@@ -7305,20 +7320,23 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||
<ml-y> "<ml-ya><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D2F> "<ml-ya><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-chillu-r> "<ml-ra><ml-virama>";<BAS>;<MIN>;IGNORE # ര = ര + ് + zwj
|
||
+<U0D7C> "<ml-ra><ml-virama>";<ml-atomic-chillu-r>;<MIN>;IGNORE
|
||
<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ര = ര + ് + അ
|
||
<ml-chillu-l> <ml-la>;<BAS>;<MIN>;IGNORE # ല് = ല + ് + zwj
|
||
+<U0D7D> "<ml-la><ml-virama>";<ml-atomic-chillu-l>;<MIN>;IGNORE
|
||
<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ല = ല + ് + അ
|
||
<ml-v> "<ml-va><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D35> "<ml-va><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-ss> "<ml-ssa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
-<U0D37> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
+<U0D36> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-sh> "<ml-sha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
-<U0D36> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
+<U0D37> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-s> "<ml-sa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D38> "<ml-sa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-h> "<ml-ha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D39> "<ml-ha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
<ml-chillu-ll> "<ml-lla><ml-virama>";<BAS>;<MIN>;IGNORE # ള് = ള + ് + zwj
|
||
+<U0D7E> "<ml-lla><ml-virama>";<ml-atomic-chillu-ll>;<MIN>;IGNORE
|
||
<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ള = ള + ് + അ
|
||
<ml-zh> "<ml-zha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||
<U0D34> "<ml-zha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||
diff --git a/malloc/arena.c b/malloc/arena.c
|
||
index 229783f3b7..4e16593d8b 100644
|
||
--- a/malloc/arena.c
|
||
+++ b/malloc/arena.c
|
||
@@ -702,8 +702,7 @@ _int_new_arena (size_t size)
|
||
}
|
||
|
||
|
||
-/* Remove an arena from free_list. The arena may be in use because it
|
||
- was attached concurrently to a thread by reused_arena below. */
|
||
+/* Remove an arena from free_list. */
|
||
static mstate
|
||
get_free_list (void)
|
||
{
|
||
@@ -718,7 +717,8 @@ get_free_list (void)
|
||
free_list = result->next_free;
|
||
|
||
/* The arena will be attached to this thread. */
|
||
- ++result->attached_threads;
|
||
+ assert (result->attached_threads == 0);
|
||
+ result->attached_threads = 1;
|
||
|
||
detach_arena (replaced_arena);
|
||
}
|
||
@@ -735,6 +735,26 @@ get_free_list (void)
|
||
return result;
|
||
}
|
||
|
||
+/* Remove the arena from the free list (if it is present).
|
||
+ free_list_lock must have been acquired by the caller. */
|
||
+static void
|
||
+remove_from_free_list (mstate arena)
|
||
+{
|
||
+ mstate *previous = &free_list;
|
||
+ for (mstate p = free_list; p != NULL; p = p->next_free)
|
||
+ {
|
||
+ assert (p->attached_threads == 0);
|
||
+ if (p == arena)
|
||
+ {
|
||
+ /* Remove the requested arena from the list. */
|
||
+ *previous = p->next_free;
|
||
+ break;
|
||
+ }
|
||
+ else
|
||
+ previous = &p->next_free;
|
||
+ }
|
||
+}
|
||
+
|
||
/* Lock and return an arena that can be reused for memory allocation.
|
||
Avoid AVOID_ARENA as we have already failed to allocate memory in
|
||
it and it is currently locked. */
|
||
@@ -782,14 +802,25 @@ reused_arena (mstate avoid_arena)
|
||
(void) mutex_lock (&result->mutex);
|
||
|
||
out:
|
||
- /* Attach the arena to the current thread. Note that we may have
|
||
- selected an arena which was on free_list. */
|
||
+ /* Attach the arena to the current thread. */
|
||
{
|
||
/* Update the arena thread attachment counters. */
|
||
mstate replaced_arena = thread_arena;
|
||
(void) mutex_lock (&free_list_lock);
|
||
detach_arena (replaced_arena);
|
||
+
|
||
+ /* We may have picked up an arena on the free list. We need to
|
||
+ preserve the invariant that no arena on the free list has a
|
||
+ positive attached_threads counter (otherwise,
|
||
+ arena_thread_freeres cannot use the counter to determine if the
|
||
+ arena needs to be put on the free list). We unconditionally
|
||
+ remove the selected arena from the free list. The caller of
|
||
+ reused_arena checked the free list and observed it to be empty,
|
||
+ so the list is very short. */
|
||
+ remove_from_free_list (result);
|
||
+
|
||
++result->attached_threads;
|
||
+
|
||
(void) mutex_unlock (&free_list_lock);
|
||
}
|
||
|
||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||
index 0d8aadebed..fa925819ca 100644
|
||
--- a/nptl/Makefile
|
||
+++ b/nptl/Makefile
|
||
@@ -268,7 +268,7 @@ tests = tst-typesizes \
|
||
tst-flock1 tst-flock2 \
|
||
tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
|
||
tst-signal6 tst-signal7 \
|
||
- tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
|
||
+ tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \
|
||
tst-exit1 tst-exit2 tst-exit3 \
|
||
tst-stdio1 tst-stdio2 \
|
||
tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \
|
||
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
|
||
index 6b42b11d5a..7365ca606b 100644
|
||
--- a/nptl/allocatestack.c
|
||
+++ b/nptl/allocatestack.c
|
||
@@ -440,9 +440,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||
SETUP_THREAD_SYSINFO (pd);
|
||
#endif
|
||
|
||
- /* The process ID is also the same as that of the caller. */
|
||
- pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
-
|
||
/* Don't allow setxid until cloned. */
|
||
pd->setxid_futex = -1;
|
||
|
||
@@ -579,9 +576,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||
/* Don't allow setxid until cloned. */
|
||
pd->setxid_futex = -1;
|
||
|
||
- /* The process ID is also the same as that of the caller. */
|
||
- pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
-
|
||
/* Allocate the DTV for this thread. */
|
||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||
{
|
||
@@ -875,9 +869,6 @@ __reclaim_stacks (void)
|
||
/* This marks the stack as free. */
|
||
curp->tid = 0;
|
||
|
||
- /* The PID field must be initialized for the new process. */
|
||
- curp->pid = self->pid;
|
||
-
|
||
/* Account for the size of the stack. */
|
||
stack_cache_actsize += curp->stackblock_size;
|
||
|
||
@@ -903,13 +894,6 @@ __reclaim_stacks (void)
|
||
}
|
||
}
|
||
|
||
- /* Reset the PIDs in any cached stacks. */
|
||
- list_for_each (runp, &stack_cache)
|
||
- {
|
||
- struct pthread *curp = list_entry (runp, struct pthread, list);
|
||
- curp->pid = self->pid;
|
||
- }
|
||
-
|
||
/* Add the stack of all running threads to the cache. */
|
||
list_splice (&stack_used, &stack_cache);
|
||
|
||
@@ -1054,9 +1038,9 @@ setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
|
||
return 0;
|
||
|
||
int val;
|
||
+ pid_t pid = __getpid ();
|
||
INTERNAL_SYSCALL_DECL (err);
|
||
- val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
|
||
- t->tid, SIGSETXID);
|
||
+ val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, t->tid, SIGSETXID);
|
||
|
||
/* If this failed, it must have had not started yet or else exited. */
|
||
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
|
||
diff --git a/nptl/descr.h b/nptl/descr.h
|
||
index 8e4938deb5..bc92abf010 100644
|
||
--- a/nptl/descr.h
|
||
+++ b/nptl/descr.h
|
||
@@ -167,8 +167,8 @@ struct pthread
|
||
therefore stack) used' flag. */
|
||
pid_t tid;
|
||
|
||
- /* Process ID - thread group ID in kernel speak. */
|
||
- pid_t pid;
|
||
+ /* Ununsed. */
|
||
+ pid_t pid_ununsed;
|
||
|
||
/* List of robust mutexes the thread is holding. */
|
||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
|
||
index bdbdfedcef..48fab50c4e 100644
|
||
--- a/nptl/nptl-init.c
|
||
+++ b/nptl/nptl-init.c
|
||
@@ -184,18 +184,12 @@ __nptl_set_robust (struct pthread *self)
|
||
static void
|
||
sigcancel_handler (int sig, siginfo_t *si, void *ctx)
|
||
{
|
||
- /* Determine the process ID. It might be negative if the thread is
|
||
- in the middle of a fork() call. */
|
||
- pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
- if (__glibc_unlikely (pid < 0))
|
||
- pid = -pid;
|
||
-
|
||
/* Safety check. It would be possible to call this function for
|
||
other signals and send a signal from another process. This is not
|
||
correct and might even be a security problem. Try to catch as
|
||
many incorrect invocations as possible. */
|
||
if (sig != SIGCANCEL
|
||
- || si->si_pid != pid
|
||
+ || si->si_pid != __getpid()
|
||
|| si->si_code != SI_TKILL)
|
||
return;
|
||
|
||
@@ -243,19 +237,14 @@ struct xid_command *__xidcmd attribute_hidden;
|
||
static void
|
||
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
|
||
{
|
||
- /* Determine the process ID. It might be negative if the thread is
|
||
- in the middle of a fork() call. */
|
||
- pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
int result;
|
||
- if (__glibc_unlikely (pid < 0))
|
||
- pid = -pid;
|
||
|
||
/* Safety check. It would be possible to call this function for
|
||
other signals and send a signal from another process. This is not
|
||
correct and might even be a security problem. Try to catch as
|
||
many incorrect invocations as possible. */
|
||
if (sig != SIGSETXID
|
||
- || si->si_pid != pid
|
||
+ || si->si_pid != __getpid ()
|
||
|| si->si_code != SI_TKILL)
|
||
return;
|
||
|
||
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
|
||
index 1419baf988..89d02e1741 100644
|
||
--- a/nptl/pthread_cancel.c
|
||
+++ b/nptl/pthread_cancel.c
|
||
@@ -22,7 +22,7 @@
|
||
#include "pthreadP.h"
|
||
#include <atomic.h>
|
||
#include <sysdep.h>
|
||
-
|
||
+#include <unistd.h>
|
||
|
||
int
|
||
pthread_cancel (pthread_t th)
|
||
@@ -66,19 +66,11 @@ pthread_cancel (pthread_t th)
|
||
#ifdef SIGCANCEL
|
||
/* The cancellation handler will take care of marking the
|
||
thread as canceled. */
|
||
- INTERNAL_SYSCALL_DECL (err);
|
||
-
|
||
- /* One comment: The PID field in the TCB can temporarily be
|
||
- changed (in fork). But this must not affect this code
|
||
- here. Since this function would have to be called while
|
||
- the thread is executing fork, it would have to happen in
|
||
- a signal handler. But this is no allowed, pthread_cancel
|
||
- is not guaranteed to be async-safe. */
|
||
- int val;
|
||
- val = INTERNAL_SYSCALL (tgkill, err, 3,
|
||
- THREAD_GETMEM (THREAD_SELF, pid), pd->tid,
|
||
- SIGCANCEL);
|
||
+ pid_t pid = getpid ();
|
||
|
||
+ INTERNAL_SYSCALL_DECL (err);
|
||
+ int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, pd->tid,
|
||
+ SIGCANCEL);
|
||
if (INTERNAL_SYSCALL_ERROR_P (val, err))
|
||
result = INTERNAL_SYSCALL_ERRNO (val, err);
|
||
#else
|
||
diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
|
||
index fb906f0484..32d7484bf8 100644
|
||
--- a/nptl/pthread_getattr_np.c
|
||
+++ b/nptl/pthread_getattr_np.c
|
||
@@ -68,7 +68,6 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
||
{
|
||
/* No stack information available. This must be for the initial
|
||
thread. Get the info in some magical way. */
|
||
- assert (abs (thread->pid) == thread->tid);
|
||
|
||
/* Stack size limit. */
|
||
struct rlimit rl;
|
||
diff --git a/nptl/tst-exec5.c b/nptl/tst-exec5.c
|
||
new file mode 100644
|
||
index 0000000000..4327d8d41c
|
||
--- /dev/null
|
||
+++ b/nptl/tst-exec5.c
|
||
@@ -0,0 +1,196 @@
|
||
+/* Check if posix_spawn does not act as a cancellation entrypoint.
|
||
+ Copyright (C) 2016 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <paths.h>
|
||
+#include <pthread.h>
|
||
+#include <signal.h>
|
||
+#include <spawn.h>
|
||
+#include <stdbool.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <unistd.h>
|
||
+#include <sys/wait.h>
|
||
+
|
||
+static int do_test (void);
|
||
+#define TEST_FUNCTION do_test ()
|
||
+#include <test-skeleton.c>
|
||
+
|
||
+static pthread_barrier_t b;
|
||
+
|
||
+static pid_t pid;
|
||
+static int pipefd[2];
|
||
+
|
||
+static void *
|
||
+tf (void *arg)
|
||
+{
|
||
+ int r = pthread_barrier_wait (&b);
|
||
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||
+ {
|
||
+ puts ("error: pthread_barrier_wait failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ posix_spawn_file_actions_t a;
|
||
+ if (posix_spawn_file_actions_init (&a) != 0)
|
||
+ {
|
||
+ puts ("error: spawn_file_actions_init failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (posix_spawn_file_actions_adddup2 (&a, pipefd[1], STDOUT_FILENO) != 0)
|
||
+ {
|
||
+ puts ("error: spawn_file_actions_adddup2 failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (posix_spawn_file_actions_addclose (&a, pipefd[0]) != 0)
|
||
+ {
|
||
+ puts ("error: spawn_file_actions_addclose");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
|
||
+ NULL };
|
||
+ if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
|
||
+ {
|
||
+ puts ("error: spawn failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ /* The test basically pipe a 'echo $$' created by a thread with a
|
||
+ cancellation pending. It then checks if the thread is not cancelled,
|
||
+ the process is created and if the output is the expected one. */
|
||
+
|
||
+ if (pipe (pipefd) != 0)
|
||
+ {
|
||
+ puts ("error: pipe failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ /* Not interested in knowing when the pipe is closed. */
|
||
+ if (sigignore (SIGPIPE) != 0)
|
||
+ {
|
||
+ puts ("error: sigignore failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ /* To synchronize with the thread. */
|
||
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||
+ {
|
||
+ puts ("error: pthread_barrier_init failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ pthread_t th;
|
||
+ if (pthread_create (&th, NULL, &tf, NULL) != 0)
|
||
+ {
|
||
+ puts ("error: pthread_create failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (pthread_cancel (th) != 0)
|
||
+ {
|
||
+ puts ("error: pthread_cancel failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ int r = pthread_barrier_wait (&b);
|
||
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||
+ {
|
||
+ puts ("error: pthread_barrier_wait");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ void *retval;
|
||
+ if (pthread_join (th, &retval) != 0)
|
||
+ {
|
||
+ puts ("error: pthread_join failed\n");
|
||
+ }
|
||
+ if (retval == PTHREAD_CANCELED)
|
||
+ {
|
||
+ puts ("error: thread cancelled");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ close (pipefd[1]);
|
||
+
|
||
+ /* The global 'pid' should be set by thread posix_spawn calling. Check
|
||
+ below if it was executed correctly and with expected output. */
|
||
+
|
||
+ char buf[64];
|
||
+ ssize_t n;
|
||
+ bool seen_pid = false;
|
||
+ while (TEMP_FAILURE_RETRY ((n = read (pipefd[0], buf, sizeof (buf)))) > 0)
|
||
+ {
|
||
+ /* We only expect to read the PID. */
|
||
+ char *endp;
|
||
+ long int rpid = strtol (buf, &endp, 10);
|
||
+
|
||
+ if (*endp != '\n')
|
||
+ {
|
||
+ printf ("error: didn't parse whole line: \"%s\"\n", buf);
|
||
+ exit (1);
|
||
+ }
|
||
+ if (endp == buf)
|
||
+ {
|
||
+ puts ("error: read empty line");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (rpid != pid)
|
||
+ {
|
||
+ printf ("error: found \"%s\", expected PID %ld\n", buf,
|
||
+ (long int) pid);
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (seen_pid)
|
||
+ {
|
||
+ puts ("error: found more than one PID line");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ seen_pid = true;
|
||
+ }
|
||
+
|
||
+ close (pipefd[0]);
|
||
+
|
||
+ int status;
|
||
+ int err = waitpid (pid, &status, 0);
|
||
+ if (err != pid)
|
||
+ {
|
||
+ puts ("errnor: waitpid failed");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (!seen_pid)
|
||
+ {
|
||
+ puts ("error: didn't get PID");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
|
||
index 978d8271bd..513ac53f6f 100644
|
||
--- a/nptl/tst-once5.cc
|
||
+++ b/nptl/tst-once5.cc
|
||
@@ -75,5 +75,7 @@ do_test (void)
|
||
return result;
|
||
}
|
||
|
||
+// The test currently hangs and is XFAILed. Reduce the timeout.
|
||
+#define TIMEOUT 1
|
||
#define TEST_FUNCTION do_test ()
|
||
#include "../test-skeleton.c"
|
||
diff --git a/nptl_db/structs.def b/nptl_db/structs.def
|
||
index a9b621b126..1cb6a46391 100644
|
||
--- a/nptl_db/structs.def
|
||
+++ b/nptl_db/structs.def
|
||
@@ -48,7 +48,6 @@ DB_STRUCT (pthread)
|
||
DB_STRUCT_FIELD (pthread, list)
|
||
DB_STRUCT_FIELD (pthread, report_events)
|
||
DB_STRUCT_FIELD (pthread, tid)
|
||
-DB_STRUCT_FIELD (pthread, pid)
|
||
DB_STRUCT_FIELD (pthread, start_routine)
|
||
DB_STRUCT_FIELD (pthread, cancelhandling)
|
||
DB_STRUCT_FIELD (pthread, schedpolicy)
|
||
diff --git a/nptl_db/td_ta_thr_iter.c b/nptl_db/td_ta_thr_iter.c
|
||
index a990fed150..9e5059956b 100644
|
||
--- a/nptl_db/td_ta_thr_iter.c
|
||
+++ b/nptl_db/td_ta_thr_iter.c
|
||
@@ -76,48 +76,28 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
|
||
if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
|
||
return TD_ERR;
|
||
|
||
- /* Verify that this thread's pid field matches the child PID.
|
||
- If its pid field is negative, it's about to do a fork or it
|
||
- is the sole thread in a fork child. */
|
||
- psaddr_t pid;
|
||
- err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, pid, 0);
|
||
- if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
|
||
- {
|
||
- if (-(pid_t) (uintptr_t) pid == match_pid)
|
||
- /* It is about to do a fork, but is really still the parent PID. */
|
||
- pid = (psaddr_t) (uintptr_t) match_pid;
|
||
- else
|
||
- /* It must be a fork child, whose new PID is in the tid field. */
|
||
- err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, tid, 0);
|
||
- }
|
||
+ err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
|
||
+ schedpolicy, 0);
|
||
if (err != TD_OK)
|
||
break;
|
||
+ err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
|
||
+ schedparam_sched_priority, 0);
|
||
+ if (err != TD_OK)
|
||
+ break;
|
||
+
|
||
+ /* Now test whether this thread matches the specified conditions. */
|
||
|
||
- if ((pid_t) (uintptr_t) pid == match_pid)
|
||
+ /* Only if the priority level is as high or higher. */
|
||
+ int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
|
||
+ ? 0 : (uintptr_t) schedprio);
|
||
+ if (descr_pri >= ti_pri)
|
||
{
|
||
- err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
|
||
- schedpolicy, 0);
|
||
- if (err != TD_OK)
|
||
- break;
|
||
- err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
|
||
- schedparam_sched_priority, 0);
|
||
- if (err != TD_OK)
|
||
- break;
|
||
-
|
||
- /* Now test whether this thread matches the specified conditions. */
|
||
-
|
||
- /* Only if the priority level is as high or higher. */
|
||
- int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
|
||
- ? 0 : (uintptr_t) schedprio);
|
||
- if (descr_pri >= ti_pri)
|
||
- {
|
||
- /* Yep, it matches. Call the callback function. */
|
||
- td_thrhandle_t th;
|
||
- th.th_ta_p = (td_thragent_t *) ta;
|
||
- th.th_unique = addr;
|
||
- if (callback (&th, cbdata_p) != 0)
|
||
- return TD_DBERR;
|
||
- }
|
||
+ /* Yep, it matches. Call the callback function. */
|
||
+ td_thrhandle_t th;
|
||
+ th.th_ta_p = (td_thragent_t *) ta;
|
||
+ th.th_unique = addr;
|
||
+ if (callback (&th, cbdata_p) != 0)
|
||
+ return TD_DBERR;
|
||
}
|
||
|
||
/* Get the pointer to the next element. */
|
||
diff --git a/nptl_db/td_thr_validate.c b/nptl_db/td_thr_validate.c
|
||
index f3c8a7bed6..9b89fecad2 100644
|
||
--- a/nptl_db/td_thr_validate.c
|
||
+++ b/nptl_db/td_thr_validate.c
|
||
@@ -80,28 +80,5 @@ td_thr_validate (const td_thrhandle_t *th)
|
||
err = TD_OK;
|
||
}
|
||
|
||
- if (err == TD_OK)
|
||
- {
|
||
- /* Verify that this is not a stale element in a fork child. */
|
||
- pid_t match_pid = ps_getpid (th->th_ta_p->ph);
|
||
- psaddr_t pid;
|
||
- err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, pthread, pid, 0);
|
||
- if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
|
||
- {
|
||
- /* This was a thread that was about to fork, or it is the new sole
|
||
- thread in a fork child. In the latter case, its tid was stored
|
||
- via CLONE_CHILD_SETTID and so is already the proper child PID. */
|
||
- if (-(pid_t) (uintptr_t) pid == match_pid)
|
||
- /* It is about to do a fork, but is really still the parent PID. */
|
||
- pid = (psaddr_t) (uintptr_t) match_pid;
|
||
- else
|
||
- /* It must be a fork child, whose new PID is in the tid field. */
|
||
- err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique,
|
||
- pthread, tid, 0);
|
||
- }
|
||
- if (err == TD_OK && (pid_t) (uintptr_t) pid != match_pid)
|
||
- err = TD_NOTHR;
|
||
- }
|
||
-
|
||
return err;
|
||
}
|
||
diff --git a/po/de.po b/po/de.po
|
||
index 1383e8c4a9..ca14c7e386 100644
|
||
--- a/po/de.po
|
||
+++ b/po/de.po
|
||
@@ -8,7 +8,7 @@ msgid ""
|
||
msgstr ""
|
||
"Project-Id-Version: GNU libc 2.22-pre1\n"
|
||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||
-"PO-Revision-Date: 2015-08-31 18:30+0200\n"
|
||
+"PO-Revision-Date: 2016-04-22 18:44+0200\n"
|
||
"Last-Translator: Jochen Hein <jochen@jochen.org>\n"
|
||
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
|
||
"Language: de\n"
|
||
@@ -4479,13 +4479,13 @@ msgstr ""
|
||
"%15s Cache ist dauerhaft\n"
|
||
"%15s Cache wird gemeinsam verwendet\n"
|
||
"%15Zu vorgeschlagene Größe\n"
|
||
-"%15Zu Gesamtröße des Data-Pools\n"
|
||
+"%15Zu Gesamtgröße des Data-Pools\n"
|
||
"%15Zu Benutzter Speicher im Data-Pool\n"
|
||
"%15lu Time to Live für positive Einträge in Sekunden\n"
|
||
"%15lu Time to Live für negative Einträge in Sekunden\n"
|
||
"%15<PRIuMAX> Cache-Hits bei positiven Einträgen\n"
|
||
"%15<PRIuMAX> Cache-Hits bei positiven Einträgen\n"
|
||
-"%15<PRIuMAX> Cache-Misses bei positiven Einträgen\n"
|
||
+"%15<PRIuMAX> Cache-Misses bei positiven Einträgen\n"
|
||
"%15<PRIuMAX> Cache-Misses bei negativen Einträgen\n"
|
||
"%15lu%% Cache-Hit Verhältnis\n"
|
||
"%15zu aktuelle Anzahl der Werte im Cache\n"
|
||
diff --git a/po/fi.po b/po/fi.po
|
||
index 17cb3e3e1d..8a2ab8358c 100644
|
||
--- a/po/fi.po
|
||
+++ b/po/fi.po
|
||
@@ -24,16 +24,16 @@
|
||
#
|
||
msgid ""
|
||
msgstr ""
|
||
-"Project-Id-Version: libc 2.21-pre1\n"
|
||
+"Project-Id-Version: libc 2.22-pre1\n"
|
||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||
-"PO-Revision-Date: 2015-07-28 20:29+0300\n"
|
||
+"PO-Revision-Date: 2016-05-26 21:14+0300\n"
|
||
"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
|
||
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
|
||
"Language: fi\n"
|
||
"MIME-Version: 1.0\n"
|
||
"Content-Type: text/plain; charset=UTF-8\n"
|
||
"Content-Transfer-Encoding: 8bit\n"
|
||
-"X-Generator: Poedit 1.8.3\n"
|
||
+"X-Generator: Poedit 1.8.7\n"
|
||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||
|
||
#: argp/argp-help.c:227
|
||
@@ -126,7 +126,7 @@ msgid "%s%s%s:%u: %s%sUnexpected error: %s.\n"
|
||
msgstr "%s%s%s:%u: %s%sOdottamaton virhe: %s.\n"
|
||
|
||
#: assert/assert.c:101
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid ""
|
||
"%s%s%s:%u: %s%sAssertion `%s' failed.\n"
|
||
"%n"
|
||
@@ -169,12 +169,12 @@ msgstr ""
|
||
#: malloc/memusagestat.c:563 nss/getent.c:973 nss/makedb.c:369
|
||
#: posix/getconf.c:486 sunrpc/rpcinfo.c:691
|
||
#: sysdeps/unix/sysv/linux/lddlibc4.c:61
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid ""
|
||
"For bug reporting instructions, please see:\n"
|
||
"%s.\n"
|
||
msgstr ""
|
||
-"Ohjeet ohjelmistovioista ilmoittamiseen ovat osoitteessa\n"
|
||
+"Katso ohjeet vikailmoitusten tekemiseen osoitteesta:\n"
|
||
"%s.\n"
|
||
|
||
#: catgets/gencat.c:245 debug/pcprofiledump.c:225 debug/xtrace.sh:64
|
||
@@ -321,9 +321,8 @@ msgstr "Käyttö: xtrace [VALITSIN]... OHJELMA [OHJELMANVALITSIN]...\\n"
|
||
|
||
#: debug/xtrace.sh:32 elf/sotruss.sh:56 elf/sotruss.sh:67 elf/sotruss.sh:135
|
||
#: malloc/memusage.sh:26
|
||
-#, fuzzy
|
||
msgid "Try \\`%s --help' or \\`%s --usage' for more information.\\n"
|
||
-msgstr "Kokeile ”%s --help” tai ”%s --usage” saadaksesi lisää tietoa.\n"
|
||
+msgstr "Kokeile ”%s --help” tai ”%s --usage” saadaksesi lisää tietoa.\\n"
|
||
|
||
#: debug/xtrace.sh:38
|
||
#, fuzzy
|
||
@@ -594,9 +593,8 @@ msgid "cannot enable executable stack as shared object requires"
|
||
msgstr "jaettua objektikahvaa ei voi luoda"
|
||
|
||
#: elf/dl-load.c:1339
|
||
-#, fuzzy
|
||
msgid "cannot close file descriptor"
|
||
-msgstr "tiedostoa %s ei voi sulkea"
|
||
+msgstr "tiedostokahvaa ei voi sulkea"
|
||
|
||
#: elf/dl-load.c:1568
|
||
msgid "file too short"
|
||
@@ -796,9 +794,8 @@ msgid "Format to use: new, old or compat (default)"
|
||
msgstr "Käytettävä muoto: ”new”, ”old” tai ”compat” (oletus)"
|
||
|
||
#: elf/ldconfig.c:151
|
||
-#, fuzzy
|
||
msgid "Ignore auxiliary cache file"
|
||
-msgstr "Käytä CACHEa välimuistitiedostona"
|
||
+msgstr "Jätä huomiotta apuvälimuistitiedosto"
|
||
|
||
#: elf/ldconfig.c:159
|
||
msgid "Configure Dynamic Linker Run Time Bindings."
|
||
@@ -1087,9 +1084,9 @@ msgid "invalid process ID '%s'"
|
||
msgstr "virheellinen prosessi-ID ”%s”"
|
||
|
||
#: elf/pldd.c:120
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "cannot open %s"
|
||
-msgstr "laitetta %s ei voi avata"
|
||
+msgstr "tiedostoa %s ei voi avata"
|
||
|
||
#: elf/pldd.c:152
|
||
#, fuzzy, c-format
|
||
@@ -1102,24 +1099,24 @@ msgid "cannot prepare reading %s/task"
|
||
msgstr "ei voi avata laitetta %s lukutilaan"
|
||
|
||
#: elf/pldd.c:168
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "invalid thread ID '%s'"
|
||
-msgstr "virheellinen prosessi-ID ”%s”"
|
||
+msgstr "virheellinen säie-ID ”%s”"
|
||
|
||
#: elf/pldd.c:179
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "cannot attach to process %lu"
|
||
-msgstr "tiedostoa ”%s” ei voi avata"
|
||
+msgstr "ei voida kiinnittyä prosessiin %lu"
|
||
|
||
#: elf/pldd.c:294
|
||
#, c-format
|
||
msgid "cannot get information about process %lu"
|
||
-msgstr ""
|
||
+msgstr "tietojen saaminen prosessista %lu ei onnistu"
|
||
|
||
#: elf/pldd.c:307
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "process %lu is no ELF program"
|
||
-msgstr "ohjelma %lu ei ole käytettävissä\n"
|
||
+msgstr "prosessi %lu ei ole ELF-ohjelma"
|
||
|
||
#: elf/readelflib.c:34
|
||
#, c-format
|
||
@@ -1203,7 +1200,7 @@ msgstr "%s kohde ei saa olla hakemisto\n"
|
||
#: elf/sln.c:184
|
||
#, c-format
|
||
msgid "%s: failed to remove the old destination\n"
|
||
-msgstr ""
|
||
+msgstr "%s: vanhan kohteen poistaminen epäonnistui\n"
|
||
|
||
#: elf/sln.c:192
|
||
#, c-format
|
||
@@ -1237,9 +1234,8 @@ msgid "Mandatory arguments to long options are also mandatory for any correspond
|
||
msgstr "Pakolliset argumentit pitkille valitsimille ovat pakollisia kaikille vastaaville lyhyille valitsimille.\\n"
|
||
|
||
#: elf/sotruss.sh:55
|
||
-#, fuzzy
|
||
msgid "%s: option requires an argument -- '%s'\\n"
|
||
-msgstr "%s: valitsin ”%s” vaatii argumentin\n"
|
||
+msgstr "%s: valitsin vaatii argumentin -- ”%c”\\n"
|
||
|
||
#: elf/sotruss.sh:61
|
||
msgid "%s: option is ambiguous; possibilities:"
|
||
@@ -1507,7 +1503,6 @@ msgid "unknown iconv() error %d"
|
||
msgstr "tuntematon iconv()-virhe %d"
|
||
|
||
#: iconv/iconv_prog.c:791
|
||
-#, fuzzy
|
||
msgid ""
|
||
"The following list contains all the coded character sets known. This does\n"
|
||
"not necessarily mean that all combinations of these names can be used for\n"
|
||
@@ -1516,9 +1511,9 @@ msgid ""
|
||
"\n"
|
||
" "
|
||
msgstr ""
|
||
-"Seuraavassa listassa ovat kaikki tunnetut koodatut merkistöt. Se ei\n"
|
||
+"Seuraavassa listassa ovat kaikki tunnetut koodatut merkistöt. Tämä ei\n"
|
||
"kuitenkaan välttämättä tarkoita sitä, että kaikkia näiden nimien\n"
|
||
-"yhdistelmiä voidaan käyttää FROM- ja TO-komentoriviparametreina. Yksi\n"
|
||
+"yhdistelmiä voisi käyttää FROM- ja TO-komentoriviparametreina. Yksi\n"
|
||
"koodattu merkistö voi olla listalla useilla eri nimillä (aliaksilla).\n"
|
||
"\n"
|
||
" "
|
||
@@ -2733,14 +2728,12 @@ msgid "locale.alias file to consult when making archive"
|
||
msgstr "Arkistoa luotaessa käytettävä locale.alias-tiedosto"
|
||
|
||
#: locale/programs/localedef.c:150
|
||
-#, fuzzy
|
||
msgid "Generate little-endian output"
|
||
-msgstr "Tuota little-endian-koodia"
|
||
+msgstr "Tuota little-endian-muotoa"
|
||
|
||
#: locale/programs/localedef.c:152
|
||
-#, fuzzy
|
||
msgid "Generate big-endian output"
|
||
-msgstr "Tuota big-endian-koodia"
|
||
+msgstr "Tuota big-endian-muotoa"
|
||
|
||
#: locale/programs/localedef.c:157
|
||
msgid "Compile locale specification"
|
||
@@ -4275,10 +4268,9 @@ msgid ""
|
||
msgstr ""
|
||
|
||
#: nscd/nscd.c:635
|
||
-#, fuzzy, c-format
|
||
-#| msgid "lstat failed"
|
||
+#, c-format
|
||
msgid "'wait' failed\n"
|
||
-msgstr "tiedoston tilan luku epäonnistui"
|
||
+msgstr "”wait” epäonnistui\n"
|
||
|
||
#: nscd/nscd.c:642
|
||
#, c-format
|
||
@@ -4670,9 +4662,9 @@ msgid "cannot create temporary file"
|
||
msgstr "tilapäistä tiedostoa ei voi luoda"
|
||
|
||
#: nss/makedb.c:304
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "cannot stat newly created file"
|
||
-msgstr "tiedoston ”%s” tilaa ei voi lukea: %s"
|
||
+msgstr "juuri luodun tiedoston tilaa ei voi lukea"
|
||
|
||
#: nss/makedb.c:315
|
||
#, c-format
|
||
@@ -4680,9 +4672,9 @@ msgid "cannot rename temporary file"
|
||
msgstr "tilapäistä tiedostoa ei voi nimetä uudelleen"
|
||
|
||
#: nss/makedb.c:531 nss/makedb.c:554
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "cannot create search tree"
|
||
-msgstr "hakupolulle ei voi luoda välimuistia"
|
||
+msgstr "hakupuuta ei voi luoda"
|
||
|
||
#: nss/makedb.c:560
|
||
msgid "duplicate key"
|
||
@@ -4699,9 +4691,9 @@ msgid "failed to write new database file"
|
||
msgstr "uuden tietokantatiedoston kirjoittaminen epäonnistui"
|
||
|
||
#: nss/makedb.c:812
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "cannot stat database file"
|
||
-msgstr "tiedoston ”%s” tilaa ei voi lukea: %s"
|
||
+msgstr "tietokantatiedoston tilaa ei voi lukea"
|
||
|
||
#: nss/makedb.c:817
|
||
#, fuzzy, c-format
|
||
@@ -4709,9 +4701,9 @@ msgid "cannot map database file"
|
||
msgstr "Karttatietokannassa ei ole enempää tietueita"
|
||
|
||
#: nss/makedb.c:820
|
||
-#, fuzzy, c-format
|
||
+#, c-format
|
||
msgid "file not a database file"
|
||
-msgstr "luettaessa profilointidatatiedoston tilaa"
|
||
+msgstr "tiedosto ei ole tietokantatiedosto"
|
||
|
||
#: nss/makedb.c:871
|
||
#, fuzzy, c-format
|
||
@@ -4726,7 +4718,7 @@ msgstr "Käyttö: %s [-v määrittely] muuttujanimi [polku]\n"
|
||
#: posix/getconf.c:403
|
||
#, c-format
|
||
msgid " %s -a [pathname]\n"
|
||
-msgstr ""
|
||
+msgstr " %s -a [polku]\n"
|
||
|
||
#: posix/getconf.c:479
|
||
#, c-format
|
||
@@ -5094,11 +5086,11 @@ msgstr "Laitetta irrotettu"
|
||
|
||
#: stdio-common/psiginfo.c:139
|
||
msgid "Signal sent by kill()"
|
||
-msgstr ""
|
||
+msgstr "Signaalin lähetti kill()"
|
||
|
||
#: stdio-common/psiginfo.c:142
|
||
msgid "Signal sent by sigqueue()"
|
||
-msgstr ""
|
||
+msgstr "Signaalin lähetti sigqueue()"
|
||
|
||
#: stdio-common/psiginfo.c:145
|
||
msgid "Signal generated by the expiration of a timer"
|
||
@@ -5114,7 +5106,7 @@ msgstr ""
|
||
|
||
#: stdio-common/psiginfo.c:157
|
||
msgid "Signal sent by tkill()"
|
||
-msgstr ""
|
||
+msgstr "Signaalin lähetti tkill()"
|
||
|
||
#: stdio-common/psiginfo.c:162
|
||
msgid "Signal generated by the completion of an asynchronous name lookup request"
|
||
@@ -5296,9 +5288,8 @@ msgid "Failed (unspecified error)"
|
||
msgstr "Epäonnistui (määrittelemätön virhe)"
|
||
|
||
#: sunrpc/clnt_raw.c:115
|
||
-#, fuzzy
|
||
msgid "clnt_raw.c: fatal header serialization error"
|
||
-msgstr "clnt_raw.c: vakava otsikon serialisointivirhe"
|
||
+msgstr "clnt_raw.c: vakava otsikon sarjallistamisvirhe"
|
||
|
||
#: sunrpc/pm_getmaps.c:77
|
||
msgid "pmap_getmaps.c: rpc problem"
|
||
@@ -6825,9 +6816,8 @@ msgid "Interrupted by a signal"
|
||
msgstr "Signaalin keskeyttämä"
|
||
|
||
#: sysdeps/posix/gai_strerror-strs.h:17
|
||
-#, fuzzy
|
||
msgid "Parameter string not correctly encoded"
|
||
-msgstr "Parametrimerkkijono on väärin koodattu"
|
||
+msgstr "Parametrimerkkijono ei ole koodattu oikein"
|
||
|
||
#: sysdeps/unix/sysv/linux/i386/readelflib.c:65
|
||
#, c-format
|
||
diff --git a/po/sv.po b/po/sv.po
|
||
index 49d1f23904..e046577b08 100644
|
||
--- a/po/sv.po
|
||
+++ b/po/sv.po
|
||
@@ -1,13 +1,17 @@
|
||
# GNU libc message catalog for Swedish
|
||
-# Copyright © 1996, 1998, 2001, 2002, 2003, 2006, 2008, 2009, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
|
||
+# Copyright © 1996, 1998, 2001, 2002, 2003, 2006, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
|
||
# This file is distributed under the same license as the glibc package.
|
||
-# Jan Djärv <jan.h.d@swipnet.se>, 1996, 1998, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015
|
||
+#
|
||
+# Jan Djärv <jan.h.d@swipnet.se>, 1996, 1998, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015.
|
||
+# Göran Uddeborg <goeran@uddeborg.se>, 2016.
|
||
+#
|
||
+# $Revision: 1.3 $
|
||
msgid ""
|
||
msgstr ""
|
||
-"Project-Id-Version: libc 2.21-pre1\n"
|
||
+"Project-Id-Version: libc 2.22-pre1\n"
|
||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||
-"PO-Revision-Date: 2015-01-24 10:35+0100\n"
|
||
-"Last-Translator: Jan Djärv <jan.h.d@swipnet.se>\n"
|
||
+"PO-Revision-Date: 2016-08-02 17:17+0200\n"
|
||
+"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
|
||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||
"Language: sv\n"
|
||
"MIME-Version: 1.0\n"
|
||
@@ -48,7 +52,7 @@ msgstr " [FLAGGA...]"
|
||
#: argp/argp-help.c:1643
|
||
#, c-format
|
||
msgid "Try `%s --help' or `%s --usage' for more information.\n"
|
||
-msgstr "Försök med \"%s --help\" eller \"%s --usage\" för mer information\n"
|
||
+msgstr "Försök med ”%s --help” eller ”%s --usage” för mer information.\n"
|
||
|
||
#: argp/argp-help.c:1671
|
||
#, c-format
|
||
@@ -304,11 +308,11 @@ msgstr "Användning: xtrace [FLAGGA]... PROGRAM [PROGRAMFLAGGA}...\\n"
|
||
#: debug/xtrace.sh:32 elf/sotruss.sh:56 elf/sotruss.sh:67 elf/sotruss.sh:135
|
||
#: malloc/memusage.sh:26
|
||
msgid "Try \\`%s --help' or \\`%s --usage' for more information.\\n"
|
||
-msgstr "Försök med \\\"%s --help\\\" eller \\\"%s --usage\\\" för mer information\\n"
|
||
+msgstr "Försök med ”%s --help” eller ”%s --usage” för mer information\\n"
|
||
|
||
#: debug/xtrace.sh:38
|
||
msgid "%s: option '%s' requires an argument.\\n"
|
||
-msgstr "%s: flaggan \\\"%s\\\" kräver ett argument\\n"
|
||
+msgstr "%s: flaggan ”%s” kräver ett argument.\\n"
|
||
|
||
#: debug/xtrace.sh:45
|
||
msgid ""
|
||
@@ -332,19 +336,17 @@ msgstr ""
|
||
" --usage Visa en kort hjälptext\n"
|
||
" -V,--version Visa versionsinformation och avsluta\n"
|
||
"\n"
|
||
-"Obligatoriska argument för långa flaggor är obligatoriska även för\n"
|
||
+"Obligatoriska argument för långa flaggor är obligatoriska även för\n"
|
||
"motsvarande korta.\n"
|
||
|
||
#: debug/xtrace.sh:57 elf/ldd.bash.in:55 elf/sotruss.sh:49
|
||
#: malloc/memusage.sh:64
|
||
msgid "For bug reporting instructions, please see:\\\\n%s.\\\\n"
|
||
-msgstr ""
|
||
-"För felrapporteringsinstruktioner, se:\\\\n%s.\\\\n\n"
|
||
-"Rapportera fel eller synpunkter på översättningen till <tp-sv@listor.tp-sv.se>.\\\\n"
|
||
+msgstr "För felrapporteringsinstruktioner, se:\\\\n%s.\\\\nRapportera fel eller synpunkter på översättningen till:\\\\n<tp-sv@listor.tp-sv.se>.\\\\n"
|
||
|
||
#: debug/xtrace.sh:125
|
||
msgid "xtrace: unrecognized option \\`$1'\\n"
|
||
-msgstr "xtrace: okänd flagga \"$1\"\\n"
|
||
+msgstr "xtrace: okänd flagga ”$1”\\n"
|
||
|
||
#: debug/xtrace.sh:138
|
||
msgid "No program name given\\n"
|
||
@@ -353,12 +355,12 @@ msgstr "Inget programnamn givet\\n"
|
||
#: debug/xtrace.sh:146
|
||
#, sh-format
|
||
msgid "executable \\`$program' not found\\n"
|
||
-msgstr "program \"$program\" hittades inte\\n"
|
||
+msgstr "program ”$program” hittades inte\\n"
|
||
|
||
#: debug/xtrace.sh:150
|
||
#, sh-format
|
||
msgid "\\`$program' is no executable\\n"
|
||
-msgstr "\"$program\" är inte en körbar binär\\n"
|
||
+msgstr "”$program” är inte en körbar binär\\n"
|
||
|
||
#: dlfcn/dlinfo.c:63
|
||
msgid "RTLD_SELF used in code not dynamically loaded"
|
||
@@ -396,7 +398,7 @@ msgstr ", OS ABI: %s %d.%d.%d"
|
||
#: elf/cache.c:157 elf/ldconfig.c:1340
|
||
#, c-format
|
||
msgid "Can't open cache file %s\n"
|
||
-msgstr "Kan inte öppna cache-fil \"%s\"\n"
|
||
+msgstr "Kan inte öppna cache-filen %s\n"
|
||
|
||
#: elf/cache.c:171
|
||
#, c-format
|
||
@@ -416,7 +418,7 @@ msgstr "%d bibliotek hittades i cache \"%s\"\n"
|
||
#: elf/cache.c:426
|
||
#, c-format
|
||
msgid "Can't create temporary cache file %s"
|
||
-msgstr "Kan inte skapa temporär cache-fil \"%s\""
|
||
+msgstr "Kan inte skapa en temporär cache-fil %s"
|
||
|
||
#: elf/cache.c:434 elf/cache.c:444 elf/cache.c:448 elf/cache.c:453
|
||
#, c-format
|
||
@@ -829,7 +831,7 @@ msgstr "Kan inte ta status (lstat) på %s"
|
||
#: elf/ldconfig.c:609
|
||
#, c-format
|
||
msgid "Ignored file %s since it is not a regular file."
|
||
-msgstr "Ignorerar fil %s eftersom den inte är en vanlig fil"
|
||
+msgstr "Ignorerar fil %s eftersom den inte är en vanlig fil."
|
||
|
||
#: elf/ldconfig.c:618
|
||
#, c-format
|
||
@@ -951,7 +953,7 @@ msgstr ""
|
||
|
||
#: elf/ldd.bash.in:80
|
||
msgid "ldd: option \\`$1' is ambiguous"
|
||
-msgstr "ldd: flaggan \"$1\" är tvetydig"
|
||
+msgstr "ldd: flaggan ”$1” är tvetydig"
|
||
|
||
#: elf/ldd.bash.in:87
|
||
msgid "unrecognized option"
|
||
@@ -959,7 +961,7 @@ msgstr "okänd flagga"
|
||
|
||
#: elf/ldd.bash.in:88 elf/ldd.bash.in:125
|
||
msgid "Try \\`ldd --help' for more information."
|
||
-msgstr "Försök med \"ldd --help\" för mer information"
|
||
+msgstr "Försök med \"ldd --help\" för mer information."
|
||
|
||
#: elf/ldd.bash.in:124
|
||
msgid "missing file arguments"
|
||
@@ -1028,10 +1030,9 @@ msgid "cannot read object name"
|
||
msgstr "kan inte läsa objektnamn"
|
||
|
||
#: elf/pldd-xx.c:219
|
||
-#, fuzzy, c-format
|
||
-#| msgid "cannot allocate memory for program header"
|
||
+#, c-format
|
||
msgid "cannot allocate buffer for object name"
|
||
-msgstr "kan inte allokera minne för programhuvud"
|
||
+msgstr "kan inte allokera en buffert för objektnamn"
|
||
|
||
#: elf/pldd.c:64
|
||
msgid "List dynamic shared objects loaded into process."
|
||
@@ -1212,11 +1213,11 @@ msgstr ""
|
||
|
||
#: elf/sotruss.sh:46
|
||
msgid "Mandatory arguments to long options are also mandatory for any corresponding\\nshort options.\\n"
|
||
-msgstr "Obligatoriska respektive valfria argument för långa flaggor är obligatoriska respektive\\nvalfria även för korta.\\n"
|
||
+msgstr "Obligatoriska respektive valfria argument för långa flaggor är obligatoriska\\nrespektive valfria även för korta.\\n"
|
||
|
||
#: elf/sotruss.sh:55
|
||
msgid "%s: option requires an argument -- '%s'\\n"
|
||
-msgstr "%s: flaggan kräver ett argument -- \\\"%s\\\"\\n"
|
||
+msgstr "%s: flaggan kräver ett argument — ”%s”\\n"
|
||
|
||
#: elf/sotruss.sh:61
|
||
msgid "%s: option is ambiguous; possibilities:"
|
||
@@ -1240,7 +1241,7 @@ msgstr ""
|
||
|
||
#: elf/sotruss.sh:134
|
||
msgid "%s: unrecognized option '%c%s'\\n"
|
||
-msgstr "%s: okänd flagga \\\"%c%s\\\"\\n"
|
||
+msgstr "%s: okänd flagga ”%c%s”\\n"
|
||
|
||
#: elf/sprof.c:77
|
||
msgid "Output selection:"
|
||
@@ -1260,7 +1261,7 @@ msgstr "generera anropsgraf"
|
||
|
||
#: elf/sprof.c:89
|
||
msgid "Read and display shared object profiling data."
|
||
-msgstr "Läs och visa profildata för delat objekt"
|
||
+msgstr "Läs och visa profildata för delat objekt."
|
||
|
||
#: elf/sprof.c:94
|
||
msgid "SHOBJ [PROFDATA]"
|
||
@@ -1622,7 +1623,7 @@ msgstr "Fel: .netrc kan läsas av andra."
|
||
|
||
#: inet/ruserpass.c:185
|
||
msgid "Remove password or make file unreadable by others."
|
||
-msgstr "Ta bort lösenord eller gör filen oläsbar för andra"
|
||
+msgstr "Ta bort lösenord eller gör filen oläsbar för andra."
|
||
|
||
#: inet/ruserpass.c:277
|
||
#, c-format
|
||
@@ -2182,12 +2183,12 @@ msgstr "Inget namn definierat i teckenuppsättning"
|
||
#: locale/programs/ld-ctype.c:479
|
||
#, c-format
|
||
msgid "character L'\\u%0*x' in class `%s' must be in class `%s'"
|
||
-msgstr "tecken L\"\\u%0*x\" i klass \"%s\" måste vara i klass \"%s\""
|
||
+msgstr "tecken L'\\u%0*x' i klassen ”%s” måste vara i klassen ”%s”"
|
||
|
||
#: locale/programs/ld-ctype.c:494
|
||
#, c-format
|
||
msgid "character L'\\u%0*x' in class `%s' must not be in class `%s'"
|
||
-msgstr "tecken L\"\\u%0*x\" i klass \"%s\" får inte vara i klass \"%s\""
|
||
+msgstr "tecken L'\\u%0*x' i klassen ”%s” får inte vara i klassen ”%s”"
|
||
|
||
#: locale/programs/ld-ctype.c:508 locale/programs/ld-ctype.c:566
|
||
#, c-format
|
||
@@ -2611,7 +2612,7 @@ msgstr "Skriv mer information"
|
||
|
||
#: locale/programs/locale.c:85
|
||
msgid "Get locale-specific information."
|
||
-msgstr "Hämta lokalspecifik information"
|
||
+msgstr "Hämta lokalspecifik information."
|
||
|
||
#: locale/programs/locale.c:88
|
||
msgid ""
|
||
@@ -3022,7 +3023,7 @@ msgstr "felaktig mcheck_status, biblioteket är felaktigt\n"
|
||
|
||
#: malloc/memusage.sh:32
|
||
msgid "%s: option '%s' requires an argument\\n"
|
||
-msgstr "%s: flaggan \\\"%s\\\" kräver ett argument\\n"
|
||
+msgstr "%s: flaggan ”%s” kräver ett argument\\n"
|
||
|
||
#: malloc/memusage.sh:38
|
||
msgid ""
|
||
@@ -3091,11 +3092,11 @@ msgstr ""
|
||
|
||
#: malloc/memusage.sh:191
|
||
msgid "memusage: option \\`${1##*=}' is ambiguous"
|
||
-msgstr "memusage: flaggan \"${1##*=}\" är tvetydig"
|
||
+msgstr "memusage: flaggan ”${1##*=}” är tvetydig"
|
||
|
||
#: malloc/memusage.sh:200
|
||
msgid "memusage: unrecognized option \\`$1'"
|
||
-msgstr "memusage: okänd flagga \"$1\""
|
||
+msgstr "memusage: okänd flagga ”$1”"
|
||
|
||
#: malloc/memusage.sh:213
|
||
msgid "No program name given"
|
||
@@ -3341,7 +3342,7 @@ msgstr "Kan inte skapa process hos server"
|
||
|
||
#: nis/nis_error.h:48
|
||
msgid "Master server busy, full dump rescheduled."
|
||
-msgstr "Huvudserver är upptagen, full dump åter schemalagd"
|
||
+msgstr "Huvudserver är upptagen, full dump åter schemalagd."
|
||
|
||
#: nis/nis_local_names.c:121
|
||
#, c-format
|
||
@@ -3511,7 +3512,7 @@ msgstr "\t\tRättigheter : "
|
||
|
||
#: nis/nis_print.c:290
|
||
msgid "Linked Object Type : "
|
||
-msgstr "Länkad objekttyp: "
|
||
+msgstr "Länkad objekttyp : "
|
||
|
||
#: nis/nis_print.c:292
|
||
#, c-format
|
||
@@ -3802,15 +3803,14 @@ msgid " (first)"
|
||
msgstr " (första)"
|
||
|
||
#: nscd/cache.c:288
|
||
-#, fuzzy, c-format
|
||
-#| msgid "cannot stat() file `%s': %s"
|
||
+#, c-format
|
||
msgid "checking for monitored file `%s': %s"
|
||
-msgstr "kan inte ta status på fil \"%s\": %s"
|
||
+msgstr "kontrollerar den övervakade filen ”%s”: %s"
|
||
|
||
#: nscd/cache.c:298
|
||
#, c-format
|
||
msgid "monitored file `%s` changed (mtime)"
|
||
-msgstr ""
|
||
+msgstr "den övervakade filen ”%s” ändrades (mtime)"
|
||
|
||
#: nscd/cache.c:341
|
||
#, c-format
|
||
@@ -3906,34 +3906,32 @@ msgstr "kan inte få uttag (socket) att acceptera förbindelser: %s"
|
||
#: nscd/connections.c:973
|
||
#, c-format
|
||
msgid "disabled inotify-based monitoring for file `%s': %s"
|
||
-msgstr ""
|
||
+msgstr "avaktiverade inotify-baserad övervakning för filen ”%s”: %s"
|
||
|
||
#: nscd/connections.c:977
|
||
#, c-format
|
||
msgid "monitoring file `%s` (%d)"
|
||
-msgstr ""
|
||
+msgstr "övervakar filen ”%s” (%d)"
|
||
|
||
#: nscd/connections.c:990
|
||
#, c-format
|
||
msgid "disabled inotify-based monitoring for directory `%s': %s"
|
||
-msgstr ""
|
||
+msgstr "avaktiverade inotify-baserad övervakning av katalogen ”%s”: %s"
|
||
|
||
#: nscd/connections.c:994
|
||
-#, fuzzy, c-format
|
||
-#| msgid "Can't open directory %s"
|
||
+#, c-format
|
||
msgid "monitoring directory `%s` (%d)"
|
||
-msgstr "Kan inte öppna katalog %s"
|
||
+msgstr "övervakar katalogen ”%s” (%d)"
|
||
|
||
#: nscd/connections.c:1022
|
||
-#, fuzzy, c-format
|
||
-#| msgid "register trace file %s for database %s"
|
||
+#, c-format
|
||
msgid "monitoring file %s for database %s"
|
||
-msgstr "registrera spårningsfil %s för databas %s"
|
||
+msgstr "övervakar filen %s för databas %s"
|
||
|
||
#: nscd/connections.c:1032
|
||
#, c-format
|
||
msgid "stat failed for file `%s'; will try again later: %s"
|
||
-msgstr ""
|
||
+msgstr "stat misslyckades för filen ”%s”; kommer försöka igen senare: %s"
|
||
|
||
#: nscd/connections.c:1151
|
||
#, c-format
|
||
@@ -4032,44 +4030,42 @@ msgstr "handle_request: begäran mottagen (Version = %d)"
|
||
#: nscd/connections.c:1963
|
||
#, c-format
|
||
msgid "ignored inotify event for `%s` (file exists)"
|
||
-msgstr ""
|
||
+msgstr "ignorerade inotify-händelse för ”%s” (filen finns)"
|
||
|
||
#: nscd/connections.c:1968
|
||
#, c-format
|
||
msgid "monitored file `%s` was %s, removing watch"
|
||
-msgstr ""
|
||
+msgstr "den övervakade filen ”%s” var %s, tar bort vakten"
|
||
|
||
#: nscd/connections.c:1976 nscd/connections.c:2018
|
||
#, c-format
|
||
msgid "failed to remove file watch `%s`: %s"
|
||
-msgstr ""
|
||
+msgstr "misslyckades att ta bort filvakt ”%s”: %s"
|
||
|
||
#: nscd/connections.c:1991
|
||
#, c-format
|
||
msgid "monitored file `%s` was written to"
|
||
-msgstr ""
|
||
+msgstr "den övervakade filen ”%s” skrevs till"
|
||
|
||
#: nscd/connections.c:2015
|
||
#, c-format
|
||
msgid "monitored parent directory `%s` was %s, removing watch on `%s`"
|
||
-msgstr ""
|
||
+msgstr "den övervakade föräldrakatalogen ”%s” var %s, tar bort vakten av ”%s”"
|
||
|
||
#: nscd/connections.c:2041
|
||
#, c-format
|
||
msgid "monitored file `%s` was %s, adding watch"
|
||
-msgstr ""
|
||
+msgstr "den övervakade filen ”%s” var %s, lägger till vakt"
|
||
|
||
#: nscd/connections.c:2053
|
||
-#, fuzzy, c-format
|
||
-#| msgid "failed to load shared object `%s'"
|
||
+#, c-format
|
||
msgid "failed to add file watch `%s`: %s"
|
||
-msgstr "misslyckades med att ladda delat objekt \"%s\""
|
||
+msgstr "misslyckades med att lägga till filvakt ”%s”: %s"
|
||
|
||
#: nscd/connections.c:2247 nscd/connections.c:2428
|
||
-#, fuzzy, c-format
|
||
-#| msgid "disabled inotify after read error %d"
|
||
+#, c-format
|
||
msgid "disabled inotify-based monitoring after read error %d"
|
||
-msgstr "inaktiverade inotify efter läsfel %d"
|
||
+msgstr "avaktiverade inotify-baserad övervakning efter läsfel %d"
|
||
|
||
#: nscd/connections.c:2543
|
||
msgid "could not initialize conditional variable"
|
||
@@ -4199,7 +4195,7 @@ msgstr "Använd separat cache för varje användare"
|
||
|
||
#: nscd/nscd.c:122
|
||
msgid "Name Service Cache Daemon."
|
||
-msgstr "Namntjänst cache-demon"
|
||
+msgstr "Cache-demon för namntjänsten."
|
||
|
||
#: nscd/nscd.c:155 nss/getent.c:1007 nss/makedb.c:206
|
||
#, c-format
|
||
@@ -4531,11 +4527,11 @@ msgstr "Access Vector Cache (AVC) startad"
|
||
|
||
#: nscd/selinux.c:368
|
||
msgid "Error querying policy for undefined object classes or permissions."
|
||
-msgstr "Fel när policy för odefinierade objektklasser eller rättigheter hämtades"
|
||
+msgstr "Fel när policy för odefinierade objektklasser eller rättigheter hämtades."
|
||
|
||
#: nscd/selinux.c:375
|
||
msgid "Error getting security class for nscd."
|
||
-msgstr "Fel när säkerhetsklass för nscd hämtades"
|
||
+msgstr "Fel när säkerhetsklass för nscd hämtades."
|
||
|
||
#: nscd/selinux.c:380
|
||
#, c-format
|
||
@@ -4609,7 +4605,7 @@ msgstr "inaktivera DIN-kodning"
|
||
|
||
#: nss/getent.c:64
|
||
msgid "Get entries from administrative database."
|
||
-msgstr "Hämta poster från den administrativa databasen"
|
||
+msgstr "Hämta poster från den administrativa databasen."
|
||
|
||
#: nss/getent.c:148 nss/getent.c:477 nss/getent.c:522
|
||
#, c-format
|
||
@@ -4652,7 +4648,7 @@ msgstr "Genererad rad som inte ingår i iterationen"
|
||
|
||
#: nss/makedb.c:131
|
||
msgid "Create simple database from textual input."
|
||
-msgstr "Skapa en enkel databas från textuell indata"
|
||
+msgstr "Skapa en enkel databas från textuell indata."
|
||
|
||
#: nss/makedb.c:134
|
||
msgid ""
|
||
@@ -5412,7 +5408,7 @@ msgstr "Kan inte ange netid-flaggan utan TIRPC!\n"
|
||
#: sunrpc/rpc_main.c:1374
|
||
#, c-format
|
||
msgid "Cannot use table flags with newstyle!\n"
|
||
-msgstr "Kan inte ange tabellflaggor med ny stil\n"
|
||
+msgstr "Kan inte ange tabellflaggor med ny stil!\n"
|
||
|
||
#: sunrpc/rpc_main.c:1393
|
||
#, c-format
|
||
@@ -7270,18 +7266,9 @@ msgstr "tidszonsförkortning skiljer sig från POSIX-standarden"
|
||
|
||
#: timezone/zic.c:2789
|
||
msgid "too many, or too long, time zone abbreviations"
|
||
-msgstr "för många eller för långa tidszonförkortningar"
|
||
+msgstr "för många eller för långa tidszonsförkortningar"
|
||
|
||
#: timezone/zic.c:2829
|
||
#, c-format
|
||
msgid "%s: Can't create directory %s: %s\n"
|
||
msgstr "%s: Kan inte skapa katalog %s: %s\n"
|
||
-
|
||
-#~ msgid "cannot load any more object with static TLS"
|
||
-#~ msgstr "kan inte ladda fler objekt med statiskt TLS"
|
||
-
|
||
-#~ msgid "%s: no PLTREL found in object %s\n"
|
||
-#~ msgstr "%s: hittade inga PLTREL i objekt %s\n"
|
||
-
|
||
-#~ msgid "cannot create internal descriptors"
|
||
-#~ msgstr "kan inte skapa interna deskriptorer"
|
||
diff --git a/posix/execvpe.c b/posix/execvpe.c
|
||
index d933f9c92a..7cdb06a611 100644
|
||
--- a/posix/execvpe.c
|
||
+++ b/posix/execvpe.c
|
||
@@ -48,12 +48,13 @@ maybe_script_execute (const char *file, char *const argv[], char *const envp[])
|
||
}
|
||
}
|
||
|
||
- /* Construct an argument list for the shell. */
|
||
+ /* Construct an argument list for the shell. It will contain at minimum 3
|
||
+ arguments (current shell, script, and an ending NULL. */
|
||
char *new_argv[argc + 1];
|
||
new_argv[0] = (char *) _PATH_BSHELL;
|
||
new_argv[1] = (char *) file;
|
||
if (argc > 1)
|
||
- memcpy (new_argv + 2, argv + 1, argc * sizeof(char *));
|
||
+ memcpy (new_argv + 2, argv + 1, (argc - 1) * sizeof(char *));
|
||
else
|
||
new_argv[2] = NULL;
|
||
|
||
@@ -91,10 +92,11 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||
/* Although GLIBC does not enforce NAME_MAX, we set it as the maximum
|
||
size to avoid unbounded stack allocation. Same applies for
|
||
PATH_MAX. */
|
||
- size_t file_len = __strnlen (file, NAME_MAX + 1);
|
||
+ size_t file_len = __strnlen (file, NAME_MAX) + 1;
|
||
size_t path_len = __strnlen (path, PATH_MAX - 1) + 1;
|
||
|
||
- if ((file_len > NAME_MAX)
|
||
+ /* NAME_MAX does not include the terminating null character. */
|
||
+ if (((file_len-1) > NAME_MAX)
|
||
|| !__libc_alloca_cutoff (path_len + file_len + 1))
|
||
{
|
||
errno = ENAMETOOLONG;
|
||
@@ -103,6 +105,9 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||
|
||
const char *subp;
|
||
bool got_eacces = false;
|
||
+ /* The resulting string maximum size would be potentially a entry
|
||
+ in PATH plus '/' (path_len + 1) and then the the resulting file name
|
||
+ plus '\0' (file_len since it already accounts for the '\0'). */
|
||
char buffer[path_len + file_len + 1];
|
||
for (const char *p = path; ; p = subp)
|
||
{
|
||
@@ -123,7 +128,7 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||
execute. */
|
||
char *pend = mempcpy (buffer, p, subp - p);
|
||
*pend = '/';
|
||
- memcpy (pend + (p < subp), file, file_len + 1);
|
||
+ memcpy (pend + (p < subp), file, file_len);
|
||
|
||
__execve (buffer, argv, envp);
|
||
|
||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||
index 8be41d3ae1..a4c86b9762 100644
|
||
--- a/resolv/Makefile
|
||
+++ b/resolv/Makefile
|
||
@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
|
||
extra-libs += libanl
|
||
routines += gai_sigqueue
|
||
tests += tst-res_hconf_reorder
|
||
+
|
||
+# This test sends millions of packets and is rather slow.
|
||
+xtests += tst-resolv-qtypes
|
||
endif
|
||
extra-libs-others = $(extra-libs)
|
||
libresolv-routines := gethnamaddr res_comp res_debug \
|
||
@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
|
||
$(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
|
||
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
|
||
$(evaluate-test)
|
||
+
|
||
+$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||
index 5f9e35701b..d16fa4b8ed 100644
|
||
--- a/resolv/nss_dns/dns-host.c
|
||
+++ b/resolv/nss_dns/dns-host.c
|
||
@@ -323,7 +323,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||
|
||
int olderr = errno;
|
||
enum nss_status status;
|
||
- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
|
||
+ int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
|
||
host_buffer.buf->buf, 2048, &host_buffer.ptr,
|
||
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
|
||
if (n >= 0)
|
||
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||
index 12f9730199..d80b5318e5 100644
|
||
--- a/resolv/res_mkquery.c
|
||
+++ b/resolv/res_mkquery.c
|
||
@@ -103,6 +103,10 @@ res_nmkquery(res_state statp,
|
||
int n;
|
||
u_char *dnptrs[20], **dpp, **lastdnptr;
|
||
|
||
+ if (class < 0 || class > 65535
|
||
+ || type < 0 || type > 65535)
|
||
+ return -1;
|
||
+
|
||
#ifdef DEBUG
|
||
if (statp->options & RES_DEBUG)
|
||
printf(";; res_nmkquery(%s, %s, %s, %s)\n",
|
||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||
index 944d1a90f5..07dc6f6583 100644
|
||
--- a/resolv/res_query.c
|
||
+++ b/resolv/res_query.c
|
||
@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp,
|
||
int n, use_malloc = 0;
|
||
u_int oflags = statp->_flags;
|
||
|
||
- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
|
||
+ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
|
||
u_char *buf = alloca (bufsize);
|
||
u_char *query1 = buf;
|
||
int nquery1 = -1;
|
||
@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp,
|
||
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
||
#endif
|
||
|
||
- if (type == T_UNSPEC)
|
||
+ if (type == T_QUERY_A_AND_AAAA)
|
||
{
|
||
n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
|
||
query1, bufsize);
|
||
@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp,
|
||
if (__builtin_expect (n <= 0, 0) && !use_malloc) {
|
||
/* Retry just in case res_nmkquery failed because of too
|
||
short buffer. Shouldn't happen. */
|
||
- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
|
||
+ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
|
||
buf = malloc (bufsize);
|
||
if (buf != NULL) {
|
||
query1 = buf;
|
||
diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
|
||
new file mode 100644
|
||
index 0000000000..b3e60c693b
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-qtypes.c
|
||
@@ -0,0 +1,185 @@
|
||
+/* Exercise low-level query functions with different QTYPEs.
|
||
+ Copyright (C) 2016 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+/* If ture, the response function will send the actual response packet
|
||
+ over TCP instead of UDP. */
|
||
+static volatile bool force_tcp;
|
||
+
|
||
+/* Send back a fake resource record matching the QTYPE. */
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ if (force_tcp && ctx->tcp)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, &qtype, sizeof (qtype));
|
||
+ resolv_response_close_record (b);
|
||
+}
|
||
+
|
||
+static const const char *domain = "www.example.com";
|
||
+
|
||
+static int
|
||
+wrap_res_query (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_query (domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_search (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_query (domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_querydomain ("www", "example.com", C_IN, type,
|
||
+ answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_send (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ int ret = res_mkquery (QUERY, domain, C_IN, type,
|
||
+ (const unsigned char *) "", 0, NULL,
|
||
+ buf, sizeof (buf));
|
||
+ if (type < 0 || type >= 65536)
|
||
+ {
|
||
+ /* res_mkquery fails for out-of-range record types. */
|
||
+ TEST_VERIFY_EXIT (ret == -1);
|
||
+ return -1;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||
+ return res_send (buf, ret, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nquery (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
|
||
+ answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nsend (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
|
||
+ (const unsigned char *) "", 0, NULL,
|
||
+ buf, sizeof (buf));
|
||
+ if (type < 0 || type >= 65536)
|
||
+ {
|
||
+ /* res_mkquery fails for out-of-range record types. */
|
||
+ TEST_VERIFY_EXIT (ret == -1);
|
||
+ return -1;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||
+ return res_nsend (&_res, buf, ret, answer, answer_length);
|
||
+}
|
||
+
|
||
+static void
|
||
+test_function (const char *fname,
|
||
+ int (*func) (int type,
|
||
+ unsigned char *answer, int answer_length))
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ for (int tcp = 0; tcp < 2; ++tcp)
|
||
+ {
|
||
+ force_tcp = tcp;
|
||
+ for (unsigned int type = 1; type <= 65535; ++type)
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
|
||
+ type, fname, tcp);
|
||
+ int ret = func (type, buf, sizeof (buf));
|
||
+ if (ret != 47)
|
||
+ FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
|
||
+ fname,tcp, type, ret);
|
||
+ /* One question, one answer record. */
|
||
+ TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
|
||
+ /* Question section. */
|
||
+ static const char qname[] = "\3www\7example\3com";
|
||
+ size_t qname_length = sizeof (qname);
|
||
+ TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
|
||
+ /* RDATA part of answer. */
|
||
+ uint16_t type16 = type;
|
||
+ TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
|
||
+ TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ struct resolv_redirect_config config =
|
||
+ {
|
||
+ .response_callback = response,
|
||
+ };
|
||
+ struct resolv_test *obj = resolv_test_start (config);
|
||
+
|
||
+ test_function ("res_query", &wrap_res_query);
|
||
+ test_function ("res_search", &wrap_res_search);
|
||
+ test_function ("res_querydomain", &wrap_res_querydomain);
|
||
+ test_function ("res_send", &wrap_res_send);
|
||
+
|
||
+ test_function ("res_nquery", &wrap_res_nquery);
|
||
+ test_function ("res_nsearch", &wrap_res_nsearch);
|
||
+ test_function ("res_nquerydomain", &wrap_res_nquerydomain);
|
||
+ test_function ("res_nsend", &wrap_res_nsend);
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#define TIMEOUT 300
|
||
+#include <support/test-driver.c>
|
||
diff --git a/scripts/backport-support.sh b/scripts/backport-support.sh
|
||
new file mode 100644
|
||
index 0000000000..2ece7ce575
|
||
--- /dev/null
|
||
+++ b/scripts/backport-support.sh
|
||
@@ -0,0 +1,110 @@
|
||
+#!/bin/bash
|
||
+# Create a patch which backports the support/ subdirectory.
|
||
+# Copyright (C) 2017 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
|
||
+# <http://www.gnu.org/licenses/>.
|
||
+
|
||
+# This script does not backport the Makefile tweaks outside the
|
||
+# support/ directory (which need to be backported separately), or the
|
||
+# changes to test-skeleton.c (which should not be backported).
|
||
+
|
||
+set -e
|
||
+
|
||
+export LC_ALL=C
|
||
+export GIT_CONFIG=/dev/null
|
||
+export GTT_CONFIG_NOSYSTEM=0
|
||
+export GIT_PAGER=
|
||
+
|
||
+usage () {
|
||
+ cat >&2 <<EOF
|
||
+usage: $0 {patch|commit}
|
||
+EOF
|
||
+ exit 1
|
||
+}
|
||
+
|
||
+if test $# -ne 1 ; then
|
||
+ usage
|
||
+fi
|
||
+
|
||
+command="$1"
|
||
+
|
||
+case "$command" in
|
||
+ patch|commit)
|
||
+ ;;
|
||
+ *)
|
||
+ usage
|
||
+ ;;
|
||
+esac
|
||
+
|
||
+# The upstream branch to work on.
|
||
+branch=origin/master
|
||
+
|
||
+# The commit which added the support/ directory.
|
||
+initial_commit=c23de0aacbeaa7a091609b35764bed931475a16d
|
||
+
|
||
+# We backport the support directory and this script. Directories need
|
||
+# to end in a /.
|
||
+patch_targets="support/ scripts/backport-support.sh"
|
||
+
|
||
+latest_commit="$(git log --max-count=1 --pretty=format:%H "$branch" -- \
|
||
+ $patch_targets)"
|
||
+
|
||
+# Simplify the branch name somewhat for reporting.
|
||
+branch_name="$(echo "$branch" | sed s,^origin/,,)"
|
||
+
|
||
+command_patch () {
|
||
+ cat <<EOF
|
||
+This patch creates the contents of the support/ directory up to this
|
||
+upstream commit on the $branch_name branch:
|
||
+
|
||
+EOF
|
||
+ git log --max-count=1 "$latest_commit"
|
||
+ echo
|
||
+ git diff "$initial_commit"^.."$latest_commit" $patch_targets
|
||
+ echo "# Before applying the patch, run this command:" >&2
|
||
+ echo "# rm -rf $patch_targets" >&2
|
||
+}
|
||
+
|
||
+command_commit () {
|
||
+ git status --porcelain | while read line ; do
|
||
+ echo "error: working copy is not clean, cannot commit" >&2
|
||
+ exit 1
|
||
+ done
|
||
+ for path in $patch_targets; do
|
||
+ echo "# Processing $path" >&2
|
||
+ case "$path" in
|
||
+ [a-zA-Z0-9]*/)
|
||
+ # Directory.
|
||
+ git rm --cached --ignore-unmatch -r "$path"
|
||
+ rm -rf "$path"
|
||
+ git read-tree --prefix="$path" "$latest_commit":"$path"
|
||
+ git checkout "$path"
|
||
+ ;;
|
||
+ *)
|
||
+ # File.
|
||
+ git show "$latest_commit":"$path" > "$path"
|
||
+ git add "$path"
|
||
+ esac
|
||
+ done
|
||
+ git commit -m "Synchronize support/ infrastructure with $branch_name
|
||
+
|
||
+This commit updates the support/ subdirectory to
|
||
+commit $latest_commit
|
||
+on the $branch_name branch.
|
||
+"
|
||
+}
|
||
+
|
||
+command_$command
|
||
diff --git a/support/Makefile b/support/Makefile
|
||
new file mode 100644
|
||
index 0000000000..20b0343ade
|
||
--- /dev/null
|
||
+++ b/support/Makefile
|
||
@@ -0,0 +1,146 @@
|
||
+# Makefile for support library, used only at build and test time
|
||
+# Copyright (C) 2016-2017 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
|
||
+# <http://www.gnu.org/licenses/>.
|
||
+
|
||
+subdir := support
|
||
+
|
||
+include ../Makeconfig
|
||
+
|
||
+extra-libs := libsupport
|
||
+extra-libs-others = $(extra-libs)
|
||
+extra-libs-noinstall := $(extra-libs)
|
||
+
|
||
+libsupport-routines = \
|
||
+ check \
|
||
+ check_addrinfo \
|
||
+ check_dns_packet \
|
||
+ check_hostent \
|
||
+ check_netent \
|
||
+ delayed_exit \
|
||
+ ignore_stderr \
|
||
+ oom_error \
|
||
+ resolv_test \
|
||
+ set_fortify_handler \
|
||
+ support-xstat \
|
||
+ support_become_root \
|
||
+ support_can_chroot \
|
||
+ support_capture_subprocess \
|
||
+ support_capture_subprocess_check \
|
||
+ support_enter_network_namespace \
|
||
+ support_format_address_family \
|
||
+ support_format_addrinfo \
|
||
+ support_format_dns_packet \
|
||
+ support_format_herrno \
|
||
+ support_format_hostent \
|
||
+ support_format_netent \
|
||
+ support_isolate_in_subprocess \
|
||
+ support_record_failure \
|
||
+ support_run_diff \
|
||
+ support_shared_allocate \
|
||
+ support_write_file_string \
|
||
+ support_test_main \
|
||
+ support_test_verify_impl \
|
||
+ temp_file \
|
||
+ write_message \
|
||
+ xaccept \
|
||
+ xaccept4 \
|
||
+ xasprintf \
|
||
+ xbind \
|
||
+ xcalloc \
|
||
+ xchroot \
|
||
+ xclose \
|
||
+ xconnect \
|
||
+ xdup2 \
|
||
+ xfclose \
|
||
+ xfopen \
|
||
+ xfork \
|
||
+ xgetsockname \
|
||
+ xlisten \
|
||
+ xmalloc \
|
||
+ xmemstream \
|
||
+ xmkdir \
|
||
+ xmmap \
|
||
+ xmunmap \
|
||
+ xopen \
|
||
+ xpipe \
|
||
+ xpoll \
|
||
+ xpthread_attr_destroy \
|
||
+ xpthread_attr_init \
|
||
+ xpthread_attr_setdetachstate \
|
||
+ xpthread_attr_setstacksize \
|
||
+ xpthread_barrier_destroy \
|
||
+ xpthread_barrier_init \
|
||
+ xpthread_barrier_wait \
|
||
+ xpthread_cancel \
|
||
+ xpthread_check_return \
|
||
+ xpthread_cond_wait \
|
||
+ xpthread_create \
|
||
+ xpthread_detach \
|
||
+ xpthread_join \
|
||
+ xpthread_mutex_consistent \
|
||
+ xpthread_mutex_destroy \
|
||
+ xpthread_mutex_init \
|
||
+ xpthread_mutex_lock \
|
||
+ xpthread_mutex_unlock \
|
||
+ xpthread_mutexattr_destroy \
|
||
+ xpthread_mutexattr_init \
|
||
+ xpthread_mutexattr_setprotocol \
|
||
+ xpthread_mutexattr_setpshared \
|
||
+ xpthread_mutexattr_setrobust \
|
||
+ xpthread_mutexattr_settype \
|
||
+ xpthread_once \
|
||
+ xpthread_sigmask \
|
||
+ xpthread_spin_lock \
|
||
+ xpthread_spin_unlock \
|
||
+ xrealloc \
|
||
+ xrecvfrom \
|
||
+ xsendto \
|
||
+ xsetsockopt \
|
||
+ xsocket \
|
||
+ xstrdup \
|
||
+ xwaitpid \
|
||
+ xwrite \
|
||
+
|
||
+libsupport-static-only-routines := $(libsupport-routines)
|
||
+# Only build one variant of the library.
|
||
+libsupport-inhibit-o := .os
|
||
+ifeq ($(build-shared),yes)
|
||
+libsupport-inhibit-o += .o
|
||
+endif
|
||
+
|
||
+tests = \
|
||
+ README-testing \
|
||
+ tst-support-namespace \
|
||
+ tst-support_capture_subprocess \
|
||
+ tst-support_format_dns_packet \
|
||
+ tst-support_record_failure \
|
||
+
|
||
+ifeq ($(run-built-tests),yes)
|
||
+tests-special = \
|
||
+ $(objpfx)tst-support_record_failure-2.out
|
||
+
|
||
+$(objpfx)tst-support_record_failure-2.out: tst-support_record_failure-2.sh \
|
||
+ $(objpfx)tst-support_record_failure
|
||
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
|
||
+ '$(run-program-env)' '$(test-program-prefix-after-env)' \
|
||
+ > $@; \
|
||
+ $(evaluate-test)
|
||
+endif
|
||
+
|
||
+$(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so
|
||
+
|
||
+include ../Rules
|
||
diff --git a/support/README b/support/README
|
||
new file mode 100644
|
||
index 0000000000..476cfcda59
|
||
--- /dev/null
|
||
+++ b/support/README
|
||
@@ -0,0 +1,29 @@
|
||
+This subdirectory contains infrastructure which is not put into
|
||
+installed libraries, but may be linked into programs (installed or
|
||
+not) and tests.
|
||
+
|
||
+# Error-checking wrappers
|
||
+
|
||
+These wrappers test for error return codes an terminate the process on
|
||
+error. They are declared in these header files:
|
||
+
|
||
+* support.h
|
||
+* xsignal.h
|
||
+* xthread.h
|
||
+
|
||
+In general, new wrappers should be added to support.h if possible.
|
||
+However, support.h must remain fully compatible with C90 and therefore
|
||
+cannot include headers which use identifers not reserved in C90. If
|
||
+the wrappers need additional types, additional headers such as
|
||
+signal.h need to be introduced.
|
||
+
|
||
+# Test framework
|
||
+
|
||
+The test framework provides a main program for tests, including a
|
||
+timeout for hanging tests. See README-testing.c for a minimal
|
||
+example, and test-driver.c for details how to use it. The following
|
||
+header files provide related declarations:
|
||
+
|
||
+* check.h
|
||
+* temp_file.h
|
||
+* test-driver.h
|
||
diff --git a/support/README-testing.c b/support/README-testing.c
|
||
new file mode 100644
|
||
index 0000000000..9d289c3020
|
||
--- /dev/null
|
||
+++ b/support/README-testing.c
|
||
@@ -0,0 +1,19 @@
|
||
+/* This file contains an example test case which shows minimal use of
|
||
+ the test framework. Additional testing hooks are described in
|
||
+ <support/test-driver.c>. */
|
||
+
|
||
+/* This function will be called from the test driver. */
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ if (3 == 5)
|
||
+ /* Indicate failure. */
|
||
+ return 1;
|
||
+ else
|
||
+ /* Indicate success. */
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* This file references do_test above and contains the definition of
|
||
+ the main function. */
|
||
+#include <support/test-driver.c>
|
||
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
|
||
new file mode 100644
|
||
index 0000000000..43caf9bce4
|
||
--- /dev/null
|
||
+++ b/support/capture_subprocess.h
|
||
@@ -0,0 +1,61 @@
|
||
+/* Capture output from a subprocess.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_CAPTURE_SUBPROCESS_H
|
||
+#define SUPPORT_CAPTURE_SUBPROCESS_H
|
||
+
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+struct support_capture_subprocess
|
||
+{
|
||
+ struct xmemstream out;
|
||
+ struct xmemstream err;
|
||
+ int status;
|
||
+};
|
||
+
|
||
+/* Invoke CALLBACK (CLOSURE) in a subprocess and capture standard
|
||
+ output, standard error, and the exit status. The out.buffer and
|
||
+ err.buffer members in the result are null-terminated strings which
|
||
+ can be examined by the caller (out.out and err.out are NULL). */
|
||
+struct support_capture_subprocess support_capture_subprocess
|
||
+ (void (*callback) (void *), void *closure);
|
||
+
|
||
+/* Deallocate the subprocess data captured by
|
||
+ support_capture_subprocess. */
|
||
+void support_capture_subprocess_free (struct support_capture_subprocess *);
|
||
+
|
||
+enum support_capture_allow
|
||
+{
|
||
+ /* No output is allowed. */
|
||
+ sc_allow_none = 0x01,
|
||
+ /* Output to stdout is permitted. */
|
||
+ sc_allow_stdout = 0x02,
|
||
+ /* Output to standard error is permitted. */
|
||
+ sc_allow_stderr = 0x04,
|
||
+};
|
||
+
|
||
+/* Check that the subprocess exited with STATUS and that only the
|
||
+ allowed outputs happened. ALLOWED is a combination of
|
||
+ support_capture_allow flags. Report errors under the CONTEXT
|
||
+ message. */
|
||
+void support_capture_subprocess_check (struct support_capture_subprocess *,
|
||
+ const char *context, int status,
|
||
+ int allowed)
|
||
+ __attribute__ ((nonnull (1, 2)));
|
||
+
|
||
+#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
|
||
diff --git a/support/check.c b/support/check.c
|
||
new file mode 100644
|
||
index 0000000000..592f2bc856
|
||
--- /dev/null
|
||
+++ b/support/check.c
|
||
@@ -0,0 +1,57 @@
|
||
+/* Support code for reporting test results.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/test-driver.h>
|
||
+
|
||
+static void
|
||
+print_failure (const char *file, int line, const char *format, va_list ap)
|
||
+{
|
||
+ printf ("error: %s:%d: ", file, line);
|
||
+ vprintf (format, ap);
|
||
+ puts ("");
|
||
+}
|
||
+
|
||
+int
|
||
+support_print_failure_impl (const char *file, int line,
|
||
+ const char *format, ...)
|
||
+{
|
||
+ support_record_failure ();
|
||
+ va_list ap;
|
||
+ va_start (ap, format);
|
||
+ print_failure (file, line, format, ap);
|
||
+ va_end (ap);
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+void
|
||
+support_exit_failure_impl (int status, const char *file, int line,
|
||
+ const char *format, ...)
|
||
+{
|
||
+ if (status != EXIT_SUCCESS && status != EXIT_UNSUPPORTED)
|
||
+ support_record_failure ();
|
||
+ va_list ap;
|
||
+ va_start (ap, format);
|
||
+ print_failure (file, line, format, ap);
|
||
+ va_end (ap);
|
||
+ exit (status);
|
||
+}
|
||
diff --git a/support/check.h b/support/check.h
|
||
new file mode 100644
|
||
index 0000000000..1d244a3557
|
||
--- /dev/null
|
||
+++ b/support/check.h
|
||
@@ -0,0 +1,94 @@
|
||
+/* Functionality for reporting test results.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_CHECK_H
|
||
+#define SUPPORT_CHECK_H
|
||
+
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Record a test failure, print the failure message to standard output
|
||
+ and return 1. */
|
||
+#define FAIL_RET(...) \
|
||
+ return support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
|
||
+
|
||
+/* Print the failure message and terminate the process with STATUS.
|
||
+ Record a the process as failed if STATUS is neither EXIT_SUCCESS
|
||
+ nor EXIT_UNSUPPORTED. */
|
||
+#define FAIL_EXIT(status, ...) \
|
||
+ support_exit_failure_impl (status, __FILE__, __LINE__, __VA_ARGS__)
|
||
+
|
||
+/* Record a test failure, print the failure message and terminate with
|
||
+ exit status 1. */
|
||
+#define FAIL_EXIT1(...) \
|
||
+ support_exit_failure_impl (1, __FILE__, __LINE__, __VA_ARGS__)
|
||
+
|
||
+/* Print failure message and terminate with as unsupported test (exit
|
||
+ status of 77). */
|
||
+#define FAIL_UNSUPPORTED(...) \
|
||
+ support_exit_failure_impl (77, __FILE__, __LINE__, __VA_ARGS__)
|
||
+
|
||
+/* Record a test failure (but continue executing) if EXPR evaluates to
|
||
+ false. */
|
||
+#define TEST_VERIFY(expr) \
|
||
+ ({ \
|
||
+ if (expr) \
|
||
+ ; \
|
||
+ else \
|
||
+ support_test_verify_impl (-1, __FILE__, __LINE__, #expr); \
|
||
+ })
|
||
+
|
||
+/* Record a test failure and exit if EXPR evaluates to false. */
|
||
+#define TEST_VERIFY_EXIT(expr) \
|
||
+ ({ \
|
||
+ if (expr) \
|
||
+ ; \
|
||
+ else \
|
||
+ support_test_verify_impl (1, __FILE__, __LINE__, #expr); \
|
||
+ })
|
||
+
|
||
+int support_print_failure_impl (const char *file, int line,
|
||
+ const char *format, ...)
|
||
+ __attribute__ ((nonnull (1), format (printf, 3, 4)));
|
||
+void support_exit_failure_impl (int exit_status,
|
||
+ const char *file, int line,
|
||
+ const char *format, ...)
|
||
+ __attribute__ ((noreturn, nonnull (2), format (printf, 4, 5)));
|
||
+void support_test_verify_impl (int status, const char *file, int line,
|
||
+ const char *expr);
|
||
+
|
||
+/* Record a test failure. This function returns and does not
|
||
+ terminate the process. The failure counter is stored in a shared
|
||
+ memory mapping, so that failures reported in child processes are
|
||
+ visible to the parent process and test driver. This function
|
||
+ depends on initialization by an ELF constructor, so it can only be
|
||
+ invoked after the test driver has run. Note that this function
|
||
+ does not support reporting failures from a DSO. */
|
||
+void support_record_failure (void);
|
||
+
|
||
+/* Internal function called by the test driver. */
|
||
+int support_report_failure (int status)
|
||
+ __attribute__ ((weak, warn_unused_result));
|
||
+
|
||
+/* Internal function used to test the failure recording framework. */
|
||
+void support_record_failure_reset (void);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_CHECK_H */
|
||
diff --git a/support/check_addrinfo.c b/support/check_addrinfo.c
|
||
new file mode 100644
|
||
index 0000000000..55895ace3c
|
||
--- /dev/null
|
||
+++ b/support/check_addrinfo.c
|
||
@@ -0,0 +1,42 @@
|
||
+/* Compare struct addrinfo values against a formatted string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check_nss.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/format_nss.h>
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+void
|
||
+check_addrinfo (const char *query_description, struct addrinfo *ai, int ret,
|
||
+ const char *expected)
|
||
+{
|
||
+ char *formatted = support_format_addrinfo (ai, ret);
|
||
+ if (strcmp (formatted, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: addrinfo comparison failure\n");
|
||
+ if (query_description != NULL)
|
||
+ printf ("query: %s\n", query_description);
|
||
+ support_run_diff ("expected", expected,
|
||
+ "actual", formatted);
|
||
+ }
|
||
+ free (formatted);
|
||
+}
|
||
diff --git a/support/check_dns_packet.c b/support/check_dns_packet.c
|
||
new file mode 100644
|
||
index 0000000000..d2a31bed7b
|
||
--- /dev/null
|
||
+++ b/support/check_dns_packet.c
|
||
@@ -0,0 +1,42 @@
|
||
+/* Check that a DNS packet buffer has the expected contents.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check_nss.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/format_nss.h>
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+void
|
||
+check_dns_packet (const char *query_description,
|
||
+ const unsigned char *buffer, size_t length,
|
||
+ const char *expected)
|
||
+{
|
||
+ char *formatted = support_format_dns_packet (buffer, length);
|
||
+ if (strcmp (formatted, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: packet comparison failure\n");
|
||
+ if (query_description != NULL)
|
||
+ printf ("query: %s\n", query_description);
|
||
+ support_run_diff ("expected", expected, "actual", formatted);
|
||
+ }
|
||
+ free (formatted);
|
||
+}
|
||
diff --git a/support/check_hostent.c b/support/check_hostent.c
|
||
new file mode 100644
|
||
index 0000000000..890d672d50
|
||
--- /dev/null
|
||
+++ b/support/check_hostent.c
|
||
@@ -0,0 +1,42 @@
|
||
+/* Compare struct hostent values against a formatted string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check_nss.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/format_nss.h>
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+void
|
||
+check_hostent (const char *query_description, struct hostent *h,
|
||
+ const char *expected)
|
||
+{
|
||
+ char *formatted = support_format_hostent (h);
|
||
+ if (strcmp (formatted, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: hostent comparison failure\n");
|
||
+ if (query_description != NULL)
|
||
+ printf ("query: %s\n", query_description);
|
||
+ support_run_diff ("expected", expected,
|
||
+ "actual", formatted);
|
||
+ }
|
||
+ free (formatted);
|
||
+}
|
||
diff --git a/support/check_netent.c b/support/check_netent.c
|
||
new file mode 100644
|
||
index 0000000000..daa3083fd1
|
||
--- /dev/null
|
||
+++ b/support/check_netent.c
|
||
@@ -0,0 +1,42 @@
|
||
+/* Compare struct netent values against a formatted string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check_nss.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/format_nss.h>
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+void
|
||
+check_netent (const char *query_description, struct netent *e,
|
||
+ const char *expected)
|
||
+{
|
||
+ char *formatted = support_format_netent (e);
|
||
+ if (strcmp (formatted, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: netent comparison failure\n");
|
||
+ if (query_description != NULL)
|
||
+ printf ("query: %s\n", query_description);
|
||
+ support_run_diff ("expected", expected,
|
||
+ "actual", formatted);
|
||
+ }
|
||
+ free (formatted);
|
||
+}
|
||
diff --git a/support/check_nss.h b/support/check_nss.h
|
||
new file mode 100644
|
||
index 0000000000..2893f2c295
|
||
--- /dev/null
|
||
+++ b/support/check_nss.h
|
||
@@ -0,0 +1,42 @@
|
||
+/* Test verification functions for NSS- and DNS-related data.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_CHECK_NSS_H
|
||
+#define SUPPORT_CHECK_NSS_H
|
||
+
|
||
+#include <netdb.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Compare the data structures against the expected values (which have
|
||
+ to be formatted according to the support_format_* functions in
|
||
+ <support/format_nss.h>). If there is a difference, a delayed test
|
||
+ failure is recorded, and a diff is written to standard output. */
|
||
+void check_addrinfo (const char *query_description,
|
||
+ struct addrinfo *, int ret, const char *expected);
|
||
+void check_dns_packet (const char *query_description,
|
||
+ const unsigned char *, size_t, const char *expected);
|
||
+void check_hostent (const char *query_description,
|
||
+ struct hostent *, const char *expected);
|
||
+void check_netent (const char *query_description,
|
||
+ struct netent *, const char *expected);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_CHECK_NSS_H */
|
||
diff --git a/support/delayed_exit.c b/support/delayed_exit.c
|
||
new file mode 100644
|
||
index 0000000000..67442f95df
|
||
--- /dev/null
|
||
+++ b/support/delayed_exit.c
|
||
@@ -0,0 +1,55 @@
|
||
+/* Time-triggered process termination.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+#include <support/xsignal.h>
|
||
+
|
||
+#include <stdint.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <time.h>
|
||
+
|
||
+static void *
|
||
+delayed_exit_thread (void *seconds_as_ptr)
|
||
+{
|
||
+ int seconds = (uintptr_t) seconds_as_ptr;
|
||
+ struct timespec delay = { seconds, 0 };
|
||
+ struct timespec remaining = { 0 };
|
||
+ if (nanosleep (&delay, &remaining) != 0)
|
||
+ FAIL_EXIT1 ("nanosleep: %m");
|
||
+ /* Exit the process sucessfully. */
|
||
+ exit (0);
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+void
|
||
+delayed_exit (int seconds)
|
||
+{
|
||
+ /* Create the new thread with all signals blocked. */
|
||
+ sigset_t all_blocked;
|
||
+ sigfillset (&all_blocked);
|
||
+ sigset_t old_set;
|
||
+ xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
|
||
+ /* Create a detached thread. */
|
||
+ pthread_t thr = xpthread_create
|
||
+ (NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
|
||
+ xpthread_detach (thr);
|
||
+ /* Restore the original signal mask. */
|
||
+ xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
|
||
+}
|
||
diff --git a/support/format_nss.h b/support/format_nss.h
|
||
new file mode 100644
|
||
index 0000000000..fb4597c238
|
||
--- /dev/null
|
||
+++ b/support/format_nss.h
|
||
@@ -0,0 +1,41 @@
|
||
+/* String formatting functions for NSS- and DNS-related data.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_FORMAT_NSS_H
|
||
+#define SUPPORT_FORMAT_NSS_H
|
||
+
|
||
+#include <netdb.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* The following functions format their arguments as human-readable
|
||
+ strings (which can span multiple lines). The caller must free the
|
||
+ returned buffer. For NULL pointers or failure status arguments,
|
||
+ error variables such as h_errno and errno are included in the
|
||
+ result. */
|
||
+char *support_format_address_family (int);
|
||
+char *support_format_addrinfo (struct addrinfo *, int ret);
|
||
+char *support_format_dns_packet (const unsigned char *buffer, size_t length);
|
||
+char *support_format_herrno (int);
|
||
+char *support_format_hostent (struct hostent *);
|
||
+char *support_format_netent (struct netent *);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_FORMAT_NSS_H */
|
||
diff --git a/support/ignore_stderr.c b/support/ignore_stderr.c
|
||
new file mode 100644
|
||
index 0000000000..7b77a2cd56
|
||
--- /dev/null
|
||
+++ b/support/ignore_stderr.c
|
||
@@ -0,0 +1,38 @@
|
||
+/* Avoid all the buffer overflow messages on stderr.
|
||
+ Copyright (C) 2015-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <fcntl.h>
|
||
+#include <paths.h>
|
||
+#include <stdlib.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+void
|
||
+ignore_stderr (void)
|
||
+{
|
||
+ int fd = open (_PATH_DEVNULL, O_WRONLY);
|
||
+ if (fd == -1)
|
||
+ close (STDERR_FILENO);
|
||
+ else
|
||
+ {
|
||
+ dup2 (fd, STDERR_FILENO);
|
||
+ close (fd);
|
||
+ }
|
||
+ setenv ("LIBC_FATAL_STDERR_", "1", 1);
|
||
+}
|
||
diff --git a/support/namespace.h b/support/namespace.h
|
||
new file mode 100644
|
||
index 0000000000..e1ccaa1ef0
|
||
--- /dev/null
|
||
+++ b/support/namespace.h
|
||
@@ -0,0 +1,65 @@
|
||
+/* Entering namespaces for test case isolation.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_NAMESPACE_H
|
||
+#define SUPPORT_NAMESPACE_H
|
||
+
|
||
+#include <stdbool.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Attempts to become root (or acquire root-like privileges), possibly
|
||
+ with the help of user namespaces. Return true if (restricted) root
|
||
+ privileges could be attained in some way. Print diagnostics to
|
||
+ standard output.
|
||
+
|
||
+ Note that this function generally has to be called before a process
|
||
+ becomes multi-threaded, otherwise it may fail with insufficient
|
||
+ privileges on systems which would support this operation for
|
||
+ single-threaded processes. */
|
||
+bool support_become_root (void);
|
||
+
|
||
+/* Return true if this process can perform a chroot operation. In
|
||
+ general, this is only possible if support_become_root has been
|
||
+ called. Note that the actual test is performed in a subprocess,
|
||
+ after fork, so that the file system root of the original process is
|
||
+ not changed. */
|
||
+bool support_can_chroot (void);
|
||
+
|
||
+/* Enter a network namespace (and a UTS namespace if possible) and
|
||
+ configure the loopback interface. Return true if a network
|
||
+ namespace could be created. Print diagnostics to standard output.
|
||
+ If a network namespace could be created, but networking in it could
|
||
+ not be configured, terminate the process. It is recommended to
|
||
+ call support_become_root before this function so that the process
|
||
+ has sufficient privileges. */
|
||
+bool support_enter_network_namespace (void);
|
||
+
|
||
+/* Return true if support_enter_network_namespace managed to enter a
|
||
+ UTS namespace. */
|
||
+bool support_in_uts_namespace (void);
|
||
+
|
||
+/* Invoke CALLBACK (CLOSURE) in a subprocess created using fork.
|
||
+ Terminate the calling process if the subprocess exits with a
|
||
+ non-zero exit status. */
|
||
+void support_isolate_in_subprocess (void (*callback) (void *), void *closure);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif
|
||
diff --git a/sysdeps/sparc/sparc64/fpu/s_fdimf.S b/support/oom_error.c
|
||
similarity index 69%
|
||
rename from sysdeps/sparc/sparc64/fpu/s_fdimf.S
|
||
rename to support/oom_error.c
|
||
index 356c23c4e3..7816978273 100644
|
||
--- a/sysdeps/sparc/sparc64/fpu/s_fdimf.S
|
||
+++ b/support/oom_error.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 64-bit.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* Reporting out-of-memory errors.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,15 +16,14 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
+#include <support/support.h>
|
||
|
||
-ENTRY(__fdimf)
|
||
- fcmps %f1, %f3
|
||
- fbug 1f
|
||
- nop
|
||
- fzeros %f1
|
||
- fnegs %f1, %f3
|
||
-1: retl
|
||
- fsubs %f1, %f3, %f0
|
||
-END(__fdimf)
|
||
-weak_alias (__fdimf, fdimf)
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void
|
||
+oom_error (const char *function, size_t size)
|
||
+{
|
||
+ printf ("%s: unable to allocate %zu bytes: %m\n", function, size);
|
||
+ exit (1);
|
||
+}
|
||
diff --git a/support/resolv_test.c b/support/resolv_test.c
|
||
new file mode 100644
|
||
index 0000000000..050cd7154b
|
||
--- /dev/null
|
||
+++ b/support/resolv_test.c
|
||
@@ -0,0 +1,1202 @@
|
||
+/* DNS test framework and libresolv redirection.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/resolv_test.h>
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <errno.h>
|
||
+#include <fcntl.h>
|
||
+#include <nss.h>
|
||
+#include <resolv.h>
|
||
+#include <search.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/namespace.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xsocket.h>
|
||
+#include <support/xthread.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/uio.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+/* Response builder. */
|
||
+
|
||
+enum
|
||
+ {
|
||
+ max_response_length = 65536
|
||
+ };
|
||
+
|
||
+/* List of pointers to be freed. The hash table implementation
|
||
+ (struct hsearch_data) does not provide a way to deallocate all
|
||
+ objects, so this approach is used to avoid memory leaks. */
|
||
+struct to_be_freed
|
||
+{
|
||
+ struct to_be_freed *next;
|
||
+ void *ptr;
|
||
+};
|
||
+
|
||
+struct resolv_response_builder
|
||
+{
|
||
+ const unsigned char *query_buffer;
|
||
+ size_t query_length;
|
||
+
|
||
+ size_t offset; /* Bytes written so far in buffer. */
|
||
+ ns_sect section; /* Current section in the DNS packet. */
|
||
+ unsigned int truncate_bytes; /* Bytes to remove at end of response. */
|
||
+ bool drop; /* Discard generated response. */
|
||
+ bool close; /* Close TCP client connection. */
|
||
+
|
||
+ /* Offset of the two-byte RDATA length field in the currently
|
||
+ written RDATA sub-structure. 0 if no RDATA is being written. */
|
||
+ size_t current_rdata_offset;
|
||
+
|
||
+ /* Hash table for locating targets for label compression. */
|
||
+ struct hsearch_data compression_offsets;
|
||
+ /* List of pointers which need to be freed. Used for domain names
|
||
+ involved in label compression. */
|
||
+ struct to_be_freed *to_be_freed;
|
||
+
|
||
+ /* Must be last. Not zeroed for performance reasons. */
|
||
+ unsigned char buffer[max_response_length];
|
||
+};
|
||
+
|
||
+/* Response builder. */
|
||
+
|
||
+/* Add a pointer to the list of pointers to be freed when B is
|
||
+ deallocated. */
|
||
+static void
|
||
+response_push_pointer_to_free (struct resolv_response_builder *b, void *ptr)
|
||
+{
|
||
+ if (ptr == NULL)
|
||
+ return;
|
||
+ struct to_be_freed *e = xmalloc (sizeof (*e));
|
||
+ *e = (struct to_be_freed) {b->to_be_freed, ptr};
|
||
+ b->to_be_freed = e;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_init (struct resolv_response_builder *b,
|
||
+ struct resolv_response_flags flags)
|
||
+{
|
||
+ if (b->offset > 0)
|
||
+ FAIL_EXIT1 ("response_init: called at offset %zu", b->offset);
|
||
+ if (b->query_length < 12)
|
||
+ FAIL_EXIT1 ("response_init called for a query of size %zu",
|
||
+ b->query_length);
|
||
+ if (flags.rcode > 15)
|
||
+ FAIL_EXIT1 ("response_init: invalid RCODE %u", flags.rcode);
|
||
+
|
||
+ /* Copy the transaction ID. */
|
||
+ b->buffer[0] = b->query_buffer[0];
|
||
+ b->buffer[1] = b->query_buffer[1];
|
||
+
|
||
+ /* Initialize the flags. */
|
||
+ b->buffer[2] = 0x80; /* Mark as response. */
|
||
+ b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */
|
||
+ if (flags.tc)
|
||
+ b->buffer[2] |= 0x02;
|
||
+ b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */
|
||
+
|
||
+ /* Fill in the initial section count values. */
|
||
+ b->buffer[4] = flags.qdcount >> 8;
|
||
+ b->buffer[5] = flags.qdcount;
|
||
+ b->buffer[6] = flags.ancount >> 8;
|
||
+ b->buffer[7] = flags.ancount;
|
||
+ b->buffer[8] = flags.nscount >> 8;
|
||
+ b->buffer[9] = flags.nscount;
|
||
+ b->buffer[10] = flags.adcount >> 8;
|
||
+ b->buffer[11] = flags.adcount;
|
||
+
|
||
+ b->offset = 12;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_section (struct resolv_response_builder *b, ns_sect section)
|
||
+{
|
||
+ if (b->offset == 0)
|
||
+ FAIL_EXIT1 ("resolv_response_section: response_init not called before");
|
||
+ if (section < b->section)
|
||
+ FAIL_EXIT1 ("resolv_response_section: cannot go back to previous section");
|
||
+ b->section = section;
|
||
+}
|
||
+
|
||
+/* Add a single byte to B. */
|
||
+static inline void
|
||
+response_add_byte (struct resolv_response_builder *b, unsigned char ch)
|
||
+{
|
||
+ if (b->offset == max_response_length)
|
||
+ FAIL_EXIT1 ("DNS response exceeds 64 KiB limit");
|
||
+ b->buffer[b->offset] = ch;
|
||
+ ++b->offset;
|
||
+}
|
||
+
|
||
+/* Add a 16-bit word VAL to B, in big-endian format. */
|
||
+static void
|
||
+response_add_16 (struct resolv_response_builder *b, uint16_t val)
|
||
+{
|
||
+ response_add_byte (b, val >> 8);
|
||
+ response_add_byte (b, val);
|
||
+}
|
||
+
|
||
+/* Increment the pers-section record counter in the packet header. */
|
||
+static void
|
||
+response_count_increment (struct resolv_response_builder *b)
|
||
+{
|
||
+ unsigned int offset = b->section;
|
||
+ offset = 4 + 2 * offset;
|
||
+ ++b->buffer[offset + 1];
|
||
+ if (b->buffer[offset + 1] == 0)
|
||
+ {
|
||
+ /* Carry. */
|
||
+ ++b->buffer[offset];
|
||
+ if (b->buffer[offset] == 0)
|
||
+ /* Overflow. */
|
||
+ FAIL_EXIT1 ("too many records in section");
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_add_question (struct resolv_response_builder *b,
|
||
+ const char *name, uint16_t class, uint16_t type)
|
||
+{
|
||
+ if (b->offset == 0)
|
||
+ FAIL_EXIT1 ("resolv_response_add_question: "
|
||
+ "resolv_response_init not called");
|
||
+ if (b->section != ns_s_qd)
|
||
+ FAIL_EXIT1 ("resolv_response_add_question: "
|
||
+ "must be called in the question section");
|
||
+
|
||
+ resolv_response_add_name (b, name);
|
||
+ response_add_16 (b, type);
|
||
+ response_add_16 (b, class);
|
||
+
|
||
+ response_count_increment (b);
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_add_name (struct resolv_response_builder *b,
|
||
+ const char *const origname)
|
||
+{
|
||
+ /* Normalized name. */
|
||
+ char *name;
|
||
+ /* Normalized name with case preserved. */
|
||
+ char *name_case;
|
||
+ {
|
||
+ size_t namelen = strlen (origname);
|
||
+ /* Remove trailing dots. FIXME: Handle trailing quoted dots. */
|
||
+ while (namelen > 0 && origname[namelen - 1] == '.')
|
||
+ --namelen;
|
||
+ name = xmalloc (namelen + 1);
|
||
+ name_case = xmalloc (namelen + 1);
|
||
+ /* Copy and convert to lowercase. FIXME: This needs to normalize
|
||
+ escaping as well. */
|
||
+ for (size_t i = 0; i < namelen; ++i)
|
||
+ {
|
||
+ char ch = origname[i];
|
||
+ name_case[i] = ch;
|
||
+ if ('A' <= ch && ch <= 'Z')
|
||
+ ch = ch - 'A' + 'a';
|
||
+ name[i] = ch;
|
||
+ }
|
||
+ name[namelen] = 0;
|
||
+ name_case[namelen] = 0;
|
||
+ }
|
||
+ char *name_start = name;
|
||
+ char *name_case_start = name_case;
|
||
+
|
||
+ bool compression = false;
|
||
+ while (*name)
|
||
+ {
|
||
+ /* Search for a previous name we can reference. */
|
||
+ ENTRY new_entry =
|
||
+ {
|
||
+ .key = name,
|
||
+ .data = (void *) (uintptr_t) b->offset,
|
||
+ };
|
||
+
|
||
+ /* If the label can be a compression target because it is at a
|
||
+ reachable offset, add it to the hash table. */
|
||
+ ACTION action;
|
||
+ if (b->offset < (1 << 12))
|
||
+ action = ENTER;
|
||
+ else
|
||
+ action = FIND;
|
||
+
|
||
+ /* Search for known compression offsets in the hash table. */
|
||
+ ENTRY *e;
|
||
+ if (hsearch_r (new_entry, action, &e, &b->compression_offsets) == 0)
|
||
+ {
|
||
+ if (action == FIND && errno == ESRCH)
|
||
+ /* Fall through. */
|
||
+ e = NULL;
|
||
+ else
|
||
+ FAIL_EXIT1 ("hsearch_r failure in name compression: %m");
|
||
+ }
|
||
+
|
||
+ /* The name is known. Reference the previous location. */
|
||
+ if (e != NULL && e->data != new_entry.data)
|
||
+ {
|
||
+ size_t old_offset = (uintptr_t) e->data;
|
||
+ response_add_byte (b, 0xC0 | (old_offset >> 8));
|
||
+ response_add_byte (b, old_offset);
|
||
+ compression = true;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* The name does not exist yet. Write one label. First, add
|
||
+ room for the label length. */
|
||
+ size_t buffer_label_offset = b->offset;
|
||
+ response_add_byte (b, 0);
|
||
+
|
||
+ /* Copy the label. */
|
||
+ while (true)
|
||
+ {
|
||
+ char ch = *name_case;
|
||
+ if (ch == '\0')
|
||
+ break;
|
||
+ ++name;
|
||
+ ++name_case;
|
||
+ if (ch == '.')
|
||
+ break;
|
||
+ /* FIXME: Handle escaping. */
|
||
+ response_add_byte (b, ch);
|
||
+ }
|
||
+
|
||
+ /* Patch in the label length. */
|
||
+ size_t label_length = b->offset - buffer_label_offset - 1;
|
||
+ if (label_length == 0)
|
||
+ FAIL_EXIT1 ("empty label in name compression: %s", origname);
|
||
+ if (label_length > 63)
|
||
+ FAIL_EXIT1 ("label too long in name compression: %s", origname);
|
||
+ b->buffer[buffer_label_offset] = label_length;
|
||
+
|
||
+ /* Continue with the tail of the name and the next label. */
|
||
+ }
|
||
+
|
||
+ if (compression)
|
||
+ {
|
||
+ /* If we found an immediate match for the name, we have not put
|
||
+ it into the hash table, and can free it immediately. */
|
||
+ if (name == name_start)
|
||
+ free (name_start);
|
||
+ else
|
||
+ response_push_pointer_to_free (b, name_start);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Terminate the sequence of labels. With compression, this is
|
||
+ implicit in the compression reference. */
|
||
+ response_add_byte (b, 0);
|
||
+ response_push_pointer_to_free (b, name_start);
|
||
+ }
|
||
+
|
||
+ free (name_case_start);
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_open_record (struct resolv_response_builder *b,
|
||
+ const char *name,
|
||
+ uint16_t class, uint16_t type, uint32_t ttl)
|
||
+{
|
||
+ if (b->section == ns_s_qd)
|
||
+ FAIL_EXIT1 ("resolv_response_open_record called in question section");
|
||
+ if (b->current_rdata_offset != 0)
|
||
+ FAIL_EXIT1 ("resolv_response_open_record called with open record");
|
||
+
|
||
+ resolv_response_add_name (b, name);
|
||
+ response_add_16 (b, type);
|
||
+ response_add_16 (b, class);
|
||
+ response_add_16 (b, ttl >> 16);
|
||
+ response_add_16 (b, ttl);
|
||
+
|
||
+ b->current_rdata_offset = b->offset;
|
||
+ /* Add room for the RDATA length. */
|
||
+ response_add_16 (b, 0);
|
||
+}
|
||
+
|
||
+
|
||
+void
|
||
+resolv_response_close_record (struct resolv_response_builder *b)
|
||
+{
|
||
+ size_t rdata_offset = b->current_rdata_offset;
|
||
+ if (rdata_offset == 0)
|
||
+ FAIL_EXIT1 ("response_close_record called without open record");
|
||
+ size_t rdata_length = b->offset - rdata_offset - 2;
|
||
+ if (rdata_length > 65535)
|
||
+ FAIL_EXIT1 ("RDATA length %zu exceeds limit", rdata_length);
|
||
+ b->buffer[rdata_offset] = rdata_length >> 8;
|
||
+ b->buffer[rdata_offset + 1] = rdata_length;
|
||
+ response_count_increment (b);
|
||
+ b->current_rdata_offset = 0;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_add_data (struct resolv_response_builder *b,
|
||
+ const void *data, size_t length)
|
||
+{
|
||
+ size_t remaining = max_response_length - b->offset;
|
||
+ if (remaining < length)
|
||
+ FAIL_EXIT1 ("resolv_response_add_data: not enough room for %zu bytes",
|
||
+ length);
|
||
+ memcpy (b->buffer + b->offset, data, length);
|
||
+ b->offset += length;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_drop (struct resolv_response_builder *b)
|
||
+{
|
||
+ b->drop = true;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_close (struct resolv_response_builder *b)
|
||
+{
|
||
+ b->close = true;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_response_truncate_data (struct resolv_response_builder *b, size_t count)
|
||
+{
|
||
+ if (count > 65535)
|
||
+ FAIL_EXIT1 ("resolv_response_truncate_data: argument too large: %zu",
|
||
+ count);
|
||
+ b->truncate_bytes = count;
|
||
+}
|
||
+
|
||
+
|
||
+size_t
|
||
+resolv_response_length (const struct resolv_response_builder *b)
|
||
+{
|
||
+ return b->offset;
|
||
+}
|
||
+
|
||
+unsigned char *
|
||
+resolv_response_buffer (const struct resolv_response_builder *b)
|
||
+{
|
||
+ unsigned char *result = xmalloc (b->offset);
|
||
+ memcpy (result, b->buffer, b->offset);
|
||
+ return result;
|
||
+}
|
||
+
|
||
+static struct resolv_response_builder *
|
||
+response_builder_allocate
|
||
+ (const unsigned char *query_buffer, size_t query_length)
|
||
+{
|
||
+ struct resolv_response_builder *b = xmalloc (sizeof (*b));
|
||
+ memset (b, 0, offsetof (struct resolv_response_builder, buffer));
|
||
+ b->query_buffer = query_buffer;
|
||
+ b->query_length = query_length;
|
||
+ TEST_VERIFY_EXIT (hcreate_r (10000, &b->compression_offsets) != 0);
|
||
+ return b;
|
||
+}
|
||
+
|
||
+static void
|
||
+response_builder_free (struct resolv_response_builder *b)
|
||
+{
|
||
+ struct to_be_freed *current = b->to_be_freed;
|
||
+ while (current != NULL)
|
||
+ {
|
||
+ struct to_be_freed *next = current->next;
|
||
+ free (current->ptr);
|
||
+ free (current);
|
||
+ current = next;
|
||
+ }
|
||
+ hdestroy_r (&b->compression_offsets);
|
||
+ free (b);
|
||
+}
|
||
+
|
||
+/* DNS query processing. */
|
||
+
|
||
+/* Data extracted from the question section of a DNS packet. */
|
||
+struct query_info
|
||
+{
|
||
+ char qname[MAXDNAME];
|
||
+ uint16_t qclass;
|
||
+ uint16_t qtype;
|
||
+ struct resolv_edns_info edns;
|
||
+};
|
||
+
|
||
+/* Update *INFO from the specified DNS packet. */
|
||
+static void
|
||
+parse_query (struct query_info *info,
|
||
+ const unsigned char *buffer, size_t length)
|
||
+{
|
||
+ HEADER hd;
|
||
+ _Static_assert (sizeof (hd) == 12, "DNS header size");
|
||
+ if (length < sizeof (hd))
|
||
+ FAIL_EXIT1 ("malformed DNS query: too short: %zu bytes", length);
|
||
+ memcpy (&hd, buffer, sizeof (hd));
|
||
+
|
||
+ if (ntohs (hd.qdcount) != 1)
|
||
+ FAIL_EXIT1 ("malformed DNS query: wrong question count: %d",
|
||
+ (int) ntohs (hd.qdcount));
|
||
+ if (ntohs (hd.ancount) != 0)
|
||
+ FAIL_EXIT1 ("malformed DNS query: wrong answer count: %d",
|
||
+ (int) ntohs (hd.ancount));
|
||
+ if (ntohs (hd.nscount) != 0)
|
||
+ FAIL_EXIT1 ("malformed DNS query: wrong authority count: %d",
|
||
+ (int) ntohs (hd.nscount));
|
||
+ if (ntohs (hd.arcount) > 1)
|
||
+ FAIL_EXIT1 ("malformed DNS query: wrong additional count: %d",
|
||
+ (int) ntohs (hd.arcount));
|
||
+
|
||
+ int ret = dn_expand (buffer, buffer + length, buffer + sizeof (hd),
|
||
+ info->qname, sizeof (info->qname));
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("malformed DNS query: cannot uncompress QNAME");
|
||
+
|
||
+ /* Obtain QTYPE and QCLASS. */
|
||
+ size_t remaining = length - (12 + ret);
|
||
+ struct
|
||
+ {
|
||
+ uint16_t qtype;
|
||
+ uint16_t qclass;
|
||
+ } qtype_qclass;
|
||
+ if (remaining < sizeof (qtype_qclass))
|
||
+ FAIL_EXIT1 ("malformed DNS query: "
|
||
+ "query lacks QCLASS/QTYPE, QNAME: %s", info->qname);
|
||
+ memcpy (&qtype_qclass, buffer + 12 + ret, sizeof (qtype_qclass));
|
||
+ info->qclass = ntohs (qtype_qclass.qclass);
|
||
+ info->qtype = ntohs (qtype_qclass.qtype);
|
||
+
|
||
+ memset (&info->edns, 0, sizeof (info->edns));
|
||
+ if (ntohs (hd.arcount) > 0)
|
||
+ {
|
||
+ /* Parse EDNS record. */
|
||
+ struct __attribute__ ((packed, aligned (1)))
|
||
+ {
|
||
+ uint8_t root;
|
||
+ uint16_t rtype;
|
||
+ uint16_t payload;
|
||
+ uint8_t edns_extended_rcode;
|
||
+ uint8_t edns_version;
|
||
+ uint16_t flags;
|
||
+ uint16_t rdatalen;
|
||
+ } rr;
|
||
+ _Static_assert (sizeof (rr) == 11, "EDNS record size");
|
||
+
|
||
+ if (remaining < 4 + sizeof (rr))
|
||
+ FAIL_EXIT1 ("mailformed DNS query: no room for EDNS record");
|
||
+ memcpy (&rr, buffer + 12 + ret + 4, sizeof (rr));
|
||
+ if (rr.root != 0)
|
||
+ FAIL_EXIT1 ("malformed DNS query: invalid OPT RNAME: %d\n", rr.root);
|
||
+ if (rr.rtype != htons (41))
|
||
+ FAIL_EXIT1 ("malformed DNS query: invalid OPT type: %d\n",
|
||
+ ntohs (rr.rtype));
|
||
+ info->edns.active = true;
|
||
+ info->edns.extended_rcode = rr.edns_extended_rcode;
|
||
+ info->edns.version = rr.edns_version;
|
||
+ info->edns.flags = ntohs (rr.flags);
|
||
+ info->edns.payload_size = ntohs (rr.payload);
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+/* Main testing framework. */
|
||
+
|
||
+/* Per-server information. One struct is allocated for each test
|
||
+ server. */
|
||
+struct resolv_test_server
|
||
+{
|
||
+ /* Local address of the server. UDP and TCP use the same port. */
|
||
+ struct sockaddr_in address;
|
||
+
|
||
+ /* File descriptor of the UDP server, or -1 if this server is
|
||
+ disabled. */
|
||
+ int socket_udp;
|
||
+
|
||
+ /* File descriptor of the TCP server, or -1 if this server is
|
||
+ disabled. */
|
||
+ int socket_tcp;
|
||
+
|
||
+ /* Counter of the number of responses processed so far. */
|
||
+ size_t response_number;
|
||
+
|
||
+ /* Thread handles for the server threads (if not disabled in the
|
||
+ configuration). */
|
||
+ pthread_t thread_udp;
|
||
+ pthread_t thread_tcp;
|
||
+};
|
||
+
|
||
+/* Main struct for keeping track of libresolv redirection and
|
||
+ testing. */
|
||
+struct resolv_test
|
||
+{
|
||
+ /* After initialization, any access to the struct must be performed
|
||
+ while this lock is acquired. */
|
||
+ pthread_mutex_t lock;
|
||
+
|
||
+ /* Data for each test server. */
|
||
+ struct resolv_test_server servers[resolv_max_test_servers];
|
||
+
|
||
+ /* Used if config.single_thread_udp is true. */
|
||
+ pthread_t thread_udp_single;
|
||
+
|
||
+ struct resolv_redirect_config config;
|
||
+ bool termination_requested;
|
||
+};
|
||
+
|
||
+/* Function implementing a server thread. */
|
||
+typedef void (*thread_callback) (struct resolv_test *, int server_index);
|
||
+
|
||
+/* Storage for thread-specific data, for passing to the
|
||
+ thread_callback function. */
|
||
+struct thread_closure
|
||
+{
|
||
+ struct resolv_test *obj; /* Current test object. */
|
||
+ thread_callback callback; /* Function to call. */
|
||
+ int server_index; /* Index of the implemented server. */
|
||
+};
|
||
+
|
||
+/* Wrap response_callback as a function which can be passed to
|
||
+ pthread_create. */
|
||
+static void *
|
||
+thread_callback_wrapper (void *arg)
|
||
+{
|
||
+ struct thread_closure *closure = arg;
|
||
+ closure->callback (closure->obj, closure->server_index);
|
||
+ free (closure);
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* Start a server thread for the specified SERVER_INDEX, implemented
|
||
+ by CALLBACK. */
|
||
+static pthread_t
|
||
+start_server_thread (struct resolv_test *obj, int server_index,
|
||
+ thread_callback callback)
|
||
+{
|
||
+ struct thread_closure *closure = xmalloc (sizeof (*closure));
|
||
+ *closure = (struct thread_closure)
|
||
+ {
|
||
+ .obj = obj,
|
||
+ .callback = callback,
|
||
+ .server_index = server_index,
|
||
+ };
|
||
+ return xpthread_create (NULL, thread_callback_wrapper, closure);
|
||
+}
|
||
+
|
||
+/* Process one UDP query. Return false if a termination requested has
|
||
+ been detected. */
|
||
+static bool
|
||
+server_thread_udp_process_one (struct resolv_test *obj, int server_index)
|
||
+{
|
||
+ unsigned char query[512];
|
||
+ struct sockaddr_storage peer;
|
||
+ socklen_t peerlen = sizeof (peer);
|
||
+ size_t length = xrecvfrom (obj->servers[server_index].socket_udp,
|
||
+ query, sizeof (query), 0,
|
||
+ (struct sockaddr *) &peer, &peerlen);
|
||
+ /* Check for termination. */
|
||
+ {
|
||
+ bool termination_requested;
|
||
+ xpthread_mutex_lock (&obj->lock);
|
||
+ termination_requested = obj->termination_requested;
|
||
+ xpthread_mutex_unlock (&obj->lock);
|
||
+ if (termination_requested)
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+
|
||
+ struct query_info qinfo;
|
||
+ parse_query (&qinfo, query, length);
|
||
+ if (test_verbose > 0)
|
||
+ {
|
||
+ if (test_verbose > 1)
|
||
+ printf ("info: UDP server %d: incoming query:"
|
||
+ " %zd bytes, %s/%u/%u, tnxid=0x%02x%02x\n",
|
||
+ server_index, length, qinfo.qname, qinfo.qclass, qinfo.qtype,
|
||
+ query[0], query[1]);
|
||
+ else
|
||
+ printf ("info: UDP server %d: incoming query:"
|
||
+ " %zd bytes, %s/%u/%u\n",
|
||
+ server_index, length, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ }
|
||
+
|
||
+ struct resolv_response_context ctx =
|
||
+ {
|
||
+ .query_buffer = query,
|
||
+ .query_length = length,
|
||
+ .server_index = server_index,
|
||
+ .tcp = false,
|
||
+ .edns = qinfo.edns,
|
||
+ };
|
||
+ struct resolv_response_builder *b = response_builder_allocate (query, length);
|
||
+ obj->config.response_callback
|
||
+ (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+
|
||
+ if (b->drop)
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ printf ("info: UDP server %d: dropping response to %s/%u/%u\n",
|
||
+ server_index, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ {
|
||
+ if (b->offset >= 12)
|
||
+ printf ("info: UDP server %d: sending response:"
|
||
+ " %zu bytes, RCODE %d (for %s/%u/%u)\n",
|
||
+ server_index, b->offset, b->buffer[3] & 0x0f,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ else
|
||
+ printf ("info: UDP server %d: sending response: %zu bytes"
|
||
+ " (for %s/%u/%u)\n",
|
||
+ server_index, b->offset,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ if (b->truncate_bytes > 0)
|
||
+ printf ("info: truncated by %u bytes\n", b->truncate_bytes);
|
||
+ }
|
||
+ size_t to_send = b->offset;
|
||
+ if (to_send < b->truncate_bytes)
|
||
+ to_send = 0;
|
||
+ else
|
||
+ to_send -= b->truncate_bytes;
|
||
+
|
||
+ /* Ignore most errors here because the other end may have closed
|
||
+ the socket. */
|
||
+ if (sendto (obj->servers[server_index].socket_udp,
|
||
+ b->buffer, to_send, 0,
|
||
+ (struct sockaddr *) &peer, peerlen) < 0)
|
||
+ TEST_VERIFY_EXIT (errno != EBADF);
|
||
+ }
|
||
+ response_builder_free (b);
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* UDP thread_callback function. Variant for one thread per
|
||
+ server. */
|
||
+static void
|
||
+server_thread_udp (struct resolv_test *obj, int server_index)
|
||
+{
|
||
+ while (server_thread_udp_process_one (obj, server_index))
|
||
+ ;
|
||
+}
|
||
+
|
||
+/* Single-threaded UDP processing function, for the single_thread_udp
|
||
+ case. */
|
||
+static void *
|
||
+server_thread_udp_single (void *closure)
|
||
+{
|
||
+ struct resolv_test *obj = closure;
|
||
+
|
||
+ struct pollfd fds[resolv_max_test_servers];
|
||
+ for (int server_index = 0; server_index < resolv_max_test_servers;
|
||
+ ++server_index)
|
||
+ if (obj->config.servers[server_index].disable_udp)
|
||
+ fds[server_index] = (struct pollfd) {.fd = -1};
|
||
+ else
|
||
+ {
|
||
+ fds[server_index] = (struct pollfd)
|
||
+ {
|
||
+ .fd = obj->servers[server_index].socket_udp,
|
||
+ .events = POLLIN
|
||
+ };
|
||
+
|
||
+ /* Make the socket non-blocking. */
|
||
+ int flags = fcntl (obj->servers[server_index].socket_udp, F_GETFL, 0);
|
||
+ if (flags < 0)
|
||
+ FAIL_EXIT1 ("fcntl (F_GETFL): %m");
|
||
+ flags |= O_NONBLOCK;
|
||
+ if (fcntl (obj->servers[server_index].socket_udp, F_SETFL, flags) < 0)
|
||
+ FAIL_EXIT1 ("fcntl (F_SETFL): %m");
|
||
+ }
|
||
+
|
||
+ while (true)
|
||
+ {
|
||
+ xpoll (fds, resolv_max_test_servers, -1);
|
||
+ for (int server_index = 0; server_index < resolv_max_test_servers;
|
||
+ ++server_index)
|
||
+ if (fds[server_index].revents != 0)
|
||
+ {
|
||
+ if (!server_thread_udp_process_one (obj, server_index))
|
||
+ goto out;
|
||
+ fds[server_index].revents = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ out:
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* Start the single UDP handler thread (for the single_thread_udp
|
||
+ case). */
|
||
+static void
|
||
+start_server_thread_udp_single (struct resolv_test *obj)
|
||
+{
|
||
+ obj->thread_udp_single
|
||
+ = xpthread_create (NULL, server_thread_udp_single, obj);
|
||
+}
|
||
+
|
||
+/* Data describing a TCP client connect. */
|
||
+struct tcp_thread_closure
|
||
+{
|
||
+ struct resolv_test *obj;
|
||
+ int server_index;
|
||
+ int client_socket;
|
||
+};
|
||
+
|
||
+/* Read a complete DNS query packet. If EOF_OK, an immediate
|
||
+ end-of-file condition is acceptable. */
|
||
+static bool
|
||
+read_fully (int fd, void *buf, size_t len, bool eof_ok)
|
||
+{
|
||
+ const void *const end = buf + len;
|
||
+ while (buf < end)
|
||
+ {
|
||
+ ssize_t ret = read (fd, buf, end - buf);
|
||
+ if (ret == 0)
|
||
+ {
|
||
+ if (!eof_ok)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected EOF on TCP connection\n");
|
||
+ }
|
||
+ return false;
|
||
+ }
|
||
+ else if (ret < 0)
|
||
+ {
|
||
+ if (!eof_ok || errno != ECONNRESET)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: TCP read: %m\n");
|
||
+ }
|
||
+ return false;
|
||
+ }
|
||
+ buf += ret;
|
||
+ eof_ok = false;
|
||
+ }
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* Write an array of iovecs. Terminate the process on failure. */
|
||
+static void
|
||
+writev_fully (int fd, struct iovec *buffers, size_t count)
|
||
+{
|
||
+ while (count > 0)
|
||
+ {
|
||
+ /* Skip zero-length write requests. */
|
||
+ if (buffers->iov_len == 0)
|
||
+ {
|
||
+ ++buffers;
|
||
+ --count;
|
||
+ continue;
|
||
+ }
|
||
+ /* Try to rewrite the remaing buffers. */
|
||
+ ssize_t ret = writev (fd, buffers, count);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("writev: %m");
|
||
+ if (ret == 0)
|
||
+ FAIL_EXIT1 ("writev: invalid return value zero");
|
||
+ /* Find the buffers that were successfully written. */
|
||
+ while (ret > 0)
|
||
+ {
|
||
+ if (count == 0)
|
||
+ FAIL_EXIT1 ("internal writev consistency failure");
|
||
+ /* Current buffer was partially written. */
|
||
+ if (buffers->iov_len > (size_t) ret)
|
||
+ {
|
||
+ buffers->iov_base += ret;
|
||
+ buffers->iov_len -= ret;
|
||
+ ret = 0;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ ret -= buffers->iov_len;
|
||
+ buffers->iov_len = 0;
|
||
+ ++buffers;
|
||
+ --count;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Thread callback for handling a single established TCP connection to
|
||
+ a client. */
|
||
+static void *
|
||
+server_thread_tcp_client (void *arg)
|
||
+{
|
||
+ struct tcp_thread_closure *closure = arg;
|
||
+
|
||
+ while (true)
|
||
+ {
|
||
+ /* Read packet length. */
|
||
+ uint16_t query_length;
|
||
+ if (!read_fully (closure->client_socket,
|
||
+ &query_length, sizeof (query_length), true))
|
||
+ break;
|
||
+ query_length = ntohs (query_length);
|
||
+
|
||
+ /* Read the packet. */
|
||
+ unsigned char *query_buffer = xmalloc (query_length);
|
||
+ read_fully (closure->client_socket, query_buffer, query_length, false);
|
||
+
|
||
+ struct query_info qinfo;
|
||
+ parse_query (&qinfo, query_buffer, query_length);
|
||
+ if (test_verbose > 0)
|
||
+ {
|
||
+ if (test_verbose > 1)
|
||
+ printf ("info: UDP server %d: incoming query:"
|
||
+ " %d bytes, %s/%u/%u, tnxid=0x%02x%02x\n",
|
||
+ closure->server_index, query_length,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype,
|
||
+ query_buffer[0], query_buffer[1]);
|
||
+ else
|
||
+ printf ("info: TCP server %d: incoming query:"
|
||
+ " %u bytes, %s/%u/%u\n",
|
||
+ closure->server_index, query_length,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ }
|
||
+
|
||
+ struct resolv_response_context ctx =
|
||
+ {
|
||
+ .query_buffer = query_buffer,
|
||
+ .query_length = query_length,
|
||
+ .server_index = closure->server_index,
|
||
+ .tcp = true,
|
||
+ .edns = qinfo.edns,
|
||
+ };
|
||
+ struct resolv_response_builder *b = response_builder_allocate
|
||
+ (query_buffer, query_length);
|
||
+ closure->obj->config.response_callback
|
||
+ (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+
|
||
+ if (b->drop)
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ printf ("info: TCP server %d: dropping response to %s/%u/%u\n",
|
||
+ closure->server_index,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ printf ("info: TCP server %d: sending response: %zu bytes"
|
||
+ " (for %s/%u/%u)\n",
|
||
+ closure->server_index, b->offset,
|
||
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
|
||
+ uint16_t length = htons (b->offset);
|
||
+ size_t to_send = b->offset;
|
||
+ if (to_send < b->truncate_bytes)
|
||
+ to_send = 0;
|
||
+ else
|
||
+ to_send -= b->truncate_bytes;
|
||
+ struct iovec buffers[2] =
|
||
+ {
|
||
+ {&length, sizeof (length)},
|
||
+ {b->buffer, to_send}
|
||
+ };
|
||
+ writev_fully (closure->client_socket, buffers, 2);
|
||
+ }
|
||
+ bool close_flag = b->close;
|
||
+ response_builder_free (b);
|
||
+ free (query_buffer);
|
||
+ if (close_flag)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ xclose (closure->client_socket);
|
||
+ free (closure);
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* thread_callback for the TCP case. Accept connections and create a
|
||
+ new thread for each client. */
|
||
+static void
|
||
+server_thread_tcp (struct resolv_test *obj, int server_index)
|
||
+{
|
||
+ while (true)
|
||
+ {
|
||
+ /* Get the client conenction. */
|
||
+ int client_socket = xaccept
|
||
+ (obj->servers[server_index].socket_tcp, NULL, NULL);
|
||
+
|
||
+ /* Check for termination. */
|
||
+ xpthread_mutex_lock (&obj->lock);
|
||
+ if (obj->termination_requested)
|
||
+ {
|
||
+ xpthread_mutex_unlock (&obj->lock);
|
||
+ xclose (client_socket);
|
||
+ break;
|
||
+ }
|
||
+ xpthread_mutex_unlock (&obj->lock);
|
||
+
|
||
+ /* Spawn a new thread for handling this connection. */
|
||
+ struct tcp_thread_closure *closure = xmalloc (sizeof (*closure));
|
||
+ *closure = (struct tcp_thread_closure)
|
||
+ {
|
||
+ .obj = obj,
|
||
+ .server_index = server_index,
|
||
+ .client_socket = client_socket,
|
||
+ };
|
||
+
|
||
+ pthread_t thr
|
||
+ = xpthread_create (NULL, server_thread_tcp_client, closure);
|
||
+ /* TODO: We should keep track of this thread so that we can
|
||
+ block in resolv_test_end until it has exited. */
|
||
+ xpthread_detach (thr);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Create UDP and TCP server sockets. */
|
||
+static void
|
||
+make_server_sockets (struct resolv_test_server *server)
|
||
+{
|
||
+ while (true)
|
||
+ {
|
||
+ server->socket_udp = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
+ server->socket_tcp = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
+
|
||
+ /* Pick the address for the UDP socket. */
|
||
+ server->address = (struct sockaddr_in)
|
||
+ {
|
||
+ .sin_family = AF_INET,
|
||
+ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK)}
|
||
+ };
|
||
+ xbind (server->socket_udp,
|
||
+ (struct sockaddr *)&server->address, sizeof (server->address));
|
||
+
|
||
+ /* Retrieve the address. */
|
||
+ socklen_t addrlen = sizeof (server->address);
|
||
+ xgetsockname (server->socket_udp,
|
||
+ (struct sockaddr *)&server->address, &addrlen);
|
||
+
|
||
+ /* Bind the TCP socket to the same address. */
|
||
+ {
|
||
+ int on = 1;
|
||
+ xsetsockopt (server->socket_tcp, SOL_SOCKET, SO_REUSEADDR,
|
||
+ &on, sizeof (on));
|
||
+ }
|
||
+ if (bind (server->socket_tcp,
|
||
+ (struct sockaddr *)&server->address,
|
||
+ sizeof (server->address)) != 0)
|
||
+ {
|
||
+ /* Port collision. The UDP bind succeeded, but the TCP BIND
|
||
+ failed. We assume here that the kernel will pick the
|
||
+ next local UDP address randomly. */
|
||
+ if (errno == EADDRINUSE)
|
||
+ {
|
||
+ xclose (server->socket_udp);
|
||
+ xclose (server->socket_tcp);
|
||
+ continue;
|
||
+ }
|
||
+ FAIL_EXIT1 ("TCP bind: %m");
|
||
+ }
|
||
+ xlisten (server->socket_tcp, 5);
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* One-time initialization of NSS. */
|
||
+static void
|
||
+resolv_redirect_once (void)
|
||
+{
|
||
+ /* Only use nss_dns. */
|
||
+ __nss_configure_lookup ("hosts", "dns");
|
||
+ __nss_configure_lookup ("networks", "dns");
|
||
+ /* Enter a network namespace for isolation and firewall state
|
||
+ cleanup. The tests will still work if these steps fail, but they
|
||
+ may be less reliable. */
|
||
+ support_become_root ();
|
||
+ support_enter_network_namespace ();
|
||
+}
|
||
+pthread_once_t resolv_redirect_once_var = PTHREAD_ONCE_INIT;
|
||
+
|
||
+void
|
||
+resolv_test_init (void)
|
||
+{
|
||
+ /* Perform one-time initialization of NSS. */
|
||
+ xpthread_once (&resolv_redirect_once_var, resolv_redirect_once);
|
||
+}
|
||
+
|
||
+/* Copy the search path from CONFIG.search to the _res object. */
|
||
+static void
|
||
+set_search_path (struct resolv_redirect_config config)
|
||
+{
|
||
+ memset (_res.defdname, 0, sizeof (_res.defdname));
|
||
+ memset (_res.dnsrch, 0, sizeof (_res.dnsrch));
|
||
+
|
||
+ char *current = _res.defdname;
|
||
+ char *end = current + sizeof (_res.defdname);
|
||
+
|
||
+ for (unsigned int i = 0;
|
||
+ i < sizeof (config.search) / sizeof (config.search[0]); ++i)
|
||
+ {
|
||
+ if (config.search[i] == NULL)
|
||
+ continue;
|
||
+
|
||
+ size_t length = strlen (config.search[i]) + 1;
|
||
+ size_t remaining = end - current;
|
||
+ TEST_VERIFY_EXIT (length <= remaining);
|
||
+ memcpy (current, config.search[i], length);
|
||
+ _res.dnsrch[i] = current;
|
||
+ current += length;
|
||
+ }
|
||
+}
|
||
+
|
||
+struct resolv_test *
|
||
+resolv_test_start (struct resolv_redirect_config config)
|
||
+{
|
||
+ /* Apply configuration defaults. */
|
||
+ if (config.nscount == 0)
|
||
+ config.nscount = resolv_max_test_servers;
|
||
+
|
||
+ struct resolv_test *obj = xmalloc (sizeof (*obj));
|
||
+ *obj = (struct resolv_test) {
|
||
+ .config = config,
|
||
+ .lock = PTHREAD_MUTEX_INITIALIZER,
|
||
+ };
|
||
+
|
||
+ resolv_test_init ();
|
||
+
|
||
+ /* Create all the servers, to reserve the necessary ports. */
|
||
+ for (int server_index = 0; server_index < config.nscount; ++server_index)
|
||
+ make_server_sockets (obj->servers + server_index);
|
||
+
|
||
+ /* Start server threads. Disable the server ports, as
|
||
+ requested. */
|
||
+ for (int server_index = 0; server_index < config.nscount; ++server_index)
|
||
+ {
|
||
+ struct resolv_test_server *server = obj->servers + server_index;
|
||
+ if (config.servers[server_index].disable_udp)
|
||
+ {
|
||
+ xclose (server->socket_udp);
|
||
+ server->socket_udp = -1;
|
||
+ }
|
||
+ else if (!config.single_thread_udp)
|
||
+ server->thread_udp = start_server_thread (obj, server_index,
|
||
+ server_thread_udp);
|
||
+ if (config.servers[server_index].disable_tcp)
|
||
+ {
|
||
+ xclose (server->socket_tcp);
|
||
+ server->socket_tcp = -1;
|
||
+ }
|
||
+ else
|
||
+ server->thread_tcp = start_server_thread (obj, server_index,
|
||
+ server_thread_tcp);
|
||
+ }
|
||
+ if (config.single_thread_udp)
|
||
+ start_server_thread_udp_single (obj);
|
||
+
|
||
+ int timeout = 1;
|
||
+
|
||
+ /* Initialize libresolv. */
|
||
+ TEST_VERIFY_EXIT (res_init () == 0);
|
||
+
|
||
+ /* Disable IPv6 name server addresses. The code below only
|
||
+ overrides the IPv4 addresses. */
|
||
+ __res_iclose (&_res, true);
|
||
+ _res._u._ext.nscount = 0;
|
||
+
|
||
+ /* Redirect queries to the server socket. */
|
||
+ if (test_verbose)
|
||
+ {
|
||
+ printf ("info: old timeout value: %d\n", _res.retrans);
|
||
+ printf ("info: old retry attempt value: %d\n", _res.retry);
|
||
+ printf ("info: old _res.options: 0x%lx\n", _res.options);
|
||
+ printf ("info: old _res.nscount value: %d\n", _res.nscount);
|
||
+ printf ("info: old _res.ndots value: %d\n", _res.ndots);
|
||
+ }
|
||
+ _res.retrans = timeout;
|
||
+ _res.retry = 4;
|
||
+ _res.nscount = config.nscount;
|
||
+ _res.options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
|
||
+ _res.ndots = 1;
|
||
+ if (test_verbose)
|
||
+ {
|
||
+ printf ("info: new timeout value: %d\n", _res.retrans);
|
||
+ printf ("info: new retry attempt value: %d\n", _res.retry);
|
||
+ printf ("info: new _res.options: 0x%lx\n", _res.options);
|
||
+ printf ("info: new _res.nscount value: %d\n", _res.nscount);
|
||
+ printf ("info: new _res.ndots value: %d\n", _res.ndots);
|
||
+ }
|
||
+ for (int server_index = 0; server_index < config.nscount; ++server_index)
|
||
+ {
|
||
+ _res.nsaddr_list[server_index] = obj->servers[server_index].address;
|
||
+ if (test_verbose)
|
||
+ {
|
||
+ char buf[256];
|
||
+ TEST_VERIFY_EXIT
|
||
+ (inet_ntop (AF_INET, &obj->servers[server_index].address.sin_addr,
|
||
+ buf, sizeof (buf)) != NULL);
|
||
+ printf ("info: server %d: %s/%u\n",
|
||
+ server_index, buf,
|
||
+ htons (obj->servers[server_index].address.sin_port));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ set_search_path (config);
|
||
+
|
||
+ return obj;
|
||
+}
|
||
+
|
||
+void
|
||
+resolv_test_end (struct resolv_test *obj)
|
||
+{
|
||
+ res_close ();
|
||
+
|
||
+ xpthread_mutex_lock (&obj->lock);
|
||
+ obj->termination_requested = true;
|
||
+ xpthread_mutex_unlock (&obj->lock);
|
||
+
|
||
+ /* Send trigger packets to unblock the server threads. */
|
||
+ for (int server_index = 0; server_index < obj->config.nscount;
|
||
+ ++server_index)
|
||
+ {
|
||
+ if (!obj->config.servers[server_index].disable_udp)
|
||
+ {
|
||
+ int sock = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
+ xsendto (sock, "", 1, 0,
|
||
+ (struct sockaddr *) &obj->servers[server_index].address,
|
||
+ sizeof (obj->servers[server_index].address));
|
||
+ xclose (sock);
|
||
+ }
|
||
+ if (!obj->config.servers[server_index].disable_tcp)
|
||
+ {
|
||
+ int sock = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
+ xconnect (sock,
|
||
+ (struct sockaddr *) &obj->servers[server_index].address,
|
||
+ sizeof (obj->servers[server_index].address));
|
||
+ xclose (sock);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (obj->config.single_thread_udp)
|
||
+ xpthread_join (obj->thread_udp_single);
|
||
+
|
||
+ /* Wait for the server threads to terminate. */
|
||
+ for (int server_index = 0; server_index < obj->config.nscount;
|
||
+ ++server_index)
|
||
+ {
|
||
+ if (!obj->config.servers[server_index].disable_udp)
|
||
+ {
|
||
+ if (!obj->config.single_thread_udp)
|
||
+ xpthread_join (obj->servers[server_index].thread_udp);
|
||
+ xclose (obj->servers[server_index].socket_udp);
|
||
+ }
|
||
+ if (!obj->config.servers[server_index].disable_tcp)
|
||
+ {
|
||
+ xpthread_join (obj->servers[server_index].thread_tcp);
|
||
+ xclose (obj->servers[server_index].socket_tcp);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ free (obj);
|
||
+}
|
||
diff --git a/support/resolv_test.h b/support/resolv_test.h
|
||
new file mode 100644
|
||
index 0000000000..6498751569
|
||
--- /dev/null
|
||
+++ b/support/resolv_test.h
|
||
@@ -0,0 +1,180 @@
|
||
+/* DNS test framework and libresolv redirection.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_RESOLV_TEST_H
|
||
+#define SUPPORT_RESOLV_TEST_H
|
||
+
|
||
+#include <arpa/nameser.h>
|
||
+#include <stdbool.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Information about EDNS properties of a DNS query. */
|
||
+struct resolv_edns_info
|
||
+{
|
||
+ bool active;
|
||
+ uint8_t extended_rcode;
|
||
+ uint8_t version;
|
||
+ uint16_t flags;
|
||
+ uint16_t payload_size;
|
||
+};
|
||
+
|
||
+/* This struct provides context information when the response callback
|
||
+ specified in struct resolv_redirect_config is invoked. */
|
||
+struct resolv_response_context
|
||
+{
|
||
+ const unsigned char *query_buffer;
|
||
+ size_t query_length;
|
||
+ int server_index;
|
||
+ bool tcp;
|
||
+ struct resolv_edns_info edns;
|
||
+};
|
||
+
|
||
+/* This opaque struct is used to construct responses from within the
|
||
+ response callback function. */
|
||
+struct resolv_response_builder;
|
||
+
|
||
+/* This opaque struct collects information about the resolver testing
|
||
+ currently in progress. */
|
||
+struct resolv_test;
|
||
+
|
||
+enum
|
||
+ {
|
||
+ /* Maximum number of test servers supported by the framework. */
|
||
+ resolv_max_test_servers = 3,
|
||
+ };
|
||
+
|
||
+/* Configuration settings specific to individual test servers. */
|
||
+struct resolv_redirect_server_config
|
||
+{
|
||
+ bool disable_tcp; /* If true, no TCP server is listening. */
|
||
+ bool disable_udp; /* If true, no UDP server is listening. */
|
||
+};
|
||
+
|
||
+/* Instructions for setting up the libresolv redirection. */
|
||
+struct resolv_redirect_config
|
||
+{
|
||
+ /* The response_callback function is called for every incoming DNS
|
||
+ packet, over UDP or TCP. It must be specified, the other
|
||
+ configuration settings are optional. */
|
||
+ void (*response_callback) (const struct resolv_response_context *,
|
||
+ struct resolv_response_builder *,
|
||
+ const char *qname,
|
||
+ uint16_t qclass, uint16_t qtype);
|
||
+
|
||
+ /* Per-server configuration. */
|
||
+ struct resolv_redirect_server_config servers[resolv_max_test_servers];
|
||
+
|
||
+ /* Search path entries. The first entry serves as the default
|
||
+ domain name as well. */
|
||
+ const char *search[7];
|
||
+
|
||
+ /* Number of servers to activate in resolv. 0 means the default,
|
||
+ resolv_max_test_servers. */
|
||
+ int nscount;
|
||
+
|
||
+ /* If true, use a single thread to process all UDP queries. This
|
||
+ may results in more predictable ordering of queries and
|
||
+ responses. */
|
||
+ bool single_thread_udp;
|
||
+};
|
||
+
|
||
+/* Configure NSS to use, nss_dns only for aplicable databases, and try
|
||
+ to put the process into a network namespace for better isolation.
|
||
+ This may have to be called before resolv_test_start, before the
|
||
+ process creates any threads. Otherwise, initialization is
|
||
+ performed by resolv_test_start implicitly. */
|
||
+void resolv_test_init (void);
|
||
+
|
||
+/* Initiate resolver testing. This updates the _res variable as
|
||
+ needed. As a side effect, NSS is reconfigured to use nss_dns only
|
||
+ for aplicable databases, and the process may enter a network
|
||
+ namespace for better isolation. */
|
||
+struct resolv_test *resolv_test_start (struct resolv_redirect_config);
|
||
+
|
||
+/* Call this function at the end of resolver testing, to free
|
||
+ resources and report pending errors (if any). */
|
||
+void resolv_test_end (struct resolv_test *);
|
||
+
|
||
+/* The remaining facilities in this file are used for constructing
|
||
+ response packets from the response_callback function. */
|
||
+
|
||
+/* Special settings for constructing responses from the callback. */
|
||
+struct resolv_response_flags
|
||
+{
|
||
+ /* 4-bit response code to incorporate into the response. */
|
||
+ unsigned char rcode;
|
||
+
|
||
+ /* If true, the TC (truncation) flag will be set. */
|
||
+ bool tc;
|
||
+
|
||
+ /* Initial section count values. Can be used to artificially
|
||
+ increase the counts, for malformed packet testing.*/
|
||
+ unsigned short qdcount;
|
||
+ unsigned short ancount;
|
||
+ unsigned short nscount;
|
||
+ unsigned short adcount;
|
||
+};
|
||
+
|
||
+/* Begin a new response with the requested flags. Must be called
|
||
+ first. */
|
||
+void resolv_response_init (struct resolv_response_builder *,
|
||
+ struct resolv_response_flags);
|
||
+
|
||
+/* Switches to the section in the response packet. Only forward
|
||
+ movement is supported. */
|
||
+void resolv_response_section (struct resolv_response_builder *, ns_sect);
|
||
+
|
||
+/* Add a question record to the question section. */
|
||
+void resolv_response_add_question (struct resolv_response_builder *,
|
||
+ const char *name, uint16_t class,
|
||
+ uint16_t type);
|
||
+/* Starts a new resource record with the specified owner name, class,
|
||
+ type, and TTL. Data is supplied with resolv_response_add_data or
|
||
+ resolv_response_add_name. */
|
||
+void resolv_response_open_record (struct resolv_response_builder *,
|
||
+ const char *name, uint16_t class,
|
||
+ uint16_t type, uint32_t ttl);
|
||
+
|
||
+/* Add unstructed bytes to the RDATA part of a resource record. */
|
||
+void resolv_response_add_data (struct resolv_response_builder *,
|
||
+ const void *, size_t);
|
||
+
|
||
+/* Add a compressed domain name to the RDATA part of a resource
|
||
+ record. */
|
||
+void resolv_response_add_name (struct resolv_response_builder *,
|
||
+ const char *name);
|
||
+
|
||
+/* Mark the end of the constructed record. Must be called last. */
|
||
+void resolv_response_close_record (struct resolv_response_builder *);
|
||
+
|
||
+/* Drop this query packet (that is, do not send a response, not even
|
||
+ an empty packet). */
|
||
+void resolv_response_drop (struct resolv_response_builder *);
|
||
+
|
||
+/* In TCP mode, close the connection after this packet (if a response
|
||
+ is sent). */
|
||
+void resolv_response_close (struct resolv_response_builder *);
|
||
+
|
||
+/* The size of the response packet built so far. */
|
||
+size_t resolv_response_length (const struct resolv_response_builder *);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_RESOLV_TEST_H */
|
||
diff --git a/support/run_diff.h b/support/run_diff.h
|
||
new file mode 100644
|
||
index 0000000000..f65b5dd22c
|
||
--- /dev/null
|
||
+++ b/support/run_diff.h
|
||
@@ -0,0 +1,31 @@
|
||
+/* Invoke the system diff tool to compare two strings.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_RUN_DIFF_H
|
||
+#define SUPPORT_RUN_DIFF_H
|
||
+
|
||
+/* Compare the two NUL-terminated strings LEFT and RIGHT using the
|
||
+ diff tool. Label the sides of the diff with LEFT_LABEL and
|
||
+ RIGHT_LABEL, respectively.
|
||
+
|
||
+ This function assumes that LEFT and RIGHT are different
|
||
+ strings. */
|
||
+void support_run_diff (const char *left_label, const char *left,
|
||
+ const char *right_label, const char *right);
|
||
+
|
||
+#endif /* SUPPORT_RUN_DIFF_H */
|
||
diff --git a/support/set_fortify_handler.c b/support/set_fortify_handler.c
|
||
new file mode 100644
|
||
index 0000000000..f434a8082a
|
||
--- /dev/null
|
||
+++ b/support/set_fortify_handler.c
|
||
@@ -0,0 +1,34 @@
|
||
+/* Set signal handler for use in fortify tests.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <signal.h>
|
||
+
|
||
+void
|
||
+set_fortify_handler (void (*handler) (int sig))
|
||
+{
|
||
+ struct sigaction sa;
|
||
+
|
||
+ sa.sa_handler = handler;
|
||
+ sa.sa_flags = 0;
|
||
+ sigemptyset (&sa.sa_mask);
|
||
+
|
||
+ sigaction (SIGABRT, &sa, NULL);
|
||
+ ignore_stderr ();
|
||
+}
|
||
diff --git a/support/support-xstat.c b/support/support-xstat.c
|
||
new file mode 100644
|
||
index 0000000000..86a81ec601
|
||
--- /dev/null
|
||
+++ b/support/support-xstat.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* stat64 with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* NB: Non-standard file name to avoid sysdeps override for xstat. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/stat.h>
|
||
+
|
||
+void
|
||
+xstat (const char *path, struct stat64 *result)
|
||
+{
|
||
+ if (stat64 (path, result) != 0)
|
||
+ FAIL_EXIT1 ("stat64 (\"%s\"): %m", path);
|
||
+}
|
||
diff --git a/support/support.h b/support/support.h
|
||
new file mode 100644
|
||
index 0000000000..4b5f04c2cc
|
||
--- /dev/null
|
||
+++ b/support/support.h
|
||
@@ -0,0 +1,74 @@
|
||
+/* Common extra functions.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This header file should only contain definitions compatible with
|
||
+ C90. (Using __attribute__ is fine because <features.h> provides a
|
||
+ fallback.) */
|
||
+
|
||
+#ifndef SUPPORT_H
|
||
+#define SUPPORT_H
|
||
+
|
||
+#include <stddef.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Write a message to standard output. Can be used in signal
|
||
+ handlers. */
|
||
+void write_message (const char *message) __attribute__ ((nonnull (1)));
|
||
+
|
||
+/* Avoid all the buffer overflow messages on stderr. */
|
||
+void ignore_stderr (void);
|
||
+
|
||
+/* Set fortification error handler. Used when tests want to verify that bad
|
||
+ code is caught by the library. */
|
||
+void set_fortify_handler (void (*handler) (int sig));
|
||
+
|
||
+/* Report an out-of-memory error for the allocation of SIZE bytes in
|
||
+ FUNCTION, terminating the process. */
|
||
+void oom_error (const char *function, size_t size)
|
||
+ __attribute__ ((nonnull (1)));
|
||
+
|
||
+/* Return a pointer to a memory region of SIZE bytes. The memory is
|
||
+ initialized to zero and will be shared with subprocesses (across
|
||
+ fork). The returned pointer must be freed using
|
||
+ support_shared_free; it is not compatible with the malloc
|
||
+ functions. */
|
||
+void *support_shared_allocate (size_t size);
|
||
+
|
||
+/* Deallocate a pointer returned by support_shared_allocate. */
|
||
+void support_shared_free (void *);
|
||
+
|
||
+/* Write CONTENTS to the file PATH. Create or truncate the file as
|
||
+ needed. The file mode is 0666 masked by the umask. Terminate the
|
||
+ process on error. */
|
||
+void support_write_file_string (const char *path, const char *contents);
|
||
+
|
||
+/* Error-checking wrapper functions which terminate the process on
|
||
+ error. */
|
||
+
|
||
+void *xmalloc (size_t) __attribute__ ((malloc));
|
||
+void *xcalloc (size_t n, size_t s) __attribute__ ((malloc));
|
||
+void *xrealloc (void *p, size_t n);
|
||
+char *xasprintf (const char *format, ...)
|
||
+ __attribute__ ((format (printf, 1, 2), malloc));
|
||
+char *xstrdup (const char *);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_H */
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/s_fdim.S b/support/support_become_root.c
|
||
similarity index 57%
|
||
rename from sysdeps/sparc/sparc32/sparcv9/fpu/s_fdim.S
|
||
rename to support/support_become_root.c
|
||
index 37f7f44dfa..3fa0bd4ac0 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/s_fdim.S
|
||
+++ b/support/support_become_root.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit+v9.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* Acquire root privileges.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,24 +16,25 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
-#include <math_ldbl_opt.h>
|
||
+#include <support/namespace.h>
|
||
|
||
-ENTRY(__fdim)
|
||
- std %o0, [%sp + 72]
|
||
- std %o2, [%sp + 80]
|
||
- ldd [%sp + 72], %f0
|
||
- ldd [%sp + 80], %f2
|
||
- fcmpd %f0, %f2
|
||
- fbug 1f
|
||
- nop
|
||
- fzero %f0
|
||
- fnegd %f0, %f2
|
||
-1: retl
|
||
- fsubd %f0, %f2, %f0
|
||
-END(__fdim)
|
||
-weak_alias (__fdim, fdim)
|
||
+#include <sched.h>
|
||
+#include <stdio.h>
|
||
+#include <unistd.h>
|
||
|
||
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
|
||
-compat_symbol (libm, __fdim, fdiml, GLIBC_2_1);
|
||
+bool
|
||
+support_become_root (void)
|
||
+{
|
||
+#ifdef CLONE_NEWUSER
|
||
+ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0)
|
||
+ /* Even if we do not have UID zero, we have extended privileges at
|
||
+ this point. */
|
||
+ return true;
|
||
#endif
|
||
+ if (setuid (0) != 0)
|
||
+ {
|
||
+ printf ("warning: could not become root outside namespace (%m)\n");
|
||
+ return false;
|
||
+ }
|
||
+ return true;
|
||
+}
|
||
diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c
|
||
new file mode 100644
|
||
index 0000000000..0dfd2deb54
|
||
--- /dev/null
|
||
+++ b/support/support_can_chroot.c
|
||
@@ -0,0 +1,65 @@
|
||
+/* Return true if the process can perform a chroot operation.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <stdio.h>
|
||
+#include <support/check.h>
|
||
+#include <support/namespace.h>
|
||
+#include <support/support.h>
|
||
+#include <sys/stat.h>
|
||
+#include <unistd.h>
|
||
+#include <xunistd.h>
|
||
+
|
||
+static void
|
||
+callback (void *closure)
|
||
+{
|
||
+ int *result = closure;
|
||
+ struct stat64 before;
|
||
+ xstat ("/dev", &before);
|
||
+ if (chroot ("/dev") != 0)
|
||
+ {
|
||
+ *result = errno;
|
||
+ return;
|
||
+ }
|
||
+ struct stat64 after;
|
||
+ xstat ("/", &after);
|
||
+ TEST_VERIFY (before.st_dev == after.st_dev);
|
||
+ TEST_VERIFY (before.st_ino == after.st_ino);
|
||
+ *result = 0;
|
||
+}
|
||
+
|
||
+bool
|
||
+support_can_chroot (void)
|
||
+{
|
||
+ int *result = support_shared_allocate (sizeof (*result));
|
||
+ *result = 0;
|
||
+ support_isolate_in_subprocess (callback, result);
|
||
+ bool ok = *result == 0;
|
||
+ if (!ok)
|
||
+ {
|
||
+ static bool already_warned;
|
||
+ if (!already_warned)
|
||
+ {
|
||
+ already_warned = true;
|
||
+ errno = *result;
|
||
+ printf ("warning: this process does not support chroot: %m\n");
|
||
+ }
|
||
+ }
|
||
+ support_shared_free (result);
|
||
+ return ok;
|
||
+}
|
||
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
|
||
new file mode 100644
|
||
index 0000000000..030f124252
|
||
--- /dev/null
|
||
+++ b/support/support_capture_subprocess.c
|
||
@@ -0,0 +1,108 @@
|
||
+/* Capture output from a subprocess.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/capture_subprocess.h>
|
||
+
|
||
+#include <errno.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+static void
|
||
+transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
|
||
+{
|
||
+ if (pfd->revents != 0)
|
||
+ {
|
||
+ char buf[1024];
|
||
+ ssize_t ret = TEMP_FAILURE_RETRY (read (pfd->fd, buf, sizeof (buf)));
|
||
+ if (ret < 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: reading from subprocess %s: %m", what);
|
||
+ pfd->events = 0;
|
||
+ pfd->revents = 0;
|
||
+ }
|
||
+ else if (ret == 0)
|
||
+ {
|
||
+ /* EOF reached. Stop listening. */
|
||
+ pfd->events = 0;
|
||
+ pfd->revents = 0;
|
||
+ }
|
||
+ else
|
||
+ /* Store the data just read. */
|
||
+ TEST_VERIFY (fwrite (buf, ret, 1, stream->out) == 1);
|
||
+ }
|
||
+}
|
||
+
|
||
+struct support_capture_subprocess
|
||
+support_capture_subprocess (void (*callback) (void *), void *closure)
|
||
+{
|
||
+ struct support_capture_subprocess result;
|
||
+ xopen_memstream (&result.out);
|
||
+ xopen_memstream (&result.err);
|
||
+
|
||
+ int stdout_pipe[2];
|
||
+ xpipe (stdout_pipe);
|
||
+ int stderr_pipe[2];
|
||
+ xpipe (stderr_pipe);
|
||
+
|
||
+ TEST_VERIFY (fflush (stdout) == 0);
|
||
+ TEST_VERIFY (fflush (stderr) == 0);
|
||
+
|
||
+ pid_t pid = xfork ();
|
||
+ if (pid == 0)
|
||
+ {
|
||
+ xclose (stdout_pipe[0]);
|
||
+ xclose (stderr_pipe[0]);
|
||
+ xdup2 (stdout_pipe[1], STDOUT_FILENO);
|
||
+ xdup2 (stderr_pipe[1], STDERR_FILENO);
|
||
+ callback (closure);
|
||
+ _exit (0);
|
||
+ }
|
||
+ xclose (stdout_pipe[1]);
|
||
+ xclose (stderr_pipe[1]);
|
||
+
|
||
+ struct pollfd fds[2] =
|
||
+ {
|
||
+ { .fd = stdout_pipe[0], .events = POLLIN },
|
||
+ { .fd = stderr_pipe[0], .events = POLLIN },
|
||
+ };
|
||
+
|
||
+ do
|
||
+ {
|
||
+ xpoll (fds, 2, -1);
|
||
+ transfer ("stdout", &fds[0], &result.out);
|
||
+ transfer ("stderr", &fds[1], &result.err);
|
||
+ }
|
||
+ while (fds[0].events != 0 || fds[1].events != 0);
|
||
+ xclose (stdout_pipe[0]);
|
||
+ xclose (stderr_pipe[0]);
|
||
+
|
||
+ xfclose_memstream (&result.out);
|
||
+ xfclose_memstream (&result.err);
|
||
+ xwaitpid (pid, &result.status, 0);
|
||
+ return result;
|
||
+}
|
||
+
|
||
+void
|
||
+support_capture_subprocess_free (struct support_capture_subprocess *p)
|
||
+{
|
||
+ free (p->out.buffer);
|
||
+ free (p->err.buffer);
|
||
+}
|
||
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
|
||
new file mode 100644
|
||
index 0000000000..708c89f331
|
||
--- /dev/null
|
||
+++ b/support/support_capture_subprocess_check.c
|
||
@@ -0,0 +1,67 @@
|
||
+/* Verify capture output from a subprocess.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <stdbool.h>
|
||
+#include <stdio.h>
|
||
+#include <support/capture_subprocess.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+static void
|
||
+print_context (const char *context, bool *failed)
|
||
+{
|
||
+ if (*failed)
|
||
+ /* Do not duplicate message. */
|
||
+ return;
|
||
+ support_record_failure ();
|
||
+ printf ("error: subprocess failed: %s\n", context);
|
||
+}
|
||
+
|
||
+void
|
||
+support_capture_subprocess_check (struct support_capture_subprocess *proc,
|
||
+ const char *context, int status,
|
||
+ int allowed)
|
||
+{
|
||
+ TEST_VERIFY ((allowed & sc_allow_none)
|
||
+ || (allowed & sc_allow_stdout)
|
||
+ || (allowed & sc_allow_stderr));
|
||
+ TEST_VERIFY (!((allowed & sc_allow_none)
|
||
+ && ((allowed & sc_allow_stdout)
|
||
+ || (allowed & sc_allow_stderr))));
|
||
+
|
||
+ bool failed = false;
|
||
+ if (proc->status != status)
|
||
+ {
|
||
+ print_context (context, &failed);
|
||
+ printf ("error: expected exit status: %d\n", status);
|
||
+ printf ("error: actual exit status: %d\n", status);
|
||
+ }
|
||
+ if (!(allowed & sc_allow_stdout) && proc->out.length != 0)
|
||
+ {
|
||
+ print_context (context, &failed);
|
||
+ printf ("error: unexpected output from subprocess\n");
|
||
+ fwrite (proc->out.buffer, proc->out.length, 1, stdout);
|
||
+ puts ("\n");
|
||
+ }
|
||
+ if (!(allowed & sc_allow_stderr) && proc->err.length != 0)
|
||
+ {
|
||
+ print_context (context, &failed);
|
||
+ printf ("error: unexpected error output from subprocess\n");
|
||
+ fwrite (proc->err.buffer, proc->err.length, 1, stdout);
|
||
+ puts ("\n");
|
||
+ }
|
||
+}
|
||
diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c
|
||
new file mode 100644
|
||
index 0000000000..28b0ee29cf
|
||
--- /dev/null
|
||
+++ b/support/support_enter_network_namespace.c
|
||
@@ -0,0 +1,75 @@
|
||
+/* Enter a network namespace.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/namespace.h>
|
||
+
|
||
+#include <net/if.h>
|
||
+#include <sched.h>
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/xsocket.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/ioctl.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+static bool in_uts_namespace;
|
||
+
|
||
+bool
|
||
+support_enter_network_namespace (void)
|
||
+{
|
||
+#ifdef CLONE_NEWUTS
|
||
+ if (unshare (CLONE_NEWUTS) == 0)
|
||
+ in_uts_namespace = true;
|
||
+ else
|
||
+ printf ("warning: unshare (CLONE_NEWUTS) failed: %m\n");
|
||
+#endif
|
||
+
|
||
+#ifdef CLONE_NEWNET
|
||
+ if (unshare (CLONE_NEWNET) == 0)
|
||
+ {
|
||
+ /* Bring up the loopback interface. */
|
||
+ int fd = xsocket (AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||
+ struct ifreq req;
|
||
+ strcpy (req.ifr_name, "lo");
|
||
+ TEST_VERIFY_EXIT (ioctl (fd, SIOCGIFFLAGS, &req) == 0);
|
||
+ bool already_up = req.ifr_flags & IFF_UP;
|
||
+ if (already_up)
|
||
+ /* This means that we likely have not achieved isolation from
|
||
+ the parent namespace. */
|
||
+ printf ("warning: loopback interface already exists"
|
||
+ " in new network namespace\n");
|
||
+ else
|
||
+ {
|
||
+ req.ifr_flags |= IFF_UP | IFF_RUNNING;
|
||
+ TEST_VERIFY_EXIT (ioctl (fd, SIOCSIFFLAGS, &req) == 0);
|
||
+ }
|
||
+ xclose (fd);
|
||
+
|
||
+ return !already_up;
|
||
+ }
|
||
+#endif
|
||
+ printf ("warning: could not enter network namespace\n");
|
||
+ return false;
|
||
+}
|
||
+
|
||
+bool
|
||
+support_in_uts_namespace (void)
|
||
+{
|
||
+ return in_uts_namespace;
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/s_fdimf.S b/support/support_format_address_family.c
|
||
similarity index 63%
|
||
rename from sysdeps/sparc/sparc32/sparcv9/fpu/s_fdimf.S
|
||
rename to support/support_format_address_family.c
|
||
index 9e0e3f21be..5d42c42a45 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/s_fdimf.S
|
||
+++ b/support/support_format_address_family.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit+v9.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* Convert an address family to a string.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,19 +16,20 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
+#include <support/format_nss.h>
|
||
|
||
-ENTRY(__fdimf)
|
||
- st %o0, [%sp + 72]
|
||
- st %o1, [%sp + 76]
|
||
- ld [%sp + 72], %f0
|
||
- ld [%sp + 76], %f1
|
||
- fcmps %f0, %f1
|
||
- fbug 1f
|
||
- nop
|
||
- fzeros %f0
|
||
- fnegs %f0, %f1
|
||
-1: retl
|
||
- fsubs %f0, %f1, %f0
|
||
-END(__fdimf)
|
||
-weak_alias (__fdimf, fdimf)
|
||
+#include <support/support.h>
|
||
+
|
||
+char *
|
||
+support_format_address_family (int family)
|
||
+{
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ return xstrdup ("INET");
|
||
+ case AF_INET6:
|
||
+ return xstrdup ("INET6");
|
||
+ default:
|
||
+ return xasprintf ("<unknown address family %d>", family);
|
||
+ }
|
||
+}
|
||
diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c
|
||
new file mode 100644
|
||
index 0000000000..eedb030591
|
||
--- /dev/null
|
||
+++ b/support/support_format_addrinfo.c
|
||
@@ -0,0 +1,239 @@
|
||
+/* Convert struct addrinfo values to a string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/format_nss.h>
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <errno.h>
|
||
+#include <stdio.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+static size_t
|
||
+socket_address_length (int family)
|
||
+{
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ return sizeof (struct sockaddr_in);
|
||
+ case AF_INET6:
|
||
+ return sizeof (struct sockaddr_in6);
|
||
+ default:
|
||
+ return -1;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+format_ai_flags_1 (FILE *out, struct addrinfo *ai, int flag, const char *name,
|
||
+ int * flags_printed)
|
||
+{
|
||
+ if ((ai->ai_flags & flag) != 0)
|
||
+ fprintf (out, " %s", name);
|
||
+ *flags_printed |= flag;
|
||
+}
|
||
+
|
||
+static void
|
||
+format_ai_flags (FILE *out, struct addrinfo *ai)
|
||
+{
|
||
+ if (ai == NULL)
|
||
+ return;
|
||
+
|
||
+ if (ai->ai_flags != 0)
|
||
+ {
|
||
+ fprintf (out, "flags:");
|
||
+ int flags_printed = 0;
|
||
+#define FLAG(flag) format_ai_flags_1 (out, ai, flag, #flag, &flags_printed)
|
||
+ FLAG (AI_PASSIVE);
|
||
+ FLAG (AI_CANONNAME);
|
||
+ FLAG (AI_NUMERICHOST);
|
||
+ FLAG (AI_V4MAPPED);
|
||
+ FLAG (AI_ALL);
|
||
+ FLAG (AI_ADDRCONFIG);
|
||
+ FLAG (AI_IDN);
|
||
+ FLAG (AI_CANONIDN);
|
||
+ FLAG (AI_IDN_ALLOW_UNASSIGNED);
|
||
+ FLAG (AI_IDN_USE_STD3_ASCII_RULES);
|
||
+ FLAG (AI_NUMERICSERV);
|
||
+#undef FLAG
|
||
+ int remaining = ai->ai_flags & ~flags_printed;
|
||
+ if (remaining != 0)
|
||
+ fprintf (out, " %08x", remaining);
|
||
+ fprintf (out, "\n");
|
||
+ }
|
||
+
|
||
+ /* Report flag mismatches within the list. */
|
||
+ int flags = ai->ai_flags;
|
||
+ int index = 1;
|
||
+ ai = ai->ai_next;
|
||
+ while (ai != NULL)
|
||
+ {
|
||
+ if (ai->ai_flags != flags)
|
||
+ fprintf (out, "error: flags at %d: 0x%x expected, 0x%x actual\n",
|
||
+ index, flags, ai->ai_flags);
|
||
+ ai = ai->ai_next;
|
||
+ ++index;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+format_ai_canonname (FILE *out, struct addrinfo *ai)
|
||
+{
|
||
+ if (ai == NULL)
|
||
+ return;
|
||
+ if (ai->ai_canonname != NULL)
|
||
+ fprintf (out, "canonname: %s\n", ai->ai_canonname);
|
||
+
|
||
+ /* Report incorrectly set ai_canonname fields on subsequent list
|
||
+ entries. */
|
||
+ int index = 1;
|
||
+ ai = ai->ai_next;
|
||
+ while (ai != NULL)
|
||
+ {
|
||
+ if (ai->ai_canonname != NULL)
|
||
+ fprintf (out, "error: canonname set at %d: %s\n",
|
||
+ index, ai->ai_canonname);
|
||
+ ai = ai->ai_next;
|
||
+ ++index;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+format_ai_one (FILE *out, struct addrinfo *ai)
|
||
+{
|
||
+ {
|
||
+ char type_buf[32];
|
||
+ const char *type_str;
|
||
+ char proto_buf[32];
|
||
+ const char *proto_str;
|
||
+
|
||
+ /* ai_socktype */
|
||
+ switch (ai->ai_socktype)
|
||
+ {
|
||
+ case SOCK_RAW:
|
||
+ type_str = "RAW";
|
||
+ break;
|
||
+ case SOCK_DGRAM:
|
||
+ type_str = "DGRAM";
|
||
+ break;
|
||
+ case SOCK_STREAM:
|
||
+ type_str = "STREAM";
|
||
+ break;
|
||
+ default:
|
||
+ snprintf (type_buf, sizeof (type_buf), "%d", ai->ai_socktype);
|
||
+ type_str = type_buf;
|
||
+ }
|
||
+
|
||
+ /* ai_protocol */
|
||
+ switch (ai->ai_protocol)
|
||
+ {
|
||
+ case IPPROTO_IP:
|
||
+ proto_str = "IP";
|
||
+ break;
|
||
+ case IPPROTO_UDP:
|
||
+ proto_str = "UDP";
|
||
+ break;
|
||
+ case IPPROTO_TCP:
|
||
+ proto_str = "TCP";
|
||
+ break;
|
||
+ default:
|
||
+ snprintf (proto_buf, sizeof (proto_buf), "%d", ai->ai_protocol);
|
||
+ proto_str = proto_buf;
|
||
+ }
|
||
+ fprintf (out, "address: %s/%s", type_str, proto_str);
|
||
+ }
|
||
+
|
||
+ /* ai_addrlen */
|
||
+ if (ai->ai_addrlen != socket_address_length (ai->ai_family))
|
||
+ {
|
||
+ char *family = support_format_address_family (ai->ai_family);
|
||
+ fprintf (out, "error: invalid address length %d for %s\n",
|
||
+ ai->ai_addrlen, family);
|
||
+ free (family);
|
||
+ }
|
||
+
|
||
+ /* ai_addr */
|
||
+ {
|
||
+ char buf[128];
|
||
+ uint16_t port;
|
||
+ const char *ret;
|
||
+ switch (ai->ai_family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ {
|
||
+ struct sockaddr_in *sin = (struct sockaddr_in *) ai->ai_addr;
|
||
+ ret = inet_ntop (AF_INET, &sin->sin_addr, buf, sizeof (buf));
|
||
+ port = sin->sin_port;
|
||
+ }
|
||
+ break;
|
||
+ case AF_INET6:
|
||
+ {
|
||
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) ai->ai_addr;
|
||
+ ret = inet_ntop (AF_INET6, &sin->sin6_addr, buf, sizeof (buf));
|
||
+ port = sin->sin6_port;
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ errno = EAFNOSUPPORT;
|
||
+ ret = NULL;
|
||
+ }
|
||
+ if (ret == NULL)
|
||
+ fprintf (out, "error: inet_top failed: %m\n");
|
||
+ else
|
||
+ fprintf (out, " %s %u\n", buf, ntohs (port));
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Format all the addresses in one address family. */
|
||
+static void
|
||
+format_ai_family (FILE *out, struct addrinfo *ai, int family)
|
||
+{
|
||
+ while (ai)
|
||
+ {
|
||
+ if (ai->ai_family == family)
|
||
+ format_ai_one (out, ai);
|
||
+ ai = ai->ai_next;
|
||
+ }
|
||
+}
|
||
+
|
||
+char *
|
||
+support_format_addrinfo (struct addrinfo *ai, int ret)
|
||
+{
|
||
+ int errno_copy = errno;
|
||
+
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+ if (ret != 0)
|
||
+ {
|
||
+ fprintf (mem.out, "error: %s\n", gai_strerror (ret));
|
||
+ if (ret == EAI_SYSTEM)
|
||
+ {
|
||
+ errno = errno_copy;
|
||
+ fprintf (mem.out, "error: %m\n");
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ format_ai_flags (mem.out, ai);
|
||
+ format_ai_canonname (mem.out, ai);
|
||
+ format_ai_family (mem.out, ai, AF_INET);
|
||
+ format_ai_family (mem.out, ai, AF_INET6);
|
||
+ }
|
||
+
|
||
+ xfclose_memstream (&mem);
|
||
+ return mem.buffer;
|
||
+}
|
||
diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c
|
||
new file mode 100644
|
||
index 0000000000..2992c57971
|
||
--- /dev/null
|
||
+++ b/support/support_format_dns_packet.c
|
||
@@ -0,0 +1,222 @@
|
||
+/* Convert a DNS packet to a human-readable representation.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/format_nss.h>
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <resolv.h>
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+struct in_buffer
|
||
+{
|
||
+ const unsigned char *data;
|
||
+ size_t size;
|
||
+};
|
||
+
|
||
+static inline bool
|
||
+extract_8 (struct in_buffer *in, unsigned char *value)
|
||
+{
|
||
+ if (in->size == 0)
|
||
+ return false;
|
||
+ *value = in->data[0];
|
||
+ ++in->data;
|
||
+ --in->size;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+static inline bool
|
||
+extract_16 (struct in_buffer *in, unsigned short *value)
|
||
+{
|
||
+ if (in->size < 2)
|
||
+ return false;
|
||
+ *value = (in->data[0] << 8) | in->data[1];
|
||
+ in->data += 2;
|
||
+ in->size -= 2;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+static inline bool
|
||
+extract_32 (struct in_buffer *in, unsigned *value)
|
||
+{
|
||
+ if (in->size < 4)
|
||
+ return false;
|
||
+ unsigned a = in->data[0];
|
||
+ unsigned b = in->data[1];
|
||
+ unsigned c = in->data[2];
|
||
+ unsigned d = in->data[3];
|
||
+ *value = (a << 24) | (b << 16) | (c << 8) | d;
|
||
+ in->data += 4;
|
||
+ in->size -= 4;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+static inline bool
|
||
+extract_bytes (struct in_buffer *in, size_t length, struct in_buffer *value)
|
||
+{
|
||
+ if (in->size < length)
|
||
+ return false;
|
||
+ *value = (struct in_buffer) {in->data, length};
|
||
+ in->data += length;
|
||
+ in->size -= length;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+struct dname
|
||
+{
|
||
+ char name[MAXDNAME + 1];
|
||
+};
|
||
+
|
||
+static bool
|
||
+extract_name (struct in_buffer full, struct in_buffer *in, struct dname *value)
|
||
+{
|
||
+ const unsigned char *full_end = full.data + full.size;
|
||
+ /* Sanity checks; these indicate buffer misuse. */
|
||
+ TEST_VERIFY_EXIT
|
||
+ (!(in->data < full.data || in->data > full_end
|
||
+ || in->size > (size_t) (full_end - in->data)));
|
||
+ int ret = dn_expand (full.data, full_end, in->data,
|
||
+ value->name, sizeof (value->name));
|
||
+ if (ret < 0)
|
||
+ return false;
|
||
+ in->data += ret;
|
||
+ in->size -= ret;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+char *
|
||
+support_format_dns_packet (const unsigned char *buffer, size_t length)
|
||
+{
|
||
+ struct in_buffer full = { buffer, length };
|
||
+ struct in_buffer in = full;
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+
|
||
+ unsigned short txnid;
|
||
+ unsigned short flags;
|
||
+ unsigned short qdcount;
|
||
+ unsigned short ancount;
|
||
+ unsigned short nscount;
|
||
+ unsigned short adcount;
|
||
+ if (!(extract_16 (&in, &txnid)
|
||
+ && extract_16 (&in, &flags)
|
||
+ && extract_16 (&in, &qdcount)
|
||
+ && extract_16 (&in, &ancount)
|
||
+ && extract_16 (&in, &nscount)
|
||
+ && extract_16 (&in, &adcount)))
|
||
+ {
|
||
+ fprintf (mem.out, "error: could not parse DNS header\n");
|
||
+ goto out;
|
||
+ }
|
||
+ if (qdcount != 1)
|
||
+ {
|
||
+ fprintf (mem.out, "error: question count is %d, not 1\n", qdcount);
|
||
+ goto out;
|
||
+ }
|
||
+ struct dname qname;
|
||
+ if (!extract_name (full, &in, &qname))
|
||
+ {
|
||
+ fprintf (mem.out, "error: malformed QNAME\n");
|
||
+ goto out;
|
||
+ }
|
||
+ unsigned short qtype;
|
||
+ unsigned short qclass;
|
||
+ if (!(extract_16 (&in, &qtype)
|
||
+ && extract_16 (&in, &qclass)))
|
||
+ {
|
||
+ fprintf (mem.out, "error: malformed question\n");
|
||
+ goto out;
|
||
+ }
|
||
+ if (qtype != T_A && qtype != T_AAAA && qtype != T_PTR)
|
||
+ {
|
||
+ fprintf (mem.out, "error: unsupported QTYPE %d\n", qtype);
|
||
+ goto out;
|
||
+ }
|
||
+
|
||
+ fprintf (mem.out, "name: %s\n", qname.name);
|
||
+
|
||
+ for (int i = 0; i < ancount; ++i)
|
||
+ {
|
||
+ struct dname rname;
|
||
+ if (!extract_name (full, &in, &rname))
|
||
+ {
|
||
+ fprintf (mem.out, "error: malformed record name\n");
|
||
+ goto out;
|
||
+ }
|
||
+ unsigned short rtype;
|
||
+ unsigned short rclass;
|
||
+ unsigned ttl;
|
||
+ unsigned short rdlen;
|
||
+ struct in_buffer rdata;
|
||
+ if (!(extract_16 (&in, &rtype)
|
||
+ && extract_16 (&in, &rclass)
|
||
+ && extract_32 (&in, &ttl)
|
||
+ && extract_16 (&in, &rdlen)
|
||
+ && extract_bytes (&in, rdlen, &rdata)))
|
||
+ {
|
||
+ fprintf (mem.out, "error: malformed record header\n");
|
||
+ goto out;
|
||
+ }
|
||
+ /* Skip non-matching record types. */
|
||
+ if ((rtype != qtype && rtype != T_CNAME) || rclass != qclass)
|
||
+ continue;
|
||
+ switch (rtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ if (rdlen == 4)
|
||
+ fprintf (mem.out, "address: %d.%d.%d.%d\n",
|
||
+ rdata.data[0],
|
||
+ rdata.data[1],
|
||
+ rdata.data[2],
|
||
+ rdata.data[3]);
|
||
+ else
|
||
+ fprintf (mem.out, "error: A record of size %d: %s\n",
|
||
+ rdlen, rname.name);
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ if (rdlen == 16)
|
||
+ {
|
||
+ char buf[100];
|
||
+ if (inet_ntop (AF_INET6, rdata.data, buf, sizeof (buf)) == NULL)
|
||
+ fprintf (mem.out, "error: AAAA record decoding failed: %m\n");
|
||
+ else
|
||
+ fprintf (mem.out, "address: %s\n", buf);
|
||
+ }
|
||
+ else
|
||
+ fprintf (mem.out, "error: AAAA record of size %d: %s\n",
|
||
+ rdlen, rname.name);
|
||
+ }
|
||
+ break;
|
||
+ case T_CNAME:
|
||
+ case T_PTR:
|
||
+ {
|
||
+ struct dname name;
|
||
+ if (extract_name (full, &rdata, &name))
|
||
+ fprintf (mem.out, "name: %s\n", name.name);
|
||
+ else
|
||
+ fprintf (mem.out, "error: malformed CNAME/PTR record\n");
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ out:
|
||
+ xfclose_memstream (&mem);
|
||
+ return mem.buffer;
|
||
+}
|
||
diff --git a/support/support_format_herrno.c b/support/support_format_herrno.c
|
||
new file mode 100644
|
||
index 0000000000..493d6ae962
|
||
--- /dev/null
|
||
+++ b/support/support_format_herrno.c
|
||
@@ -0,0 +1,45 @@
|
||
+/* Convert a h_errno error code to a string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/format_nss.h>
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+char *
|
||
+support_format_herrno (int code)
|
||
+{
|
||
+ const char *errstr;
|
||
+ switch (code)
|
||
+ {
|
||
+ case HOST_NOT_FOUND:
|
||
+ errstr = "HOST_NOT_FOUND";
|
||
+ break;
|
||
+ case NO_ADDRESS:
|
||
+ errstr = "NO_ADDRESS";
|
||
+ break;
|
||
+ case NO_RECOVERY:
|
||
+ errstr = "NO_RECOVERY";
|
||
+ break;
|
||
+ case TRY_AGAIN:
|
||
+ errstr = "TRY_AGAIN";
|
||
+ break;
|
||
+ default:
|
||
+ return xasprintf ("<invalid h_errno value %d>\n", code);
|
||
+ }
|
||
+ return xstrdup (errstr);
|
||
+}
|
||
diff --git a/support/support_format_hostent.c b/support/support_format_hostent.c
|
||
new file mode 100644
|
||
index 0000000000..5b5f26082e
|
||
--- /dev/null
|
||
+++ b/support/support_format_hostent.c
|
||
@@ -0,0 +1,75 @@
|
||
+/* Convert a struct hostent object to a string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/format_nss.h>
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <stdio.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+static int
|
||
+address_length (int family)
|
||
+{
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ return 4;
|
||
+ case AF_INET6:
|
||
+ return 16;
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+char *
|
||
+support_format_hostent (struct hostent *h)
|
||
+{
|
||
+ if (h == NULL)
|
||
+ {
|
||
+ char *value = support_format_herrno (h_errno);
|
||
+ char *result = xasprintf ("error: %s\n", value);
|
||
+ free (value);
|
||
+ return result;
|
||
+ }
|
||
+
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+
|
||
+ fprintf (mem.out, "name: %s\n", h->h_name);
|
||
+ for (char **alias = h->h_aliases; *alias != NULL; ++alias)
|
||
+ fprintf (mem.out, "alias: %s\n", *alias);
|
||
+ for (unsigned i = 0; h->h_addr_list[i] != NULL; ++i)
|
||
+ {
|
||
+ char buf[128];
|
||
+ if (inet_ntop (h->h_addrtype, h->h_addr_list[i],
|
||
+ buf, sizeof (buf)) == NULL)
|
||
+ fprintf (mem.out, "error: inet_ntop failed: %m\n");
|
||
+ else
|
||
+ fprintf (mem.out, "address: %s\n", buf);
|
||
+ }
|
||
+ if (h->h_length != address_length (h->h_addrtype))
|
||
+ {
|
||
+ char *family = support_format_address_family (h->h_addrtype);
|
||
+ fprintf (mem.out, "error: invalid address length %d for %s\n",
|
||
+ h->h_length, family);
|
||
+ free (family);
|
||
+ }
|
||
+
|
||
+ xfclose_memstream (&mem);
|
||
+ return mem.buffer;
|
||
+}
|
||
diff --git a/support/support_format_netent.c b/support/support_format_netent.c
|
||
new file mode 100644
|
||
index 0000000000..020f5720d9
|
||
--- /dev/null
|
||
+++ b/support/support_format_netent.c
|
||
@@ -0,0 +1,52 @@
|
||
+/* Convert a struct netent object to a string.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/format_nss.h>
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <stdio.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+char *
|
||
+support_format_netent (struct netent *e)
|
||
+{
|
||
+ if (e == NULL)
|
||
+ {
|
||
+ char *value = support_format_herrno (h_errno);
|
||
+ char *result = xasprintf ("error: %s\n", value);
|
||
+ free (value);
|
||
+ return result;
|
||
+ }
|
||
+
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+
|
||
+ if (e->n_name != NULL)
|
||
+ fprintf (mem.out, "name: %s\n", e->n_name);
|
||
+ for (char **ap = e->n_aliases; *ap != NULL; ++ap)
|
||
+ fprintf (mem.out, "alias: %s\n", *ap);
|
||
+ if (e->n_addrtype != AF_INET)
|
||
+ fprintf (mem.out, "addrtype: %d\n", e->n_addrtype);
|
||
+ /* On alpha, e->n_net is an unsigned long. */
|
||
+ unsigned int n_net = e->n_net;
|
||
+ fprintf (mem.out, "net: 0x%08x\n", n_net);
|
||
+
|
||
+ xfclose_memstream (&mem);
|
||
+ return mem.buffer;
|
||
+}
|
||
diff --git a/support/support_isolate_in_subprocess.c b/support/support_isolate_in_subprocess.c
|
||
new file mode 100644
|
||
index 0000000000..cf48614383
|
||
--- /dev/null
|
||
+++ b/support/support_isolate_in_subprocess.c
|
||
@@ -0,0 +1,38 @@
|
||
+/* Run a function in a subprocess.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+void
|
||
+support_isolate_in_subprocess (void (*callback) (void *), void *closure)
|
||
+{
|
||
+ pid_t pid = xfork ();
|
||
+ if (pid == 0)
|
||
+ {
|
||
+ /* Child process. */
|
||
+ callback (closure);
|
||
+ _exit (0);
|
||
+ }
|
||
+
|
||
+ /* Parent process. */
|
||
+ int status;
|
||
+ xwaitpid (pid, &status, 0);
|
||
+ if (status != 0)
|
||
+ FAIL_EXIT1 ("child process exited with status %d", status);
|
||
+}
|
||
diff --git a/support/support_record_failure.c b/support/support_record_failure.c
|
||
new file mode 100644
|
||
index 0000000000..684055c746
|
||
--- /dev/null
|
||
+++ b/support/support_record_failure.c
|
||
@@ -0,0 +1,106 @@
|
||
+/* Global test failure counter.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+
|
||
+#include <stdbool.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <sys/mman.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+/* This structure keeps track of test failures. The counter is
|
||
+ incremented on each failure. The failed member is set to true if a
|
||
+ failure is detected, so that even if the counter wraps around to
|
||
+ zero, the failure of a test can be detected.
|
||
+
|
||
+ The init constructor function below puts *state on a shared
|
||
+ annonymous mapping, so that failure reports from subprocesses
|
||
+ propagate to the parent process. */
|
||
+struct test_failures
|
||
+{
|
||
+ unsigned int counter;
|
||
+ unsigned int failed;
|
||
+};
|
||
+static struct test_failures *state;
|
||
+
|
||
+static __attribute__ ((constructor)) void
|
||
+init (void)
|
||
+{
|
||
+ void *ptr = mmap (NULL, sizeof (*state), PROT_READ | PROT_WRITE,
|
||
+ MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||
+ if (ptr == MAP_FAILED)
|
||
+ {
|
||
+ printf ("error: could not map %zu bytes: %m\n", sizeof (*state));
|
||
+ exit (1);
|
||
+ }
|
||
+ /* Zero-initialization of the struct is sufficient. */
|
||
+ state = ptr;
|
||
+}
|
||
+
|
||
+void
|
||
+support_record_failure (void)
|
||
+{
|
||
+ if (state == NULL)
|
||
+ {
|
||
+ write_message
|
||
+ ("error: support_record_failure called without initialization\n");
|
||
+ _exit (1);
|
||
+ }
|
||
+ /* Relaxed MO is sufficient because we are only interested in the
|
||
+ values themselves, in isolation. */
|
||
+ __atomic_store_n (&state->failed, 1, __ATOMIC_RELEASE);
|
||
+ __atomic_add_fetch (&state->counter, 1, __ATOMIC_RELEASE);
|
||
+}
|
||
+
|
||
+int
|
||
+support_report_failure (int status)
|
||
+{
|
||
+ if (state == NULL)
|
||
+ {
|
||
+ write_message
|
||
+ ("error: support_report_failure called without initialization\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ /* Relaxed MO is sufficient because acquire test result reporting
|
||
+ assumes that exiting from the main thread happens before the
|
||
+ error reporting via support_record_failure, which requires some
|
||
+ form of external synchronization. */
|
||
+ bool failed = __atomic_load_n (&state->failed, __ATOMIC_RELAXED);
|
||
+ if (failed)
|
||
+ printf ("error: %u test failures\n",
|
||
+ __atomic_load_n (&state->counter, __ATOMIC_RELAXED));
|
||
+
|
||
+ if ((status == 0 || status == EXIT_UNSUPPORTED) && failed)
|
||
+ /* If we have a recorded failure, it overrides a non-failure
|
||
+ report from the test function. */
|
||
+ status = 1;
|
||
+ return status;
|
||
+}
|
||
+
|
||
+void
|
||
+support_record_failure_reset (void)
|
||
+{
|
||
+ /* Only used for testing the test framework, with external
|
||
+ synchronization, but use release MO for consistency. */
|
||
+ __atomic_store_n (&state->failed, 0, __ATOMIC_RELAXED);
|
||
+ __atomic_add_fetch (&state->counter, 0, __ATOMIC_RELAXED);
|
||
+}
|
||
diff --git a/support/support_run_diff.c b/support/support_run_diff.c
|
||
new file mode 100644
|
||
index 0000000000..f5155de727
|
||
--- /dev/null
|
||
+++ b/support/support_run_diff.c
|
||
@@ -0,0 +1,76 @@
|
||
+/* Invoke the system diff tool to compare two strings.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <support/temp_file.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/wait.h>
|
||
+
|
||
+static char *
|
||
+write_to_temp_file (const char *prefix, const char *str)
|
||
+{
|
||
+ char *template = xasprintf ("run_diff-%s", prefix);
|
||
+ char *name = NULL;
|
||
+ int fd = create_temp_file (template, &name);
|
||
+ TEST_VERIFY_EXIT (fd >= 0);
|
||
+ free (template);
|
||
+ xwrite (fd, str, strlen (str));
|
||
+ xclose (fd);
|
||
+ return name;
|
||
+}
|
||
+
|
||
+void
|
||
+support_run_diff (const char *left_label, const char *left,
|
||
+ const char *right_label, const char *right)
|
||
+{
|
||
+ /* Ensure that the diff command output is ordered properly with
|
||
+ standard output. */
|
||
+ TEST_VERIFY_EXIT (fflush (stdout) == 0);
|
||
+
|
||
+ char *left_path = write_to_temp_file ("left-diff", left);
|
||
+ char *right_path = write_to_temp_file ("right-diff", right);
|
||
+
|
||
+ pid_t pid = xfork ();
|
||
+ if (pid == 0)
|
||
+ {
|
||
+ execlp ("diff", "diff", "-u",
|
||
+ "--label", left_label, "--label", right_label,
|
||
+ "--", left_path, right_path,
|
||
+ NULL);
|
||
+ _exit (17);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ int status;
|
||
+ xwaitpid (pid, &status, 0);
|
||
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 1)
|
||
+ printf ("warning: could not run diff, exit status: %d\n"
|
||
+ "*** %s ***\n%s\n"
|
||
+ "*** %s ***\n%s\n",
|
||
+ status, left_label, left, right_label, right);
|
||
+ }
|
||
+
|
||
+ free (right_path);
|
||
+ free (left_path);
|
||
+}
|
||
diff --git a/support/support_shared_allocate.c b/support/support_shared_allocate.c
|
||
new file mode 100644
|
||
index 0000000000..61d088e8cf
|
||
--- /dev/null
|
||
+++ b/support/support_shared_allocate.c
|
||
@@ -0,0 +1,57 @@
|
||
+/* Allocate a memory region shared across processes.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <stddef.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/mman.h>
|
||
+
|
||
+/* Header for the allocation. It contains the size of the allocation
|
||
+ for subsequent unmapping. */
|
||
+struct header
|
||
+{
|
||
+ size_t total_size;
|
||
+ char data[] __attribute__ ((aligned (__alignof__ (max_align_t))));
|
||
+};
|
||
+
|
||
+void *
|
||
+support_shared_allocate (size_t size)
|
||
+{
|
||
+ size_t total_size = size + offsetof (struct header, data);
|
||
+ if (total_size < size)
|
||
+ {
|
||
+ errno = ENOMEM;
|
||
+ oom_error (__func__, size);
|
||
+ return NULL;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ struct header *result = xmmap (NULL, total_size, PROT_READ | PROT_WRITE,
|
||
+ MAP_ANONYMOUS | MAP_SHARED, -1);
|
||
+ result->total_size = total_size;
|
||
+ return &result->data;
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+support_shared_free (void *data)
|
||
+{
|
||
+ struct header *header = data - offsetof (struct header, data);
|
||
+ xmunmap (header, header->total_size);
|
||
+}
|
||
diff --git a/support/support_test_main.c b/support/support_test_main.c
|
||
new file mode 100644
|
||
index 0000000000..914d64f603
|
||
--- /dev/null
|
||
+++ b/support/support_test_main.c
|
||
@@ -0,0 +1,423 @@
|
||
+/* Main worker function for the test driver.
|
||
+ Copyright (C) 1998-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/test-driver.h>
|
||
+#include <support/check.h>
|
||
+#include <support/temp_file-internal.h>
|
||
+
|
||
+#include <assert.h>
|
||
+#include <errno.h>
|
||
+#include <getopt.h>
|
||
+#include <malloc.h>
|
||
+#include <signal.h>
|
||
+#include <stdbool.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <sys/param.h>
|
||
+#include <sys/resource.h>
|
||
+#include <sys/types.h>
|
||
+#include <sys/wait.h>
|
||
+#include <time.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+static const struct option default_options[] =
|
||
+{
|
||
+ TEST_DEFAULT_OPTIONS
|
||
+ { NULL, 0, NULL, 0 }
|
||
+};
|
||
+
|
||
+/* Show people how to run the program. */
|
||
+static void
|
||
+usage (const struct option *options)
|
||
+{
|
||
+ size_t i;
|
||
+
|
||
+ printf ("Usage: %s [options]\n"
|
||
+ "\n"
|
||
+ "Environment Variables:\n"
|
||
+ " TIMEOUTFACTOR An integer used to scale the timeout\n"
|
||
+ " TMPDIR Where to place temporary files\n"
|
||
+ " TEST_COREDUMPS Do not disable coredumps if set\n"
|
||
+ "\n",
|
||
+ program_invocation_short_name);
|
||
+ printf ("Options:\n");
|
||
+ for (i = 0; options[i].name; ++i)
|
||
+ {
|
||
+ int indent;
|
||
+
|
||
+ indent = printf (" --%s", options[i].name);
|
||
+ if (options[i].has_arg == required_argument)
|
||
+ indent += printf (" <arg>");
|
||
+ printf ("%*s", 25 - indent, "");
|
||
+ switch (options[i].val)
|
||
+ {
|
||
+ case 'v':
|
||
+ printf ("Increase the output verbosity");
|
||
+ break;
|
||
+ case OPT_DIRECT:
|
||
+ printf ("Run the test directly (instead of forking & monitoring)");
|
||
+ break;
|
||
+ case OPT_TESTDIR:
|
||
+ printf ("Override the TMPDIR env var");
|
||
+ break;
|
||
+ }
|
||
+ printf ("\n");
|
||
+ }
|
||
+}
|
||
+
|
||
+/* The PID of the test process. */
|
||
+static pid_t test_pid;
|
||
+
|
||
+/* The cleanup handler passed to test_main. */
|
||
+static void (*cleanup_function) (void);
|
||
+
|
||
+/* Timeout handler. We kill the child and exit with an error. */
|
||
+static void
|
||
+__attribute__ ((noreturn))
|
||
+signal_handler (int sig)
|
||
+{
|
||
+ int killed;
|
||
+ int status;
|
||
+
|
||
+ assert (test_pid > 1);
|
||
+ /* Kill the whole process group. */
|
||
+ kill (-test_pid, SIGKILL);
|
||
+ /* In case setpgid failed in the child, kill it individually too. */
|
||
+ kill (test_pid, SIGKILL);
|
||
+
|
||
+ /* Wait for it to terminate. */
|
||
+ int i;
|
||
+ for (i = 0; i < 5; ++i)
|
||
+ {
|
||
+ killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
|
||
+ if (killed != 0)
|
||
+ break;
|
||
+
|
||
+ /* Delay, give the system time to process the kill. If the
|
||
+ nanosleep() call return prematurely, all the better. We
|
||
+ won't restart it since this probably means the child process
|
||
+ finally died. */
|
||
+ struct timespec ts;
|
||
+ ts.tv_sec = 0;
|
||
+ ts.tv_nsec = 100000000;
|
||
+ nanosleep (&ts, NULL);
|
||
+ }
|
||
+ if (killed != 0 && killed != test_pid)
|
||
+ {
|
||
+ printf ("Failed to kill test process: %m\n");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ if (cleanup_function != NULL)
|
||
+ cleanup_function ();
|
||
+
|
||
+ if (sig == SIGINT)
|
||
+ {
|
||
+ signal (sig, SIG_DFL);
|
||
+ raise (sig);
|
||
+ }
|
||
+
|
||
+ if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
|
||
+ puts ("Timed out: killed the child process");
|
||
+ else if (WIFSTOPPED (status))
|
||
+ printf ("Timed out: the child process was %s\n",
|
||
+ strsignal (WSTOPSIG (status)));
|
||
+ else if (WIFSIGNALED (status))
|
||
+ printf ("Timed out: the child process got signal %s\n",
|
||
+ strsignal (WTERMSIG (status)));
|
||
+ else
|
||
+ printf ("Timed out: killed the child process but it exited %d\n",
|
||
+ WEXITSTATUS (status));
|
||
+
|
||
+ /* Exit with an error. */
|
||
+ exit (1);
|
||
+}
|
||
+
|
||
+/* Run test_function or test_function_argv. */
|
||
+static int
|
||
+run_test_function (int argc, char **argv, const struct test_config *config)
|
||
+{
|
||
+ if (config->test_function != NULL)
|
||
+ return config->test_function ();
|
||
+ else if (config->test_function_argv != NULL)
|
||
+ return config->test_function_argv (argc, argv);
|
||
+ else
|
||
+ {
|
||
+ printf ("error: no test function defined\n");
|
||
+ exit (1);
|
||
+ }
|
||
+}
|
||
+
|
||
+static bool test_main_called;
|
||
+
|
||
+const char *test_dir = NULL;
|
||
+unsigned int test_verbose = 0;
|
||
+
|
||
+/* If test failure reporting has been linked in, it may contribute
|
||
+ additional test failures. */
|
||
+static int
|
||
+adjust_exit_status (int status)
|
||
+{
|
||
+ if (support_report_failure != NULL)
|
||
+ return support_report_failure (status);
|
||
+ return status;
|
||
+}
|
||
+
|
||
+int
|
||
+support_test_main (int argc, char **argv, const struct test_config *config)
|
||
+{
|
||
+ if (test_main_called)
|
||
+ {
|
||
+ printf ("error: test_main called for a second time\n");
|
||
+ exit (1);
|
||
+ }
|
||
+ test_main_called = true;
|
||
+ const struct option *options;
|
||
+ if (config->options != NULL)
|
||
+ options = config->options;
|
||
+ else
|
||
+ options = default_options;
|
||
+
|
||
+ cleanup_function = config->cleanup_function;
|
||
+
|
||
+ int direct = 0; /* Directly call the test function? */
|
||
+ int status;
|
||
+ int opt;
|
||
+ unsigned int timeoutfactor = 1;
|
||
+ pid_t termpid;
|
||
+
|
||
+ if (!config->no_mallopt)
|
||
+ {
|
||
+ /* Make uses of freed and uninitialized memory known. Do not
|
||
+ pull in a definition for mallopt if it has not been defined
|
||
+ already. */
|
||
+ extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
|
||
+ if (mallopt != NULL)
|
||
+ mallopt (M_PERTURB, 42);
|
||
+ }
|
||
+
|
||
+ while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
|
||
+ switch (opt)
|
||
+ {
|
||
+ case '?':
|
||
+ usage (options);
|
||
+ exit (1);
|
||
+ case 'v':
|
||
+ ++test_verbose;
|
||
+ break;
|
||
+ case OPT_DIRECT:
|
||
+ direct = 1;
|
||
+ break;
|
||
+ case OPT_TESTDIR:
|
||
+ test_dir = optarg;
|
||
+ break;
|
||
+ default:
|
||
+ if (config->cmdline_function != NULL)
|
||
+ config->cmdline_function (opt);
|
||
+ }
|
||
+
|
||
+ /* If set, read the test TIMEOUTFACTOR value from the environment.
|
||
+ This value is used to scale the default test timeout values. */
|
||
+ char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
|
||
+ if (envstr_timeoutfactor != NULL)
|
||
+ {
|
||
+ char *envstr_conv = envstr_timeoutfactor;
|
||
+ unsigned long int env_fact;
|
||
+
|
||
+ env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
|
||
+ if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
|
||
+ timeoutfactor = MAX (env_fact, 1);
|
||
+ }
|
||
+
|
||
+ /* Set TMPDIR to specified test directory. */
|
||
+ if (test_dir != NULL)
|
||
+ {
|
||
+ setenv ("TMPDIR", test_dir, 1);
|
||
+
|
||
+ if (chdir (test_dir) < 0)
|
||
+ {
|
||
+ printf ("chdir: %m\n");
|
||
+ exit (1);
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ test_dir = getenv ("TMPDIR");
|
||
+ if (test_dir == NULL || test_dir[0] == '\0')
|
||
+ test_dir = "/tmp";
|
||
+ }
|
||
+ if (support_set_test_dir != NULL)
|
||
+ support_set_test_dir (test_dir);
|
||
+
|
||
+ int timeout = config->timeout;
|
||
+ if (timeout == 0)
|
||
+ timeout = DEFAULT_TIMEOUT;
|
||
+
|
||
+ /* Make sure we see all message, even those on stdout. */
|
||
+ setvbuf (stdout, NULL, _IONBF, 0);
|
||
+
|
||
+ /* Make sure temporary files are deleted. */
|
||
+ if (support_delete_temp_files != NULL)
|
||
+ atexit (support_delete_temp_files);
|
||
+
|
||
+ /* Correct for the possible parameters. */
|
||
+ argv[optind - 1] = argv[0];
|
||
+ argv += optind - 1;
|
||
+ argc -= optind - 1;
|
||
+
|
||
+ /* Call the initializing function, if one is available. */
|
||
+ if (config->prepare_function != NULL)
|
||
+ config->prepare_function (argc, argv);
|
||
+
|
||
+ const char *envstr_direct = getenv ("TEST_DIRECT");
|
||
+ if (envstr_direct != NULL)
|
||
+ {
|
||
+ FILE *f = fopen (envstr_direct, "w");
|
||
+ if (f == NULL)
|
||
+ {
|
||
+ printf ("cannot open TEST_DIRECT output file '%s': %m\n",
|
||
+ envstr_direct);
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
|
||
+ config->timeout, timeoutfactor);
|
||
+ if (config->expected_status != 0)
|
||
+ fprintf (f, "exit=%u\n", config->expected_status);
|
||
+ if (config->expected_signal != 0)
|
||
+ fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
|
||
+
|
||
+ if (support_print_temp_files != NULL)
|
||
+ support_print_temp_files (f);
|
||
+
|
||
+ fclose (f);
|
||
+ direct = 1;
|
||
+ }
|
||
+
|
||
+ bool disable_coredumps;
|
||
+ {
|
||
+ const char *coredumps = getenv ("TEST_COREDUMPS");
|
||
+ disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
|
||
+ }
|
||
+
|
||
+ /* If we are not expected to fork run the function immediately. */
|
||
+ if (direct)
|
||
+ return adjust_exit_status (run_test_function (argc, argv, config));
|
||
+
|
||
+ /* Set up the test environment:
|
||
+ - prevent core dumps
|
||
+ - set up the timer
|
||
+ - fork and execute the function. */
|
||
+
|
||
+ test_pid = fork ();
|
||
+ if (test_pid == 0)
|
||
+ {
|
||
+ /* This is the child. */
|
||
+ if (disable_coredumps)
|
||
+ {
|
||
+ /* Try to avoid dumping core. This is necessary because we
|
||
+ run the test from the source tree, and the coredumps
|
||
+ would end up there (and not in the build tree). */
|
||
+ struct rlimit core_limit;
|
||
+ core_limit.rlim_cur = 0;
|
||
+ core_limit.rlim_max = 0;
|
||
+ setrlimit (RLIMIT_CORE, &core_limit);
|
||
+ }
|
||
+
|
||
+ /* We put the test process in its own pgrp so that if it bogusly
|
||
+ generates any job control signals, they won't hit the whole build. */
|
||
+ if (setpgid (0, 0) != 0)
|
||
+ printf ("Failed to set the process group ID: %m\n");
|
||
+
|
||
+ /* Execute the test function and exit with the return value. */
|
||
+ exit (run_test_function (argc, argv, config));
|
||
+ }
|
||
+ else if (test_pid < 0)
|
||
+ {
|
||
+ printf ("Cannot fork test program: %m\n");
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ /* Set timeout. */
|
||
+ signal (SIGALRM, signal_handler);
|
||
+ alarm (timeout * timeoutfactor);
|
||
+
|
||
+ /* Make sure we clean up if the wrapper gets interrupted. */
|
||
+ signal (SIGINT, signal_handler);
|
||
+
|
||
+ /* Wait for the regular termination. */
|
||
+ termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
|
||
+ if (termpid == -1)
|
||
+ {
|
||
+ printf ("Waiting for test program failed: %m\n");
|
||
+ exit (1);
|
||
+ }
|
||
+ if (termpid != test_pid)
|
||
+ {
|
||
+ printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
|
||
+ (long int) test_pid, (long int) termpid);
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ /* Process terminated normaly without timeout etc. */
|
||
+ if (WIFEXITED (status))
|
||
+ {
|
||
+ if (config->expected_status == 0)
|
||
+ {
|
||
+ if (config->expected_signal == 0)
|
||
+ /* Exit with the return value of the test. */
|
||
+ return adjust_exit_status (WEXITSTATUS (status));
|
||
+ else
|
||
+ {
|
||
+ printf ("Expected signal '%s' from child, got none\n",
|
||
+ strsignal (config->expected_signal));
|
||
+ exit (1);
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Non-zero exit status is expected */
|
||
+ if (WEXITSTATUS (status) != config->expected_status)
|
||
+ {
|
||
+ printf ("Expected status %d, got %d\n",
|
||
+ config->expected_status, WEXITSTATUS (status));
|
||
+ exit (1);
|
||
+ }
|
||
+ }
|
||
+ return adjust_exit_status (0);
|
||
+ }
|
||
+ /* Process was killed by timer or other signal. */
|
||
+ else
|
||
+ {
|
||
+ if (config->expected_signal == 0)
|
||
+ {
|
||
+ printf ("Didn't expect signal from child: got `%s'\n",
|
||
+ strsignal (WTERMSIG (status)));
|
||
+ exit (1);
|
||
+ }
|
||
+ else if (WTERMSIG (status) != config->expected_signal)
|
||
+ {
|
||
+ printf ("Incorrect signal from child: got `%s', need `%s'\n",
|
||
+ strsignal (WTERMSIG (status)),
|
||
+ strsignal (config->expected_signal));
|
||
+ exit (1);
|
||
+ }
|
||
+
|
||
+ return adjust_exit_status (0);
|
||
+ }
|
||
+}
|
||
diff --git a/support/support_test_verify_impl.c b/support/support_test_verify_impl.c
|
||
new file mode 100644
|
||
index 0000000000..5bae38f8b1
|
||
--- /dev/null
|
||
+++ b/support/support_test_verify_impl.c
|
||
@@ -0,0 +1,33 @@
|
||
+/* Implementation of the TEST_VERIFY and TEST_VERIFY_EXIT macros.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void
|
||
+support_test_verify_impl (int status, const char *file, int line,
|
||
+ const char *expr)
|
||
+{
|
||
+ support_record_failure ();
|
||
+ printf ("error: %s:%d: not true: %s\n", file, line, expr);
|
||
+ if (status >= 0)
|
||
+ exit (status);
|
||
+
|
||
+}
|
||
diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c
|
||
new file mode 100644
|
||
index 0000000000..48e89597f3
|
||
--- /dev/null
|
||
+++ b/support/support_write_file_string.c
|
||
@@ -0,0 +1,39 @@
|
||
+/* Write a string to a file.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <fcntl.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <xunistd.h>
|
||
+
|
||
+void
|
||
+support_write_file_string (const char *path, const char *contents)
|
||
+{
|
||
+ int fd = xopen (path, O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
||
+ const char *end = contents + strlen (contents);
|
||
+ for (const char *p = contents; p < end; )
|
||
+ {
|
||
+ ssize_t ret = write (fd, p, end - p);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("cannot write to \"%s\": %m", path);
|
||
+ if (ret == 0)
|
||
+ FAIL_EXIT1 ("zero-length write to \"%s\"", path);
|
||
+ p += ret;
|
||
+ }
|
||
+ xclose (fd);
|
||
+}
|
||
diff --git a/support/temp_file-internal.h b/support/temp_file-internal.h
|
||
new file mode 100644
|
||
index 0000000000..fb6cceb065
|
||
--- /dev/null
|
||
+++ b/support/temp_file-internal.h
|
||
@@ -0,0 +1,31 @@
|
||
+/* Internal weak declarations for temporary file handling.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_TEMP_FILE_INTERNAL_H
|
||
+#define SUPPORT_TEMP_FILE_INTERNAL_H
|
||
+
|
||
+/* These functions are called by the test driver if they are
|
||
+ defined. Tests should not call them directly. */
|
||
+
|
||
+#include <stdio.h>
|
||
+
|
||
+void support_set_test_dir (const char *name) __attribute__ ((weak));
|
||
+void support_delete_temp_files (void) __attribute__ ((weak));
|
||
+void support_print_temp_files (FILE *) __attribute__ ((weak));
|
||
+
|
||
+#endif /* SUPPORT_TEMP_FILE_INTERNAL_H */
|
||
diff --git a/support/temp_file.c b/support/temp_file.c
|
||
new file mode 100644
|
||
index 0000000000..fdb2477ab9
|
||
--- /dev/null
|
||
+++ b/support/temp_file.c
|
||
@@ -0,0 +1,132 @@
|
||
+/* Temporary file handling for tests.
|
||
+ Copyright (C) 1998-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This is required to get an mkstemp which can create large files on
|
||
+ some 32-bit platforms. */
|
||
+#define _FILE_OFFSET_BITS 64
|
||
+
|
||
+#include <support/temp_file.h>
|
||
+#include <support/temp_file-internal.h>
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <paths.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+/* List of temporary files. */
|
||
+static struct temp_name_list
|
||
+{
|
||
+ struct temp_name_list *next;
|
||
+ char *name;
|
||
+ pid_t owner;
|
||
+} *temp_name_list;
|
||
+
|
||
+/* Location of the temporary files. Set by the test skeleton via
|
||
+ support_set_test_dir. The string is not be freed. */
|
||
+static const char *test_dir = _PATH_TMP;
|
||
+
|
||
+void
|
||
+add_temp_file (const char *name)
|
||
+{
|
||
+ struct temp_name_list *newp
|
||
+ = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
|
||
+ char *newname = strdup (name);
|
||
+ if (newname != NULL)
|
||
+ {
|
||
+ newp->name = newname;
|
||
+ newp->next = temp_name_list;
|
||
+ newp->owner = getpid ();
|
||
+ temp_name_list = newp;
|
||
+ }
|
||
+ else
|
||
+ free (newp);
|
||
+}
|
||
+
|
||
+int
|
||
+create_temp_file (const char *base, char **filename)
|
||
+{
|
||
+ char *fname;
|
||
+ int fd;
|
||
+
|
||
+ fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
|
||
+ + sizeof ("XXXXXX"));
|
||
+ strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
|
||
+
|
||
+ fd = mkstemp (fname);
|
||
+ if (fd == -1)
|
||
+ {
|
||
+ printf ("cannot open temporary file '%s': %m\n", fname);
|
||
+ free (fname);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ add_temp_file (fname);
|
||
+ if (filename != NULL)
|
||
+ *filename = fname;
|
||
+ else
|
||
+ free (fname);
|
||
+
|
||
+ return fd;
|
||
+}
|
||
+
|
||
+/* Helper functions called by the test skeleton follow. */
|
||
+
|
||
+void
|
||
+support_set_test_dir (const char *path)
|
||
+{
|
||
+ test_dir = path;
|
||
+}
|
||
+
|
||
+void
|
||
+support_delete_temp_files (void)
|
||
+{
|
||
+ pid_t pid = getpid ();
|
||
+ while (temp_name_list != NULL)
|
||
+ {
|
||
+ /* Only perform the removal if the path was registed in the same
|
||
+ process, as identified by the PID. (This assumes that the
|
||
+ parent process which registered the temporary file sticks
|
||
+ around, to prevent PID reuse.) */
|
||
+ if (temp_name_list->owner == pid)
|
||
+ {
|
||
+ if (remove (temp_name_list->name) != 0)
|
||
+ printf ("warning: could not remove temporary file: %s: %m\n",
|
||
+ temp_name_list->name);
|
||
+ }
|
||
+ free (temp_name_list->name);
|
||
+
|
||
+ struct temp_name_list *next = temp_name_list->next;
|
||
+ free (temp_name_list);
|
||
+ temp_name_list = next;
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+support_print_temp_files (FILE *f)
|
||
+{
|
||
+ if (temp_name_list != NULL)
|
||
+ {
|
||
+ struct temp_name_list *n;
|
||
+ fprintf (f, "temp_files=(\n");
|
||
+ for (n = temp_name_list; n != NULL; n = n->next)
|
||
+ fprintf (f, " '%s'\n", n->name);
|
||
+ fprintf (f, ")\n");
|
||
+ }
|
||
+}
|
||
diff --git a/support/temp_file.h b/support/temp_file.h
|
||
new file mode 100644
|
||
index 0000000000..6fed8df1ea
|
||
--- /dev/null
|
||
+++ b/support/temp_file.h
|
||
@@ -0,0 +1,37 @@
|
||
+/* Declarations for temporary file handling.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_TEMP_FILE_H
|
||
+#define SUPPORT_TEMP_FILE_H
|
||
+
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Schedule a temporary file for deletion on exit. */
|
||
+void add_temp_file (const char *name);
|
||
+
|
||
+/* Create a temporary file. Return the opened file descriptor on
|
||
+ success, or -1 on failure. Write the file name to *FILENAME if
|
||
+ FILENAME is not NULL. In this case, the caller is expected to free
|
||
+ *FILENAME. */
|
||
+int create_temp_file (const char *base, char **filename);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_TEMP_FILE_H */
|
||
diff --git a/support/test-driver.c b/support/test-driver.c
|
||
new file mode 100644
|
||
index 0000000000..482066dbeb
|
||
--- /dev/null
|
||
+++ b/support/test-driver.c
|
||
@@ -0,0 +1,156 @@
|
||
+/* Main function for test programs.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This file should be included from test cases. It will define a
|
||
+ main function which provides the test wrapper.
|
||
+
|
||
+ It assumes that the test case defines a function
|
||
+
|
||
+ int do_test (void);
|
||
+
|
||
+ and arranges for that function being called under the test wrapper.
|
||
+ The do_test function should return 0 to indicate a passing test, 1
|
||
+ to indicate a failing test, or 77 to indicate an unsupported test.
|
||
+ Other result values could be used to indicate a failing test, but
|
||
+ the result of the expression is passed to exit and exit only
|
||
+ returns the lower 8 bits of its input. A non-zero return with some
|
||
+ values could cause a test to incorrectly be considered passing when
|
||
+ it really failed. For this reason, the function should always
|
||
+ return 0 (EXIT_SUCCESS), 1 (EXIT_FAILURE), or 77
|
||
+ (EXIT_UNSUPPORTED).
|
||
+
|
||
+ The test function may print out diagnostic or warning messages as well
|
||
+ as messages about failures. These messages should be printed to stdout
|
||
+ and not stderr so that the output is properly ordered with respect to
|
||
+ the rest of the glibc testsuite run output.
|
||
+
|
||
+ Several preprocessors macros can be defined before including this
|
||
+ file.
|
||
+
|
||
+ The name of the do_test function can be changed with the
|
||
+ TEST_FUNCTION macro. It must expand to the desired function name.
|
||
+
|
||
+ If the test case needs access to command line parameters, it must
|
||
+ define the TEST_FUNCTION_ARGV macro with the name of the test
|
||
+ function. It must have the following type:
|
||
+
|
||
+ int TEST_FUNCTION_ARGV (int argc, char **argv);
|
||
+
|
||
+ This overrides the do_test default function and is incompatible
|
||
+ with the TEST_FUNCTION macro.
|
||
+
|
||
+ If PREPARE is defined, it must expand to the name of a function of
|
||
+ the type
|
||
+
|
||
+ void PREPARE (int argc, char **);
|
||
+
|
||
+ This function will be called early, after parsing the command line,
|
||
+ but before running the test, in the parent process which acts as
|
||
+ the test supervisor.
|
||
+
|
||
+ If CLEANUP_HANDLER is defined, it must expand to the name of a
|
||
+ function of the type
|
||
+
|
||
+ void CLEANUP_HANDLER (void);
|
||
+
|
||
+ This function will be called from the timeout (SIGALRM) signal
|
||
+ handler.
|
||
+
|
||
+ If EXPECTED_SIGNAL is defined, it must expanded to a constant which
|
||
+ denotes the expected signal number.
|
||
+
|
||
+ If EXPECTED_STATUS is defined, it must expand to the expected exit
|
||
+ status.
|
||
+
|
||
+ If TIMEOUT is defined, it must be positive constant. It overrides
|
||
+ the default test timeout and is measured in seconds.
|
||
+
|
||
+ If TEST_NO_MALLOPT is defined, the test wrapper will not call
|
||
+ mallopt.
|
||
+
|
||
+ Custom command line handling can be implemented by defining the
|
||
+ CMDLINE_OPTION macro (after including the <getopt.h> header; this
|
||
+ requires _GNU_SOURCE to be defined). This macro must expand to a
|
||
+ to a comma-separated list of braced initializers for struct option
|
||
+ from <getopt.h>, with a trailing comma. CMDLINE_PROCESS can be
|
||
+ defined as the name of a function which is called to process these
|
||
+ options. The function is passed the option character/number and
|
||
+ has this type:
|
||
+
|
||
+ void CMDLINE_PROCESS (int);
|
||
+*/
|
||
+
|
||
+#include <support/test-driver.h>
|
||
+
|
||
+#include <string.h>
|
||
+
|
||
+int
|
||
+main (int argc, char **argv)
|
||
+{
|
||
+ struct test_config test_config;
|
||
+ memset (&test_config, 0, sizeof (test_config));
|
||
+
|
||
+#ifdef PREPARE
|
||
+ test_config.prepare_function = (PREPARE);
|
||
+#endif
|
||
+
|
||
+#if defined (TEST_FUNCTION) && defined (TEST_FUNCTON_ARGV)
|
||
+# error TEST_FUNCTION and TEST_FUNCTION_ARGV cannot be defined at the same time
|
||
+#endif
|
||
+#if defined (TEST_FUNCTION)
|
||
+ test_config.test_function = TEST_FUNCTION;
|
||
+#elif defined (TEST_FUNCTION_ARGV)
|
||
+ test_config.test_function_argv = TEST_FUNCTION_ARGV;
|
||
+#else
|
||
+ test_config.test_function = do_test;
|
||
+#endif
|
||
+
|
||
+#ifdef CLEANUP_HANDLER
|
||
+ test_config.cleanup_function = CLEANUP_HANDLER;
|
||
+#endif
|
||
+
|
||
+#ifdef EXPECTED_SIGNAL
|
||
+ test_config.expected_signal = (EXPECTED_SIGNAL);
|
||
+#endif
|
||
+
|
||
+#ifdef EXPECTED_STATUS
|
||
+ test_config.expected_status = (EXPECTED_STATUS);
|
||
+#endif
|
||
+
|
||
+#ifdef TEST_NO_MALLOPT
|
||
+ test_config.no_mallopt = 1;
|
||
+#endif
|
||
+
|
||
+#ifdef TIMEOUT
|
||
+ test_config.timeout = TIMEOUT;
|
||
+#endif
|
||
+
|
||
+#ifdef CMDLINE_OPTIONS
|
||
+ struct option options[] =
|
||
+ {
|
||
+ CMDLINE_OPTIONS
|
||
+ TEST_DEFAULT_OPTIONS
|
||
+ };
|
||
+ test_config.options = &options;
|
||
+#endif
|
||
+#ifdef CMDLINE_PROCESS
|
||
+ test_config.cmdline_function = CMDLINE_PROCESS;
|
||
+#endif
|
||
+
|
||
+ return support_test_main (argc, argv, &test_config);
|
||
+}
|
||
diff --git a/support/test-driver.h b/support/test-driver.h
|
||
new file mode 100644
|
||
index 0000000000..af1971a9ca
|
||
--- /dev/null
|
||
+++ b/support/test-driver.h
|
||
@@ -0,0 +1,74 @@
|
||
+/* Interfaces for the test driver.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_TEST_DRIVER_H
|
||
+#define SUPPORT_TEST_DRIVER_H
|
||
+
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+struct test_config
|
||
+{
|
||
+ void (*prepare_function) (int argc, char **argv);
|
||
+ int (*test_function) (void);
|
||
+ int (*test_function_argv) (int argc, char **argv);
|
||
+ void (*cleanup_function) (void);
|
||
+ void (*cmdline_function) (int);
|
||
+ const void *options; /* Custom options if not NULL. */
|
||
+ int timeout; /* Test timeout in seconds. */
|
||
+ int expected_status; /* Expected exit status. */
|
||
+ int expected_signal; /* If non-zero, expect termination by signal. */
|
||
+ char no_mallopt; /* Boolean flag to disable mallopt. */
|
||
+};
|
||
+
|
||
+enum
|
||
+ {
|
||
+ /* Test exit status which indicates that the feature is
|
||
+ unsupported. */
|
||
+ EXIT_UNSUPPORTED = 77,
|
||
+
|
||
+ /* Default timeout is twenty seconds. Tests should normally
|
||
+ complete faster than this, but if they don't, that's abnormal
|
||
+ (a bug) anyways. */
|
||
+ DEFAULT_TIMEOUT = 20,
|
||
+
|
||
+ /* Used for command line argument parsing. */
|
||
+ OPT_DIRECT = 1000,
|
||
+ OPT_TESTDIR,
|
||
+ };
|
||
+
|
||
+/* Options provided by the test driver. */
|
||
+#define TEST_DEFAULT_OPTIONS \
|
||
+ { "verbose", no_argument, NULL, 'v' }, \
|
||
+ { "direct", no_argument, NULL, OPT_DIRECT }, \
|
||
+ { "test-dir", required_argument, NULL, OPT_TESTDIR }, \
|
||
+
|
||
+/* The directory the test should use for temporary files. */
|
||
+extern const char *test_dir;
|
||
+
|
||
+/* The number of --verbose arguments specified during program
|
||
+ invocation. This variable can be used to control the verbosity of
|
||
+ tests. */
|
||
+extern unsigned int test_verbose;
|
||
+
|
||
+int support_test_main (int argc, char **argv, const struct test_config *);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_TEST_DRIVER_H */
|
||
diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c
|
||
new file mode 100644
|
||
index 0000000000..a50b074f5e
|
||
--- /dev/null
|
||
+++ b/support/tst-support-namespace.c
|
||
@@ -0,0 +1,34 @@
|
||
+/* Test entering namespaces.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <support/namespace.h>
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ if (support_become_root ())
|
||
+ printf ("info: acquired root-like privileges\n");
|
||
+ if (support_enter_network_namespace ())
|
||
+ printf ("info: entered network namespace\n");
|
||
+ if (support_in_uts_namespace ())
|
||
+ printf ("info: also entered UTS namespace\n");
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
|
||
new file mode 100644
|
||
index 0000000000..5672fba0f7
|
||
--- /dev/null
|
||
+++ b/support/tst-support_capture_subprocess.c
|
||
@@ -0,0 +1,188 @@
|
||
+/* Test capturing output from a subprocess.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <stdbool.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/capture_subprocess.h>
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <sys/wait.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+/* Write one byte at *P to FD and advance *P. Do nothing if *P is
|
||
+ '\0'. */
|
||
+static void
|
||
+transfer (const unsigned char **p, int fd)
|
||
+{
|
||
+ if (**p != '\0')
|
||
+ {
|
||
+ TEST_VERIFY (write (fd, *p, 1) == 1);
|
||
+ ++*p;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Determine the order in which stdout and stderr are written. */
|
||
+enum write_mode { out_first, err_first, interleave,
|
||
+ write_mode_last = interleave };
|
||
+
|
||
+/* Describe what to write in the subprocess. */
|
||
+struct test
|
||
+{
|
||
+ char *out;
|
||
+ char *err;
|
||
+ enum write_mode write_mode;
|
||
+ int signal;
|
||
+ int status;
|
||
+};
|
||
+
|
||
+/* For use with support_capture_subprocess. */
|
||
+static void
|
||
+callback (void *closure)
|
||
+{
|
||
+ const struct test *test = closure;
|
||
+ bool mode_ok = false;
|
||
+ switch (test->write_mode)
|
||
+ {
|
||
+ case out_first:
|
||
+ TEST_VERIFY (fputs (test->out, stdout) >= 0);
|
||
+ TEST_VERIFY (fflush (stdout) == 0);
|
||
+ TEST_VERIFY (fputs (test->err, stderr) >= 0);
|
||
+ TEST_VERIFY (fflush (stderr) == 0);
|
||
+ mode_ok = true;
|
||
+ break;
|
||
+ case err_first:
|
||
+ TEST_VERIFY (fputs (test->err, stderr) >= 0);
|
||
+ TEST_VERIFY (fflush (stderr) == 0);
|
||
+ TEST_VERIFY (fputs (test->out, stdout) >= 0);
|
||
+ TEST_VERIFY (fflush (stdout) == 0);
|
||
+ mode_ok = true;
|
||
+ break;
|
||
+ case interleave:
|
||
+ {
|
||
+ const unsigned char *pout = (const unsigned char *) test->out;
|
||
+ const unsigned char *perr = (const unsigned char *) test->err;
|
||
+ do
|
||
+ {
|
||
+ transfer (&pout, STDOUT_FILENO);
|
||
+ transfer (&perr, STDERR_FILENO);
|
||
+ }
|
||
+ while (*pout != '\0' || *perr != '\0');
|
||
+ }
|
||
+ mode_ok = true;
|
||
+ break;
|
||
+ }
|
||
+ TEST_VERIFY (mode_ok);
|
||
+
|
||
+ if (test->signal != 0)
|
||
+ raise (test->signal);
|
||
+ exit (test->status);
|
||
+}
|
||
+
|
||
+/* Create a heap-allocated random string of letters. */
|
||
+static char *
|
||
+random_string (size_t length)
|
||
+{
|
||
+ char *result = xmalloc (length + 1);
|
||
+ for (size_t i = 0; i < length; ++i)
|
||
+ result[i] = 'a' + (rand () % 26);
|
||
+ result[length] = '\0';
|
||
+ return result;
|
||
+}
|
||
+
|
||
+/* Check that the specific stream from the captured subprocess matches
|
||
+ expectations. */
|
||
+static void
|
||
+check_stream (const char *what, const struct xmemstream *stream,
|
||
+ const char *expected)
|
||
+{
|
||
+ if (strcmp (stream->buffer, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: captured %s data incorrect\n"
|
||
+ " expected: %s\n"
|
||
+ " actual: %s\n",
|
||
+ what, expected, stream->buffer);
|
||
+ }
|
||
+ if (stream->length != strlen (expected))
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: captured %s data length incorrect\n"
|
||
+ " expected: %zu\n"
|
||
+ " actual: %zu\n",
|
||
+ what, strlen (expected), stream->length);
|
||
+ }
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ const int lengths[] = {0, 1, 17, 512, 20000, -1};
|
||
+
|
||
+ /* Test multiple combinations of support_capture_subprocess.
|
||
+
|
||
+ length_idx_stdout: Index into the lengths array above,
|
||
+ controls how many bytes are written by the subprocess to
|
||
+ standard output.
|
||
+ length_idx_stderr: Same for standard error.
|
||
+ write_mode: How standard output and standard error writes are
|
||
+ ordered.
|
||
+ signal: Exit with no signal if zero, with SIGTERM if one.
|
||
+ status: Process exit status: 0 if zero, 3 if one. */
|
||
+ for (int length_idx_stdout = 0; lengths[length_idx_stdout] >= 0;
|
||
+ ++length_idx_stdout)
|
||
+ for (int length_idx_stderr = 0; lengths[length_idx_stderr] >= 0;
|
||
+ ++length_idx_stderr)
|
||
+ for (int write_mode = 0; write_mode < write_mode_last; ++write_mode)
|
||
+ for (int signal = 0; signal < 2; ++signal)
|
||
+ for (int status = 0; status < 2; ++status)
|
||
+ {
|
||
+ struct test test =
|
||
+ {
|
||
+ .out = random_string (lengths[length_idx_stdout]),
|
||
+ .err = random_string (lengths[length_idx_stderr]),
|
||
+ .write_mode = write_mode,
|
||
+ .signal = signal * SIGTERM, /* 0 or SIGTERM. */
|
||
+ .status = status * 3, /* 0 or 3. */
|
||
+ };
|
||
+ TEST_VERIFY (strlen (test.out) == lengths[length_idx_stdout]);
|
||
+ TEST_VERIFY (strlen (test.err) == lengths[length_idx_stderr]);
|
||
+
|
||
+ struct support_capture_subprocess result
|
||
+ = support_capture_subprocess (callback, &test);
|
||
+ check_stream ("stdout", &result.out, test.out);
|
||
+ check_stream ("stderr", &result.err, test.err);
|
||
+ if (test.signal != 0)
|
||
+ {
|
||
+ TEST_VERIFY (WIFSIGNALED (result.status));
|
||
+ TEST_VERIFY (WTERMSIG (result.status) == test.signal);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ TEST_VERIFY (WIFEXITED (result.status));
|
||
+ TEST_VERIFY (WEXITSTATUS (result.status) == test.status);
|
||
+ }
|
||
+ support_capture_subprocess_free (&result);
|
||
+ free (test.out);
|
||
+ free (test.err);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c
|
||
new file mode 100644
|
||
index 0000000000..9c8589c09c
|
||
--- /dev/null
|
||
+++ b/support/tst-support_format_dns_packet.c
|
||
@@ -0,0 +1,101 @@
|
||
+/* Tests for the support_format_dns_packet function.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/format_nss.h>
|
||
+#include <support/run_diff.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+
|
||
+static void
|
||
+check_packet (const void *buffer, size_t length,
|
||
+ const char *name, const char *expected)
|
||
+{
|
||
+ char *actual = support_format_dns_packet (buffer, length);
|
||
+ if (strcmp (actual, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: formatted packet does not match: %s\n", name);
|
||
+ support_run_diff ("expected", expected,
|
||
+ "actual", actual);
|
||
+ }
|
||
+ free (actual);
|
||
+}
|
||
+
|
||
+static void
|
||
+test_aaaa_length (void)
|
||
+{
|
||
+ static const char packet[] =
|
||
+ /* Header: Response with two records. */
|
||
+ "\x12\x34\x80\x00\x00\x01\x00\x02\x00\x00\x00\x00"
|
||
+ /* Question section. www.example/IN/AAAA. */
|
||
+ "\x03www\x07""example\x00\x00\x1c\x00\x01"
|
||
+ /* Answer section. www.example AAAA [corrupted]. */
|
||
+ "\xc0\x0c"
|
||
+ "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x10"
|
||
+ "\x20\x01\x0d\xb8\x05\x06\x07\x08"
|
||
+ "\x11\x12\x13\x14\x15\x16\x17\x18"
|
||
+ /* www.example AAAA [corrupted]. */
|
||
+ "\xc0\x0c"
|
||
+ "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x11"
|
||
+ "\x01\x02\x03\x04\x05\x06\x07\x08"
|
||
+ "\x11\x12\x13\x14\x15\x16\x17\x18" "\xff";
|
||
+ check_packet (packet, sizeof (packet) - 1, __func__,
|
||
+ "name: www.example\n"
|
||
+ "address: 2001:db8:506:708:1112:1314:1516:1718\n"
|
||
+ "error: AAAA record of size 17: www.example\n");
|
||
+}
|
||
+
|
||
+static void
|
||
+test_multiple_cnames (void)
|
||
+{
|
||
+ static const char packet[] =
|
||
+ /* Header: Response with three records. */
|
||
+ "\x12\x34\x80\x00\x00\x01\x00\x03\x00\x00\x00\x00"
|
||
+ /* Question section. www.example/IN/A. */
|
||
+ "\x03www\x07""example\x00\x00\x01\x00\x01"
|
||
+ /* Answer section. www.example CNAME www1.example. */
|
||
+ "\xc0\x0c"
|
||
+ "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07"
|
||
+ "\x04www1\xc0\x10"
|
||
+ /* www1 CNAME www2. */
|
||
+ "\x04www1\xc0\x10"
|
||
+ "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07"
|
||
+ "\x04www2\xc0\x10"
|
||
+ /* www2 A 192.0.2.1. */
|
||
+ "\x04www2\xc0\x10"
|
||
+ "\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04"
|
||
+ "\xc0\x00\x02\x01";
|
||
+ check_packet (packet, sizeof (packet) - 1, __func__,
|
||
+ "name: www.example\n"
|
||
+ "name: www1.example\n"
|
||
+ "name: www2.example\n"
|
||
+ "address: 192.0.2.1\n");
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ test_aaaa_length ();
|
||
+ test_multiple_cnames ();
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/support/tst-support_record_failure-2.sh b/support/tst-support_record_failure-2.sh
|
||
new file mode 100644
|
||
index 0000000000..2c9372cc29
|
||
--- /dev/null
|
||
+++ b/support/tst-support_record_failure-2.sh
|
||
@@ -0,0 +1,69 @@
|
||
+#!/bin/sh
|
||
+# Test failure recording (with and without --direct).
|
||
+# Copyright (C) 2016-2017 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
|
||
+# <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+set -e
|
||
+
|
||
+common_objpfx=$1; shift
|
||
+test_program_prefix_before_env=$1; shift
|
||
+run_program_env=$1; shift
|
||
+test_program_prefix_after_env=$1; shift
|
||
+
|
||
+run_test () {
|
||
+ expected_status="$1"
|
||
+ expected_output="$2"
|
||
+ shift 2
|
||
+ args="${common_objpfx}support/tst-support_record_failure $*"
|
||
+ echo "running: $args"
|
||
+ set +e
|
||
+ output="$(${test_program_prefix_before_env} \
|
||
+ ${run_program} ${test_program_prefix_after_env} $args)"
|
||
+ status=$?
|
||
+ set -e
|
||
+ echo " exit status: $status"
|
||
+ if test "$output" != "$expected_output" ; then
|
||
+ echo "error: unexpected output: $output"
|
||
+ exit 1
|
||
+ fi
|
||
+ if test "$status" -ne "$expected_status" ; then
|
||
+ echo "error: exit status $expected_status expected"
|
||
+ exit 1
|
||
+ fi
|
||
+}
|
||
+
|
||
+different_status () {
|
||
+ direct="$1"
|
||
+ run_test 1 "error: 1 test failures" $direct --status=0
|
||
+ run_test 1 "error: 1 test failures" $direct --status=1
|
||
+ run_test 2 "error: 1 test failures" $direct --status=2
|
||
+ run_test 1 "error: 1 test failures" $direct --status=77
|
||
+ run_test 2 "error: tst-support_record_failure.c:109: not true: false
|
||
+error: 1 test failures" $direct --test-verify
|
||
+ run_test 2 "error: tst-support_record_failure.c:109: not true: false
|
||
+info: execution passed failed TEST_VERIFY
|
||
+error: 1 test failures" $direct --test-verify --verbose
|
||
+}
|
||
+
|
||
+different_status
|
||
+different_status --direct
|
||
+
|
||
+run_test 1 "error: tst-support_record_failure.c:116: not true: false
|
||
+error: 1 test failures" --test-verify-exit
|
||
+# --direct does not print the summary error message if exit is called.
|
||
+run_test 1 "error: tst-support_record_failure.c:116: not true: false" \
|
||
+ --direct --test-verify-exit
|
||
diff --git a/support/tst-support_record_failure.c b/support/tst-support_record_failure.c
|
||
new file mode 100644
|
||
index 0000000000..e739e739c3
|
||
--- /dev/null
|
||
+++ b/support/tst-support_record_failure.c
|
||
@@ -0,0 +1,153 @@
|
||
+/* Test support_record_failure state sharing.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <getopt.h>
|
||
+#include <stdbool.h>
|
||
+#include <stdlib.h>
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+
|
||
+static int exit_status_with_failure = -1;
|
||
+static bool test_verify;
|
||
+static bool test_verify_exit;
|
||
+enum
|
||
+ {
|
||
+ OPT_STATUS = 10001,
|
||
+ OPT_TEST_VERIFY,
|
||
+ OPT_TEST_VERIFY_EXIT,
|
||
+ };
|
||
+#define CMDLINE_OPTIONS \
|
||
+ { "status", required_argument, NULL, OPT_STATUS }, \
|
||
+ { "test-verify", no_argument, NULL, OPT_TEST_VERIFY }, \
|
||
+ { "test-verify-exit", no_argument, NULL, OPT_TEST_VERIFY_EXIT },
|
||
+static void
|
||
+cmdline_process (int c)
|
||
+{
|
||
+ switch (c)
|
||
+ {
|
||
+ case OPT_STATUS:
|
||
+ exit_status_with_failure = atoi (optarg);
|
||
+ break;
|
||
+ case OPT_TEST_VERIFY:
|
||
+ test_verify = true;
|
||
+ break;
|
||
+ case OPT_TEST_VERIFY_EXIT:
|
||
+ test_verify_exit = true;
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+#define CMDLINE_PROCESS cmdline_process
|
||
+
|
||
+static void
|
||
+check_failure_reporting (int phase, int zero, int unsupported)
|
||
+{
|
||
+ int status = support_report_failure (0);
|
||
+ if (status != zero)
|
||
+ {
|
||
+ printf ("real-error (phase %d): support_report_failure (0) == %d\n",
|
||
+ phase, status);
|
||
+ exit (1);
|
||
+ }
|
||
+ status = support_report_failure (1);
|
||
+ if (status != 1)
|
||
+ {
|
||
+ printf ("real-error (phase %d): support_report_failure (1) == %d\n",
|
||
+ phase, status);
|
||
+ exit (1);
|
||
+ }
|
||
+ status = support_report_failure (2);
|
||
+ if (status != 2)
|
||
+ {
|
||
+ printf ("real-error (phase %d): support_report_failure (2) == %d\n",
|
||
+ phase, status);
|
||
+ exit (1);
|
||
+ }
|
||
+ status = support_report_failure (EXIT_UNSUPPORTED);
|
||
+ if (status != unsupported)
|
||
+ {
|
||
+ printf ("real-error (phase %d): "
|
||
+ "support_report_failure (EXIT_UNSUPPORTED) == %d\n",
|
||
+ phase, status);
|
||
+ exit (1);
|
||
+ }
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ if (exit_status_with_failure >= 0)
|
||
+ {
|
||
+ /* External invocation with requested error status. Used by
|
||
+ tst-support_report_failure-2.sh. */
|
||
+ support_record_failure ();
|
||
+ return exit_status_with_failure;
|
||
+ }
|
||
+ TEST_VERIFY (true);
|
||
+ TEST_VERIFY_EXIT (true);
|
||
+ if (test_verify)
|
||
+ {
|
||
+ TEST_VERIFY (false);
|
||
+ if (test_verbose)
|
||
+ printf ("info: execution passed failed TEST_VERIFY\n");
|
||
+ return 2; /* Expected exit status. */
|
||
+ }
|
||
+ if (test_verify_exit)
|
||
+ {
|
||
+ TEST_VERIFY_EXIT (false);
|
||
+ return 3; /* Not reached. Expected exit status is 1. */
|
||
+ }
|
||
+
|
||
+ printf ("info: This test tests the test framework.\n"
|
||
+ "info: It reports some expected errors on stdout.\n");
|
||
+
|
||
+ /* Check that the status is passed through unchanged. */
|
||
+ check_failure_reporting (1, 0, EXIT_UNSUPPORTED);
|
||
+
|
||
+ /* Check state propagation from a subprocess. */
|
||
+ pid_t pid = xfork ();
|
||
+ if (pid == 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ _exit (0);
|
||
+ }
|
||
+ int status;
|
||
+ xwaitpid (pid, &status, 0);
|
||
+ if (status != 0)
|
||
+ {
|
||
+ printf ("real-error: incorrect status from subprocess: %d\n", status);
|
||
+ return 1;
|
||
+ }
|
||
+ check_failure_reporting (2, 1, 1);
|
||
+
|
||
+ /* Also test directly in the parent process. */
|
||
+ support_record_failure_reset ();
|
||
+ check_failure_reporting (3, 0, EXIT_UNSUPPORTED);
|
||
+ support_record_failure ();
|
||
+ check_failure_reporting (4, 1, 1);
|
||
+
|
||
+ /* We need to mask the failure above. */
|
||
+ support_record_failure_reset ();
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/pwrite64.c b/support/write_message.c
|
||
similarity index 68%
|
||
rename from sysdeps/unix/sysv/linux/sh/pwrite64.c
|
||
rename to support/write_message.c
|
||
index 683a5d9886..f03ed931d6 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/pwrite64.c
|
||
+++ b/support/write_message.c
|
||
@@ -1,6 +1,6 @@
|
||
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||
+/* Write a message to standard output.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by Ralf Baechle <ralf@gnu.org>, 1998.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -16,8 +16,14 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||
- the kernel interface for pread adds a dummy long argument before the
|
||
- offset. */
|
||
-#define __ALIGNMENT_ARG
|
||
-#include <sysdeps/unix/sysv/linux/pwrite64.c>
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <string.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+void
|
||
+write_message (const char *message)
|
||
+{
|
||
+ ssize_t unused __attribute__ ((unused));
|
||
+ unused = write (STDOUT_FILENO, message, strlen (message));
|
||
+}
|
||
diff --git a/support/xaccept.c b/support/xaccept.c
|
||
new file mode 100644
|
||
index 0000000000..7b25af3b05
|
||
--- /dev/null
|
||
+++ b/support/xaccept.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* accept with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+int
|
||
+xaccept (int fd, struct sockaddr *sa, socklen_t *salen)
|
||
+{
|
||
+ int clientfd = accept (fd, sa, salen);
|
||
+ if (clientfd < 0)
|
||
+ FAIL_EXIT1 ("accept (%d): %m", fd);
|
||
+ return clientfd;
|
||
+}
|
||
diff --git a/support/xaccept4.c b/support/xaccept4.c
|
||
new file mode 100644
|
||
index 0000000000..67dd95e9fb
|
||
--- /dev/null
|
||
+++ b/support/xaccept4.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* accept4 with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+int
|
||
+xaccept4 (int fd, struct sockaddr *sa, socklen_t *salen, int flags)
|
||
+{
|
||
+ int clientfd = accept4 (fd, sa, salen, flags);
|
||
+ if (clientfd < 0)
|
||
+ FAIL_EXIT1 ("accept4 (%d, 0x%x): %m", fd, flags);
|
||
+ return clientfd;
|
||
+}
|
||
diff --git a/support/xasprintf.c b/support/xasprintf.c
|
||
new file mode 100644
|
||
index 0000000000..5157680fa2
|
||
--- /dev/null
|
||
+++ b/support/xasprintf.c
|
||
@@ -0,0 +1,36 @@
|
||
+/* Error-checking wrapper for asprintf.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+char *
|
||
+xasprintf (const char *format, ...)
|
||
+{
|
||
+ va_list ap;
|
||
+ va_start (ap, format);
|
||
+ char *result;
|
||
+ if (vasprintf (&result, format, ap) < 0)
|
||
+ FAIL_EXIT1 ("asprintf: %m");
|
||
+ va_end (ap);
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xbind.c b/support/xbind.c
|
||
new file mode 100644
|
||
index 0000000000..cfc6dd8fa8
|
||
--- /dev/null
|
||
+++ b/support/xbind.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* bind with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xbind (int fd, const struct sockaddr *sa, socklen_t sa_len)
|
||
+{
|
||
+ if (bind (fd, sa, sa_len) != 0)
|
||
+ FAIL_EXIT1 ("bind (%d), family %d: %m", fd, sa->sa_family);
|
||
+}
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/pread.c b/support/xcalloc.c
|
||
similarity index 68%
|
||
rename from sysdeps/unix/sysv/linux/sh/pread.c
|
||
rename to support/xcalloc.c
|
||
index d3f99f35db..135f42dab2 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/pread.c
|
||
+++ b/support/xcalloc.c
|
||
@@ -1,6 +1,6 @@
|
||
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||
+/* Error-checking wrapper for calloc.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -16,8 +16,19 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||
- the kernel interface for pread adds a dummy long argument before the
|
||
- offset. */
|
||
-#define __ALIGNMENT_ARG
|
||
-#include <sysdeps/unix/sysv/linux/pread.c>
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void *
|
||
+xcalloc (size_t n, size_t s)
|
||
+{
|
||
+ void *p;
|
||
+
|
||
+ p = calloc (n, s);
|
||
+ if (p == NULL)
|
||
+ oom_error ("calloc", n * s);
|
||
+ return p;
|
||
+}
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/pread64.c b/support/xchroot.c
|
||
similarity index 67%
|
||
rename from sysdeps/unix/sysv/linux/sh/pread64.c
|
||
rename to support/xchroot.c
|
||
index b2e8a25788..abcc299e00 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/pread64.c
|
||
+++ b/support/xchroot.c
|
||
@@ -1,6 +1,6 @@
|
||
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||
+/* chroot with error checking.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -16,8 +16,13 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||
- the kernel interface for pread adds a dummy long argument before the
|
||
- offset. */
|
||
-#define __ALIGNMENT_ARG
|
||
-#include <sysdeps/unix/sysv/linux/pread64.c>
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/stat.h>
|
||
+
|
||
+void
|
||
+xchroot (const char *path)
|
||
+{
|
||
+ if (chroot (path) != 0)
|
||
+ FAIL_EXIT1 ("chroot (\"%s\"): %m", path);
|
||
+}
|
||
diff --git a/support/xclose.c b/support/xclose.c
|
||
new file mode 100644
|
||
index 0000000000..c931e08421
|
||
--- /dev/null
|
||
+++ b/support/xclose.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* close with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+#include <support/check.h>
|
||
+#include <errno.h>
|
||
+
|
||
+void
|
||
+xclose (int fd)
|
||
+{
|
||
+ if (close (fd) < 0 && errno != EINTR)
|
||
+ FAIL_EXIT1 ("close of descriptor %d failed: %m", fd);
|
||
+}
|
||
diff --git a/support/xconnect.c b/support/xconnect.c
|
||
new file mode 100644
|
||
index 0000000000..0266dbc643
|
||
--- /dev/null
|
||
+++ b/support/xconnect.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* connect with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xconnect (int fd, const struct sockaddr *sa, socklen_t sa_len)
|
||
+{
|
||
+ if (connect (fd, sa, sa_len) != 0)
|
||
+ FAIL_EXIT1 ("connect (%d), family %d: %m", fd, sa->sa_family);
|
||
+}
|
||
diff --git a/support/xdup2.c b/support/xdup2.c
|
||
new file mode 100644
|
||
index 0000000000..dc08c94518
|
||
--- /dev/null
|
||
+++ b/support/xdup2.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* dup2 with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xdup2 (int from, int to)
|
||
+{
|
||
+ if (dup2 (from, to) < 0)
|
||
+ FAIL_EXIT1 ("dup2 (%d, %d): %m", from, to);
|
||
+}
|
||
diff --git a/support/xfclose.c b/support/xfclose.c
|
||
new file mode 100644
|
||
index 0000000000..2737f05044
|
||
--- /dev/null
|
||
+++ b/support/xfclose.c
|
||
@@ -0,0 +1,33 @@
|
||
+/* fclose with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xstdio.h>
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void
|
||
+xfclose (FILE *fp)
|
||
+{
|
||
+ if (ferror (fp))
|
||
+ FAIL_EXIT1 ("stdio stream closed with pending errors");
|
||
+ if (fflush (fp) != 0)
|
||
+ FAIL_EXIT1 ("fflush: %m");
|
||
+ if (fclose (fp) != 0)
|
||
+ FAIL_EXIT1 ("fclose: %m");
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf-vis3.S b/support/xfopen.c
|
||
similarity index 67%
|
||
rename from sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf-vis3.S
|
||
rename to support/xfopen.c
|
||
index 081fc15b62..14532a09f3 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf-vis3.S
|
||
+++ b/support/xfopen.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit+v9+vis3.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* fopen with error checking.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,16 +16,16 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
+#include <support/xstdio.h>
|
||
|
||
-ENTRY(__fdimf_vis3)
|
||
- movwtos %o0, %f0
|
||
- movwtos %o1, %f1
|
||
- fcmps %f0, %f1
|
||
- fbug 1f
|
||
- nop
|
||
- fzeros %f0
|
||
- fnegs %f0, %f1
|
||
-1: retl
|
||
- fsubs %f0, %f1, %f0
|
||
-END(__fdimf_vis3)
|
||
+#include <support/check.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+FILE *
|
||
+xfopen (const char *path, const char *mode)
|
||
+{
|
||
+ FILE *fp = fopen (path, mode);
|
||
+ if (fp == NULL)
|
||
+ FAIL_EXIT1 ("could not open %s (mode \"%s\"): %m", path, mode);
|
||
+ return fp;
|
||
+}
|
||
diff --git a/support/xfork.c b/support/xfork.c
|
||
new file mode 100644
|
||
index 0000000000..aa52ba62c5
|
||
--- /dev/null
|
||
+++ b/support/xfork.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* fork with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+pid_t
|
||
+xfork (void)
|
||
+{
|
||
+ pid_t result = fork ();
|
||
+ if (result < 0)
|
||
+ FAIL_EXIT1 ("fork: %m");
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xgetsockname.c b/support/xgetsockname.c
|
||
new file mode 100644
|
||
index 0000000000..c3bd884f8d
|
||
--- /dev/null
|
||
+++ b/support/xgetsockname.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* getsockname with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xgetsockname (int fd, struct sockaddr *sa, socklen_t *plen)
|
||
+{
|
||
+ if (getsockname (fd, sa, plen) != 0)
|
||
+ FAIL_EXIT1 ("setsockopt (%d): %m", fd);
|
||
+}
|
||
diff --git a/support/xlisten.c b/support/xlisten.c
|
||
new file mode 100644
|
||
index 0000000000..1953e5900a
|
||
--- /dev/null
|
||
+++ b/support/xlisten.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* listen with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xlisten (int fd, int backlog)
|
||
+{
|
||
+ if (listen (fd, backlog) != 0)
|
||
+ FAIL_EXIT1 ("listen (%d, %d): %m", fd, backlog);
|
||
+}
|
||
diff --git a/support/xmalloc.c b/support/xmalloc.c
|
||
new file mode 100644
|
||
index 0000000000..450f699789
|
||
--- /dev/null
|
||
+++ b/support/xmalloc.c
|
||
@@ -0,0 +1,34 @@
|
||
+/* Error-checking wrapper for malloc.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void *
|
||
+xmalloc (size_t n)
|
||
+{
|
||
+ void *p;
|
||
+
|
||
+ p = malloc (n);
|
||
+ if (p == NULL)
|
||
+ oom_error ("malloc", n);
|
||
+ return p;
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc32/fpu/s_fdim.S b/support/xmemstream.c
|
||
similarity index 54%
|
||
rename from sysdeps/sparc/sparc32/fpu/s_fdim.S
|
||
rename to support/xmemstream.c
|
||
index e93970faae..bce6dc9170 100644
|
||
--- a/sysdeps/sparc/sparc32/fpu/s_fdim.S
|
||
+++ b/support/xmemstream.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* Error-checking wrappers for memstream functions.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,26 +16,27 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
-#include <math_ldbl_opt.h>
|
||
+#include <support/xmemstream.h>
|
||
|
||
-ENTRY(__fdim)
|
||
- std %o0, [%sp + 72]
|
||
- std %o2, [%sp + 80]
|
||
- ldd [%sp + 72], %f0
|
||
- ldd [%sp + 80], %f2
|
||
- fcmpd %f0, %f2
|
||
- st %g0, [%sp + 72]
|
||
- fbug 1f
|
||
- st %g0, [%sp + 76]
|
||
- ldd [%sp + 72], %f0
|
||
- fnegs %f0, %f2
|
||
- fmovs %f1, %f3
|
||
-1: retl
|
||
- fsubd %f0, %f2, %f0
|
||
-END(__fdim)
|
||
-weak_alias (__fdim, fdim)
|
||
+#include <errno.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <support/xstdio.h>
|
||
|
||
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
|
||
-compat_symbol (libm, __fdim, fdiml, GLIBC_2_1);
|
||
-#endif
|
||
+void
|
||
+xopen_memstream (struct xmemstream *stream)
|
||
+{
|
||
+ int old_errno = errno;
|
||
+ *stream = (struct xmemstream) {};
|
||
+ stream->out = open_memstream (&stream->buffer, &stream->length);
|
||
+ if (stream->out == NULL)
|
||
+ FAIL_EXIT1 ("open_memstream: %m");
|
||
+ errno = old_errno;
|
||
+}
|
||
+
|
||
+void
|
||
+xfclose_memstream (struct xmemstream *stream)
|
||
+{
|
||
+ xfclose (stream->out);
|
||
+ stream->out = NULL;
|
||
+}
|
||
diff --git a/support/xmemstream.h b/support/xmemstream.h
|
||
new file mode 100644
|
||
index 0000000000..e5ba231e4d
|
||
--- /dev/null
|
||
+++ b/support/xmemstream.h
|
||
@@ -0,0 +1,49 @@
|
||
+/* Error-checking wrappers for memstream functions.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_XMEMSTREAM_H
|
||
+#define SUPPORT_XMEMSTREAM_H
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Wrappers for other libc functions. */
|
||
+struct xmemstream
|
||
+{
|
||
+ FILE *out;
|
||
+ char *buffer;
|
||
+ size_t length;
|
||
+};
|
||
+
|
||
+/* Create a new in-memory stream. Initializes *STREAM. After this
|
||
+ function returns, STREAM->out is a file descriptor open for
|
||
+ writing. errno is preserved, so that the %m format specifier can
|
||
+ be used for writing to STREAM->out. */
|
||
+void xopen_memstream (struct xmemstream *stream);
|
||
+
|
||
+/* Closes STREAM->OUT. After this function returns, STREAM->buffer
|
||
+ and STREAM->length denote a memory range which contains the bytes
|
||
+ written to the output stream. The caller should free
|
||
+ STREAM->buffer. */
|
||
+void xfclose_memstream (struct xmemstream *stream);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_XMEMSTREAM_H */
|
||
diff --git a/support/xmkdir.c b/support/xmkdir.c
|
||
new file mode 100644
|
||
index 0000000000..ea17d49391
|
||
--- /dev/null
|
||
+++ b/support/xmkdir.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* mkdir with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/stat.h>
|
||
+
|
||
+void
|
||
+xmkdir (const char *path, mode_t mode)
|
||
+{
|
||
+ if (mkdir (path, mode) != 0)
|
||
+ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", path, mode);
|
||
+}
|
||
diff --git a/support/xmmap.c b/support/xmmap.c
|
||
new file mode 100644
|
||
index 0000000000..435b1eb733
|
||
--- /dev/null
|
||
+++ b/support/xmmap.c
|
||
@@ -0,0 +1,31 @@
|
||
+/* mmap with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/mman.h>
|
||
+
|
||
+void *
|
||
+xmmap (void *addr, size_t length, int prot, int flags, int fd)
|
||
+{
|
||
+ void *result = mmap (addr, length, prot, flags, fd, 0);
|
||
+ if (result == MAP_FAILED)
|
||
+ FAIL_EXIT1 ("mmap of %zu bytes, prot=0x%x, flags=0x%x: %m",
|
||
+ length, prot, flags);
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xmunmap.c b/support/xmunmap.c
|
||
new file mode 100644
|
||
index 0000000000..6ef5a4a468
|
||
--- /dev/null
|
||
+++ b/support/xmunmap.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* munmap with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <sys/mman.h>
|
||
+
|
||
+void
|
||
+xmunmap (void *addr, size_t length)
|
||
+{
|
||
+ if (munmap (addr, length) != 0)
|
||
+ FAIL_EXIT1 ("munmap of %zu bytes: %m", length);
|
||
+}
|
||
diff --git a/support/xopen.c b/support/xopen.c
|
||
new file mode 100644
|
||
index 0000000000..7f033a03a7
|
||
--- /dev/null
|
||
+++ b/support/xopen.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* open64 with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/check.h>
|
||
+#include <support/xunistd.h>
|
||
+#include <fcntl.h>
|
||
+
|
||
+int
|
||
+xopen (const char *path, int flags, mode_t mode)
|
||
+{
|
||
+ int ret = open64 (path, flags, mode);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("open64 (\"%s\", 0x%x, 0%o): %m", path, flags, mode);
|
||
+ return ret;
|
||
+}
|
||
diff --git a/support/xpipe.c b/support/xpipe.c
|
||
new file mode 100644
|
||
index 0000000000..89a64a55c1
|
||
--- /dev/null
|
||
+++ b/support/xpipe.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* pipe with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xpipe (int fds[2])
|
||
+{
|
||
+ if (pipe (fds) < 0)
|
||
+ FAIL_EXIT1 ("pipe: %m");
|
||
+}
|
||
diff --git a/support/xpoll.c b/support/xpoll.c
|
||
new file mode 100644
|
||
index 0000000000..bec2521ffc
|
||
--- /dev/null
|
||
+++ b/support/xpoll.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* poll with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+int
|
||
+xpoll (struct pollfd *fds, nfds_t nfds, int timeout)
|
||
+{
|
||
+ int ret = poll (fds, nfds, timeout);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("poll: %m");
|
||
+ return ret;
|
||
+}
|
||
diff --git a/support/xpthread_attr_destroy.c b/support/xpthread_attr_destroy.c
|
||
new file mode 100644
|
||
index 0000000000..664c809e9f
|
||
--- /dev/null
|
||
+++ b/support/xpthread_attr_destroy.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_attr_destroy with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_attr_destroy (pthread_attr_t *attr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_attr_destroy",
|
||
+ pthread_attr_destroy (attr));
|
||
+}
|
||
diff --git a/support/xpthread_attr_init.c b/support/xpthread_attr_init.c
|
||
new file mode 100644
|
||
index 0000000000..2e30ade9ab
|
||
--- /dev/null
|
||
+++ b/support/xpthread_attr_init.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_attr_init with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_attr_init (pthread_attr_t *attr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_attr_init", pthread_attr_init (attr));
|
||
+}
|
||
diff --git a/support/xpthread_attr_setdetachstate.c b/support/xpthread_attr_setdetachstate.c
|
||
new file mode 100644
|
||
index 0000000000..b544dbaa42
|
||
--- /dev/null
|
||
+++ b/support/xpthread_attr_setdetachstate.c
|
||
@@ -0,0 +1,27 @@
|
||
+/* pthread_attr_setdetachstate with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate)
|
||
+{
|
||
+ xpthread_check_return ("pthread_attr_setdetachstate",
|
||
+ pthread_attr_setdetachstate (attr,
|
||
+ detachstate));
|
||
+}
|
||
diff --git a/support/xpthread_attr_setstacksize.c b/support/xpthread_attr_setstacksize.c
|
||
new file mode 100644
|
||
index 0000000000..02d06310a9
|
||
--- /dev/null
|
||
+++ b/support/xpthread_attr_setstacksize.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_attr_setstacksize with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize)
|
||
+{
|
||
+ xpthread_check_return ("pthread_attr_setstacksize",
|
||
+ pthread_attr_setstacksize (attr, stacksize));
|
||
+}
|
||
diff --git a/support/xpthread_barrier_destroy.c b/support/xpthread_barrier_destroy.c
|
||
new file mode 100644
|
||
index 0000000000..efc0719a63
|
||
--- /dev/null
|
||
+++ b/support/xpthread_barrier_destroy.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_barrier_destroy with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_barrier_destroy (pthread_barrier_t *barrier)
|
||
+{
|
||
+ xpthread_check_return ("pthread_barrier_destroy",
|
||
+ pthread_barrier_destroy (barrier));
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim-vis3.S b/support/xpthread_barrier_init.c
|
||
similarity index 65%
|
||
rename from sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim-vis3.S
|
||
rename to support/xpthread_barrier_init.c
|
||
index 4a479b1a59..b32dad1315 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim-vis3.S
|
||
+++ b/support/xpthread_barrier_init.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit+v9+vis3.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* pthread_barrier_init with error checking.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,18 +16,12 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
+#include <support/xthread.h>
|
||
|
||
-ENTRY(__fdim_vis3)
|
||
- movwtos %o0, %f0
|
||
- movwtos %o1, %f1
|
||
- movwtos %o2, %f2
|
||
- movwtos %o3, %f3
|
||
- fcmpd %f0, %f2
|
||
- fbug 1f
|
||
- nop
|
||
- fzero %f0
|
||
- fnegd %f0, %f2
|
||
-1: retl
|
||
- fsubd %f0, %f2, %f0
|
||
-END(__fdim_vis3)
|
||
+void
|
||
+xpthread_barrier_init (pthread_barrier_t *barrier,
|
||
+ pthread_barrierattr_t *attr, unsigned int count)
|
||
+{
|
||
+ xpthread_check_return ("pthread_barrier_init",
|
||
+ pthread_barrier_init (barrier, attr, count));
|
||
+}
|
||
diff --git a/support/xpthread_barrier_wait.c b/support/xpthread_barrier_wait.c
|
||
new file mode 100644
|
||
index 0000000000..7cee44d0a3
|
||
--- /dev/null
|
||
+++ b/support/xpthread_barrier_wait.c
|
||
@@ -0,0 +1,28 @@
|
||
+/* pthread_barrier_wait with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+int
|
||
+xpthread_barrier_wait (pthread_barrier_t *barrier)
|
||
+{
|
||
+ int ret = pthread_barrier_wait (barrier);
|
||
+ if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
|
||
+ xpthread_check_return ("pthread_barrier_wait", ret);
|
||
+ return ret == PTHREAD_BARRIER_SERIAL_THREAD;
|
||
+}
|
||
diff --git a/support/xpthread_cancel.c b/support/xpthread_cancel.c
|
||
new file mode 100644
|
||
index 0000000000..3af16f9b54
|
||
--- /dev/null
|
||
+++ b/support/xpthread_cancel.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_cancel with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_cancel (pthread_t thr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_cancel", pthread_cancel (thr));
|
||
+}
|
||
diff --git a/support/xpthread_check_return.c b/support/xpthread_check_return.c
|
||
new file mode 100644
|
||
index 0000000000..3094d82e9c
|
||
--- /dev/null
|
||
+++ b/support/xpthread_check_return.c
|
||
@@ -0,0 +1,34 @@
|
||
+/* Return value checking for pthread functions, exit variant.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+#include <errno.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xpthread_check_return (const char *function, int value)
|
||
+{
|
||
+ if (value != 0)
|
||
+ {
|
||
+ errno = value;
|
||
+ FAIL_EXIT1 ("%s: %m", function);
|
||
+ }
|
||
+}
|
||
diff --git a/support/xpthread_cond_wait.c b/support/xpthread_cond_wait.c
|
||
new file mode 100644
|
||
index 0000000000..b0e9b2a232
|
||
--- /dev/null
|
||
+++ b/support/xpthread_cond_wait.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_cond_wait with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||
+{
|
||
+ xpthread_check_return
|
||
+ ("pthread_cond_wait", pthread_cond_wait (cond, mutex));
|
||
+}
|
||
diff --git a/support/xpthread_create.c b/support/xpthread_create.c
|
||
new file mode 100644
|
||
index 0000000000..98c63e54c3
|
||
--- /dev/null
|
||
+++ b/support/xpthread_create.c
|
||
@@ -0,0 +1,29 @@
|
||
+/* pthread_create with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+pthread_t
|
||
+xpthread_create (pthread_attr_t *attr,
|
||
+ void *(*thread_func) (void *), void *closure)
|
||
+{
|
||
+ pthread_t thr;
|
||
+ xpthread_check_return
|
||
+ ("pthread_create", pthread_create (&thr, attr, thread_func, closure));
|
||
+ return thr;
|
||
+}
|
||
diff --git a/support/xpthread_detach.c b/support/xpthread_detach.c
|
||
new file mode 100644
|
||
index 0000000000..2088af2f57
|
||
--- /dev/null
|
||
+++ b/support/xpthread_detach.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_detach with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_detach (pthread_t thr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_detach", pthread_detach (thr));
|
||
+}
|
||
diff --git a/support/xpthread_join.c b/support/xpthread_join.c
|
||
new file mode 100644
|
||
index 0000000000..f23bb9a5ae
|
||
--- /dev/null
|
||
+++ b/support/xpthread_join.c
|
||
@@ -0,0 +1,27 @@
|
||
+/* pthread_join with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void *
|
||
+xpthread_join (pthread_t thr)
|
||
+{
|
||
+ void *result;
|
||
+ xpthread_check_return ("pthread_join", pthread_join (thr, &result));
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xpthread_mutex_consistent.c b/support/xpthread_mutex_consistent.c
|
||
new file mode 100644
|
||
index 0000000000..52364be365
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutex_consistent.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutex_consistent with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutex_consistent (pthread_mutex_t *mutex)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutex_consistent",
|
||
+ pthread_mutex_consistent (mutex));
|
||
+}
|
||
diff --git a/support/xpthread_mutex_destroy.c b/support/xpthread_mutex_destroy.c
|
||
new file mode 100644
|
||
index 0000000000..f11f8f0acd
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutex_destroy.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutex_destroy with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutex_destroy (pthread_mutex_t *mutex)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutex_destroy",
|
||
+ pthread_mutex_destroy (mutex));
|
||
+}
|
||
diff --git a/support/xpthread_mutex_init.c b/support/xpthread_mutex_init.c
|
||
new file mode 100644
|
||
index 0000000000..2d16d1b9d9
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutex_init.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutex_init with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutex_init",
|
||
+ pthread_mutex_init (mutex, attr));
|
||
+}
|
||
diff --git a/support/xpthread_mutex_lock.c b/support/xpthread_mutex_lock.c
|
||
new file mode 100644
|
||
index 0000000000..af727b45f3
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutex_lock.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_mutex_lock with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutex_lock (pthread_mutex_t *mutex)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutex_lock", pthread_mutex_lock (mutex));
|
||
+}
|
||
diff --git a/support/xpthread_mutex_unlock.c b/support/xpthread_mutex_unlock.c
|
||
new file mode 100644
|
||
index 0000000000..161b41edf6
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutex_unlock.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_mutex_unlock with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutex_unlock (pthread_mutex_t *mutex)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutex_unlock", pthread_mutex_unlock (mutex));
|
||
+}
|
||
diff --git a/support/xpthread_mutexattr_destroy.c b/support/xpthread_mutexattr_destroy.c
|
||
new file mode 100644
|
||
index 0000000000..c699e32b41
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutexattr_destroy.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutexattr_destroy with error checking.
|
||
+ Copyright (C) 2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutexattr_destroy (pthread_mutexattr_t *attr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_destroy",
|
||
+ pthread_mutexattr_destroy (attr));
|
||
+}
|
||
diff --git a/support/xpthread_mutexattr_init.c b/support/xpthread_mutexattr_init.c
|
||
new file mode 100644
|
||
index 0000000000..fa93fab178
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutexattr_init.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_mutexattr_init with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutexattr_init (pthread_mutexattr_t *attr)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_init", pthread_mutexattr_init (attr));
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc64/fpu/s_fdim.S b/support/xpthread_mutexattr_setprotocol.c
|
||
similarity index 67%
|
||
rename from sysdeps/sparc/sparc64/fpu/s_fdim.S
|
||
rename to support/xpthread_mutexattr_setprotocol.c
|
||
index 7fae72a251..353f75e3d7 100644
|
||
--- a/sysdeps/sparc/sparc64/fpu/s_fdim.S
|
||
+++ b/support/xpthread_mutexattr_setprotocol.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 64-bit.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* pthread_mutexattr_setprotocol with error checking.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,16 +16,11 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
-#include <math_ldbl_opt.h>
|
||
+#include <support/xthread.h>
|
||
|
||
-ENTRY(__fdim)
|
||
- fcmpd %f0, %f2
|
||
- fbug 1f
|
||
- nop
|
||
- fzero %f0
|
||
- fnegd %f0, %f2
|
||
-1: retl
|
||
- fsubd %f0, %f2, %f0
|
||
-END(__fdim)
|
||
-weak_alias (__fdim, fdim)
|
||
+void
|
||
+xpthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int flag)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_setprotocol",
|
||
+ pthread_mutexattr_setprotocol (attr, flag));
|
||
+}
|
||
diff --git a/support/xpthread_mutexattr_setpshared.c b/support/xpthread_mutexattr_setpshared.c
|
||
new file mode 100644
|
||
index 0000000000..242da1aeca
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutexattr_setpshared.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutexattr_setpshared with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int flag)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_setpshared",
|
||
+ pthread_mutexattr_setpshared (attr, flag));
|
||
+}
|
||
diff --git a/support/xpthread_mutexattr_setrobust.c b/support/xpthread_mutexattr_setrobust.c
|
||
new file mode 100644
|
||
index 0000000000..d7d6fa8630
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutexattr_setrobust.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutexattr_setrobust with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutexattr_setrobust (pthread_mutexattr_t *attr, int flag)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_setrobust",
|
||
+ pthread_mutexattr_setrobust (attr, flag));
|
||
+}
|
||
diff --git a/support/xpthread_mutexattr_settype.c b/support/xpthread_mutexattr_settype.c
|
||
new file mode 100644
|
||
index 0000000000..cf22170b56
|
||
--- /dev/null
|
||
+++ b/support/xpthread_mutexattr_settype.c
|
||
@@ -0,0 +1,26 @@
|
||
+/* pthread_mutexattr_settype with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_mutexattr_settype (pthread_mutexattr_t *attr, int flag)
|
||
+{
|
||
+ xpthread_check_return ("pthread_mutexattr_settype",
|
||
+ pthread_mutexattr_settype (attr, flag));
|
||
+}
|
||
diff --git a/support/xpthread_once.c b/support/xpthread_once.c
|
||
new file mode 100644
|
||
index 0000000000..70d58dbab2
|
||
--- /dev/null
|
||
+++ b/support/xpthread_once.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_once with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_once (pthread_once_t *guard, void (*func) (void))
|
||
+{
|
||
+ xpthread_check_return ("pthread_once", pthread_once (guard, func));
|
||
+}
|
||
diff --git a/support/xpthread_sigmask.c b/support/xpthread_sigmask.c
|
||
new file mode 100644
|
||
index 0000000000..0ba9ca02dc
|
||
--- /dev/null
|
||
+++ b/support/xpthread_sigmask.c
|
||
@@ -0,0 +1,34 @@
|
||
+/* pthread_sigmask with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsignal.h>
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <unistd.h>
|
||
+
|
||
+void
|
||
+xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset)
|
||
+{
|
||
+ if (pthread_sigmask (how, set, oldset) != 0)
|
||
+ {
|
||
+ write_message ("error: pthread_setmask failed\n");
|
||
+ /* Do not use exit because pthread_sigmask can be called from a
|
||
+ signal handler. */
|
||
+ _exit (1);
|
||
+ }
|
||
+}
|
||
diff --git a/support/xpthread_spin_lock.c b/support/xpthread_spin_lock.c
|
||
new file mode 100644
|
||
index 0000000000..6975215b17
|
||
--- /dev/null
|
||
+++ b/support/xpthread_spin_lock.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_spin_lock with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_spin_lock (pthread_spinlock_t *lock)
|
||
+{
|
||
+ xpthread_check_return ("pthread_spin_lock", pthread_spin_lock (lock));
|
||
+}
|
||
diff --git a/support/xpthread_spin_unlock.c b/support/xpthread_spin_unlock.c
|
||
new file mode 100644
|
||
index 0000000000..4f19a44c48
|
||
--- /dev/null
|
||
+++ b/support/xpthread_spin_unlock.c
|
||
@@ -0,0 +1,25 @@
|
||
+/* pthread_spin_unlock with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xthread.h>
|
||
+
|
||
+void
|
||
+xpthread_spin_unlock (pthread_spinlock_t *lock)
|
||
+{
|
||
+ xpthread_check_return ("pthread_spin_unlock", pthread_spin_unlock (lock));
|
||
+}
|
||
diff --git a/support/xrealloc.c b/support/xrealloc.c
|
||
new file mode 100644
|
||
index 0000000000..00c313880c
|
||
--- /dev/null
|
||
+++ b/support/xrealloc.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* Error-checking wrapper for realloc.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+
|
||
+void *
|
||
+xrealloc (void *p, size_t n)
|
||
+{
|
||
+ void *result = realloc (p, n);
|
||
+ if (result == NULL && (n > 0 || p == NULL))
|
||
+ oom_error ("realloc", n);
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xrecvfrom.c b/support/xrecvfrom.c
|
||
new file mode 100644
|
||
index 0000000000..17809c4dd2
|
||
--- /dev/null
|
||
+++ b/support/xrecvfrom.c
|
||
@@ -0,0 +1,33 @@
|
||
+/* recvfrom with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+size_t
|
||
+xrecvfrom (int fd, void *buf, size_t buflen, int flags,
|
||
+ struct sockaddr *sa, socklen_t *salen)
|
||
+{
|
||
+ ssize_t ret = recvfrom (fd, buf, buflen, flags, sa, salen);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("error: recvfrom (%d), %zu bytes buffer: %m", fd, buflen);
|
||
+ return ret;
|
||
+}
|
||
diff --git a/support/xsendto.c b/support/xsendto.c
|
||
new file mode 100644
|
||
index 0000000000..20bddf6965
|
||
--- /dev/null
|
||
+++ b/support/xsendto.c
|
||
@@ -0,0 +1,35 @@
|
||
+/* sendto with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xsendto (int fd, const void *buf, size_t buflen, int flags,
|
||
+ const struct sockaddr *sa, socklen_t salen)
|
||
+{
|
||
+ ssize_t ret = sendto (fd, buf, buflen, flags, sa, salen);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("sendto (%d), %zu bytes, family %d: %m",
|
||
+ fd, buflen, sa->sa_family);
|
||
+ if (ret != buflen)
|
||
+ FAIL_EXIT1 ("sendto (%d) sent %zd bytes instead of %zu", fd, ret, buflen);
|
||
+}
|
||
diff --git a/sysdeps/sparc/sparc32/fpu/s_fdimf.S b/support/xsetsockopt.c
|
||
similarity index 62%
|
||
rename from sysdeps/sparc/sparc32/fpu/s_fdimf.S
|
||
rename to support/xsetsockopt.c
|
||
index c3fe8afa98..9931882e75 100644
|
||
--- a/sysdeps/sparc/sparc32/fpu/s_fdimf.S
|
||
+++ b/support/xsetsockopt.c
|
||
@@ -1,7 +1,6 @@
|
||
-/* Compute positive difference, sparc 32-bit.
|
||
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||
+/* setsockopt with error checking.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
- Contributed by David S. Miller <davem@davemloft.net>.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU Lesser General Public
|
||
@@ -17,19 +16,16 @@
|
||
License along with the GNU C Library; if not, see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
-#include <sysdep.h>
|
||
+#include <support/xsocket.h>
|
||
|
||
-ENTRY(__fdimf)
|
||
- st %o0, [%sp + 72]
|
||
- st %o1, [%sp + 76]
|
||
- ld [%sp + 72], %f0
|
||
- ld [%sp + 76], %f1
|
||
- fcmps %f0, %f1
|
||
- fbug 1f
|
||
- st %g0, [%sp + 72]
|
||
- ld [%sp + 72], %f0
|
||
- fnegs %f0, %f1
|
||
-1: retl
|
||
- fsubs %f0, %f1, %f0
|
||
-END(__fdimf)
|
||
-weak_alias (__fdimf, fdimf)
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xsetsockopt (int fd, int level, int name, const void *val, socklen_t vallen)
|
||
+{
|
||
+ if (setsockopt (fd, level, name, val, vallen) != 0)
|
||
+ FAIL_EXIT1 ("setsockopt (%d, %d, %d), %zu bytes: %m",
|
||
+ fd, level, name, (size_t) vallen);
|
||
+}
|
||
diff --git a/support/xsignal.h b/support/xsignal.h
|
||
new file mode 100644
|
||
index 0000000000..3dc0d9d5ce
|
||
--- /dev/null
|
||
+++ b/support/xsignal.h
|
||
@@ -0,0 +1,34 @@
|
||
+/* Support functionality for using signals.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_SIGNAL_H
|
||
+#define SUPPORT_SIGNAL_H
|
||
+
|
||
+#include <signal.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* The following functions call the corresponding libpthread functions
|
||
+ and terminate the process on error. */
|
||
+
|
||
+void xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_SIGNAL_H */
|
||
diff --git a/support/xsocket.c b/support/xsocket.c
|
||
new file mode 100644
|
||
index 0000000000..c1deaee924
|
||
--- /dev/null
|
||
+++ b/support/xsocket.c
|
||
@@ -0,0 +1,32 @@
|
||
+/* socket with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xsocket.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+
|
||
+int
|
||
+xsocket (int domain, int type, int protocol)
|
||
+{
|
||
+ int fd = socket (domain, type, protocol);
|
||
+ if (fd < 0)
|
||
+ FAIL_EXIT1 ("socket (%d, %d, %d): %m\n", domain, type, protocol);
|
||
+ return fd;
|
||
+}
|
||
diff --git a/support/xsocket.h b/support/xsocket.h
|
||
new file mode 100644
|
||
index 0000000000..d6724948d8
|
||
--- /dev/null
|
||
+++ b/support/xsocket.h
|
||
@@ -0,0 +1,39 @@
|
||
+/* Error-checking wrappers for socket functions.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_XSOCKET_H
|
||
+#define SUPPORT_XSOCKET_H
|
||
+
|
||
+#include <poll.h>
|
||
+#include <sys/socket.h>
|
||
+#include <sys/types.h>
|
||
+
|
||
+int xsocket (int, int, int);
|
||
+void xsetsockopt (int, int, int, const void *, socklen_t);
|
||
+void xgetsockname (int, struct sockaddr *, socklen_t *);
|
||
+void xconnect (int, const struct sockaddr *, socklen_t);
|
||
+void xbind (int, const struct sockaddr *, socklen_t);
|
||
+void xlisten (int, int);
|
||
+int xaccept (int, struct sockaddr *, socklen_t *);
|
||
+int xaccept4 (int, struct sockaddr *, socklen_t *, int);
|
||
+void xsendto (int, const void *, size_t, int,
|
||
+ const struct sockaddr *, socklen_t);
|
||
+size_t xrecvfrom (int, void *, size_t, int, struct sockaddr *, socklen_t *);
|
||
+int xpoll (struct pollfd *, nfds_t, int);
|
||
+
|
||
+#endif /* SUPPORT_XSOCKET_H */
|
||
diff --git a/support/xstdio.h b/support/xstdio.h
|
||
new file mode 100644
|
||
index 0000000000..bcc2e863bf
|
||
--- /dev/null
|
||
+++ b/support/xstdio.h
|
||
@@ -0,0 +1,32 @@
|
||
+/* Error-checking wrappers for stdio functions.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_XSTDIO_H
|
||
+#define SUPPORT_XSTDIO_H
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+FILE *xfopen (const char *path, const char *mode);
|
||
+void xfclose (FILE *);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_XSTDIO_H */
|
||
diff --git a/support/xstrdup.c b/support/xstrdup.c
|
||
new file mode 100644
|
||
index 0000000000..d6a8c04baf
|
||
--- /dev/null
|
||
+++ b/support/xstrdup.c
|
||
@@ -0,0 +1,30 @@
|
||
+/* strdup with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/support.h>
|
||
+
|
||
+#include <string.h>
|
||
+
|
||
+char *
|
||
+xstrdup (const char *s)
|
||
+{
|
||
+ char *p = strdup (s);
|
||
+ if (p == NULL)
|
||
+ oom_error ("strdup", strlen (s));
|
||
+ return p;
|
||
+}
|
||
diff --git a/support/xthread.h b/support/xthread.h
|
||
new file mode 100644
|
||
index 0000000000..6dd7e709be
|
||
--- /dev/null
|
||
+++ b/support/xthread.h
|
||
@@ -0,0 +1,77 @@
|
||
+/* Support functionality for using threads.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#ifndef SUPPORT_THREAD_H
|
||
+#define SUPPORT_THREAD_H
|
||
+
|
||
+#include <pthread.h>
|
||
+#include <sys/cdefs.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+/* Terminate the process (with exit status 0) after SECONDS have
|
||
+ elapsed, from a helper thread. The process is terminated with the
|
||
+ exit function, so atexit handlers are executed. */
|
||
+void delayed_exit (int seconds);
|
||
+
|
||
+/* Terminate the process (with exit status 1) if VALUE is not zero.
|
||
+ In that case, print a failure message to standard output mentioning
|
||
+ FUNCTION. The process is terminated with the exit function, so
|
||
+ atexit handlers are executed. */
|
||
+void xpthread_check_return (const char *function, int value);
|
||
+
|
||
+/* The following functions call the corresponding libpthread functions
|
||
+ and terminate the process on error. */
|
||
+
|
||
+void xpthread_barrier_init (pthread_barrier_t *barrier,
|
||
+ pthread_barrierattr_t *attr, unsigned int count);
|
||
+void xpthread_barrier_destroy (pthread_barrier_t *barrier);
|
||
+void xpthread_mutexattr_destroy (pthread_mutexattr_t *);
|
||
+void xpthread_mutexattr_init (pthread_mutexattr_t *);
|
||
+void xpthread_mutexattr_setprotocol (pthread_mutexattr_t *, int);
|
||
+void xpthread_mutexattr_setpshared (pthread_mutexattr_t *, int);
|
||
+void xpthread_mutexattr_setrobust (pthread_mutexattr_t *, int);
|
||
+void xpthread_mutexattr_settype (pthread_mutexattr_t *, int);
|
||
+void xpthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
|
||
+void xpthread_mutex_destroy (pthread_mutex_t *);
|
||
+void xpthread_mutex_lock (pthread_mutex_t *mutex);
|
||
+void xpthread_mutex_unlock (pthread_mutex_t *mutex);
|
||
+void xpthread_mutex_consistent (pthread_mutex_t *);
|
||
+void xpthread_spin_lock (pthread_spinlock_t *lock);
|
||
+void xpthread_spin_unlock (pthread_spinlock_t *lock);
|
||
+void xpthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex);
|
||
+pthread_t xpthread_create (pthread_attr_t *attr,
|
||
+ void *(*thread_func) (void *), void *closure);
|
||
+void xpthread_detach (pthread_t thr);
|
||
+void xpthread_cancel (pthread_t thr);
|
||
+void *xpthread_join (pthread_t thr);
|
||
+void xpthread_once (pthread_once_t *guard, void (*func) (void));
|
||
+void xpthread_attr_destroy (pthread_attr_t *attr);
|
||
+void xpthread_attr_init (pthread_attr_t *attr);
|
||
+void xpthread_attr_setdetachstate (pthread_attr_t *attr,
|
||
+ int detachstate);
|
||
+void xpthread_attr_setstacksize (pthread_attr_t *attr,
|
||
+ size_t stacksize);
|
||
+
|
||
+/* This function returns non-zero if pthread_barrier_wait returned
|
||
+ PTHREAD_BARRIER_SERIAL_THREAD. */
|
||
+int xpthread_barrier_wait (pthread_barrier_t *barrier);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_THREAD_H */
|
||
diff --git a/support/xunistd.h b/support/xunistd.h
|
||
new file mode 100644
|
||
index 0000000000..151d743e1f
|
||
--- /dev/null
|
||
+++ b/support/xunistd.h
|
||
@@ -0,0 +1,56 @@
|
||
+/* POSIX-specific extra functions.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* These wrapper functions use POSIX types and therefore cannot be
|
||
+ declared in <support/support.h>. */
|
||
+
|
||
+#ifndef SUPPORT_XUNISTD_H
|
||
+#define SUPPORT_XUNISTD_H
|
||
+
|
||
+#include <sys/cdefs.h>
|
||
+#include <sys/types.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+__BEGIN_DECLS
|
||
+
|
||
+struct stat64;
|
||
+
|
||
+pid_t xfork (void);
|
||
+pid_t xwaitpid (pid_t, int *status, int flags);
|
||
+void xpipe (int[2]);
|
||
+void xdup2 (int, int);
|
||
+int xopen (const char *path, int flags, mode_t);
|
||
+void xstat (const char *path, struct stat64 *);
|
||
+void xmkdir (const char *path, mode_t);
|
||
+void xchroot (const char *path);
|
||
+
|
||
+/* Close the file descriptor. Ignore EINTR errors, but terminate the
|
||
+ process on other errors. */
|
||
+void xclose (int);
|
||
+
|
||
+/* Write the buffer. Retry on short writes. */
|
||
+void xwrite (int, const void *, size_t);
|
||
+
|
||
+/* Invoke mmap with a zero file offset. */
|
||
+void *xmmap (void *addr, size_t length, int prot, int flags, int fd);
|
||
+
|
||
+void xmunmap (void *addr, size_t length);
|
||
+
|
||
+__END_DECLS
|
||
+
|
||
+#endif /* SUPPORT_XUNISTD_H */
|
||
diff --git a/support/xwaitpid.c b/support/xwaitpid.c
|
||
new file mode 100644
|
||
index 0000000000..204795e4c0
|
||
--- /dev/null
|
||
+++ b/support/xwaitpid.c
|
||
@@ -0,0 +1,33 @@
|
||
+/* waitpid with error checking.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <support/check.h>
|
||
+#include <sys/wait.h>
|
||
+
|
||
+int
|
||
+xwaitpid (int pid, int *status, int flags)
|
||
+{
|
||
+ pid_t result = waitpid (pid, status, flags);
|
||
+ if (result < 0)
|
||
+ FAIL_EXIT1 ("waitpid: %m\n");
|
||
+ return result;
|
||
+}
|
||
diff --git a/support/xwrite.c b/support/xwrite.c
|
||
new file mode 100644
|
||
index 0000000000..134e8ee4c1
|
||
--- /dev/null
|
||
+++ b/support/xwrite.c
|
||
@@ -0,0 +1,39 @@
|
||
+/* write with error checking and retries.
|
||
+ Copyright (C) 2016-2017 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
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+#include <support/check.h>
|
||
+
|
||
+void
|
||
+xwrite (int fd, const void *buffer, size_t length)
|
||
+{
|
||
+ const char *p = buffer;
|
||
+ const char *end = p + length;
|
||
+ while (p < end)
|
||
+ {
|
||
+ ssize_t ret = write (fd, p, end - p);
|
||
+ if (ret < 0)
|
||
+ FAIL_EXIT1 ("write of %zu bytes failed after %td: %m",
|
||
+ length, p - (const char *) buffer);
|
||
+ if (ret == 0)
|
||
+ FAIL_EXIT1 ("write return 0 after writing %td bytes of %zu",
|
||
+ p - (const char *) buffer, length);
|
||
+ p += ret;
|
||
+ }
|
||
+}
|
||
diff --git a/sysdeps/aarch64/nptl/tcb-offsets.sym b/sysdeps/aarch64/nptl/tcb-offsets.sym
|
||
index 0677aeabff..238647dd47 100644
|
||
--- a/sysdeps/aarch64/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/aarch64/nptl/tcb-offsets.sym
|
||
@@ -2,6 +2,5 @@
|
||
#include <tls.h>
|
||
|
||
PTHREAD_MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
|
||
-PTHREAD_PID_OFFSET offsetof (struct pthread, pid)
|
||
PTHREAD_TID_OFFSET offsetof (struct pthread, tid)
|
||
PTHREAD_SIZEOF sizeof (struct pthread)
|
||
diff --git a/sysdeps/alpha/fpu/s_ceil.c b/sysdeps/alpha/fpu/s_ceil.c
|
||
index c1ff864d4b..e9c350af1c 100644
|
||
--- a/sysdeps/alpha/fpu/s_ceil.c
|
||
+++ b/sysdeps/alpha/fpu/s_ceil.c
|
||
@@ -26,17 +26,16 @@
|
||
double
|
||
__ceil (double x)
|
||
{
|
||
+ if (isnan (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
|
||
{
|
||
double tmp1, new_x;
|
||
|
||
new_x = -x;
|
||
__asm (
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "cvttq/svim %2,%1\n\t"
|
||
-#else
|
||
"cvttq/svm %2,%1\n\t"
|
||
-#endif
|
||
"cvtqt/m %1,%0\n\t"
|
||
: "=f"(new_x), "=&f"(tmp1)
|
||
: "f"(new_x));
|
||
diff --git a/sysdeps/alpha/fpu/s_ceilf.c b/sysdeps/alpha/fpu/s_ceilf.c
|
||
index 7e63a6fe94..77e01a99f7 100644
|
||
--- a/sysdeps/alpha/fpu/s_ceilf.c
|
||
+++ b/sysdeps/alpha/fpu/s_ceilf.c
|
||
@@ -25,6 +25,9 @@
|
||
float
|
||
__ceilf (float x)
|
||
{
|
||
+ if (isnanf (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */
|
||
{
|
||
/* Note that Alpha S_Floating is stored in registers in a
|
||
@@ -36,11 +39,7 @@ __ceilf (float x)
|
||
|
||
new_x = -x;
|
||
__asm ("cvtst/s %3,%2\n\t"
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "cvttq/svim %2,%1\n\t"
|
||
-#else
|
||
"cvttq/svm %2,%1\n\t"
|
||
-#endif
|
||
"cvtqt/m %1,%0\n\t"
|
||
: "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2)
|
||
: "f"(new_x));
|
||
diff --git a/sysdeps/alpha/fpu/s_floor.c b/sysdeps/alpha/fpu/s_floor.c
|
||
index 1a6f8c4617..9930f6be42 100644
|
||
--- a/sysdeps/alpha/fpu/s_floor.c
|
||
+++ b/sysdeps/alpha/fpu/s_floor.c
|
||
@@ -27,16 +27,15 @@
|
||
double
|
||
__floor (double x)
|
||
{
|
||
+ if (isnan (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
|
||
{
|
||
double tmp1, new_x;
|
||
|
||
__asm (
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "cvttq/svim %2,%1\n\t"
|
||
-#else
|
||
"cvttq/svm %2,%1\n\t"
|
||
-#endif
|
||
"cvtqt/m %1,%0\n\t"
|
||
: "=f"(new_x), "=&f"(tmp1)
|
||
: "f"(x));
|
||
diff --git a/sysdeps/alpha/fpu/s_floorf.c b/sysdeps/alpha/fpu/s_floorf.c
|
||
index 8cd80e2b42..015c04f40d 100644
|
||
--- a/sysdeps/alpha/fpu/s_floorf.c
|
||
+++ b/sysdeps/alpha/fpu/s_floorf.c
|
||
@@ -26,6 +26,9 @@
|
||
float
|
||
__floorf (float x)
|
||
{
|
||
+ if (isnanf (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */
|
||
{
|
||
/* Note that Alpha S_Floating is stored in registers in a
|
||
@@ -36,11 +39,7 @@ __floorf (float x)
|
||
float tmp1, tmp2, new_x;
|
||
|
||
__asm ("cvtst/s %3,%2\n\t"
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "cvttq/svim %2,%1\n\t"
|
||
-#else
|
||
"cvttq/svm %2,%1\n\t"
|
||
-#endif
|
||
"cvtqt/m %1,%0\n\t"
|
||
: "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2)
|
||
: "f"(x));
|
||
diff --git a/sysdeps/alpha/fpu/s_rint.c b/sysdeps/alpha/fpu/s_rint.c
|
||
index f33fe72c11..259348afc0 100644
|
||
--- a/sysdeps/alpha/fpu/s_rint.c
|
||
+++ b/sysdeps/alpha/fpu/s_rint.c
|
||
@@ -23,6 +23,9 @@
|
||
double
|
||
__rint (double x)
|
||
{
|
||
+ if (isnan (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
|
||
{
|
||
double tmp1, new_x;
|
||
diff --git a/sysdeps/alpha/fpu/s_rintf.c b/sysdeps/alpha/fpu/s_rintf.c
|
||
index 1400dfe8d7..645728ad5b 100644
|
||
--- a/sysdeps/alpha/fpu/s_rintf.c
|
||
+++ b/sysdeps/alpha/fpu/s_rintf.c
|
||
@@ -22,6 +22,9 @@
|
||
float
|
||
__rintf (float x)
|
||
{
|
||
+ if (isnanf (x))
|
||
+ return x + x;
|
||
+
|
||
if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */
|
||
{
|
||
/* Note that Alpha S_Floating is stored in registers in a
|
||
diff --git a/sysdeps/alpha/fpu/s_trunc.c b/sysdeps/alpha/fpu/s_trunc.c
|
||
index 16cb114a72..4b986a6926 100644
|
||
--- a/sysdeps/alpha/fpu/s_trunc.c
|
||
+++ b/sysdeps/alpha/fpu/s_trunc.c
|
||
@@ -28,12 +28,11 @@ __trunc (double x)
|
||
double two52 = copysign (0x1.0p52, x);
|
||
double r, tmp;
|
||
|
||
+ if (isgreaterequal (fabs (x), 0x1.0p52))
|
||
+ return x;
|
||
+
|
||
__asm (
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "addt/suic %2, %3, %1\n\tsubt/suic %1, %3, %0"
|
||
-#else
|
||
"addt/suc %2, %3, %1\n\tsubt/suc %1, %3, %0"
|
||
-#endif
|
||
: "=&f"(r), "=&f"(tmp)
|
||
: "f"(x), "f"(two52));
|
||
|
||
diff --git a/sysdeps/alpha/fpu/s_truncf.c b/sysdeps/alpha/fpu/s_truncf.c
|
||
index 2290f28295..3e93356166 100644
|
||
--- a/sysdeps/alpha/fpu/s_truncf.c
|
||
+++ b/sysdeps/alpha/fpu/s_truncf.c
|
||
@@ -27,12 +27,11 @@ __truncf (float x)
|
||
float two23 = copysignf (0x1.0p23, x);
|
||
float r, tmp;
|
||
|
||
+ if (isgreaterequal (fabsf (x), 0x1.0p23))
|
||
+ return x;
|
||
+
|
||
__asm (
|
||
-#ifdef _IEEE_FP_INEXACT
|
||
- "adds/suic %2, %3, %1\n\tsubs/suic %1, %3, %0"
|
||
-#else
|
||
"adds/suc %2, %3, %1\n\tsubs/suc %1, %3, %0"
|
||
-#endif
|
||
: "=&f"(r), "=&f"(tmp)
|
||
: "f"(x), "f"(two23));
|
||
|
||
diff --git a/sysdeps/alpha/nptl/tcb-offsets.sym b/sysdeps/alpha/nptl/tcb-offsets.sym
|
||
index c21a791040..1005621b37 100644
|
||
--- a/sysdeps/alpha/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/alpha/nptl/tcb-offsets.sym
|
||
@@ -10,5 +10,4 @@
|
||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
|
||
index 2f7751d167..dfa7198306 100644
|
||
--- a/sysdeps/arm/nacl/libc.abilist
|
||
+++ b/sysdeps/arm/nacl/libc.abilist
|
||
@@ -1840,4 +1840,5 @@ GLIBC_2.23 fts64_close F
|
||
GLIBC_2.23 fts64_open F
|
||
GLIBC_2.23 fts64_read F
|
||
GLIBC_2.23 fts64_set F
|
||
+GLIBC_2.24 GLIBC_2.24 A
|
||
GLIBC_2.24 quick_exit F
|
||
diff --git a/sysdeps/arm/nptl/tcb-offsets.sym b/sysdeps/arm/nptl/tcb-offsets.sym
|
||
index 92cc441d3d..bf9c0a1c17 100644
|
||
--- a/sysdeps/arm/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/arm/nptl/tcb-offsets.sym
|
||
@@ -7,5 +7,4 @@
|
||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h
|
||
index d5b8119c9c..3e56538b51 100644
|
||
--- a/sysdeps/generic/unsecvars.h
|
||
+++ b/sysdeps/generic/unsecvars.h
|
||
@@ -4,6 +4,7 @@
|
||
#define UNSECURE_ENVVARS \
|
||
"GCONV_PATH\0" \
|
||
"GETCONF_DIR\0" \
|
||
+ "GLIBC_TUNABLES\0" \
|
||
"HOSTALIASES\0" \
|
||
"LD_AUDIT\0" \
|
||
"LD_DEBUG\0" \
|
||
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
|
||
index 9404211819..01bd5bf197 100644
|
||
--- a/sysdeps/hppa/dl-machine.h
|
||
+++ b/sysdeps/hppa/dl-machine.h
|
||
@@ -302,6 +302,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||
#define ARCH_LA_PLTENTER hppa_gnu_pltenter
|
||
#define ARCH_LA_PLTEXIT hppa_gnu_pltexit
|
||
|
||
+/* Adjust DL_STACK_END to get value we want in __libc_stack_end. */
|
||
+#define DL_STACK_END(cookie) \
|
||
+ ((void *) (((long) (cookie)) + 0x160))
|
||
+
|
||
/* Initial entry point code for the dynamic linker.
|
||
The C function `_dl_start' is the real entry point;
|
||
its return value is the user program's entry point. */
|
||
@@ -401,11 +405,6 @@ asm ( \
|
||
/* Save the entry point in %r3. */ \
|
||
" copy %ret0,%r3\n" \
|
||
\
|
||
- /* Remember the lowest stack address. */ \
|
||
-" addil LT'__libc_stack_end,%r19\n" \
|
||
-" ldw RT'__libc_stack_end(%r1),%r20\n" \
|
||
-" stw %sp,0(%r20)\n" \
|
||
- \
|
||
/* See if we were called as a command with the executable file \
|
||
name as an extra leading argument. */ \
|
||
" addil LT'_dl_skip_args,%r19\n" \
|
||
diff --git a/sysdeps/hppa/nptl/tcb-offsets.sym b/sysdeps/hppa/nptl/tcb-offsets.sym
|
||
index c2f326ee3d..6e852f35b1 100644
|
||
--- a/sysdeps/hppa/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/hppa/nptl/tcb-offsets.sym
|
||
@@ -3,7 +3,6 @@
|
||
|
||
RESULT offsetof (struct pthread, result)
|
||
TID offsetof (struct pthread, tid)
|
||
-PID offsetof (struct pthread, pid)
|
||
CANCELHANDLING offsetof (struct pthread, cancelhandling)
|
||
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
|
||
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
|
||
@@ -14,6 +13,5 @@ MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock)
|
||
-- This way we get the offset of a member in the struct pthread that
|
||
-- preceeds the thread pointer (which points to the dtv).
|
||
#define thread_offsetof(mem) (unsigned int)(offsetof(struct pthread, mem) - sizeof(struct pthread))
|
||
-PID_THREAD_OFFSET thread_offsetof (pid)
|
||
TID_THREAD_OFFSET thread_offsetof (tid)
|
||
MULTIPLE_THREADS_THREAD_OFFSET thread_offsetof (header.multiple_threads)
|
||
diff --git a/sysdeps/i386/nptl/tcb-offsets.sym b/sysdeps/i386/nptl/tcb-offsets.sym
|
||
index 7bdf161b29..695a810386 100644
|
||
--- a/sysdeps/i386/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/i386/nptl/tcb-offsets.sym
|
||
@@ -4,7 +4,6 @@
|
||
|
||
RESULT offsetof (struct pthread, result)
|
||
TID offsetof (struct pthread, tid)
|
||
-PID offsetof (struct pthread, pid)
|
||
CANCELHANDLING offsetof (struct pthread, cancelhandling)
|
||
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
|
||
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
|
||
diff --git a/sysdeps/ia64/nptl/Makefile b/sysdeps/ia64/nptl/Makefile
|
||
index 48f1327446..1e6be8eea8 100644
|
||
--- a/sysdeps/ia64/nptl/Makefile
|
||
+++ b/sysdeps/ia64/nptl/Makefile
|
||
@@ -21,4 +21,5 @@ endif
|
||
|
||
ifeq ($(subdir),nptl)
|
||
libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
|
||
+libpthread-shared-only-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
|
||
endif
|
||
diff --git a/sysdeps/ia64/nptl/tcb-offsets.sym b/sysdeps/ia64/nptl/tcb-offsets.sym
|
||
index e1707ab1c8..b01f712be2 100644
|
||
--- a/sysdeps/ia64/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/ia64/nptl/tcb-offsets.sym
|
||
@@ -1,7 +1,6 @@
|
||
#include <sysdep.h>
|
||
#include <tls.h>
|
||
|
||
-PID offsetof (struct pthread, pid) - TLS_PRE_TCB_SIZE
|
||
TID offsetof (struct pthread, tid) - TLS_PRE_TCB_SIZE
|
||
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) - TLS_PRE_TCB_SIZE
|
||
SYSINFO_OFFSET offsetof (tcbhead_t, __private)
|
||
diff --git a/sysdeps/m68k/m680x0/m68020/atomic-machine.h b/sysdeps/m68k/m680x0/m68020/atomic-machine.h
|
||
index 24bc5c5ef7..65965cca9e 100644
|
||
--- a/sysdeps/m68k/m680x0/m68020/atomic-machine.h
|
||
+++ b/sysdeps/m68k/m680x0/m68020/atomic-machine.h
|
||
@@ -73,7 +73,7 @@ typedef uintmax_t uatomic_max_t;
|
||
__typeof (mem) __memp = (mem); \
|
||
__asm __volatile ("cas2%.l %0:%R0,%1:%R1,(%2):(%3)" \
|
||
: "=d" (__ret) \
|
||
- : "d" (newval), "r" (__memp), \
|
||
+ : "d" ((__typeof (*(mem))) (newval)), "r" (__memp), \
|
||
"r" ((char *) __memp + 4), "0" (oldval) \
|
||
: "memory"); \
|
||
__ret; })
|
||
@@ -101,8 +101,9 @@ typedef uintmax_t uatomic_max_t;
|
||
__asm __volatile ("1: cas2%.l %0:%R0,%1:%R1,(%2):(%3);" \
|
||
" jbne 1b" \
|
||
: "=d" (__result) \
|
||
- : "d" (newvalue), "r" (__memp), \
|
||
- "r" ((char *) __memp + 4), "0" (__result) \
|
||
+ : "d" ((__typeof (*(mem))) (newvalue)), \
|
||
+ "r" (__memp), "r" ((char *) __memp + 4), \
|
||
+ "0" (__result) \
|
||
: "memory"); \
|
||
} \
|
||
__result; })
|
||
@@ -144,7 +145,7 @@ typedef uintmax_t uatomic_max_t;
|
||
" cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \
|
||
" jbne 1b" \
|
||
: "=d" (__result), "=&d" (__temp) \
|
||
- : "d" (value), "r" (__memp), \
|
||
+ : "d" ((__typeof (*(mem))) (value)), "r" (__memp), \
|
||
"r" ((char *) __memp + 4), "0" (__result) \
|
||
: "memory"); \
|
||
} \
|
||
@@ -175,8 +176,9 @@ typedef uintmax_t uatomic_max_t;
|
||
" cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \
|
||
" jbne 1b" \
|
||
: "=d" (__oldval), "=&d" (__temp) \
|
||
- : "d" (value), "r" (__memp), \
|
||
- "r" ((char *) __memp + 4), "0" (__oldval) \
|
||
+ : "d" ((__typeof (*(mem))) (value)), \
|
||
+ "r" (__memp), "r" ((char *) __memp + 4), \
|
||
+ "0" (__oldval) \
|
||
: "memory"); \
|
||
} \
|
||
})
|
||
diff --git a/sysdeps/m68k/nptl/tcb-offsets.sym b/sysdeps/m68k/nptl/tcb-offsets.sym
|
||
index b1bba65868..241fb8b47c 100644
|
||
--- a/sysdeps/m68k/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/m68k/nptl/tcb-offsets.sym
|
||
@@ -7,5 +7,4 @@
|
||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
diff --git a/sysdeps/microblaze/nptl/tcb-offsets.sym b/sysdeps/microblaze/nptl/tcb-offsets.sym
|
||
index 18afbee291..614f0dfed6 100644
|
||
--- a/sysdeps/microblaze/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/microblaze/nptl/tcb-offsets.sym
|
||
@@ -7,5 +7,4 @@
|
||
#define thread_offsetof(mem) (long)(offsetof (struct pthread, mem) - sizeof (struct pthread))
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
|
||
index 3d3552322b..7c1d77941e 100644
|
||
--- a/sysdeps/mips/Makefile
|
||
+++ b/sysdeps/mips/Makefile
|
||
@@ -9,6 +9,7 @@ endif
|
||
|
||
ifeq ($(subdir),rt)
|
||
librt-sysdep_routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),debug)
|
||
diff --git a/sysdeps/mips/mips32/crti.S b/sysdeps/mips/mips32/crti.S
|
||
index 5c0ad7328a..dfbbdc4f8f 100644
|
||
--- a/sysdeps/mips/mips32/crti.S
|
||
+++ b/sysdeps/mips/mips32/crti.S
|
||
@@ -74,6 +74,7 @@ _init:
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
1: jalr $25
|
||
.Lno_weak_fn:
|
||
+ .insn
|
||
#else
|
||
lw $25,%got(PREINIT_FUNCTION)($28)
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
diff --git a/sysdeps/mips/mips64/n32/crti.S b/sysdeps/mips/mips64/n32/crti.S
|
||
index 00b89f3894..afe6d8edaa 100644
|
||
--- a/sysdeps/mips/mips64/n32/crti.S
|
||
+++ b/sysdeps/mips/mips64/n32/crti.S
|
||
@@ -74,6 +74,7 @@ _init:
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
1: jalr $25
|
||
.Lno_weak_fn:
|
||
+ .insn
|
||
#else
|
||
lw $25,%got_disp(PREINIT_FUNCTION)($28)
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
diff --git a/sysdeps/mips/mips64/n64/crti.S b/sysdeps/mips/mips64/n64/crti.S
|
||
index f59b20c631..4049d29290 100644
|
||
--- a/sysdeps/mips/mips64/n64/crti.S
|
||
+++ b/sysdeps/mips/mips64/n64/crti.S
|
||
@@ -74,6 +74,7 @@ _init:
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
1: jalr $25
|
||
.Lno_weak_fn:
|
||
+ .insn
|
||
#else
|
||
ld $25,%got_disp(PREINIT_FUNCTION)($28)
|
||
.reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
|
||
diff --git a/sysdeps/mips/nptl/Makefile b/sysdeps/mips/nptl/Makefile
|
||
index 117744ffe2..dda154d842 100644
|
||
--- a/sysdeps/mips/nptl/Makefile
|
||
+++ b/sysdeps/mips/nptl/Makefile
|
||
@@ -21,4 +21,5 @@ endif
|
||
|
||
ifeq ($(subdir),nptl)
|
||
libpthread-sysdep_routines += nptl-sysdep
|
||
+libpthread-shared-only-routines += nptl-sysdep
|
||
endif
|
||
diff --git a/sysdeps/mips/nptl/tcb-offsets.sym b/sysdeps/mips/nptl/tcb-offsets.sym
|
||
index e0e71dc430..9ea25b94a8 100644
|
||
--- a/sysdeps/mips/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/mips/nptl/tcb-offsets.sym
|
||
@@ -7,5 +7,4 @@
|
||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
diff --git a/sysdeps/nacl/clock.c b/sysdeps/nacl/clock.c
|
||
index 664ad650c3..b6fbcfd2dd 100644
|
||
--- a/sysdeps/nacl/clock.c
|
||
+++ b/sysdeps/nacl/clock.c
|
||
@@ -24,6 +24,6 @@
|
||
clock_t
|
||
clock (void)
|
||
{
|
||
- nacl_abi_clock_t result;
|
||
+ nacl_irt_clock_t result;
|
||
return NACL_CALL (__nacl_irt_basic.clock (&result), result);
|
||
}
|
||
diff --git a/sysdeps/nacl/dup.c b/sysdeps/nacl/dup.c
|
||
index 34a7cd46d4..cbce3f5a5a 100644
|
||
--- a/sysdeps/nacl/dup.c
|
||
+++ b/sysdeps/nacl/dup.c
|
||
@@ -27,4 +27,5 @@ __dup (int fd)
|
||
int result;
|
||
return NACL_CALL (__nacl_irt_fdio.dup (fd, &result), result);
|
||
}
|
||
+libc_hidden_def (__dup)
|
||
weak_alias (__dup, dup)
|
||
diff --git a/sysdeps/nios2/nptl/tcb-offsets.sym b/sysdeps/nios2/nptl/tcb-offsets.sym
|
||
index d9ae952585..3cd8d984ac 100644
|
||
--- a/sysdeps/nios2/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/nios2/nptl/tcb-offsets.sym
|
||
@@ -9,6 +9,5 @@
|
||
# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem))
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
|
||
index 616d897a36..a5d1e86d71 100644
|
||
--- a/sysdeps/nptl/fork.c
|
||
+++ b/sysdeps/nptl/fork.c
|
||
@@ -131,16 +131,6 @@ __libc_fork (void)
|
||
__malloc_fork_lock_parent ();
|
||
}
|
||
|
||
-#ifndef NDEBUG
|
||
- pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
|
||
-#endif
|
||
-
|
||
- /* We need to prevent the getpid() code to update the PID field so
|
||
- that, if a signal arrives in the child very early and the signal
|
||
- handler uses getpid(), the value returned is correct. */
|
||
- pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
- THREAD_SETMEM (THREAD_SELF, pid, -parentpid);
|
||
-
|
||
#ifdef ARCH_FORK
|
||
pid = ARCH_FORK ();
|
||
#else
|
||
@@ -153,15 +143,10 @@ __libc_fork (void)
|
||
{
|
||
struct pthread *self = THREAD_SELF;
|
||
|
||
- assert (THREAD_GETMEM (self, tid) != ppid);
|
||
-
|
||
/* See __pthread_once. */
|
||
if (__fork_generation_pointer != NULL)
|
||
*__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR;
|
||
|
||
- /* Adjust the PID field for the new process. */
|
||
- THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid));
|
||
-
|
||
#if HP_TIMING_AVAIL
|
||
/* The CPU clock of the thread and process have to be set to zero. */
|
||
hp_timing_t now;
|
||
@@ -231,11 +216,6 @@ __libc_fork (void)
|
||
}
|
||
else
|
||
{
|
||
- assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid);
|
||
-
|
||
- /* Restore the PID value. */
|
||
- THREAD_SETMEM (THREAD_SELF, pid, parentpid);
|
||
-
|
||
/* Release acquired locks in the multi-threaded case. */
|
||
if (multiple_threads)
|
||
{
|
||
diff --git a/sysdeps/posix/wait3.c b/sysdeps/posix/wait3.c
|
||
index cf43d973a7..73722d2be6 100644
|
||
--- a/sysdeps/posix/wait3.c
|
||
+++ b/sysdeps/posix/wait3.c
|
||
@@ -33,7 +33,7 @@ __wait3 (int *stat_loc, int options, struct rusage *usage)
|
||
__set_errno (ENOSYS);
|
||
return (pid_t) -1;
|
||
}
|
||
- return __waitpid (WAIT_ANY, stat_loc.__iptr, options);
|
||
+ return __waitpid (WAIT_ANY, stat_loc, options);
|
||
}
|
||
|
||
weak_alias (__wait3, wait3)
|
||
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
|
||
index 7f37c813d0..36b700c520 100644
|
||
--- a/sysdeps/powerpc/fpu/libm-test-ulps
|
||
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
|
||
@@ -36,8 +36,8 @@ double: 2
|
||
float: 2
|
||
idouble: 2
|
||
ifloat: 2
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: "acosh_downward":
|
||
double: 1
|
||
@@ -52,8 +52,8 @@ double: 2
|
||
float: 2
|
||
idouble: 2
|
||
ifloat: 2
|
||
-ildouble: 3
|
||
-ldouble: 3
|
||
+ildouble: 4
|
||
+ldouble: 4
|
||
|
||
Function: "acosh_upward":
|
||
double: 2
|
||
@@ -122,8 +122,8 @@ double: 3
|
||
float: 3
|
||
idouble: 3
|
||
ifloat: 3
|
||
-ildouble: 4
|
||
-ldouble: 4
|
||
+ildouble: 7
|
||
+ldouble: 7
|
||
|
||
Function: "atan":
|
||
double: 1
|
||
@@ -216,8 +216,8 @@ double: 3
|
||
float: 3
|
||
idouble: 3
|
||
ifloat: 3
|
||
-ildouble: 3
|
||
-ldouble: 3
|
||
+ildouble: 4
|
||
+ldouble: 4
|
||
|
||
Function: "cabs":
|
||
double: 1
|
||
@@ -272,8 +272,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Real part of "cacos_towardzero":
|
||
double: 2
|
||
@@ -288,8 +288,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Real part of "cacos_upward":
|
||
double: 2
|
||
@@ -328,8 +328,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Imaginary part of "cacosh_downward":
|
||
double: 2
|
||
@@ -344,8 +344,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Imaginary part of "cacosh_towardzero":
|
||
double: 2
|
||
@@ -432,8 +432,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Real part of "casin_towardzero":
|
||
double: 3
|
||
@@ -448,8 +448,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Real part of "casin_upward":
|
||
double: 2
|
||
@@ -488,8 +488,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Imaginary part of "casinh_downward":
|
||
double: 3
|
||
@@ -504,8 +504,8 @@ double: 5
|
||
float: 3
|
||
idouble: 5
|
||
ifloat: 3
|
||
-ildouble: 5
|
||
-ldouble: 5
|
||
+ildouble: 8
|
||
+ldouble: 8
|
||
|
||
Function: Imaginary part of "casinh_towardzero":
|
||
double: 3
|
||
@@ -696,8 +696,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: Real part of "ccos_downward":
|
||
double: 1
|
||
@@ -1132,8 +1132,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: Imaginary part of "csin":
|
||
ildouble: 1
|
||
@@ -1198,8 +1198,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: Real part of "csinh_downward":
|
||
double: 2
|
||
@@ -1318,8 +1318,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 2
|
||
-ldouble: 2
|
||
+ildouble: 3
|
||
+ldouble: 3
|
||
|
||
Function: Imaginary part of "ctan":
|
||
double: 2
|
||
@@ -1390,8 +1390,8 @@ double: 2
|
||
float: 1
|
||
idouble: 2
|
||
ifloat: 1
|
||
-ildouble: 2
|
||
-ldouble: 2
|
||
+ildouble: 3
|
||
+ldouble: 3
|
||
|
||
Function: Real part of "ctanh_downward":
|
||
double: 4
|
||
@@ -1478,8 +1478,8 @@ double: 2
|
||
float: 2
|
||
idouble: 2
|
||
ifloat: 2
|
||
-ildouble: 2
|
||
-ldouble: 2
|
||
+ildouble: 3
|
||
+ldouble: 3
|
||
|
||
Function: "erfc_downward":
|
||
double: 3
|
||
@@ -1564,8 +1564,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: "exp2_upward":
|
||
double: 1
|
||
@@ -1588,8 +1588,8 @@ ildouble: 2
|
||
ldouble: 2
|
||
|
||
Function: "exp_upward":
|
||
-float: 1
|
||
double: 1
|
||
+float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
ildouble: 1
|
||
@@ -1624,8 +1624,8 @@ double: 1
|
||
float: 1
|
||
idouble: 1
|
||
ifloat: 1
|
||
-ildouble: 4
|
||
-ldouble: 4
|
||
+ildouble: 6
|
||
+ldouble: 6
|
||
|
||
Function: "fma":
|
||
ildouble: 1
|
||
@@ -1688,8 +1688,8 @@ double: 4
|
||
float: 5
|
||
idouble: 4
|
||
ifloat: 5
|
||
-ildouble: 10
|
||
-ldouble: 10
|
||
+ildouble: 11
|
||
+ldouble: 11
|
||
|
||
Function: "hypot":
|
||
double: 1
|
||
@@ -1752,8 +1752,8 @@ double: 1
|
||
float: 2
|
||
idouble: 1
|
||
ifloat: 2
|
||
-ildouble: 1
|
||
-ldouble: 1
|
||
+ildouble: 2
|
||
+ldouble: 2
|
||
|
||
Function: "j1_downward":
|
||
double: 3
|
||
@@ -1840,8 +1840,8 @@ double: 4
|
||
float: 5
|
||
idouble: 4
|
||
ifloat: 5
|
||
-ildouble: 10
|
||
-ldouble: 10
|
||
+ildouble: 11
|
||
+ldouble: 11
|
||
|
||
Function: "log":
|
||
float: 1
|
||
@@ -1910,8 +1910,8 @@ double: 2
|
||
float: 2
|
||
idouble: 2
|
||
ifloat: 2
|
||
-ildouble: 2
|
||
-ldouble: 2
|
||
+ildouble: 3
|
||
+ldouble: 3
|
||
|
||
Function: "log2":
|
||
double: 1
|
||
@@ -2184,16 +2184,16 @@ double: 3
|
||
float: 3
|
||
idouble: 3
|
||
ifloat: 3
|
||
-ildouble: 3
|
||
-ldouble: 3
|
||
+ildouble: 4
|
||
+ldouble: 4
|
||
|
||
Function: "tanh_towardzero":
|
||
double: 2
|
||
float: 2
|
||
idouble: 2
|
||
ifloat: 2
|
||
-ildouble: 3
|
||
-ldouble: 3
|
||
+ildouble: 4
|
||
+ldouble: 4
|
||
|
||
Function: "tanh_upward":
|
||
double: 3
|
||
diff --git a/sysdeps/powerpc/ifunc-sel.h b/sysdeps/powerpc/ifunc-sel.h
|
||
index 526d8ed88b..ac589bd3c0 100644
|
||
--- a/sysdeps/powerpc/ifunc-sel.h
|
||
+++ b/sysdeps/powerpc/ifunc-sel.h
|
||
@@ -17,15 +17,17 @@ ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
|
||
"addis %0,11,%2-1b@ha\n\t"
|
||
"addi %0,%0,%2-1b@l\n\t"
|
||
"cmpwi 12,1\n\t"
|
||
- "beqlr\n\t"
|
||
+ "beq 2f\n\t"
|
||
"addis %0,11,%3-1b@ha\n\t"
|
||
"addi %0,%0,%3-1b@l\n\t"
|
||
"cmpwi 12,-1\n\t"
|
||
- "beqlr\n\t"
|
||
+ "beq 2f\n\t"
|
||
"addis %0,11,%4-1b@ha\n\t"
|
||
- "addi %0,%0,%4-1b@l"
|
||
+ "addi %0,%0,%4-1b@l\n\t"
|
||
+ "2:"
|
||
: "=r" (ret)
|
||
- : "X" (&global), "X" (f1), "X" (f2), "X" (f3));
|
||
+ : "i" (&global), "i" (f1), "i" (f2), "i" (f3)
|
||
+ : "11", "12", "cr0");
|
||
return ret;
|
||
}
|
||
|
||
@@ -40,7 +42,8 @@ ifunc_one (int (*f1) (void))
|
||
"addis %0,%0,%1-1b@ha\n\t"
|
||
"addi %0,%0,%1-1b@l"
|
||
: "=r" (ret)
|
||
- : "X" (f1));
|
||
+ : "i" (f1)
|
||
+ : "12");
|
||
return ret;
|
||
}
|
||
#endif
|
||
diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||
index f580e69555..7c9fd33562 100644
|
||
--- a/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||
@@ -13,7 +13,6 @@
|
||
#if TLS_MULTIPLE_THREADS_IN_TCB
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
#endif
|
||
-PID thread_offsetof (pid)
|
||
TID thread_offsetof (tid)
|
||
POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||
TAR_SAVE (offsetof (tcbhead_t, tar_save) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||
diff --git a/sysdeps/powerpc/powerpc32/power6/memset.S b/sysdeps/powerpc/powerpc32/power6/memset.S
|
||
index b2a222edd2..d5dbe83af2 100644
|
||
--- a/sysdeps/powerpc/powerpc32/power6/memset.S
|
||
+++ b/sysdeps/powerpc/powerpc32/power6/memset.S
|
||
@@ -394,7 +394,7 @@ L(cacheAlignedx):
|
||
/* A simple loop for the longer (>640 bytes) lengths. This form limits
|
||
the branch miss-predicted to exactly 1 at loop exit.*/
|
||
L(cacheAligned512):
|
||
- cmpli cr1,rLEN,128
|
||
+ cmplwi cr1,rLEN,128
|
||
blt cr1,L(cacheAligned1)
|
||
dcbz 0,rMEMP
|
||
addi rLEN,rLEN,-128
|
||
diff --git a/sysdeps/powerpc/powerpc32/power9/multiarch/Implies b/sysdeps/powerpc/powerpc32/power9/multiarch/Implies
|
||
index 4393b56872..1a46ef0035 100644
|
||
--- a/sysdeps/powerpc/powerpc32/power9/multiarch/Implies
|
||
+++ b/sysdeps/powerpc/powerpc32/power9/multiarch/Implies
|
||
@@ -1 +1 @@
|
||
-powerpc/powerpc32/power8/fpu/multiarch
|
||
+powerpc/powerpc32/power8/multiarch
|
||
diff --git a/sysdeps/powerpc/powerpc64/power6/memset.S b/sysdeps/powerpc/powerpc64/power6/memset.S
|
||
index c2d1c4e600..d445b1e1ef 100644
|
||
--- a/sysdeps/powerpc/powerpc64/power6/memset.S
|
||
+++ b/sysdeps/powerpc/powerpc64/power6/memset.S
|
||
@@ -251,7 +251,7 @@ L(cacheAlignedx):
|
||
/* A simple loop for the longer (>640 bytes) lengths. This form limits
|
||
the branch miss-predicted to exactly 1 at loop exit.*/
|
||
L(cacheAligned512):
|
||
- cmpli cr1,rLEN,128
|
||
+ cmpldi cr1,rLEN,128
|
||
blt cr1,L(cacheAligned1)
|
||
dcbz 0,rMEMP
|
||
addi rLEN,rLEN,-128
|
||
diff --git a/sysdeps/powerpc/powerpc64/power9/fpu/Implies b/sysdeps/powerpc/powerpc64/power9/fpu/Implies
|
||
index fad2505ab9..ae0dbaf857 100644
|
||
--- a/sysdeps/powerpc/powerpc64/power9/fpu/Implies
|
||
+++ b/sysdeps/powerpc/powerpc64/power9/fpu/Implies
|
||
@@ -1,2 +1 @@
|
||
powerpc/powerpc64/power8/fpu
|
||
-powerpc/powerpc64/power8
|
||
diff --git a/sysdeps/s390/nptl/Makefile b/sysdeps/s390/nptl/Makefile
|
||
index 5734b983b0..3a391c8217 100644
|
||
--- a/sysdeps/s390/nptl/Makefile
|
||
+++ b/sysdeps/s390/nptl/Makefile
|
||
@@ -21,4 +21,5 @@ endif
|
||
|
||
ifeq ($(subdir),nptl)
|
||
libpthread-routines += ptw-sysdep
|
||
+libpthread-shared-only-routines += ptw-sysdep
|
||
endif
|
||
diff --git a/sysdeps/s390/nptl/tcb-offsets.sym b/sysdeps/s390/nptl/tcb-offsets.sym
|
||
index 9cfae211e0..9c1c01f353 100644
|
||
--- a/sysdeps/s390/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/s390/nptl/tcb-offsets.sym
|
||
@@ -3,5 +3,4 @@
|
||
|
||
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
|
||
STACK_GUARD offsetof (tcbhead_t, stack_guard)
|
||
-PID offsetof (struct pthread, pid)
|
||
TID offsetof (struct pthread, tid)
|
||
diff --git a/sysdeps/sh/nptl/tcb-offsets.sym b/sysdeps/sh/nptl/tcb-offsets.sym
|
||
index ac63b5b93b..4963e1506f 100644
|
||
--- a/sysdeps/sh/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/sh/nptl/tcb-offsets.sym
|
||
@@ -4,7 +4,6 @@
|
||
|
||
RESULT offsetof (struct pthread, result)
|
||
TID offsetof (struct pthread, tid)
|
||
-PID offsetof (struct pthread, pid)
|
||
CANCELHANDLING offsetof (struct pthread, cancelhandling)
|
||
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
|
||
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
|
||
diff --git a/sysdeps/sparc/nptl/tcb-offsets.sym b/sysdeps/sparc/nptl/tcb-offsets.sym
|
||
index 923af8a5b7..f75d02065e 100644
|
||
--- a/sysdeps/sparc/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/sparc/nptl/tcb-offsets.sym
|
||
@@ -3,5 +3,4 @@
|
||
|
||
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
|
||
POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
|
||
-PID offsetof (struct pthread, pid)
|
||
TID offsetof (struct pthread, tid)
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/Makefile b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/Makefile
|
||
index ebbe28b07f..13d3c6db51 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/Makefile
|
||
+++ b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/Makefile
|
||
@@ -4,8 +4,8 @@ libm-sysdep_routines += m_copysignf-vis3 m_copysign-vis3 s_fabs-vis3 \
|
||
s_fabsf-vis3 s_llrintf-vis3 s_llrint-vis3 \
|
||
s_rintf-vis3 s_rint-vis3 w_sqrt-vis3 w_sqrtf-vis3 \
|
||
s_fminf-vis3 s_fmin-vis3 s_fmaxf-vis3 s_fmax-vis3 \
|
||
- s_fmaf-vis3 s_fma-vis3 s_fdimf-vis3 s_fdim-vis3 \
|
||
- s_nearbyint-vis3 s_nearbyintf-vis3
|
||
+ s_fmaf-vis3 s_fma-vis3 s_nearbyint-vis3 \
|
||
+ s_nearbyintf-vis3
|
||
sysdep_routines += s_copysignf-vis3 s_copysign-vis3
|
||
endif
|
||
endif
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim.S b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim.S
|
||
deleted file mode 100644
|
||
index 4b13408244..0000000000
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim.S
|
||
+++ /dev/null
|
||
@@ -1,19 +0,0 @@
|
||
-#include <sparc-ifunc.h>
|
||
-#include <math_ldbl_opt.h>
|
||
-
|
||
-SPARC_ASM_VIS3_IFUNC(fdim)
|
||
-
|
||
-weak_alias (__fdim, fdim)
|
||
-
|
||
-#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1)
|
||
-compat_symbol (libm, __fdim, fdiml, GLIBC_2_1);
|
||
-#endif
|
||
-
|
||
-# undef weak_alias
|
||
-# define weak_alias(a, b)
|
||
-# undef compat_symbol
|
||
-# define compat_symbol(a, b, c, d)
|
||
-
|
||
-#define __fdim __fdim_generic
|
||
-
|
||
-#include "../s_fdim.S"
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf.S b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf.S
|
||
deleted file mode 100644
|
||
index 30381d6a59..0000000000
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdimf.S
|
||
+++ /dev/null
|
||
@@ -1,12 +0,0 @@
|
||
-#include <sparc-ifunc.h>
|
||
-
|
||
-SPARC_ASM_VIS3_IFUNC(fdimf)
|
||
-
|
||
-weak_alias (__fdimf, fdimf)
|
||
-
|
||
-# undef weak_alias
|
||
-# define weak_alias(a, b)
|
||
-
|
||
-#define __fdimf __fdimf_generic
|
||
-
|
||
-#include "../s_fdimf.S"
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyint-vis3.S b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyint-vis3.S
|
||
index d9ff0cc288..ff81b0da83 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyint-vis3.S
|
||
+++ b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyint-vis3.S
|
||
@@ -36,15 +36,15 @@
|
||
#define SIGN_BIT %f12 /* -0.0 */
|
||
|
||
ENTRY (__nearbyint_vis3)
|
||
+ sllx %o0, 32, %o0
|
||
+ or %o0, %o1, %o0
|
||
+ movxtod %o0, %f0
|
||
fcmpd %fcc3, %f0, %f0 /* Check for sNaN */
|
||
st %fsr, [%sp + 88]
|
||
sethi %hi(TWO_FIFTYTWO), %o2
|
||
sethi %hi(0xf8003e0), %o5
|
||
ld [%sp + 88], %o4
|
||
- sllx %o0, 32, %o0
|
||
or %o5, %lo(0xf8003e0), %o5
|
||
- or %o0, %o1, %o0
|
||
- movxtod %o0, %f0
|
||
andn %o4, %o5, %o4
|
||
fzero ZERO
|
||
st %o4, [%sp + 80]
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyintf-vis3.S b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyintf-vis3.S
|
||
index 5cd1eb02db..833a0dfc24 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyintf-vis3.S
|
||
+++ b/sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_nearbyintf-vis3.S
|
||
@@ -35,9 +35,9 @@
|
||
#define SIGN_BIT %f12 /* -0.0 */
|
||
|
||
ENTRY (__nearbyintf_vis3)
|
||
+ movwtos %o0, %f1
|
||
fcmps %fcc3, %f1, %f1 /* Check for sNaN */
|
||
st %fsr, [%sp + 88]
|
||
- movwtos %o0, %f1
|
||
sethi %hi(TWO_TWENTYTHREE), %o2
|
||
sethi %hi(0xf8003e0), %o5
|
||
ld [%sp + 88], %o4
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyint.S b/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyint.S
|
||
index 84a10971a4..198440a5bc 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyint.S
|
||
+++ b/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyint.S
|
||
@@ -36,21 +36,21 @@
|
||
#define SIGN_BIT %f12 /* -0.0 */
|
||
|
||
ENTRY (__nearbyint)
|
||
+ sllx %o0, 32, %o0
|
||
+ or %o0, %o1, %o0
|
||
+ stx %o0, [%sp + 72]
|
||
+ ldd [%sp + 72], %f0
|
||
fcmpd %fcc3, %f0, %f0 /* Check for sNaN */
|
||
st %fsr, [%sp + 88]
|
||
sethi %hi(TWO_FIFTYTWO), %o2
|
||
sethi %hi(0xf8003e0), %o5
|
||
ld [%sp + 88], %o4
|
||
- sllx %o0, 32, %o0
|
||
or %o5, %lo(0xf8003e0), %o5
|
||
- or %o0, %o1, %o0
|
||
andn %o4, %o5, %o4
|
||
fzero ZERO
|
||
st %o4, [%sp + 80]
|
||
- stx %o0, [%sp + 72]
|
||
sllx %o2, 32, %o2
|
||
fnegd ZERO, SIGN_BIT
|
||
- ldd [%sp + 72], %f0
|
||
ld [%sp + 80], %fsr
|
||
stx %o2, [%sp + 72]
|
||
fabsd %f0, %f14
|
||
diff --git a/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyintf.S b/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyintf.S
|
||
index d5cf5ce815..9be41f6c22 100644
|
||
--- a/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyintf.S
|
||
+++ b/sysdeps/sparc/sparc32/sparcv9/fpu/s_nearbyintf.S
|
||
@@ -35,9 +35,10 @@
|
||
#define SIGN_BIT %f12 /* -0.0 */
|
||
|
||
ENTRY (__nearbyintf)
|
||
+ st %o0, [%sp + 68]
|
||
+ ld [%sp + 68], %f1
|
||
fcmps %fcc3, %f1, %f1 /* Check for sNaN */
|
||
st %fsr, [%sp + 88]
|
||
- st %o0, [%sp + 68]
|
||
sethi %hi(TWO_TWENTYTHREE), %o2
|
||
sethi %hi(0xf8003e0), %o5
|
||
ld [%sp + 88], %o4
|
||
@@ -46,7 +47,6 @@ ENTRY (__nearbyintf)
|
||
fnegs ZERO, SIGN_BIT
|
||
andn %o4, %o5, %o4
|
||
st %o4, [%sp + 80]
|
||
- ld [%sp + 68], %f1
|
||
ld [%sp + 80], %fsr
|
||
st %o2, [%sp + 68]
|
||
fabss %f1, %f14
|
||
diff --git a/sysdeps/tile/nptl/tcb-offsets.sym b/sysdeps/tile/nptl/tcb-offsets.sym
|
||
index 6740bc976f..0147ffafb7 100644
|
||
--- a/sysdeps/tile/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/tile/nptl/tcb-offsets.sym
|
||
@@ -9,7 +9,6 @@
|
||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
||
|
||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||
-PID_OFFSET thread_offsetof (pid)
|
||
TID_OFFSET thread_offsetof (tid)
|
||
POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||
FEEDBACK_DATA_OFFSET (offsetof (tcbhead_t, feedback_data) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||
diff --git a/sysdeps/unix/alpha/Makefile b/sysdeps/unix/alpha/Makefile
|
||
index 441aa02a83..0660847f15 100644
|
||
--- a/sysdeps/unix/alpha/Makefile
|
||
+++ b/sysdeps/unix/alpha/Makefile
|
||
@@ -1,3 +1,4 @@
|
||
ifeq ($(subdir),rt)
|
||
librt-sysdep_routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
|
||
index 94a2ce0e37..38c2432002 100644
|
||
--- a/sysdeps/unix/sysdep.h
|
||
+++ b/sysdeps/unix/sysdep.h
|
||
@@ -24,42 +24,79 @@
|
||
#define SYSCALL__(name, args) PSEUDO (__##name, name, args)
|
||
#define SYSCALL(name, args) PSEUDO (name, name, args)
|
||
|
||
-#define __SYSCALL0(name) \
|
||
+#define __SYSCALL_CONCAT_X(a,b) a##b
|
||
+#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b)
|
||
+
|
||
+
|
||
+#define __INTERNAL_SYSCALL0(name, err) \
|
||
+ INTERNAL_SYSCALL (name, err, 0)
|
||
+#define __INTERNAL_SYSCALL1(name, err, a1) \
|
||
+ INTERNAL_SYSCALL (name, err, 1, a1)
|
||
+#define __INTERNAL_SYSCALL2(name, err, a1, a2) \
|
||
+ INTERNAL_SYSCALL (name, err, 2, a1, a2)
|
||
+#define __INTERNAL_SYSCALL3(name, err, a1, a2, a3) \
|
||
+ INTERNAL_SYSCALL (name, err, 3, a1, a2, a3)
|
||
+#define __INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \
|
||
+ INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4)
|
||
+#define __INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \
|
||
+ INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5)
|
||
+#define __INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \
|
||
+ INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6)
|
||
+#define __INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \
|
||
+ INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7)
|
||
+
|
||
+#define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,o,...) o
|
||
+#define __INTERNAL_SYSCALL_NARGS(...) \
|
||
+ __INTERNAL_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
|
||
+#define __INTERNAL_SYSCALL_DISP(b,...) \
|
||
+ __SYSCALL_CONCAT (b,__INTERNAL_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
|
||
+
|
||
+/* Issue a syscall defined by syscall number plus any other argument required.
|
||
+ It is similar to INTERNAL_SYSCALL macro, but without the need to pass the
|
||
+ expected argument number as second parameter. */
|
||
+#define INTERNAL_SYSCALL_CALL(...) \
|
||
+ __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__)
|
||
+
|
||
+#define __INLINE_SYSCALL0(name) \
|
||
INLINE_SYSCALL (name, 0)
|
||
-#define __SYSCALL1(name, a1) \
|
||
+#define __INLINE_SYSCALL1(name, a1) \
|
||
INLINE_SYSCALL (name, 1, a1)
|
||
-#define __SYSCALL2(name, a1, a2) \
|
||
+#define __INLINE_SYSCALL2(name, a1, a2) \
|
||
INLINE_SYSCALL (name, 2, a1, a2)
|
||
-#define __SYSCALL3(name, a1, a2, a3) \
|
||
+#define __INLINE_SYSCALL3(name, a1, a2, a3) \
|
||
INLINE_SYSCALL (name, 3, a1, a2, a3)
|
||
-#define __SYSCALL4(name, a1, a2, a3, a4) \
|
||
+#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \
|
||
INLINE_SYSCALL (name, 4, a1, a2, a3, a4)
|
||
-#define __SYSCALL5(name, a1, a2, a3, a4, a5) \
|
||
+#define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \
|
||
INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5)
|
||
-#define __SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
|
||
+#define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
|
||
INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6)
|
||
-#define __SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
|
||
+#define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
|
||
INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7)
|
||
|
||
-#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
|
||
-#define __SYSCALL_NARGS(...) \
|
||
- __SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
|
||
-#define __SYSCALL_CONCAT_X(a,b) a##b
|
||
-#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b)
|
||
-#define __SYSCALL_DISP(b,...) \
|
||
- __SYSCALL_CONCAT (b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
|
||
+#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
|
||
+#define __INLINE_SYSCALL_NARGS(...) \
|
||
+ __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
|
||
+#define __INLINE_SYSCALL_DISP(b,...) \
|
||
+ __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
|
||
|
||
-#define __SYSCALL_CALL(...) __SYSCALL_DISP (__SYSCALL, __VA_ARGS__)
|
||
+/* Issue a syscall defined by syscall number plus any other argument
|
||
+ required. Any error will be handled using arch defined macros and errno
|
||
+ will be set accordingly.
|
||
+ It is similar to INLINE_SYSCALL macro, but without the need to pass the
|
||
+ expected argument number as second parameter. */
|
||
+#define INLINE_SYSCALL_CALL(...) \
|
||
+ __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
|
||
|
||
#define SYSCALL_CANCEL(...) \
|
||
({ \
|
||
long int sc_ret; \
|
||
if (SINGLE_THREAD_P) \
|
||
- sc_ret = __SYSCALL_CALL (__VA_ARGS__); \
|
||
+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
|
||
else \
|
||
{ \
|
||
int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
|
||
- sc_ret = __SYSCALL_CALL (__VA_ARGS__); \
|
||
+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
|
||
LIBC_CANCEL_RESET (sc_cancel_oldtype); \
|
||
} \
|
||
sc_ret; \
|
||
diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||
index 76baa7a698..96482e53c0 100644
|
||
--- a/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||
@@ -72,16 +72,6 @@ thread_start:
|
||
cfi_undefined (x30)
|
||
mov x29, 0
|
||
|
||
- tbnz x11, #CLONE_VM_BIT, 1f
|
||
-
|
||
- mov x8, #SYS_ify(getpid)
|
||
- svc 0x0
|
||
- mrs x1, tpidr_el0
|
||
- sub x1, x1, #PTHREAD_SIZEOF
|
||
- str w0, [x1, #PTHREAD_PID_OFFSET]
|
||
- str w0, [x1, #PTHREAD_TID_OFFSET]
|
||
-1:
|
||
-
|
||
/* Pick the function arg and execute. */
|
||
mov x0, x12
|
||
blr x10
|
||
diff --git a/sysdeps/unix/sysv/linux/aarch64/vfork.S b/sysdeps/unix/sysv/linux/aarch64/vfork.S
|
||
index 577895eeb2..aeed0b29ce 100644
|
||
--- a/sysdeps/unix/sysv/linux/aarch64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/aarch64/vfork.S
|
||
@@ -27,27 +27,10 @@
|
||
|
||
ENTRY (__vfork)
|
||
|
||
- /* Save the TCB-cached PID away in w3, and then negate the TCB
|
||
- field. But if it's zero, set it to 0x80000000 instead. See
|
||
- raise.c for the logic that relies on this value. */
|
||
- mrs x2, tpidr_el0
|
||
- sub x2, x2, #PTHREAD_SIZEOF
|
||
- ldr w3, [x2, #PTHREAD_PID_OFFSET]
|
||
- mov w1, #0x80000000
|
||
- negs w0, w3
|
||
- csel w0, w1, w0, eq
|
||
- str w0, [x2, #PTHREAD_PID_OFFSET]
|
||
-
|
||
mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
|
||
mov x1, sp
|
||
DO_CALL (clone, 2)
|
||
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- cbz x0, 1f
|
||
- str w3, [x2, #PTHREAD_PID_OFFSET]
|
||
-1:
|
||
cmn x0, #4095
|
||
b.cs .Lsyscall_error
|
||
RET
|
||
diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
|
||
index c089545e9b..3b523b70cf 100644
|
||
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
|
||
@@ -40,4 +40,5 @@ endif # math
|
||
ifeq ($(subdir),nptl)
|
||
# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction
|
||
libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
|
||
+libpthread-shared-only-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
|
||
endif
|
||
diff --git a/sysdeps/unix/sysv/linux/alpha/clone.S b/sysdeps/unix/sysv/linux/alpha/clone.S
|
||
index 6a3154f9a7..2757bf20c3 100644
|
||
--- a/sysdeps/unix/sysv/linux/alpha/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/alpha/clone.S
|
||
@@ -91,13 +91,6 @@ thread_start:
|
||
cfi_def_cfa_register(fp)
|
||
cfi_undefined(ra)
|
||
|
||
- /* Check and see if we need to reset the PID. */
|
||
- ldq t0, 16(sp)
|
||
- lda t1, CLONE_VM
|
||
- and t0, t1, t2
|
||
- beq t2, 2f
|
||
-1:
|
||
-
|
||
/* Load up the arguments. */
|
||
ldq pv, 0(sp)
|
||
ldq a0, 8(sp)
|
||
@@ -120,15 +113,6 @@ thread_start:
|
||
halt
|
||
|
||
.align 4
|
||
-2:
|
||
- rduniq
|
||
- mov v0, s0
|
||
- lda v0, __NR_getxpid
|
||
- callsys
|
||
-3:
|
||
- stl v0, PID_OFFSET(s0)
|
||
- stl v0, TID_OFFSET(s0)
|
||
- br 1b
|
||
cfi_endproc
|
||
.end thread_start
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/alpha/vfork.S b/sysdeps/unix/sysv/linux/alpha/vfork.S
|
||
index 9fc199ac41..e5f7ed0661 100644
|
||
--- a/sysdeps/unix/sysv/linux/alpha/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/alpha/vfork.S
|
||
@@ -25,24 +25,9 @@ ENTRY(__libc_vfork)
|
||
rduniq
|
||
mov v0, a1
|
||
|
||
- /* Save the TCB-cached PID away in A2, and then negate the TCB
|
||
- field. But if it's zero, set it to 0x80000000 instead. See
|
||
- raise.c for the logic that relies on this value. */
|
||
- ldl a2, PID_OFFSET(v0)
|
||
- ldah t0, -0x8000
|
||
- negl a2, t1
|
||
- cmovne a2, t1, t0
|
||
- stl t0, PID_OFFSET(v0);
|
||
-
|
||
lda v0, SYS_ify(vfork)
|
||
call_pal PAL_callsys
|
||
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- beq v0, 1f
|
||
- stl a2, PID_OFFSET(a1)
|
||
-1:
|
||
/* Normal error check and return. */
|
||
bne a3, SYSCALL_ERROR_LABEL
|
||
ret
|
||
diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S
|
||
index 7ff681804b..4c6325d088 100644
|
||
--- a/sysdeps/unix/sysv/linux/arm/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/arm/clone.S
|
||
@@ -70,16 +70,6 @@ PSEUDO_END (__clone)
|
||
1:
|
||
.fnstart
|
||
.cantunwind
|
||
- tst ip, #CLONE_VM
|
||
- bne 2f
|
||
- GET_TLS (lr)
|
||
- mov r1, r0
|
||
- ldr r7, =SYS_ify(getpid)
|
||
- swi 0x0
|
||
- NEGOFF_ADJ_BASE (r1, TID_OFFSET)
|
||
- str r0, NEGOFF_OFF1 (r1, TID_OFFSET)
|
||
- str r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET)
|
||
-2:
|
||
@ pick the function arg and call address off the stack and execute
|
||
ldr r0, [sp, #4]
|
||
ldr ip, [sp], #8
|
||
diff --git a/sysdeps/unix/sysv/linux/arm/setcontext.S b/sysdeps/unix/sysv/linux/arm/setcontext.S
|
||
index 603e508858..d1f168fece 100644
|
||
--- a/sysdeps/unix/sysv/linux/arm/setcontext.S
|
||
+++ b/sysdeps/unix/sysv/linux/arm/setcontext.S
|
||
@@ -86,12 +86,19 @@ weak_alias(__setcontext, setcontext)
|
||
|
||
/* Called when a makecontext() context returns. Start the
|
||
context in R4 or fall through to exit(). */
|
||
+ /* Unwind descriptors are looked up based on PC - 2, so we have to
|
||
+ make sure to mark the instruction preceding the __startcontext
|
||
+ label as .cantunwind. */
|
||
+ .fnstart
|
||
+ .cantunwind
|
||
+ nop
|
||
ENTRY(__startcontext)
|
||
movs r0, r4
|
||
bne PLTJMP(__setcontext)
|
||
|
||
@ New context was 0 - exit
|
||
b PLTJMP(HIDDEN_JUMPTARGET(exit))
|
||
+ .fnend
|
||
END(__startcontext)
|
||
|
||
#ifdef PIC
|
||
diff --git a/sysdeps/unix/sysv/linux/arm/vfork.S b/sysdeps/unix/sysv/linux/arm/vfork.S
|
||
index 500f5ca4be..794372ee12 100644
|
||
--- a/sysdeps/unix/sysv/linux/arm/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/arm/vfork.S
|
||
@@ -28,16 +28,6 @@
|
||
and the process ID of the new process to the old process. */
|
||
|
||
ENTRY (__vfork)
|
||
- /* Save the PID value. */
|
||
- GET_TLS (r2)
|
||
- NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET) /* Save the TLS addr in r2. */
|
||
- ldr r3, NEGOFF_OFF1 (r2, PID_OFFSET) /* Load the saved PID. */
|
||
- rsbs r0, r3, #0 /* Negate it, and test for zero. */
|
||
- /* Use 0x80000000 if it was 0. See raise.c for how this is used. */
|
||
- it eq
|
||
- moveq r0, #0x80000000
|
||
- str r0, NEGOFF_OFF1 (r2, PID_OFFSET) /* Store the temp PID. */
|
||
-
|
||
/* The DO_CALL macro saves r7 on the stack, to enable generation
|
||
of ARM unwind info. Since the stack is initially shared between
|
||
parent and child of vfork, that saved value could be corrupted.
|
||
@@ -57,11 +47,6 @@ ENTRY (__vfork)
|
||
mov r7, ip
|
||
cfi_restore (r7)
|
||
|
||
- /* Restore the old PID value in the parent. */
|
||
- cmp r0, #0 /* If we are the parent... */
|
||
- it ne
|
||
- strne r3, NEGOFF_OFF1 (r2, PID_OFFSET) /* restore the saved PID. */
|
||
-
|
||
cmn a1, #4096
|
||
it cc
|
||
RETINSTR(cc, lr)
|
||
diff --git a/sysdeps/unix/sysv/linux/createthread.c b/sysdeps/unix/sysv/linux/createthread.c
|
||
index 6d32cece48..ec86f50814 100644
|
||
--- a/sysdeps/unix/sysv/linux/createthread.c
|
||
+++ b/sysdeps/unix/sysv/linux/createthread.c
|
||
@@ -128,10 +128,10 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||
/* The operation failed. We have to kill the thread.
|
||
We let the normal cancellation mechanism do the work. */
|
||
|
||
+ pid_t pid = __getpid ();
|
||
INTERNAL_SYSCALL_DECL (err2);
|
||
- (void) INTERNAL_SYSCALL (tgkill, err2, 3,
|
||
- THREAD_GETMEM (THREAD_SELF, pid),
|
||
- pd->tid, SIGCANCEL);
|
||
+ (void) INTERNAL_SYSCALL_CALL (tgkill, err2, pid, pd->tid,
|
||
+ SIGCANCEL);
|
||
|
||
return INTERNAL_SYSCALL_ERRNO (res, err);
|
||
}
|
||
diff --git a/sysdeps/unix/sysv/linux/getpid.c b/sysdeps/unix/sysv/linux/getpid.c
|
||
deleted file mode 100644
|
||
index 1124549326..0000000000
|
||
--- a/sysdeps/unix/sysv/linux/getpid.c
|
||
+++ /dev/null
|
||
@@ -1,64 +0,0 @@
|
||
-/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
|
||
- This file is part of the GNU C Library.
|
||
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
||
-
|
||
- 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
|
||
- <http://www.gnu.org/licenses/>. */
|
||
-
|
||
-#include <unistd.h>
|
||
-#include <tls.h>
|
||
-#include <sysdep.h>
|
||
-
|
||
-
|
||
-#if IS_IN (libc)
|
||
-static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval);
|
||
-
|
||
-static inline __attribute__((always_inline)) pid_t
|
||
-really_getpid (pid_t oldval)
|
||
-{
|
||
- if (__glibc_likely (oldval == 0))
|
||
- {
|
||
- pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid);
|
||
- if (__glibc_likely (selftid != 0))
|
||
- return selftid;
|
||
- }
|
||
-
|
||
- INTERNAL_SYSCALL_DECL (err);
|
||
- pid_t result = INTERNAL_SYSCALL (getpid, err, 0);
|
||
-
|
||
- /* We do not set the PID field in the TID here since we might be
|
||
- called from a signal handler while the thread executes fork. */
|
||
- if (oldval == 0)
|
||
- THREAD_SETMEM (THREAD_SELF, tid, result);
|
||
- return result;
|
||
-}
|
||
-#endif
|
||
-
|
||
-pid_t
|
||
-__getpid (void)
|
||
-{
|
||
-#if !IS_IN (libc)
|
||
- INTERNAL_SYSCALL_DECL (err);
|
||
- pid_t result = INTERNAL_SYSCALL (getpid, err, 0);
|
||
-#else
|
||
- pid_t result = THREAD_GETMEM (THREAD_SELF, pid);
|
||
- if (__glibc_unlikely (result <= 0))
|
||
- result = really_getpid (result);
|
||
-#endif
|
||
- return result;
|
||
-}
|
||
-
|
||
-libc_hidden_def (__getpid)
|
||
-weak_alias (__getpid, getpid)
|
||
-libc_hidden_def (getpid)
|
||
diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S
|
||
index 3d037f1430..25fcd497f7 100644
|
||
--- a/sysdeps/unix/sysv/linux/hppa/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/hppa/clone.S
|
||
@@ -132,18 +132,6 @@ ENTRY(__clone)
|
||
ldwm -64(%sp), %r4
|
||
|
||
.LthreadStart:
|
||
-# define CLONE_VM_BIT 23 /* 0x00000100 */
|
||
- /* Load original clone flags.
|
||
- If CLONE_VM was passed, don't modify PID/TID.
|
||
- Otherwise store the result of getpid to PID/TID. */
|
||
- ldw -56(%sp), %r26
|
||
- bb,<,n %r26, CLONE_VM_BIT, 1f
|
||
- ble 0x100(%sr2, %r0)
|
||
- ldi __NR_getpid, %r20
|
||
- mfctl %cr27, %r26
|
||
- stw %ret0, PID_THREAD_OFFSET(%r26)
|
||
- stw %ret0, TID_THREAD_OFFSET(%r26)
|
||
-1:
|
||
/* Load up the arguments. */
|
||
ldw -60(%sp), %arg0
|
||
ldw -64(%sp), %r22
|
||
diff --git a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
|
||
index df532362d2..4684048502 100644
|
||
--- a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
|
||
@@ -25,26 +25,6 @@
|
||
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||
and the process ID of the new process to the old process. */
|
||
|
||
-/* Load the thread register.
|
||
- Load the saved PID value.
|
||
- Negate the value.
|
||
- Store the temporary PID. */
|
||
-#define SAVE_PID \
|
||
- mfctl %cr27, %r26 ASM_LINE_SEP \
|
||
- ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \
|
||
- sub %r0,%r1,%r1 ASM_LINE_SEP \
|
||
- stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP
|
||
-/* If we are the parent...
|
||
- Get the thread pointer.
|
||
- Load the saved PID.
|
||
- Negate the value (got back original)
|
||
- Restore the PID. */
|
||
-#define RESTORE_PID \
|
||
- cmpb,=,n %r0,%ret0,.Lthread_start ASM_LINE_SEP \
|
||
- mfctl %cr27, %r26 ASM_LINE_SEP \
|
||
- ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \
|
||
- sub %r0,%r1,%r1 ASM_LINE_SEP \
|
||
- stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP \
|
||
.Lthread_start: ASM_LINE_SEP
|
||
|
||
/* r26, r25, r24, r23 are free since vfork has no arguments */
|
||
@@ -58,16 +38,10 @@ ENTRY(__vfork)
|
||
copy %r19, %r25 /* parent */
|
||
#endif
|
||
|
||
- /* Save the process PID */
|
||
- SAVE_PID
|
||
-
|
||
/* Syscall saves and restores all register states */
|
||
ble 0x100(%sr2,%r0)
|
||
ldi __NR_vfork,%r20
|
||
|
||
- /* Conditionally restore the PID */
|
||
- RESTORE_PID
|
||
-
|
||
/* Check for error */
|
||
ldi -4096,%r1
|
||
comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */
|
||
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
|
||
index 71ba61e9d7..6073a9fe04 100644
|
||
--- a/sysdeps/unix/sysv/linux/i386/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
|
||
@@ -31,6 +31,7 @@ endif
|
||
# libpthread uses six-argument inline syscalls.
|
||
ifeq ($(subdir),nptl)
|
||
libpthread-sysdep_routines += libc-do-syscall
|
||
+libpthread-shared-only-routines += libc-do-syscall
|
||
endif
|
||
|
||
ifeq ($(subdir),resource)
|
||
@@ -48,9 +49,11 @@ endif
|
||
ifeq ($(subdir),nptl)
|
||
# pull in __syscall_error routine
|
||
libpthread-routines += sysdep
|
||
+libpthread-shared-only-routines += sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),rt)
|
||
# pull in __syscall_error routine
|
||
librt-routines += sysdep
|
||
+librt-shared-only-routines += sysdep
|
||
endif
|
||
diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S
|
||
index 25f2a9c340..feae504ce6 100644
|
||
--- a/sysdeps/unix/sysv/linux/i386/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/i386/clone.S
|
||
@@ -107,9 +107,6 @@ L(thread_start):
|
||
cfi_undefined (eip);
|
||
/* Note: %esi is zero. */
|
||
movl %esi,%ebp /* terminate the stack frame */
|
||
- testl $CLONE_VM, %edi
|
||
- je L(newpid)
|
||
-L(haspid):
|
||
call *%ebx
|
||
#ifdef PIC
|
||
call L(here)
|
||
@@ -121,18 +118,6 @@ L(here):
|
||
movl $SYS_ify(exit), %eax
|
||
ENTER_KERNEL
|
||
|
||
- .subsection 2
|
||
-L(newpid):
|
||
- movl $SYS_ify(getpid), %eax
|
||
- ENTER_KERNEL
|
||
-L(nomoregetpid):
|
||
- movl %eax, %gs:PID
|
||
- movl %eax, %gs:TID
|
||
- jmp L(haspid)
|
||
- .previous
|
||
- cfi_endproc;
|
||
-
|
||
- cfi_startproc
|
||
PSEUDO_END (__clone)
|
||
|
||
libc_hidden_def (__clone)
|
||
diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S
|
||
index 7a1d3373bb..a865de2201 100644
|
||
--- a/sysdeps/unix/sysv/linux/i386/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/i386/vfork.S
|
||
@@ -34,17 +34,6 @@ ENTRY (__vfork)
|
||
cfi_adjust_cfa_offset (-4)
|
||
cfi_register (%eip, %ecx)
|
||
|
||
- /* Save the TCB-cached PID away in %edx, and then negate the TCB
|
||
- field. But if it's zero, set it to 0x80000000 instead. See
|
||
- raise.c for the logic that relies on this value. */
|
||
- movl %gs:PID, %edx
|
||
- movl %edx, %eax
|
||
- negl %eax
|
||
- jne 1f
|
||
- movl $0x80000000, %eax
|
||
-1: movl %eax, %gs:PID
|
||
-
|
||
-
|
||
/* Stuff the syscall number in EAX and enter into the kernel. */
|
||
movl $SYS_ify (vfork), %eax
|
||
int $0x80
|
||
@@ -55,14 +44,6 @@ ENTRY (__vfork)
|
||
pushl %ecx
|
||
cfi_adjust_cfa_offset (4)
|
||
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- testl %eax, %eax
|
||
- je 1f
|
||
- movl %edx, %gs:PID
|
||
-1:
|
||
-
|
||
cmpl $-4095, %eax
|
||
/* Branch forward if it failed. */
|
||
jae SYSCALL_ERROR_LABEL
|
||
diff --git a/sysdeps/unix/sysv/linux/ia64/Makefile b/sysdeps/unix/sysv/linux/ia64/Makefile
|
||
index 1de62c528a..4d6766db5e 100644
|
||
--- a/sysdeps/unix/sysv/linux/ia64/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/ia64/Makefile
|
||
@@ -19,6 +19,7 @@ endif
|
||
|
||
ifeq ($(subdir),rt)
|
||
librt-routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),nptl)
|
||
diff --git a/sysdeps/unix/sysv/linux/ia64/clone2.S b/sysdeps/unix/sysv/linux/ia64/clone2.S
|
||
index b4cfdfc959..e637b6d4a5 100644
|
||
--- a/sysdeps/unix/sysv/linux/ia64/clone2.S
|
||
+++ b/sysdeps/unix/sysv/linux/ia64/clone2.S
|
||
@@ -67,19 +67,7 @@ ENTRY(__clone2)
|
||
(CHILD) mov loc0=gp
|
||
(PARENT) ret
|
||
;;
|
||
- tbit.nz p6,p0=in3,8 /* CLONE_VM */
|
||
-(p6) br.cond.dptk 1f
|
||
- ;;
|
||
- mov r15=SYS_ify (getpid)
|
||
-(p7) break __BREAK_SYSCALL
|
||
- ;;
|
||
- add r9=PID,r13
|
||
- add r10=TID,r13
|
||
- ;;
|
||
- st4 [r9]=r8
|
||
- st4 [r10]=r8
|
||
- ;;
|
||
-1: ld8 out1=[in0],8 /* Retrieve code pointer. */
|
||
+ ld8 out1=[in0],8 /* Retrieve code pointer. */
|
||
mov out0=in4 /* Pass proper argument to fn */
|
||
;;
|
||
ld8 gp=[in0] /* Load function gp. */
|
||
diff --git a/sysdeps/unix/sysv/linux/ia64/vfork.S b/sysdeps/unix/sysv/linux/ia64/vfork.S
|
||
index 9154d7c0fd..84bfdd5d8a 100644
|
||
--- a/sysdeps/unix/sysv/linux/ia64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/ia64/vfork.S
|
||
@@ -33,32 +33,12 @@ ENTRY (__libc_vfork)
|
||
.prologue // work around a GAS bug which triggers if
|
||
.body // first .prologue is not at the beginning of proc.
|
||
alloc r2=ar.pfs,0,0,2,0
|
||
- adds r14=PID,r13
|
||
- ;;
|
||
- ld4 r16=[r14]
|
||
- ;;
|
||
- sub r15=0,r16
|
||
- cmp.eq p6,p0=0,r16
|
||
- ;;
|
||
-(p6) movl r15=0x80000000
|
||
mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
|
||
mov out1=0 /* Standard sp value. */
|
||
;;
|
||
- st4 [r14]=r15
|
||
DO_CALL (SYS_ify (clone))
|
||
cmp.eq p6,p0=0,r8
|
||
- adds r14=PID,r13
|
||
(p6) br.cond.dptk 1f
|
||
- ;;
|
||
- ld4 r15=[r14]
|
||
- ;;
|
||
- extr.u r16=r15,0,31
|
||
- ;;
|
||
- cmp.eq p0,p6=0,r16
|
||
- ;;
|
||
-(p6) sub r16=0,r15
|
||
- ;;
|
||
- st4 [r14]=r16
|
||
1:
|
||
cmp.eq p6,p0=-1,r10
|
||
(p6) br.cond.spnt.few __syscall_error
|
||
diff --git a/sysdeps/unix/sysv/linux/m68k/clone.S b/sysdeps/unix/sysv/linux/m68k/clone.S
|
||
index 3a828443dc..630a29209d 100644
|
||
--- a/sysdeps/unix/sysv/linux/m68k/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/m68k/clone.S
|
||
@@ -98,19 +98,6 @@ ENTRY (__clone)
|
||
cfi_startproc
|
||
cfi_undefined (pc) /* Mark end of stack */
|
||
subl %fp, %fp /* terminate the stack frame */
|
||
- /* Check and see if we need to reset the PID. */
|
||
- andl #CLONE_VM, %d1
|
||
- jne 1f
|
||
- movel #SYS_ify (getpid), %d0
|
||
- trap #0
|
||
- movel %a0, -(%sp)
|
||
- movel %d0, -(%sp)
|
||
- bsrl __m68k_read_tp@PLTPC
|
||
- movel (%sp)+, %d0
|
||
- movel %d0, PID_OFFSET(%a0)
|
||
- movel %d0, TID_OFFSET(%a0)
|
||
- movel (%sp)+, %a0
|
||
-1:
|
||
jsr (%a0)
|
||
movel %d0, %d1
|
||
movel #SYS_ify (exit), %d0
|
||
diff --git a/sysdeps/unix/sysv/linux/m68k/vfork.S b/sysdeps/unix/sysv/linux/m68k/vfork.S
|
||
index 1625a7b7a0..e27479361b 100644
|
||
--- a/sysdeps/unix/sysv/linux/m68k/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/m68k/vfork.S
|
||
@@ -28,18 +28,6 @@
|
||
|
||
ENTRY (__vfork)
|
||
|
||
- /* Save the TCB-cached PID away in %d1, and then negate the TCB
|
||
- field. But if it's zero, set it to 0x80000000 instead. See
|
||
- raise.c for the logic that relies on this value. */
|
||
- jbsr __m68k_read_tp@PLTPC
|
||
- movel %a0, %a1
|
||
- movel PID_OFFSET(%a1), %d0
|
||
- movel %d0, %d1
|
||
- negl %d0
|
||
- jne 1f
|
||
- movel #0x80000000, %d0
|
||
-1: movel %d0, PID_OFFSET(%a1)
|
||
-
|
||
/* Pop the return PC value into A0. */
|
||
movel %sp@+, %a0
|
||
cfi_adjust_cfa_offset (-4)
|
||
@@ -49,14 +37,6 @@ ENTRY (__vfork)
|
||
movel #SYS_ify (vfork), %d0
|
||
trap #0
|
||
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- tstl %d0
|
||
- jeq 1f
|
||
- movel %d1, PID_OFFSET(%a1)
|
||
-1:
|
||
-
|
||
tstl %d0
|
||
jmi .Lerror /* Branch forward if it failed. */
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/microblaze/Makefile b/sysdeps/unix/sysv/linux/microblaze/Makefile
|
||
index 44a838fa11..d178bc6f34 100644
|
||
--- a/sysdeps/unix/sysv/linux/microblaze/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/microblaze/Makefile
|
||
@@ -5,4 +5,5 @@ endif
|
||
ifeq ($(subdir),nptl)
|
||
# pull in __syscall_error routine
|
||
libpthread-routines += sysdep
|
||
-endif
|
||
\ No newline at end of file
|
||
+libpthread-shared-only-routines += sysdep
|
||
+endif
|
||
diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S
|
||
index 39634c5cf0..7ae65ef723 100644
|
||
--- a/sysdeps/unix/sysv/linux/mips/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/mips/clone.S
|
||
@@ -130,11 +130,6 @@ L(thread_start):
|
||
SAVE_GP (GPOFF)
|
||
/* The stackframe has been created on entry of clone(). */
|
||
|
||
- /* Check and see if we need to reset the PID. */
|
||
- and a1,a0,CLONE_VM
|
||
- beqz a1,L(restore_pid)
|
||
-L(donepid):
|
||
-
|
||
/* Restore the arg for user's function. */
|
||
PTR_L t9,0(sp) /* Function pointer. */
|
||
PTR_L a0,PTRSIZE(sp) /* Argument pointer. */
|
||
@@ -151,14 +146,6 @@ L(donepid):
|
||
jal _exit
|
||
#endif
|
||
|
||
-L(restore_pid):
|
||
- li v0,__NR_getpid
|
||
- syscall
|
||
- READ_THREAD_POINTER(v1)
|
||
- INT_S v0,PID_OFFSET(v1)
|
||
- INT_S v0,TID_OFFSET(v1)
|
||
- b L(donepid)
|
||
-
|
||
END(__thread_start)
|
||
|
||
libc_hidden_def (__clone)
|
||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list b/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
|
||
index 890a74494a..26ab6d0b75 100644
|
||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
|
||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
|
||
@@ -4,6 +4,8 @@ mmap - mmap b:aniiii __mmap mmap __mmap64 mmap64
|
||
|
||
sync_file_range - sync_file_range Ci:iiii sync_file_range
|
||
|
||
+readahead - readahead i:iii __readahead readahead
|
||
+
|
||
prlimit EXTRA prlimit64 i:iipp prlimit prlimit64
|
||
|
||
fanotify_mark EXTRA fanotify_mark i:iiiis fanotify_mark
|
||
diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S
|
||
index 1867c8626e..0b9244b7f8 100644
|
||
--- a/sysdeps/unix/sysv/linux/mips/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/mips/vfork.S
|
||
@@ -60,14 +60,6 @@ NESTED(__libc_vfork,FRAMESZ,sp)
|
||
PTR_ADDU sp, FRAMESZ
|
||
cfi_adjust_cfa_offset (-FRAMESZ)
|
||
|
||
- /* Save the PID value. */
|
||
- READ_THREAD_POINTER(v1) /* Get the thread pointer. */
|
||
- lw a2, PID_OFFSET(v1) /* Load the saved PID. */
|
||
- subu a2, $0, a2 /* Negate it. */
|
||
- bnez a2, 1f /* If it was zero... */
|
||
- lui a2, 0x8000 /* use 0x80000000 instead. */
|
||
-1: sw a2, PID_OFFSET(v1) /* Store the temporary PID. */
|
||
-
|
||
li a0, 0x4112 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
|
||
move a1, sp
|
||
|
||
@@ -75,17 +67,6 @@ NESTED(__libc_vfork,FRAMESZ,sp)
|
||
li v0,__NR_clone
|
||
syscall
|
||
|
||
- /* Restore the old PID value in the parent. */
|
||
- beqz v0, 1f /* If we are the parent... */
|
||
- READ_THREAD_POINTER(v1) /* Get the thread pointer. */
|
||
- lw a2, PID_OFFSET(v1) /* Load the saved PID. */
|
||
- subu a2, $0, a2 /* Re-negate it. */
|
||
- lui a0, 0x8000 /* Load 0x80000000... */
|
||
- bne a2, a0, 2f /* ... compare against it... */
|
||
- li a2, 0 /* ... use 0 instead. */
|
||
-2: sw a2, PID_OFFSET(v1) /* Restore the PID. */
|
||
-1:
|
||
-
|
||
cfi_remember_state
|
||
bnez a3,L(error)
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/nios2/clone.S b/sysdeps/unix/sysv/linux/nios2/clone.S
|
||
index 30b6e4a6c8..c9fa00f94c 100644
|
||
--- a/sysdeps/unix/sysv/linux/nios2/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/nios2/clone.S
|
||
@@ -68,14 +68,6 @@ thread_start:
|
||
cfi_startproc
|
||
cfi_undefined (ra)
|
||
|
||
- /* We expect the argument registers to be preserved across system
|
||
- calls and across task cloning, so flags should be in r4 here. */
|
||
- andi r2, r4, CLONE_VM
|
||
- bne r2, zero, 2f
|
||
- DO_CALL (getpid, 0)
|
||
- stw r2, PID_OFFSET(r23)
|
||
- stw r2, TID_OFFSET(r23)
|
||
-2:
|
||
ldw r5, 4(sp) /* Function pointer. */
|
||
ldw r4, 0(sp) /* Argument pointer. */
|
||
addi sp, sp, 8
|
||
diff --git a/sysdeps/unix/sysv/linux/nios2/vfork.S b/sysdeps/unix/sysv/linux/nios2/vfork.S
|
||
index c1bb9c7134..8997269199 100644
|
||
--- a/sysdeps/unix/sysv/linux/nios2/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/nios2/vfork.S
|
||
@@ -21,20 +21,10 @@
|
||
|
||
ENTRY(__vfork)
|
||
|
||
- ldw r6, PID_OFFSET(r23)
|
||
- sub r7, zero, r6
|
||
- bne r7, zero, 2f
|
||
- movhi r7, %hi(0x80000000)
|
||
-2:
|
||
- stw r7, PID_OFFSET(r23)
|
||
-
|
||
movi r4, 0x4111 /* (CLONE_VM | CLONE_VFORK | SIGCHLD) */
|
||
mov r5, zero
|
||
DO_CALL (clone, 2)
|
||
|
||
- beq r2, zero, 1f
|
||
- stw r6, PID_OFFSET(r23)
|
||
-1:
|
||
bne r7, zero, SYSCALL_ERROR_LABEL
|
||
ret
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
|
||
index c89ed9ec7d..2cfb46eca3 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
|
||
@@ -8,6 +8,7 @@ abi-64-v2-condition := __WORDSIZE == 64 && _CALL_ELF == 2
|
||
|
||
ifeq ($(subdir),rt)
|
||
librt-routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),stdlib)
|
||
@@ -34,4 +35,5 @@ ifeq ($(subdir),nptl)
|
||
libpthread-routines += sysdep
|
||
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
|
||
elision-trylock
|
||
+libpthread-shared-only-routines += sysdep
|
||
endif
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-lock.c b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
|
||
index dd1e4c3b17..7dd3d835b6 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
|
||
@@ -45,7 +45,9 @@
|
||
int
|
||
__lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
|
||
{
|
||
- if (*adapt_count > 0)
|
||
+ /* adapt_count is accessed concurrently but is just a hint. Thus,
|
||
+ use atomic accesses but relaxed MO is sufficient. */
|
||
+ if (atomic_load_relaxed (adapt_count) > 0)
|
||
{
|
||
goto use_lock;
|
||
}
|
||
@@ -67,7 +69,8 @@ __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
|
||
if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
|
||
{
|
||
if (aconf.skip_lock_internal_abort > 0)
|
||
- *adapt_count = aconf.skip_lock_internal_abort;
|
||
+ atomic_store_relaxed (adapt_count,
|
||
+ aconf.skip_lock_internal_abort);
|
||
goto use_lock;
|
||
}
|
||
}
|
||
@@ -75,7 +78,8 @@ __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
|
||
|
||
/* Fall back to locks for a bit if retries have been exhausted */
|
||
if (aconf.try_tbegin > 0 && aconf.skip_lock_out_of_tbegin_retries > 0)
|
||
- *adapt_count = aconf.skip_lock_out_of_tbegin_retries;
|
||
+ atomic_store_relaxed (adapt_count,
|
||
+ aconf.skip_lock_out_of_tbegin_retries);
|
||
|
||
use_lock:
|
||
return LLL_LOCK ((*lock), pshared);
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
|
||
index 0807a6a432..606185670d 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
|
||
@@ -34,7 +34,7 @@ __lll_trylock_elision (int *futex, short *adapt_count)
|
||
__libc_tabort (_ABORT_NESTED_TRYLOCK);
|
||
|
||
/* Only try a transaction if it's worth it. */
|
||
- if (*adapt_count > 0)
|
||
+ if (atomic_load_relaxed (adapt_count) > 0)
|
||
{
|
||
goto use_lock;
|
||
}
|
||
@@ -49,7 +49,7 @@ __lll_trylock_elision (int *futex, short *adapt_count)
|
||
__libc_tend (0);
|
||
|
||
if (aconf.skip_lock_busy > 0)
|
||
- *adapt_count = aconf.skip_lock_busy;
|
||
+ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy);
|
||
}
|
||
else
|
||
{
|
||
@@ -59,7 +59,8 @@ __lll_trylock_elision (int *futex, short *adapt_count)
|
||
result in another failure. Use normal locking now and
|
||
for the next couple of calls. */
|
||
if (aconf.skip_trylock_internal_abort > 0)
|
||
- *adapt_count = aconf.skip_trylock_internal_abort;
|
||
+ atomic_store_relaxed (adapt_count,
|
||
+ aconf.skip_trylock_internal_abort);
|
||
}
|
||
}
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
|
||
index 43c5a67df2..51d7018e4c 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
|
||
@@ -28,13 +28,16 @@ __lll_unlock_elision (int *lock, short *adapt_count, int pshared)
|
||
__libc_tend (0);
|
||
else
|
||
{
|
||
- lll_unlock ((*lock), pshared);
|
||
+ /* Update adapt_count in the critical section to prevent a
|
||
+ write-after-destroy error as mentioned in BZ 20822. The
|
||
+ following update of adapt_count has to be contained within
|
||
+ the critical region of the fall-back lock in order to not violate
|
||
+ the mutex destruction requirements. */
|
||
+ short __tmp = atomic_load_relaxed (adapt_count);
|
||
+ if (__tmp > 0)
|
||
+ atomic_store_relaxed (adapt_count, __tmp - 1);
|
||
|
||
- /* Update the adapt count AFTER completing the critical section.
|
||
- Doing this here prevents unneeded stalling when entering
|
||
- a critical section. Saving about 8% runtime on P8. */
|
||
- if (*adapt_count > 0)
|
||
- (*adapt_count)--;
|
||
+ lll_unlock ((*lock), pshared);
|
||
}
|
||
return 0;
|
||
}
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
|
||
index bebadbfbb9..49fe01ecde 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
|
||
@@ -76,15 +76,6 @@ ENTRY (__clone)
|
||
crandc cr1*4+eq,cr1*4+eq,cr0*4+so
|
||
bne- cr1,L(parent) /* The '-' is to minimise the race. */
|
||
|
||
- /* If CLONE_VM is set do not update the pid/tid field. */
|
||
- andi. r0,r28,CLONE_VM
|
||
- bne+ cr0,L(oldpid)
|
||
-
|
||
- DO_CALL(SYS_ify(getpid))
|
||
- stw r3,TID(r2)
|
||
- stw r3,PID(r2)
|
||
-L(oldpid):
|
||
-
|
||
/* Call procedure. */
|
||
mtctr r30
|
||
mr r3,r31
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
|
||
index edbc7de1e6..0a724953a4 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
|
||
@@ -27,34 +27,8 @@
|
||
|
||
ENTRY (__vfork)
|
||
|
||
- /* Load the TCB-cached PID value and negates it. If It it is zero
|
||
- sets it to 0x800000. And then sets its value again on TCB field.
|
||
- See raise.c for the logic that relies on this value. */
|
||
-
|
||
- lwz r0,PID(r2)
|
||
- cmpwi cr0,r0,0
|
||
- neg r0,r0
|
||
- bne- cr0,1f
|
||
- lis r0,0x8000
|
||
-1: stw r0,PID(r2)
|
||
-
|
||
DO_CALL (SYS_ify (vfork))
|
||
|
||
- cmpwi cr1,r3,0
|
||
- beqlr- 1
|
||
-
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- lwz r0,PID(r2)
|
||
- /* Cannot use clrlwi. here, because cr0 needs to be preserved
|
||
- until PSEUDO_RET. */
|
||
- clrlwi r4,r0,1
|
||
- cmpwi cr1,r4,0
|
||
- beq- cr1,1f
|
||
- neg r4,r0
|
||
-1: stw r4,PID(r2)
|
||
-
|
||
PSEUDO_RET
|
||
|
||
PSEUDO_END (__vfork)
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
|
||
index 7c59b9b4e9..d8604f6731 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
|
||
@@ -78,15 +78,6 @@ ENTRY (__clone)
|
||
crandc cr1*4+eq,cr1*4+eq,cr0*4+so
|
||
bne- cr1,L(parent) /* The '-' is to minimise the race. */
|
||
|
||
- /* If CLONE_VM is set do not update the pid/tid field. */
|
||
- rldicl. r0,r29,56,63 /* flags & CLONE_VM. */
|
||
- bne+ cr0,L(oldpid)
|
||
-
|
||
- DO_CALL(SYS_ify(getpid))
|
||
- stw r3,TID(r13)
|
||
- stw r3,PID(r13)
|
||
-L(oldpid):
|
||
-
|
||
std r2,FRAME_TOC_SAVE(r1)
|
||
/* Call procedure. */
|
||
PPC64_LOAD_FUNCPTR r30
|
||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
|
||
index 3083ab7b3c..6b4cf432c1 100644
|
||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
|
||
@@ -28,31 +28,8 @@
|
||
ENTRY (__vfork)
|
||
CALL_MCOUNT 0
|
||
|
||
- /* Load the TCB-cached PID value and negates it. If It it is zero
|
||
- sets it to 0x800000. And then sets its value again on TCB field.
|
||
- See raise.c for the logic that relies on this value. */
|
||
- lwz r0,PID(r13)
|
||
- cmpwi cr0,r0,0
|
||
- neg r0,r0
|
||
- bne- cr0,1f
|
||
- lis r0,0x8000
|
||
-1: stw r0,PID(r13)
|
||
-
|
||
DO_CALL (SYS_ify (vfork))
|
||
|
||
- cmpwi cr1,r3,0
|
||
- beqlr- 1
|
||
-
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- lwz r0,PID(r13)
|
||
- clrlwi r4,r0,1
|
||
- cmpwi cr1,r4,0
|
||
- beq- cr1,1f
|
||
- neg r4,r0
|
||
-1: stw r4,PID(r13)
|
||
-
|
||
PSEUDO_RET
|
||
|
||
PSEUDO_END (__vfork)
|
||
diff --git a/sysdeps/unix/sysv/linux/pread.c b/sysdeps/unix/sysv/linux/pread.c
|
||
index 1bcff64781..46d974d952 100644
|
||
--- a/sysdeps/unix/sysv/linux/pread.c
|
||
+++ b/sysdeps/unix/sysv/linux/pread.c
|
||
@@ -28,8 +28,7 @@
|
||
ssize_t
|
||
__libc_pread (int fd, void *buf, size_t count, off_t offset)
|
||
{
|
||
- return SYSCALL_CANCEL (pread, fd, buf, count,
|
||
- __ALIGNMENT_ARG SYSCALL_LL (offset));
|
||
+ return SYSCALL_CANCEL (pread, fd, buf, count, SYSCALL_LL_PRW (offset));
|
||
}
|
||
|
||
strong_alias (__libc_pread, __pread)
|
||
diff --git a/sysdeps/unix/sysv/linux/pread64.c b/sysdeps/unix/sysv/linux/pread64.c
|
||
index 58c6aeb541..f51beae77a 100644
|
||
--- a/sysdeps/unix/sysv/linux/pread64.c
|
||
+++ b/sysdeps/unix/sysv/linux/pread64.c
|
||
@@ -26,8 +26,7 @@
|
||
ssize_t
|
||
__libc_pread64 (int fd, void *buf, size_t count, off64_t offset)
|
||
{
|
||
- return SYSCALL_CANCEL (pread64, fd, buf, count,
|
||
- __ALIGNMENT_ARG SYSCALL_LL64 (offset));
|
||
+ return SYSCALL_CANCEL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset));
|
||
}
|
||
|
||
weak_alias (__libc_pread64, __pread64)
|
||
diff --git a/sysdeps/unix/sysv/linux/pthread-pids.h b/sysdeps/unix/sysv/linux/pthread-pids.h
|
||
index d42bba03cf..618a5b1b9f 100644
|
||
--- a/sysdeps/unix/sysv/linux/pthread-pids.h
|
||
+++ b/sysdeps/unix/sysv/linux/pthread-pids.h
|
||
@@ -26,5 +26,5 @@ static inline void
|
||
__pthread_initialize_pids (struct pthread *pd)
|
||
{
|
||
INTERNAL_SYSCALL_DECL (err);
|
||
- pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
|
||
+ pd->tid = INTERNAL_SYSCALL_CALL (set_tid_address, err, &pd->tid);
|
||
}
|
||
diff --git a/sysdeps/unix/sysv/linux/pthread_kill.c b/sysdeps/unix/sysv/linux/pthread_kill.c
|
||
index bcb3009675..cc109973cc 100644
|
||
--- a/sysdeps/unix/sysv/linux/pthread_kill.c
|
||
+++ b/sysdeps/unix/sysv/linux/pthread_kill.c
|
||
@@ -21,6 +21,7 @@
|
||
#include <pthreadP.h>
|
||
#include <tls.h>
|
||
#include <sysdep.h>
|
||
+#include <unistd.h>
|
||
|
||
|
||
int
|
||
@@ -49,15 +50,9 @@ __pthread_kill (pthread_t threadid, int signo)
|
||
/* We have a special syscall to do the work. */
|
||
INTERNAL_SYSCALL_DECL (err);
|
||
|
||
- /* One comment: The PID field in the TCB can temporarily be changed
|
||
- (in fork). But this must not affect this code here. Since this
|
||
- function would have to be called while the thread is executing
|
||
- fork, it would have to happen in a signal handler. But this is
|
||
- no allowed, pthread_kill is not guaranteed to be async-safe. */
|
||
- int val;
|
||
- val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
|
||
- tid, signo);
|
||
+ pid_t pid = __getpid ();
|
||
|
||
+ int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, tid, signo);
|
||
return (INTERNAL_SYSCALL_ERROR_P (val, err)
|
||
? INTERNAL_SYSCALL_ERRNO (val, err) : 0);
|
||
}
|
||
diff --git a/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/sysdeps/unix/sysv/linux/pthread_sigqueue.c
|
||
index 7694d5467c..e393e0bd73 100644
|
||
--- a/sysdeps/unix/sysv/linux/pthread_sigqueue.c
|
||
+++ b/sysdeps/unix/sysv/linux/pthread_sigqueue.c
|
||
@@ -49,27 +49,22 @@ pthread_sigqueue (pthread_t threadid, int signo, const union sigval value)
|
||
if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
|
||
return EINVAL;
|
||
|
||
+ pid_t pid = getpid ();
|
||
+
|
||
/* Set up the siginfo_t structure. */
|
||
siginfo_t info;
|
||
memset (&info, '\0', sizeof (siginfo_t));
|
||
info.si_signo = signo;
|
||
info.si_code = SI_QUEUE;
|
||
- info.si_pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
+ info.si_pid = pid;
|
||
info.si_uid = getuid ();
|
||
info.si_value = value;
|
||
|
||
/* We have a special syscall to do the work. */
|
||
INTERNAL_SYSCALL_DECL (err);
|
||
|
||
- /* One comment: The PID field in the TCB can temporarily be changed
|
||
- (in fork). But this must not affect this code here. Since this
|
||
- function would have to be called while the thread is executing
|
||
- fork, it would have to happen in a signal handler. But this is
|
||
- no allowed, pthread_sigqueue is not guaranteed to be async-safe. */
|
||
- int val = INTERNAL_SYSCALL (rt_tgsigqueueinfo, err, 4,
|
||
- THREAD_GETMEM (THREAD_SELF, pid),
|
||
- tid, signo, &info);
|
||
-
|
||
+ int val = INTERNAL_SYSCALL_CALL (rt_tgsigqueueinfo, err, pid, tid, signo,
|
||
+ &info);
|
||
return (INTERNAL_SYSCALL_ERROR_P (val, err)
|
||
? INTERNAL_SYSCALL_ERRNO (val, err) : 0);
|
||
#else
|
||
diff --git a/sysdeps/unix/sysv/linux/pwrite.c b/sysdeps/unix/sysv/linux/pwrite.c
|
||
index 9c502beac1..1371df8a60 100644
|
||
--- a/sysdeps/unix/sysv/linux/pwrite.c
|
||
+++ b/sysdeps/unix/sysv/linux/pwrite.c
|
||
@@ -28,8 +28,7 @@
|
||
ssize_t
|
||
__libc_pwrite (int fd, const void *buf, size_t count, off_t offset)
|
||
{
|
||
- return SYSCALL_CANCEL (pwrite, fd, buf, count,
|
||
- __ALIGNMENT_ARG SYSCALL_LL (offset));
|
||
+ return SYSCALL_CANCEL (pwrite, fd, buf, count, SYSCALL_LL_PRW (offset));
|
||
}
|
||
|
||
strong_alias (__libc_pwrite, __pwrite)
|
||
diff --git a/sysdeps/unix/sysv/linux/pwrite64.c b/sysdeps/unix/sysv/linux/pwrite64.c
|
||
index b49e6bc286..22f1f05a44 100644
|
||
--- a/sysdeps/unix/sysv/linux/pwrite64.c
|
||
+++ b/sysdeps/unix/sysv/linux/pwrite64.c
|
||
@@ -26,8 +26,7 @@
|
||
ssize_t
|
||
__libc_pwrite64 (int fd, const void *buf, size_t count, off64_t offset)
|
||
{
|
||
- return SYSCALL_CANCEL (pwrite64, fd, buf, count,
|
||
- __ALIGNMENT_ARG SYSCALL_LL64 (offset));
|
||
+ return SYSCALL_CANCEL (pwrite64, fd, buf, count, SYSCALL_LL64_PRW (offset));
|
||
}
|
||
weak_alias (__libc_pwrite64, __pwrite64)
|
||
libc_hidden_weak (__pwrite64)
|
||
diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c
|
||
index 470033e83d..49bb7cb0d4 100644
|
||
--- a/sysdeps/unix/sysv/linux/raise.c
|
||
+++ b/sysdeps/unix/sysv/linux/raise.c
|
||
@@ -26,13 +26,6 @@
|
||
int
|
||
raise (int sig)
|
||
{
|
||
- /* raise is an async-safe function so it could be called while the
|
||
- fork/vfork function temporarily invalidated the PID field. To avoid
|
||
- relying on cached value we block all user-defined signal handler
|
||
- (which might call fork/vfork) and issue the getpid and gettid
|
||
- syscalls directly. */
|
||
-
|
||
-
|
||
/* rt_sigprocmask may fail if:
|
||
|
||
1. sigsetsize != sizeof (sigset_t) (EINVAL)
|
||
diff --git a/sysdeps/unix/sysv/linux/s390/Makefile b/sysdeps/unix/sysv/linux/s390/Makefile
|
||
index 497ffd566c..f8ed013e9e 100644
|
||
--- a/sysdeps/unix/sysv/linux/s390/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/s390/Makefile
|
||
@@ -6,6 +6,7 @@ abi-64-condition := __WORDSIZE == 64
|
||
|
||
ifeq ($(subdir),rt)
|
||
librt-routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),stdlib)
|
||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
|
||
index 2f8fa0b840..b1de1480d1 100644
|
||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
|
||
@@ -54,13 +54,6 @@ error:
|
||
PSEUDO_END (__clone)
|
||
|
||
thread_start:
|
||
- tml %r3,256 /* CLONE_VM == 0x00000100 */
|
||
- jne 1f
|
||
- svc SYS_ify(getpid)
|
||
- ear %r3,%a0
|
||
- st %r2,PID(%r3)
|
||
- st %r2,TID(%r3)
|
||
-1:
|
||
/* fn is in gpr 1, arg in gpr 0 */
|
||
lr %r2,%r0 /* set first parameter to void *arg */
|
||
ahi %r15,-96 /* make room on the stack for the save area */
|
||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S b/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S
|
||
index b7588ebd7c..cc60e139ba 100644
|
||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S
|
||
@@ -28,21 +28,9 @@
|
||
and the process ID of the new process to the old process. */
|
||
|
||
ENTRY (__libc_vfork)
|
||
- ear %r4,%a0
|
||
- lhi %r1,1
|
||
- icm %r3,15,PID(%r4)
|
||
- sll %r1,31
|
||
- je 1f
|
||
- lcr %r1,%r3
|
||
-1: st %r1,PID(%r4)
|
||
-
|
||
/* Do vfork system call. */
|
||
svc SYS_ify (vfork)
|
||
|
||
- ltr %r2,%r2
|
||
- je 1f
|
||
- st %r3,PID(%r4)
|
||
-1:
|
||
/* Check for error. */
|
||
lhi %r4,-4095
|
||
clr %r2,%r4
|
||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
|
||
index fb816922ca..29606acf03 100644
|
||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
|
||
@@ -55,15 +55,6 @@ error:
|
||
PSEUDO_END (__clone)
|
||
|
||
thread_start:
|
||
- tmll %r3,256 /* CLONE_VM == 0x00000100 */
|
||
- jne 1f
|
||
- svc SYS_ify(getpid)
|
||
- ear %r3,%a0
|
||
- sllg %r3,%r3,32
|
||
- ear %r3,%a1
|
||
- st %r2,PID(%r3)
|
||
- st %r2,TID(%r3)
|
||
-1:
|
||
/* fn is in gpr 1, arg in gpr 0 */
|
||
lgr %r2,%r0 /* set first parameter to void *arg */
|
||
aghi %r15,-160 /* make room on the stack for the save area */
|
||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
|
||
index 0bd2161381..b9a813f2cc 100644
|
||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
|
||
@@ -28,22 +28,9 @@
|
||
and the process ID of the new process to the old process. */
|
||
|
||
ENTRY (__libc_vfork)
|
||
- ear %r4,%a0
|
||
- sllg %r4,%r4,32
|
||
- ear %r4,%a1
|
||
- icm %r3,15,PID(%r4)
|
||
- llilh %r1,32768
|
||
- je 1f
|
||
- lcr %r1,%r3
|
||
-1: st %r1,PID(%r4)
|
||
-
|
||
/* Do vfork system call. */
|
||
svc SYS_ify (vfork)
|
||
|
||
- ltgr %r2,%r2
|
||
- je 1f
|
||
- st %r3,PID(%r4)
|
||
-1:
|
||
/* Check for error. */
|
||
lghi %r4,-4095
|
||
clgr %r2,%r4
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/clone.S b/sysdeps/unix/sysv/linux/sh/clone.S
|
||
index 4cd7df117c..ce7cddcb19 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/sh/clone.S
|
||
@@ -66,23 +66,7 @@ ENTRY(__clone)
|
||
2:
|
||
/* terminate the stack frame */
|
||
mov #0, r14
|
||
- mov r4, r0
|
||
- shlr8 r0
|
||
- tst #1, r0 // CLONE_VM = (1 << 8)
|
||
- bf/s 4f
|
||
- mov r4, r0
|
||
- /* new pid */
|
||
- mov #+SYS_ify(getpid), r3
|
||
- trapa #0x15
|
||
-3:
|
||
- stc gbr, r1
|
||
- mov.w .Lpidoff, r2
|
||
- add r1, r2
|
||
- mov.l r0, @r2
|
||
- mov.w .Ltidoff, r2
|
||
- add r1, r2
|
||
- mov.l r0, @r2
|
||
-4:
|
||
+
|
||
/* thread starts */
|
||
mov.l @r15, r1
|
||
jsr @r1
|
||
@@ -113,10 +97,6 @@ ENTRY(__clone)
|
||
.long _GLOBAL_OFFSET_TABLE_
|
||
.L3:
|
||
.long PLTJMP(C_SYMBOL_NAME(_exit))
|
||
-.Lpidoff:
|
||
- .word PID - TLS_PRE_TCB_SIZE
|
||
-.Ltidoff:
|
||
- .word TID - TLS_PRE_TCB_SIZE
|
||
PSEUDO_END (__clone)
|
||
|
||
libc_hidden_def (__clone)
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/kernel-features.h b/sysdeps/unix/sysv/linux/sh/kernel-features.h
|
||
index ad05fc39e1..c5240fafbd 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/kernel-features.h
|
||
+++ b/sysdeps/unix/sysv/linux/sh/kernel-features.h
|
||
@@ -44,3 +44,8 @@
|
||
|
||
/* SH does not have a 64-bit inode field. */
|
||
#undef __ASSUME_ST_INO_64_BIT
|
||
+
|
||
+/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||
+ the kernel interface for p{read,write}64 adds a dummy long argument
|
||
+ before the offset. */
|
||
+#define __ASSUME_PRW_DUMMY_ARG 1
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/pwrite.c b/sysdeps/unix/sysv/linux/sh/pwrite.c
|
||
deleted file mode 100644
|
||
index 391ed5e17b..0000000000
|
||
--- a/sysdeps/unix/sysv/linux/sh/pwrite.c
|
||
+++ /dev/null
|
||
@@ -1,23 +0,0 @@
|
||
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||
- This file is part of the GNU C Library.
|
||
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||
-
|
||
- 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
|
||
- <http://www.gnu.org/licenses/>. */
|
||
-
|
||
-/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||
- the kernel interface for pwrite adds a dummy long argument before the
|
||
- offset. */
|
||
-#define __ALIGNMENT_ARG
|
||
-#include <sysdeps/unix/sysv/linux/pwrite.c>
|
||
diff --git a/sysdeps/unix/sysv/linux/sh/vfork.S b/sysdeps/unix/sysv/linux/sh/vfork.S
|
||
index 6895bc5491..df559cb439 100644
|
||
--- a/sysdeps/unix/sysv/linux/sh/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/sh/vfork.S
|
||
@@ -26,30 +26,11 @@
|
||
and the process ID of the new process to the old process. */
|
||
|
||
ENTRY (__libc_vfork)
|
||
- /* Save the PID value. */
|
||
- stc gbr, r2
|
||
- mov.w .L2, r0
|
||
- mov.l @(r0,r2), r4
|
||
- neg r4, r1
|
||
- tst r1, r1
|
||
- bf 1f
|
||
- mov #1, r1
|
||
- rotr r1
|
||
-1:
|
||
- mov.l r1, @(r0,r2)
|
||
|
||
mov.w .L1, r3
|
||
trapa #0x10
|
||
mov r0, r1
|
||
|
||
- /* Restore the old PID value in the parent. */
|
||
- tst r0, r0
|
||
- bt.s 2f
|
||
- stc gbr, r2
|
||
- mov.w .L2, r0
|
||
- mov.l r4, @(r0,r2)
|
||
- mov r1, r0
|
||
-2:
|
||
mov #-12, r2
|
||
shad r2, r1
|
||
not r1, r1 // r1=0 means r0 = -1 to -4095
|
||
@@ -61,8 +42,6 @@ ENTRY (__libc_vfork)
|
||
nop
|
||
.L1:
|
||
.word __NR_vfork
|
||
-.L2:
|
||
- .word PID - TLS_PRE_TCB_SIZE
|
||
.align 2
|
||
PSEUDO_END (__libc_vfork)
|
||
|
||
diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile
|
||
index e67aecf8f0..a67d199eb5 100644
|
||
--- a/sysdeps/unix/sysv/linux/sparc/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/sparc/Makefile
|
||
@@ -6,6 +6,7 @@ abi-64-condition := __WORDSIZE == 64
|
||
|
||
ifeq ($(subdir),rt)
|
||
librt-routines += rt-sysdep
|
||
+librt-shared-only-routines += rt-sysdep
|
||
endif
|
||
|
||
ifeq ($(subdir),sysvipc)
|
||
@@ -15,4 +16,5 @@ endif
|
||
ifeq ($(subdir),nptl)
|
||
# pull in __syscall_error routine
|
||
libpthread-routines += sysdep
|
||
+libpthread-shared-only-routines += sysdep
|
||
endif
|
||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
|
||
index d6c92f6133..0456a0d16e 100644
|
||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
|
||
@@ -79,13 +79,6 @@ END(__clone)
|
||
|
||
.type __thread_start,@function
|
||
__thread_start:
|
||
- andcc %g4, CLONE_VM, %g0
|
||
- bne 1f
|
||
- set __NR_getpid,%g1
|
||
- ta 0x10
|
||
- st %o0,[%g7 + PID]
|
||
- st %o0,[%g7 + TID]
|
||
-1:
|
||
mov %g0, %fp /* terminate backtrace */
|
||
call %g2
|
||
mov %g3,%o0
|
||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
|
||
index 0d0a3b5298..6d985034f0 100644
|
||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
|
||
@@ -22,24 +22,14 @@
|
||
.text
|
||
.globl __syscall_error
|
||
ENTRY(__libc_vfork)
|
||
- ld [%g7 + PID], %o5
|
||
- cmp %o5, 0
|
||
- bne 1f
|
||
- sub %g0, %o5, %o4
|
||
- sethi %hi(0x80000000), %o4
|
||
-1: st %o4, [%g7 + PID]
|
||
-
|
||
LOADSYSCALL(vfork)
|
||
ta 0x10
|
||
bcc 2f
|
||
mov %o7, %g1
|
||
- st %o5, [%g7 + PID]
|
||
call __syscall_error
|
||
mov %g1, %o7
|
||
2: sub %o1, 1, %o1
|
||
andcc %o0, %o1, %o0
|
||
- bne,a 1f
|
||
- st %o5, [%g7 + PID]
|
||
1: retl
|
||
nop
|
||
END(__libc_vfork)
|
||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
|
||
index b0f62660a7..6ffead88e2 100644
|
||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
|
||
@@ -76,13 +76,6 @@ END(__clone)
|
||
|
||
.type __thread_start,@function
|
||
__thread_start:
|
||
- andcc %g4, CLONE_VM, %g0
|
||
- bne,pt %icc, 1f
|
||
- set __NR_getpid,%g1
|
||
- ta 0x6d
|
||
- st %o0,[%g7 + PID]
|
||
- st %o0,[%g7 + TID]
|
||
-1:
|
||
mov %g0, %fp /* terminate backtrace */
|
||
call %g2
|
||
mov %g3,%o0
|
||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
|
||
index 0818eba02e..298dd197a9 100644
|
||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
|
||
@@ -22,24 +22,14 @@
|
||
.text
|
||
.globl __syscall_error
|
||
ENTRY(__libc_vfork)
|
||
- ld [%g7 + PID], %o5
|
||
- sethi %hi(0x80000000), %o3
|
||
- cmp %o5, 0
|
||
- sub %g0, %o5, %o4
|
||
- move %icc, %o3, %o4
|
||
- st %o4, [%g7 + PID]
|
||
-
|
||
LOADSYSCALL(vfork)
|
||
ta 0x6d
|
||
bcc,pt %xcc, 2f
|
||
mov %o7, %g1
|
||
- st %o5, [%g7 + PID]
|
||
call __syscall_error
|
||
mov %g1, %o7
|
||
2: sub %o1, 1, %o1
|
||
andcc %o0, %o1, %o0
|
||
- bne,a,pt %icc, 1f
|
||
- st %o5, [%g7 + PID]
|
||
1: retl
|
||
nop
|
||
END(__libc_vfork)
|
||
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
|
||
index bb3eecfde1..b5f20a710b 100644
|
||
--- a/sysdeps/unix/sysv/linux/spawni.c
|
||
+++ b/sysdeps/unix/sysv/linux/spawni.c
|
||
@@ -58,22 +58,19 @@
|
||
normal program exit with the exit code 127. */
|
||
#define SPAWN_ERROR 127
|
||
|
||
-/* We need to block both SIGCANCEL and SIGSETXID. */
|
||
-#define SIGALL_SET \
|
||
- ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } })
|
||
-
|
||
#ifdef __ia64__
|
||
-# define CLONE(__fn, __stack, __stacksize, __flags, __args) \
|
||
- __clone2 (__fn, __stack, __stacksize, __flags, __args, 0, 0, 0)
|
||
+# define CLONE(__fn, __stackbase, __stacksize, __flags, __args) \
|
||
+ __clone2 (__fn, __stackbase, __stacksize, __flags, __args, 0, 0, 0)
|
||
#else
|
||
# define CLONE(__fn, __stack, __stacksize, __flags, __args) \
|
||
__clone (__fn, __stack, __flags, __args)
|
||
#endif
|
||
|
||
-#if _STACK_GROWS_DOWN
|
||
-# define STACK(__stack, __stack_size) (__stack + __stack_size)
|
||
-#elif _STACK_GROWS_UP
|
||
+/* Since ia64 wants the stackbase w/clone2, re-use the grows-up macro. */
|
||
+#if _STACK_GROWS_UP || defined (__ia64__)
|
||
# define STACK(__stack, __stack_size) (__stack)
|
||
+#elif _STACK_GROWS_DOWN
|
||
+# define STACK(__stack, __stack_size) (__stack + __stack_size)
|
||
#endif
|
||
|
||
|
||
@@ -329,6 +326,11 @@ __spawnix (pid_t * pid, const char *file,
|
||
|
||
/* Add a slack area for child's stack. */
|
||
size_t argv_size = (argc * sizeof (void *)) + 512;
|
||
+ /* We need at least a few pages in case the compiler's stack checking is
|
||
+ enabled. In some configs, it is known to use at least 24KiB. We use
|
||
+ 32KiB to be "safe" from anything the compiler might do. Besides, the
|
||
+ extra pages won't actually be allocated unless they get used. */
|
||
+ argv_size += (32 * 1024);
|
||
size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
|
||
void *stack = __mmap (NULL, stack_size, prot,
|
||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||
@@ -340,7 +342,9 @@ __spawnix (pid_t * pid, const char *file,
|
||
}
|
||
|
||
/* Disable asynchronous cancellation. */
|
||
- int cs = LIBC_CANCEL_ASYNC ();
|
||
+ int state;
|
||
+ __libc_ptf_call (__pthread_setcancelstate,
|
||
+ (PTHREAD_CANCEL_DISABLE, &state), 0);
|
||
|
||
args.file = file;
|
||
args.exec = exec;
|
||
@@ -351,7 +355,7 @@ __spawnix (pid_t * pid, const char *file,
|
||
args.envp = envp;
|
||
args.xflags = xflags;
|
||
|
||
- __sigprocmask (SIG_BLOCK, &SIGALL_SET, &args.oldmask);
|
||
+ __libc_signal_block_all (&args.oldmask);
|
||
|
||
/* The clone flags used will create a new child that will run in the same
|
||
memory space (CLONE_VM) and the execution of calling thread will be
|
||
@@ -384,9 +388,9 @@ __spawnix (pid_t * pid, const char *file,
|
||
if ((ec == 0) && (pid != NULL))
|
||
*pid = new_pid;
|
||
|
||
- __sigprocmask (SIG_SETMASK, &args.oldmask, 0);
|
||
+ __libc_signal_restore_set (&args.oldmask);
|
||
|
||
- LIBC_CANCEL_RESET (cs);
|
||
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
|
||
|
||
return ec;
|
||
}
|
||
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
|
||
index 7ae2541f8f..248641b830 100644
|
||
--- a/sysdeps/unix/sysv/linux/syscalls.list
|
||
+++ b/sysdeps/unix/sysv/linux/syscalls.list
|
||
@@ -18,6 +18,7 @@ execve - execve i:spp __execve execve
|
||
fdatasync - fdatasync Ci:i fdatasync
|
||
flock - flock i:ii __flock flock
|
||
get_kernel_syms EXTRA get_kernel_syms i:p __compat_get_kernel_syms get_kernel_syms@GLIBC_2.0:GLIBC_2.23
|
||
+getpid - getpid Ei: __getpid getpid
|
||
getegid - getegid Ei: __getegid getegid
|
||
geteuid - geteuid Ei: __geteuid geteuid
|
||
getpgid - getpgid i:i __getpgid getpgid
|
||
diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h
|
||
index a469f57121..e3ecd5638e 100644
|
||
--- a/sysdeps/unix/sysv/linux/sysdep.h
|
||
+++ b/sysdeps/unix/sysv/linux/sysdep.h
|
||
@@ -48,6 +48,16 @@
|
||
__LONG_LONG_PAIR ((long) ((val) >> 32), (long) ((val) & 0xffffffff))
|
||
#endif
|
||
|
||
+/* Provide a common macro to pass 64-bit value on pread and pwrite
|
||
+ syscalls. */
|
||
+#ifdef __ASSUME_PRW_DUMMY_ARG
|
||
+# define SYSCALL_LL_PRW(val) 0, SYSCALL_LL (val)
|
||
+# define SYSCALL_LL64_PRW(val) 0, SYSCALL_LL64 (val)
|
||
+#else
|
||
+# define SYSCALL_LL_PRW(val) __ALIGNMENT_ARG SYSCALL_LL (val)
|
||
+# define SYSCALL_LL64_PRW(val) __ALIGNMENT_ARG SYSCALL_LL64 (val)
|
||
+#endif
|
||
+
|
||
/* Provide a macro to pass the off{64}_t argument on p{readv,writev}{64}. */
|
||
#define LO_HI_LONG(val) \
|
||
(long) (val), \
|
||
diff --git a/sysdeps/unix/sysv/linux/tile/Makefile b/sysdeps/unix/sysv/linux/tile/Makefile
|
||
index 1c1cfff280..43acea3633 100644
|
||
--- a/sysdeps/unix/sysv/linux/tile/Makefile
|
||
+++ b/sysdeps/unix/sysv/linux/tile/Makefile
|
||
@@ -25,4 +25,5 @@ endif
|
||
ifeq ($(subdir),nptl)
|
||
# pull in __syscall_error routine
|
||
libpthread-routines += sysdep
|
||
+libpthread-shared-only-routines += sysdep
|
||
endif
|
||
diff --git a/sysdeps/unix/sysv/linux/tile/clone.S b/sysdeps/unix/sysv/linux/tile/clone.S
|
||
index d1d36462e7..3f9e3d56c4 100644
|
||
--- a/sysdeps/unix/sysv/linux/tile/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/tile/clone.S
|
||
@@ -163,22 +163,6 @@ ENTRY (__clone)
|
||
.Lthread_start:
|
||
cfi_def_cfa_offset (FRAME_SIZE)
|
||
cfi_undefined (lr)
|
||
- /* Check and see if we need to reset the PID, which we do if
|
||
- CLONE_VM isn't set, i.e. it's a fork-like clone with a new
|
||
- address space. In that case we update the cached values
|
||
- from the true system pid (retrieved via __NR_getpid syscall). */
|
||
- moveli r0, CLONE_VM
|
||
- and r0, r30, r0
|
||
- BNEZ r0, .Lno_reset_pid /* CLONE_VM is set */
|
||
- moveli TREG_SYSCALL_NR_NAME, __NR_getpid
|
||
- swint1
|
||
- ADDLI_PTR r2, tp, PID_OFFSET
|
||
- {
|
||
- ST4 r2, r0
|
||
- ADDLI_PTR r2, tp, TID_OFFSET
|
||
- }
|
||
- ST4 r2, r0
|
||
-.Lno_reset_pid:
|
||
{
|
||
/* Invoke user function with specified argument. */
|
||
move r0, r31
|
||
diff --git a/sysdeps/unix/sysv/linux/tile/vfork.S b/sysdeps/unix/sysv/linux/tile/vfork.S
|
||
index d8c5ce3e24..2272777187 100644
|
||
--- a/sysdeps/unix/sysv/linux/tile/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/tile/vfork.S
|
||
@@ -30,18 +30,6 @@
|
||
.text
|
||
ENTRY (__vfork)
|
||
{
|
||
- addli r11, tp, PID_OFFSET /* Point at PID. */
|
||
- movei r13, 1
|
||
- }
|
||
- {
|
||
- LD4U r12, r11 /* Load the saved PID. */
|
||
- shli r13, r13, 31 /* Build 0x80000000. */
|
||
- }
|
||
- sub r12, zero, r12 /* Negate it. */
|
||
- CMOVEQZ r12, r12, r13 /* Replace zero pids. */
|
||
- ST4 r11, r12 /* Store the temporary PID. */
|
||
-
|
||
- {
|
||
moveli r0, CLONE_VFORK | CLONE_VM | SIGCHLD
|
||
move r1, zero
|
||
}
|
||
@@ -52,22 +40,6 @@ ENTRY (__vfork)
|
||
moveli TREG_SYSCALL_NR_NAME, __NR_clone
|
||
swint1
|
||
|
||
- BEQZ r0, 1f /* If we are the parent... */
|
||
- {
|
||
- addli r11, tp, PID_OFFSET /* Point at PID. */
|
||
- movei r13, 1
|
||
- }
|
||
- {
|
||
- LD4U r12, r11 /* Load the saved PID. */
|
||
- shli r13, r13, 31 /* Build 0x80000000. */
|
||
- }
|
||
- {
|
||
- CMPEQ r13, r12, r12 /* Test for that value. */
|
||
- sub r12, zero, r12 /* Re-negate it. */
|
||
- }
|
||
- CMOVNEZ r12, r13, zero /* Replace zero pids. */
|
||
- ST4 r11, r12 /* Restore the PID. */
|
||
-1:
|
||
BNEZ r1, 0f
|
||
jrp lr
|
||
PSEUDO_END (__vfork)
|
||
diff --git a/sysdeps/unix/sysv/linux/tst-clone2.c b/sysdeps/unix/sysv/linux/tst-clone2.c
|
||
index 68a7e6d6e2..1472311947 100644
|
||
--- a/sysdeps/unix/sysv/linux/tst-clone2.c
|
||
+++ b/sysdeps/unix/sysv/linux/tst-clone2.c
|
||
@@ -28,8 +28,11 @@
|
||
#include <stdlib.h>
|
||
#include <sys/types.h>
|
||
#include <sys/wait.h>
|
||
+#include <sys/syscall.h>
|
||
|
||
-#include <tls.h> /* for THREAD_* macros. */
|
||
+#include <stackinfo.h> /* For _STACK_GROWS_{UP,DOWN}. */
|
||
+
|
||
+#include <support/check.h>
|
||
|
||
static int sig;
|
||
static int pipefd[2];
|
||
@@ -39,39 +42,35 @@ f (void *a)
|
||
{
|
||
close (pipefd[0]);
|
||
|
||
- pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||
- pid_t tid = THREAD_GETMEM (THREAD_SELF, tid);
|
||
+ pid_t ppid = getppid ();
|
||
+ pid_t pid = getpid ();
|
||
+ pid_t tid = syscall (__NR_gettid);
|
||
|
||
- while (write (pipefd[1], &pid, sizeof pid) < 0)
|
||
- continue;
|
||
- while (write (pipefd[1], &tid, sizeof tid) < 0)
|
||
- continue;
|
||
+ if (write (pipefd[1], &ppid, sizeof ppid) != sizeof (ppid))
|
||
+ FAIL_EXIT1 ("write ppid failed\n");
|
||
+ if (write (pipefd[1], &pid, sizeof pid) != sizeof (pid))
|
||
+ FAIL_EXIT1 ("write pid failed\n");
|
||
+ if (write (pipefd[1], &tid, sizeof tid) != sizeof (tid))
|
||
+ FAIL_EXIT1 ("write tid failed\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static int
|
||
-clone_test (int clone_flags)
|
||
+do_test (void)
|
||
{
|
||
sig = SIGRTMIN;
|
||
sigset_t ss;
|
||
sigemptyset (&ss);
|
||
sigaddset (&ss, sig);
|
||
if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
|
||
- {
|
||
- printf ("sigprocmask failed: %m\n");
|
||
- return 1;
|
||
- }
|
||
+ FAIL_EXIT1 ("sigprocmask failed: %m");
|
||
|
||
if (pipe2 (pipefd, O_CLOEXEC))
|
||
- {
|
||
- printf ("sigprocmask failed: %m\n");
|
||
- return 1;
|
||
- }
|
||
-
|
||
- pid_t ppid = getpid ();
|
||
+ FAIL_EXIT1 ("pipe failed: %m");
|
||
|
||
+ int clone_flags = 0;
|
||
#ifdef __ia64__
|
||
extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
|
||
size_t __child_stack_size, int __flags,
|
||
@@ -88,61 +87,47 @@ clone_test (int clone_flags)
|
||
#error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
|
||
#endif
|
||
#endif
|
||
+
|
||
close (pipefd[1]);
|
||
|
||
if (p == -1)
|
||
+ FAIL_EXIT1("clone failed: %m");
|
||
+
|
||
+ pid_t ppid, pid, tid;
|
||
+ if (read (pipefd[0], &ppid, sizeof pid) != sizeof pid)
|
||
{
|
||
- printf ("clone failed: %m\n");
|
||
- return 1;
|
||
+ kill (p, SIGKILL);
|
||
+ FAIL_EXIT1 ("read ppid failed: %m");
|
||
}
|
||
-
|
||
- pid_t pid, tid;
|
||
if (read (pipefd[0], &pid, sizeof pid) != sizeof pid)
|
||
{
|
||
- printf ("read pid failed: %m\n");
|
||
kill (p, SIGKILL);
|
||
- return 1;
|
||
+ FAIL_EXIT1 ("read pid failed: %m");
|
||
}
|
||
if (read (pipefd[0], &tid, sizeof tid) != sizeof tid)
|
||
{
|
||
- printf ("read pid failed: %m\n");
|
||
kill (p, SIGKILL);
|
||
- return 1;
|
||
+ FAIL_EXIT1 ("read tid failed: %m");
|
||
}
|
||
|
||
close (pipefd[0]);
|
||
|
||
int ret = 0;
|
||
|
||
- /* For CLONE_VM glibc clone implementation does not change the pthread
|
||
- pid/tid field. */
|
||
- if ((clone_flags & CLONE_VM) == CLONE_VM)
|
||
- {
|
||
- if ((ppid != pid) || (ppid != tid))
|
||
- {
|
||
- printf ("parent pid (%i) != received pid/tid (%i/%i)\n",
|
||
- (int)ppid, (int)pid, (int)tid);
|
||
- ret = 1;
|
||
- }
|
||
- }
|
||
- /* For any other flag clone updates the new pthread pid and tid with
|
||
- the clone return value. */
|
||
- else
|
||
- {
|
||
- if ((p != pid) || (p != tid))
|
||
- {
|
||
- printf ("child pid (%i) != received pid/tid (%i/%i)\n",
|
||
- (int)p, (int)pid, (int)tid);
|
||
- ret = 1;
|
||
- }
|
||
- }
|
||
+ pid_t own_pid = getpid ();
|
||
+ pid_t own_tid = syscall (__NR_gettid);
|
||
+
|
||
+ /* Some sanity checks for clone syscall: returned ppid should be current
|
||
+ pid and both returned tid/pid should be different from current one. */
|
||
+ if ((ppid != own_pid) || (pid == own_pid) || (tid == own_tid))
|
||
+ FAIL_RET ("ppid=%i pid=%i tid=%i | own_pid=%i own_tid=%i",
|
||
+ (int)ppid, (int)pid, (int)tid, (int)own_pid, (int)own_tid);
|
||
|
||
int e;
|
||
if (waitpid (p, &e, __WCLONE) != p)
|
||
{
|
||
- puts ("waitpid failed");
|
||
kill (p, SIGKILL);
|
||
- return 1;
|
||
+ FAIL_EXIT1 ("waitpid failed");
|
||
}
|
||
if (!WIFEXITED (e))
|
||
{
|
||
@@ -150,29 +135,12 @@ clone_test (int clone_flags)
|
||
printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
|
||
else
|
||
puts ("did not terminate correctly");
|
||
- return 1;
|
||
+ exit (EXIT_FAILURE);
|
||
}
|
||
if (WEXITSTATUS (e) != 0)
|
||
- {
|
||
- printf ("exit code %d\n", WEXITSTATUS (e));
|
||
- return 1;
|
||
- }
|
||
+ FAIL_EXIT1 ("exit code %d", WEXITSTATUS (e));
|
||
|
||
return ret;
|
||
}
|
||
|
||
-int
|
||
-do_test (void)
|
||
-{
|
||
- /* First, check that the clone implementation, without any flag, updates
|
||
- the struct pthread to contain the new PID and TID. */
|
||
- int ret = clone_test (0);
|
||
- /* Second, check that with CLONE_VM the struct pthread PID and TID fields
|
||
- remain unmodified after the clone. Any modifications would cause problem
|
||
- for the parent as described in bug 19957. */
|
||
- ret += clone_test (CLONE_VM);
|
||
- return ret;
|
||
-}
|
||
-
|
||
-#define TEST_FUNCTION do_test ()
|
||
-#include "../test-skeleton.c"
|
||
+#include <support/test-driver.c>
|
||
diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S
|
||
index 66f4b11490..5629aed395 100644
|
||
--- a/sysdeps/unix/sysv/linux/x86_64/clone.S
|
||
+++ b/sysdeps/unix/sysv/linux/x86_64/clone.S
|
||
@@ -91,14 +91,6 @@ L(thread_start):
|
||
the outermost frame obviously. */
|
||
xorl %ebp, %ebp
|
||
|
||
- andq $CLONE_VM, %rdi
|
||
- jne 1f
|
||
- movl $SYS_ify(getpid), %eax
|
||
- syscall
|
||
- movl %eax, %fs:PID
|
||
- movl %eax, %fs:TID
|
||
-1:
|
||
-
|
||
/* Set up arguments for the function call. */
|
||
popq %rax /* Function to call. */
|
||
popq %rdi /* Argument. */
|
||
diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S
|
||
index 8332ade9fb..cdd2dea32a 100644
|
||
--- a/sysdeps/unix/sysv/linux/x86_64/vfork.S
|
||
+++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S
|
||
@@ -34,16 +34,6 @@ ENTRY (__vfork)
|
||
cfi_adjust_cfa_offset(-8)
|
||
cfi_register(%rip, %rdi)
|
||
|
||
- /* Save the TCB-cached PID away in %esi, and then negate the TCB
|
||
- field. But if it's zero, set it to 0x80000000 instead. See
|
||
- raise.c for the logic that relies on this value. */
|
||
- movl %fs:PID, %esi
|
||
- movl $0x80000000, %ecx
|
||
- movl %esi, %edx
|
||
- negl %edx
|
||
- cmove %ecx, %edx
|
||
- movl %edx, %fs:PID
|
||
-
|
||
/* Stuff the syscall number in RAX and enter into the kernel. */
|
||
movl $SYS_ify (vfork), %eax
|
||
syscall
|
||
@@ -52,14 +42,6 @@ ENTRY (__vfork)
|
||
pushq %rdi
|
||
cfi_adjust_cfa_offset(8)
|
||
|
||
- /* Restore the original value of the TCB cache of the PID, if we're
|
||
- the parent. But in the child (syscall return value equals zero),
|
||
- leave things as they are. */
|
||
- testq %rax, %rax
|
||
- je 1f
|
||
- movl %esi, %fs:PID
|
||
-1:
|
||
-
|
||
cmpl $-4095, %eax
|
||
jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */
|
||
|
||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||
index 9ce4b495a5..d1ee922290 100644
|
||
--- a/sysdeps/x86/cpu-features.c
|
||
+++ b/sysdeps/x86/cpu-features.c
|
||
@@ -133,8 +133,6 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||
|
||
case 0x57:
|
||
/* Knights Landing. Enable Silvermont optimizations. */
|
||
- cpu_features->feature[index_arch_Prefer_No_VZEROUPPER]
|
||
- |= bit_arch_Prefer_No_VZEROUPPER;
|
||
|
||
case 0x5c:
|
||
case 0x5f:
|
||
@@ -205,6 +203,30 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||
if (CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable))
|
||
cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
|
||
|= bit_arch_AVX_Fast_Unaligned_Load;
|
||
+
|
||
+ /* Since AVX512ER is unique to Xeon Phi, set Prefer_No_VZEROUPPER
|
||
+ if AVX512ER is available. Don't use AVX512 to avoid lower CPU
|
||
+ frequency if AVX512ER isn't available. */
|
||
+ if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
|
||
+ cpu_features->feature[index_arch_Prefer_No_VZEROUPPER]
|
||
+ |= bit_arch_Prefer_No_VZEROUPPER;
|
||
+ else
|
||
+ cpu_features->feature[index_arch_Prefer_No_AVX512]
|
||
+ |= bit_arch_Prefer_No_AVX512;
|
||
+
|
||
+ /* To avoid SSE transition penalty, use _dl_runtime_resolve_slow.
|
||
+ If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. */
|
||
+ cpu_features->feature[index_arch_Use_dl_runtime_resolve_slow]
|
||
+ |= bit_arch_Use_dl_runtime_resolve_slow;
|
||
+ if (cpu_features->max_cpuid >= 0xd)
|
||
+ {
|
||
+ unsigned int eax;
|
||
+
|
||
+ __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
|
||
+ if ((eax & (1 << 2)) != 0)
|
||
+ cpu_features->feature[index_arch_Use_dl_runtime_resolve_opt]
|
||
+ |= bit_arch_Use_dl_runtime_resolve_opt;
|
||
+ }
|
||
}
|
||
/* This spells out "AuthenticAMD". */
|
||
else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
|
||
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
|
||
index 97ffe765f4..2609ac0999 100644
|
||
--- a/sysdeps/x86/cpu-features.h
|
||
+++ b/sysdeps/x86/cpu-features.h
|
||
@@ -37,6 +37,9 @@
|
||
#define bit_arch_Prefer_No_VZEROUPPER (1 << 17)
|
||
#define bit_arch_Fast_Unaligned_Copy (1 << 18)
|
||
#define bit_arch_Prefer_ERMS (1 << 19)
|
||
+#define bit_arch_Use_dl_runtime_resolve_opt (1 << 20)
|
||
+#define bit_arch_Use_dl_runtime_resolve_slow (1 << 21)
|
||
+#define bit_arch_Prefer_No_AVX512 (1 << 22)
|
||
|
||
/* CPUID Feature flags. */
|
||
|
||
@@ -60,6 +63,11 @@
|
||
#define bit_cpu_AVX2 (1 << 5)
|
||
#define bit_cpu_AVX512F (1 << 16)
|
||
#define bit_cpu_AVX512DQ (1 << 17)
|
||
+#define bit_cpu_AVX512PF (1 << 26)
|
||
+#define bit_cpu_AVX512ER (1 << 27)
|
||
+#define bit_cpu_AVX512CD (1 << 28)
|
||
+#define bit_cpu_AVX512BW (1 << 30)
|
||
+#define bit_cpu_AVX512VL (1u << 31)
|
||
|
||
/* XCR0 Feature flags. */
|
||
#define bit_XMM_state (1 << 1)
|
||
@@ -107,6 +115,9 @@
|
||
# define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1*FEATURE_SIZE
|
||
# define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1*FEATURE_SIZE
|
||
# define index_arch_Prefer_ERMS FEATURE_INDEX_1*FEATURE_SIZE
|
||
+# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1*FEATURE_SIZE
|
||
+# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1*FEATURE_SIZE
|
||
+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1*FEATURE_SIZE
|
||
|
||
|
||
# if defined (_LIBC) && !IS_IN (nonlib)
|
||
@@ -232,6 +243,11 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||
# define index_cpu_AVX2 COMMON_CPUID_INDEX_7
|
||
# define index_cpu_AVX512F COMMON_CPUID_INDEX_7
|
||
# define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7
|
||
+# define index_cpu_AVX512PF COMMON_CPUID_INDEX_7
|
||
+# define index_cpu_AVX512ER COMMON_CPUID_INDEX_7
|
||
+# define index_cpu_AVX512CD COMMON_CPUID_INDEX_7
|
||
+# define index_cpu_AVX512BW COMMON_CPUID_INDEX_7
|
||
+# define index_cpu_AVX512VL COMMON_CPUID_INDEX_7
|
||
# define index_cpu_ERMS COMMON_CPUID_INDEX_7
|
||
# define index_cpu_RTM COMMON_CPUID_INDEX_7
|
||
# define index_cpu_FMA COMMON_CPUID_INDEX_1
|
||
@@ -250,6 +266,11 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||
# define reg_AVX2 ebx
|
||
# define reg_AVX512F ebx
|
||
# define reg_AVX512DQ ebx
|
||
+# define reg_AVX512PF ebx
|
||
+# define reg_AVX512ER ebx
|
||
+# define reg_AVX512CD ebx
|
||
+# define reg_AVX512BW ebx
|
||
+# define reg_AVX512VL ebx
|
||
# define reg_ERMS ebx
|
||
# define reg_RTM ebx
|
||
# define reg_FMA ecx
|
||
@@ -277,6 +298,9 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||
# define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1
|
||
# define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1
|
||
# define index_arch_Prefer_ERMS FEATURE_INDEX_1
|
||
+# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1
|
||
+# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1
|
||
+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1
|
||
|
||
#endif /* !__ASSEMBLER__ */
|
||
|
||
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
|
||
index ed0c1a8efd..c0f0fa16a2 100644
|
||
--- a/sysdeps/x86_64/dl-machine.h
|
||
+++ b/sysdeps/x86_64/dl-machine.h
|
||
@@ -68,7 +68,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||
Elf64_Addr *got;
|
||
extern void _dl_runtime_resolve_sse (ElfW(Word)) attribute_hidden;
|
||
extern void _dl_runtime_resolve_avx (ElfW(Word)) attribute_hidden;
|
||
+ extern void _dl_runtime_resolve_avx_slow (ElfW(Word)) attribute_hidden;
|
||
+ extern void _dl_runtime_resolve_avx_opt (ElfW(Word)) attribute_hidden;
|
||
extern void _dl_runtime_resolve_avx512 (ElfW(Word)) attribute_hidden;
|
||
+ extern void _dl_runtime_resolve_avx512_opt (ElfW(Word)) attribute_hidden;
|
||
extern void _dl_runtime_profile_sse (ElfW(Word)) attribute_hidden;
|
||
extern void _dl_runtime_profile_avx (ElfW(Word)) attribute_hidden;
|
||
extern void _dl_runtime_profile_avx512 (ElfW(Word)) attribute_hidden;
|
||
@@ -118,9 +121,26 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||
indicated by the offset on the stack, and then jump to
|
||
the resolved address. */
|
||
if (HAS_ARCH_FEATURE (AVX512F_Usable))
|
||
- *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve_avx512;
|
||
+ {
|
||
+ if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt))
|
||
+ *(ElfW(Addr) *) (got + 2)
|
||
+ = (ElfW(Addr)) &_dl_runtime_resolve_avx512_opt;
|
||
+ else
|
||
+ *(ElfW(Addr) *) (got + 2)
|
||
+ = (ElfW(Addr)) &_dl_runtime_resolve_avx512;
|
||
+ }
|
||
else if (HAS_ARCH_FEATURE (AVX_Usable))
|
||
- *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve_avx;
|
||
+ {
|
||
+ if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt))
|
||
+ *(ElfW(Addr) *) (got + 2)
|
||
+ = (ElfW(Addr)) &_dl_runtime_resolve_avx_opt;
|
||
+ else if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_slow))
|
||
+ *(ElfW(Addr) *) (got + 2)
|
||
+ = (ElfW(Addr)) &_dl_runtime_resolve_avx_slow;
|
||
+ else
|
||
+ *(ElfW(Addr) *) (got + 2)
|
||
+ = (ElfW(Addr)) &_dl_runtime_resolve_avx;
|
||
+ }
|
||
else
|
||
*(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve_sse;
|
||
}
|
||
diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
|
||
index 12f1a5cf84..50b23633e3 100644
|
||
--- a/sysdeps/x86_64/dl-trampoline.S
|
||
+++ b/sysdeps/x86_64/dl-trampoline.S
|
||
@@ -18,6 +18,7 @@
|
||
|
||
#include <config.h>
|
||
#include <sysdep.h>
|
||
+#include <cpu-features.h>
|
||
#include <link-defines.h>
|
||
|
||
#ifndef DL_STACK_ALIGNMENT
|
||
@@ -104,9 +105,11 @@
|
||
#endif
|
||
#define VEC(i) ymm##i
|
||
#define _dl_runtime_resolve _dl_runtime_resolve_avx
|
||
+#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx_opt
|
||
#define _dl_runtime_profile _dl_runtime_profile_avx
|
||
#include "dl-trampoline.h"
|
||
#undef _dl_runtime_resolve
|
||
+#undef _dl_runtime_resolve_opt
|
||
#undef _dl_runtime_profile
|
||
#undef VEC
|
||
#undef VMOV
|
||
@@ -126,3 +129,19 @@
|
||
#define _dl_runtime_profile _dl_runtime_profile_sse
|
||
#undef RESTORE_AVX
|
||
#include "dl-trampoline.h"
|
||
+#undef _dl_runtime_resolve
|
||
+#undef _dl_runtime_profile
|
||
+#undef VMOV
|
||
+#undef VMOVA
|
||
+
|
||
+/* Used by _dl_runtime_resolve_avx_opt/_dl_runtime_resolve_avx512_opt
|
||
+ to preserve the full vector registers with zero upper bits. */
|
||
+#define VMOVA vmovdqa
|
||
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
|
||
+# define VMOV vmovdqa
|
||
+#else
|
||
+# define VMOV vmovdqu
|
||
+#endif
|
||
+#define _dl_runtime_resolve _dl_runtime_resolve_sse_vex
|
||
+#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx512_opt
|
||
+#include "dl-trampoline.h"
|
||
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
|
||
index b90836ab13..32ad3af202 100644
|
||
--- a/sysdeps/x86_64/dl-trampoline.h
|
||
+++ b/sysdeps/x86_64/dl-trampoline.h
|
||
@@ -50,6 +50,106 @@
|
||
#endif
|
||
|
||
.text
|
||
+#ifdef _dl_runtime_resolve_opt
|
||
+/* Use the smallest vector registers to preserve the full YMM/ZMM
|
||
+ registers to avoid SSE transition penalty. */
|
||
+
|
||
+# if VEC_SIZE == 32
|
||
+/* Check if the upper 128 bits in %ymm0 - %ymm7 registers are non-zero
|
||
+ and preserve %xmm0 - %xmm7 registers with the zero upper bits. Since
|
||
+ there is no SSE transition penalty on AVX512 processors which don't
|
||
+ support XGETBV with ECX == 1, _dl_runtime_resolve_avx512_slow isn't
|
||
+ provided. */
|
||
+ .globl _dl_runtime_resolve_avx_slow
|
||
+ .hidden _dl_runtime_resolve_avx_slow
|
||
+ .type _dl_runtime_resolve_avx_slow, @function
|
||
+ .align 16
|
||
+_dl_runtime_resolve_avx_slow:
|
||
+ cfi_startproc
|
||
+ cfi_adjust_cfa_offset(16) # Incorporate PLT
|
||
+ vorpd %ymm0, %ymm1, %ymm8
|
||
+ vorpd %ymm2, %ymm3, %ymm9
|
||
+ vorpd %ymm4, %ymm5, %ymm10
|
||
+ vorpd %ymm6, %ymm7, %ymm11
|
||
+ vorpd %ymm8, %ymm9, %ymm9
|
||
+ vorpd %ymm10, %ymm11, %ymm10
|
||
+ vpcmpeqd %xmm8, %xmm8, %xmm8
|
||
+ vorpd %ymm9, %ymm10, %ymm10
|
||
+ vptest %ymm10, %ymm8
|
||
+ # Preserve %ymm0 - %ymm7 registers if the upper 128 bits of any
|
||
+ # %ymm0 - %ymm7 registers aren't zero.
|
||
+ PRESERVE_BND_REGS_PREFIX
|
||
+ jnc _dl_runtime_resolve_avx
|
||
+ # Use vzeroupper to avoid SSE transition penalty.
|
||
+ vzeroupper
|
||
+ # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits
|
||
+ # when the upper 128 bits of %ymm0 - %ymm7 registers are zero.
|
||
+ PRESERVE_BND_REGS_PREFIX
|
||
+ jmp _dl_runtime_resolve_sse_vex
|
||
+ cfi_adjust_cfa_offset(-16) # Restore PLT adjustment
|
||
+ cfi_endproc
|
||
+ .size _dl_runtime_resolve_avx_slow, .-_dl_runtime_resolve_avx_slow
|
||
+# endif
|
||
+
|
||
+/* Use XGETBV with ECX == 1 to check which bits in vector registers are
|
||
+ non-zero and only preserve the non-zero lower bits with zero upper
|
||
+ bits. */
|
||
+ .globl _dl_runtime_resolve_opt
|
||
+ .hidden _dl_runtime_resolve_opt
|
||
+ .type _dl_runtime_resolve_opt, @function
|
||
+ .align 16
|
||
+_dl_runtime_resolve_opt:
|
||
+ cfi_startproc
|
||
+ cfi_adjust_cfa_offset(16) # Incorporate PLT
|
||
+ pushq %rax
|
||
+ cfi_adjust_cfa_offset(8)
|
||
+ cfi_rel_offset(%rax, 0)
|
||
+ pushq %rcx
|
||
+ cfi_adjust_cfa_offset(8)
|
||
+ cfi_rel_offset(%rcx, 0)
|
||
+ pushq %rdx
|
||
+ cfi_adjust_cfa_offset(8)
|
||
+ cfi_rel_offset(%rdx, 0)
|
||
+ movl $1, %ecx
|
||
+ xgetbv
|
||
+ movl %eax, %r11d
|
||
+ popq %rdx
|
||
+ cfi_adjust_cfa_offset(-8)
|
||
+ cfi_restore (%rdx)
|
||
+ popq %rcx
|
||
+ cfi_adjust_cfa_offset(-8)
|
||
+ cfi_restore (%rcx)
|
||
+ popq %rax
|
||
+ cfi_adjust_cfa_offset(-8)
|
||
+ cfi_restore (%rax)
|
||
+# if VEC_SIZE == 32
|
||
+ # For YMM registers, check if YMM state is in use.
|
||
+ andl $bit_YMM_state, %r11d
|
||
+ # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits if
|
||
+ # YMM state isn't in use.
|
||
+ PRESERVE_BND_REGS_PREFIX
|
||
+ jz _dl_runtime_resolve_sse_vex
|
||
+# elif VEC_SIZE == 16
|
||
+ # For ZMM registers, check if YMM state and ZMM state are in
|
||
+ # use.
|
||
+ andl $(bit_YMM_state | bit_ZMM0_15_state), %r11d
|
||
+ cmpl $bit_YMM_state, %r11d
|
||
+ # Preserve %zmm0 - %zmm7 registers if ZMM state is in use.
|
||
+ PRESERVE_BND_REGS_PREFIX
|
||
+ jg _dl_runtime_resolve_avx512
|
||
+ # Preserve %ymm0 - %ymm7 registers with the zero upper 256 bits if
|
||
+ # ZMM state isn't in use.
|
||
+ PRESERVE_BND_REGS_PREFIX
|
||
+ je _dl_runtime_resolve_avx
|
||
+ # Preserve %xmm0 - %xmm7 registers with the zero upper 384 bits if
|
||
+ # neither YMM state nor ZMM state are in use.
|
||
+# else
|
||
+# error Unsupported VEC_SIZE!
|
||
+# endif
|
||
+ cfi_adjust_cfa_offset(-16) # Restore PLT adjustment
|
||
+ cfi_endproc
|
||
+ .size _dl_runtime_resolve_opt, .-_dl_runtime_resolve_opt
|
||
+#endif
|
||
.globl _dl_runtime_resolve
|
||
.hidden _dl_runtime_resolve
|
||
.type _dl_runtime_resolve, @function
|
||
@@ -162,7 +262,10 @@ _dl_runtime_resolve:
|
||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||
|
||
|
||
-#ifndef PROF
|
||
+/* To preserve %xmm0 - %xmm7 registers, dl-trampoline.h is included
|
||
+ twice, for _dl_runtime_resolve_sse and _dl_runtime_resolve_sse_vex.
|
||
+ But we don't need another _dl_runtime_profile for XMM registers. */
|
||
+#if !defined PROF && defined _dl_runtime_profile
|
||
# if (LR_VECTOR_OFFSET % VEC_SIZE) != 0
|
||
# error LR_VECTOR_OFFSET must be multples of VEC_SIZE
|
||
# endif
|
||
diff --git a/sysdeps/x86_64/memcpy_chk.S b/sysdeps/x86_64/memcpy_chk.S
|
||
index 2296b55119..a95b3ad3cf 100644
|
||
--- a/sysdeps/x86_64/memcpy_chk.S
|
||
+++ b/sysdeps/x86_64/memcpy_chk.S
|
||
@@ -19,7 +19,7 @@
|
||
#include <sysdep.h>
|
||
#include "asm-syntax.h"
|
||
|
||
-#ifndef PIC
|
||
+#ifndef SHARED
|
||
/* For libc.so this is defined in memcpy.S.
|
||
For libc.a, this is a separate source to avoid
|
||
memcpy bringing in __chk_fail and all routines
|
||
diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S
|
||
index b8677596f9..ea4ec70d1a 100644
|
||
--- a/sysdeps/x86_64/multiarch/memcpy.S
|
||
+++ b/sysdeps/x86_64/multiarch/memcpy.S
|
||
@@ -32,6 +32,8 @@ ENTRY(__new_memcpy)
|
||
lea __memcpy_erms(%rip), %RAX_LP
|
||
HAS_ARCH_FEATURE (Prefer_ERMS)
|
||
jnz 2f
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __memcpy_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/memcpy_chk.S b/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||
index 9d92c8a7e3..26b49de6f6 100644
|
||
--- a/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||
+++ b/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||
@@ -30,6 +30,8 @@
|
||
ENTRY(__memcpy_chk)
|
||
.type __memcpy_chk, @gnu_indirect_function
|
||
LOAD_RTLD_GLOBAL_RO_RDX
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __memcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/memmove.S b/sysdeps/x86_64/multiarch/memmove.S
|
||
index ff5e041420..ef92afde5a 100644
|
||
--- a/sysdeps/x86_64/multiarch/memmove.S
|
||
+++ b/sysdeps/x86_64/multiarch/memmove.S
|
||
@@ -30,6 +30,8 @@ ENTRY(__libc_memmove)
|
||
lea __memmove_erms(%rip), %RAX_LP
|
||
HAS_ARCH_FEATURE (Prefer_ERMS)
|
||
jnz 2f
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __memmove_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/memmove_chk.S b/sysdeps/x86_64/multiarch/memmove_chk.S
|
||
index 7f861206df..a9129c460a 100644
|
||
--- a/sysdeps/x86_64/multiarch/memmove_chk.S
|
||
+++ b/sysdeps/x86_64/multiarch/memmove_chk.S
|
||
@@ -29,6 +29,8 @@
|
||
ENTRY(__memmove_chk)
|
||
.type __memmove_chk, @gnu_indirect_function
|
||
LOAD_RTLD_GLOBAL_RO_RDX
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __memmove_chk_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/mempcpy.S b/sysdeps/x86_64/multiarch/mempcpy.S
|
||
index 51970687cf..87c8299fea 100644
|
||
--- a/sysdeps/x86_64/multiarch/mempcpy.S
|
||
+++ b/sysdeps/x86_64/multiarch/mempcpy.S
|
||
@@ -32,6 +32,8 @@ ENTRY(__mempcpy)
|
||
lea __mempcpy_erms(%rip), %RAX_LP
|
||
HAS_ARCH_FEATURE (Prefer_ERMS)
|
||
jnz 2f
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __mempcpy_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/mempcpy_chk.S b/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||
index 9e49f6f26e..642c67973b 100644
|
||
--- a/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||
+++ b/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||
@@ -30,6 +30,8 @@
|
||
ENTRY(__mempcpy_chk)
|
||
.type __mempcpy_chk, @gnu_indirect_function
|
||
LOAD_RTLD_GLOBAL_RO_RDX
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 1f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 1f
|
||
lea __mempcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
|
||
index 28e71fd576..acf448c9a6 100644
|
||
--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
|
||
+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
|
||
@@ -110,6 +110,8 @@ ENTRY (__memset_erms)
|
||
ENTRY (MEMSET_SYMBOL (__memset, erms))
|
||
# endif
|
||
L(stosb):
|
||
+ /* Issue vzeroupper before rep stosb. */
|
||
+ VZEROUPPER
|
||
movq %rdx, %rcx
|
||
movzbl %sil, %eax
|
||
movq %rdi, %rdx
|
||
diff --git a/sysdeps/x86_64/multiarch/memset.S b/sysdeps/x86_64/multiarch/memset.S
|
||
index 96e99341aa..eae39e2ecd 100644
|
||
--- a/sysdeps/x86_64/multiarch/memset.S
|
||
+++ b/sysdeps/x86_64/multiarch/memset.S
|
||
@@ -41,6 +41,8 @@ ENTRY(memset)
|
||
jnz L(AVX512F)
|
||
lea __memset_avx2_unaligned(%rip), %RAX_LP
|
||
L(AVX512F):
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 2f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 2f
|
||
lea __memset_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/multiarch/memset_chk.S b/sysdeps/x86_64/multiarch/memset_chk.S
|
||
index 2efe6ed909..38d7bef6df 100644
|
||
--- a/sysdeps/x86_64/multiarch/memset_chk.S
|
||
+++ b/sysdeps/x86_64/multiarch/memset_chk.S
|
||
@@ -38,6 +38,8 @@ ENTRY(__memset_chk)
|
||
jnz L(AVX512F)
|
||
lea __memset_chk_avx2_unaligned(%rip), %RAX_LP
|
||
L(AVX512F):
|
||
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
|
||
+ jnz 2f
|
||
HAS_ARCH_FEATURE (AVX512F_Usable)
|
||
jz 2f
|
||
lea __memset_chk_avx512_no_vzeroupper(%rip), %RAX_LP
|
||
diff --git a/sysdeps/x86_64/nptl/tcb-offsets.sym b/sysdeps/x86_64/nptl/tcb-offsets.sym
|
||
index aeb752673a..8a25c482cb 100644
|
||
--- a/sysdeps/x86_64/nptl/tcb-offsets.sym
|
||
+++ b/sysdeps/x86_64/nptl/tcb-offsets.sym
|
||
@@ -4,7 +4,6 @@
|
||
|
||
RESULT offsetof (struct pthread, result)
|
||
TID offsetof (struct pthread, tid)
|
||
-PID offsetof (struct pthread, pid)
|
||
CANCELHANDLING offsetof (struct pthread, cancelhandling)
|
||
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
|
||
CLEANUP offsetof (struct pthread, cleanup)
|
||
diff --git a/sysdeps/x86_64/sysdep.h b/sysdeps/x86_64/sysdep.h
|
||
index 75ac747be8..4b67fa80c1 100644
|
||
--- a/sysdeps/x86_64/sysdep.h
|
||
+++ b/sysdeps/x86_64/sysdep.h
|
||
@@ -89,13 +89,14 @@ lose: \
|
||
END (name)
|
||
|
||
#undef JUMPTARGET
|
||
-#ifdef PIC
|
||
+#ifdef SHARED
|
||
# ifdef BIND_NOW
|
||
# define JUMPTARGET(name) *name##@GOTPCREL(%rip)
|
||
# else
|
||
# define JUMPTARGET(name) name##@PLT
|
||
# endif
|
||
#else
|
||
+/* For static archives, branch to target directly. */
|
||
# define JUMPTARGET(name) name
|
||
#endif
|
||
|