diff --git a/ChangeLog b/ChangeLog
-index 2e4afb7..f5ae211 100644
+index 2e4afb7..4764955 100644
--- a/ChangeLog
+++ b/ChangeLog
-@@ -1,5 +1,38 @@
+@@ -1,5 +1,476 @@
++2016-03-31 Adhemerval Zanella <adhemerval.zanella@linaro.org>
++
++ * elf/tst-dlsym-error.c: Include <string.h> for strchrnul.
++
++2016-03-31 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19509]
++ * elf/dl-lookup.c (_dl_lookup_symbol_x): Report error even if
++ skip_map != NULL.
++ * elf/tst-dlsym-error.c: New file.
++ * elf/Makefile (tests): Add tst-dlsym-error.
++ (tst-dlsym-error): Link against libdl.
++
++2016-03-07 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19610]
++ * elf/ldconfig.c (opt_link): Update comment.
++ (options): Update help string for option -X.
++ (search_dir): Unlink stale symbolic link only if updating symbolic
++ links.
++ * elf/tst-ldconfig-X.sh: New file.
++ * elf/Makefile (tests-special): Add tst-ldconfig-X.out.
++ (tst-ldconfig-X.out): New rule to run tst-ldconfig-X.sh.
++
++2016-05-04 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19779]
++ CVE-2016-1234
++ Avoid copying names of directory entries.
++ * posix/glob.c (DIRENT_MUST_BE, DIRENT_MIGHT_BE_SYMLINK)
++ (DIRENT_MIGHT_BE_DIR, CONVERT_D_INO, CONVERT_D_TYPE)
++ (CONVERT_DIRENT_DIRENT64, REAL_DIR_ENTRY): Remove macros.
++ (struct readdir_result): New type.
++ (D_TYPE_TO_RESULT, D_INO_TO_RESULT, READDIR_RESULT_INITIALIZER)
++ (GL_READDIR): New macros.
++ (readdir_result_might_be_symlink, readdir_result_might_be_dir)
++ (convert_dirent, convert_dirent64): New functions.
++ (glob_in_dir): Use struct readdir_result. Call convert_dirent or
++ convert_dirent64. Adjust references to the readdir result.
++ * sysdeps/unix/sysv/linux/i386/glob64.c:
++ (convert_dirent, GL_READDIR): Redefine for second file inclusion.
++ * posix/bug-glob2.c (LONG_NAME): Define.
++ (filesystem): Add LONG_NAME.
++ (my_DIR): Increase the size of room_for_dirent.
++
++2016-04-29 Florian Weimer <fweimer@redhat.com>
++
++ glob: Simplify and document the interface for the GLOB_ALTDIRFUNC
++ callback function gl_readdir.
++ * posix/glob.c (NAMELEN, CONVERT_D_NAMLEN): Remove.
++ (CONVERT_DIRENT_DIRENT64): Use strcpy instead of memcpy.
++ (glob_in_dir): Remove len. Use strdup instead of malloc and
++ memcpy to copy the name.
++ * manual/pattern.texi (Calling Glob): Document requirements for
++ implementations of the gl_readdir callback function.
++ * manual/examples/mkdirent.c: New example.
++ * posix/bug-glob2.c (my_readdir): Set d_ino to 1 unconditionally,
++ per the manual guidance.
++ * posix/tst-gnuglob.c (my_readdir): Likewise.
++
++2016-04-04 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19633]
++ Use specified locale for number formatting in strfmon_l.
++ * locale/localeinfo.h (__nl_lookup, _nl_lookup_wstr)
++ (__nl_lookup_word): New inline functions.
++ * include/printf.h (__print_fp_l): Declare.
++ * stdio-common/printf_fp.c (___printf_fp_l): Renamed from
++ ___printf_fp. Add locale argument. Replace _NL_CURRENT with
++ _nl_lookup and _NL_CURRENT_WORD with _nl_lookup_word.
++ (___printf_fp): New function.
++ * stdlib/strfmon_l.c (__printf_fp): Remove declaration.
++ (__vstrfmon_l): Call __printf_fp_l instead of printf_fp.
++ * stdlib/tst-strfmon_l.c (do_test): New test.
++ * stdlib/Makefile (tests): Add kt.
++ (LOCALES): Build additional locales.
++ (tst-strfmon_l.out): Require locales.
++
++2016-03-25 Florian Weimer <fweimer@redhat.com>
++
++ [BZ# 19860]
++ * sysdeps/x86_64/tst-audit10.c (avx512_enabled): Always return
++ zero if the compiler does not provide the AVX512F bit.
++
++2016-03-08 Roland McGrath <roland@hack.frob.com>
++
++ * sysdeps/x86_64/tst-audit10.c: #include <cpu-features.h>.
++ * sysdeps/x86_64/tst-audit10-aux.c: Move audit_test extern decl ...
++ (tst_audit10_aux) [__AVX512F__]: ... here.
++
++2016-03-07 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19269]
++ * sysdeps/x86_64/Makefile (tst-audit4): Depend on
++ tst-audit4-aux.o.
++ (tst-audit10): Depend on tst-audit10-aux.o.
++ (CFLAGS-tst-audit4-aux.c): Compile with AVX enabled.
++ (CFLAGS-tst-audit10-aux.c): Compile with AVX512 enabled.
++ * sysdeps/x86_64/tst-audit4.c (do_test): Call tst_audit4_aux
++ instead of inline AVX code.
++ * sysdeps/x86_64/tst-audit10.c (do_test): Call tst_audit10_aux
++ instead of inline AVX512 code.
++ * sysdeps/x86_64/tst-audit4-aux.c: New file
++ * sysdeps/x86_64/tst-audit10-aux.c: New file
++
++2016-04-27 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19825]
++ * resolv/res_send.c (send_vc): Remove early *resplen2
++ initialization. Set *resplen2 on socket error. Call
++ close_and_return_error for other errors.
++
++2016-03-25 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19868]
++ * resolv/nss_dns/dns-network.c (getanswer_r): Implement additional
++ DNS packet syntax checks (which were not needed before). Skip
++ over non-PTR records.
++
++2016-04-27 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19831]
++ * resolv/nss_dns/dns-host.c (rrtype_to_rdata_length): New
++ function.
++ (getanswer_r): Check RDATA length against RRTYPE and QTYPE.
++ (gaih_getanswer_slice): Check RDATA length against RRTYPE.
++
++2016-04-27 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19862]
++ * resolv/nss_dns/dns-host.c (AskedForGot): Remove.
++ (getanswer_r): Do not call syslog.
++ (gaih_getanswer_slice): Likewise.
++ * resolv/gethnamaddr.c (AskedForGot): Remove.
++ (getanswer): Do not call syslog.
++ (gethostbyaddr): Likewise.
++
++2016-04-27 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19830]
++ * resolv/nss_dns/dns-host.c (getanswer_r): Check RDATA length.
++ (gaih_getanswer_slice): Likewise.
++ * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Likewise.
++ Also check for availability of RR metadata.
++
++2016-04-11 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19865]
++ * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Restore
++ original buffer before retry.
++
++2016-04-14 Florian Weimer <fweimer@redhat.com>
++
++ * malloc/arena.c (__malloc_fork_lock_parent)
++ (__malloc_fork_unlock_parent, __malloc_fork_unlock_child): Add
++ internal_function attribute.
++
++2016-04-14 Florian Weimer <fweimer@redhat.com>
++
++ Remove malloc hooks from fork handler. They are no longer needed
++ because malloc runs right before fork, and no malloc calls from
++ other fork handlers are not possible anymore.
++ * malloc/malloc.c (malloc_atfork, free_atfork): Remove
++ declarations.
++ * malloc/arena.c (save_malloc_hook, save_free_hook, save_arena)
++ (ATFORK_ARENA_PTR, malloc_atfork, free_atfork)
++ (atfork_recursive_cntr): Remove.
++ (__malloc_fork_lock_parent): Do not override malloc hooks and
++ thread_arena.
++ (__malloc_fork_unlock_parent): Do not restore malloc hooks and
++ thread_arena.
++ (__malloc_fork_unlock_child): Do not restore malloc hooks. Use
++ thread_arena instead of save_arena.
++
++2016-04-14 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19431]
++ Run the malloc fork handler as late as possible to avoid deadlocks.
++ * malloc/malloc-internal.h: New file.
++ * malloc/malloc.c: Include it.
++ * malloc/arena.c (ATFORK_MEM): Remove.
++ (__malloc_fork_lock_parent): Rename from ptmalloc_lock_all.
++ Update comment.
++ (__malloc_fork_unlock_parent): Rename from ptmalloc_unlock_all.
++ (__malloc_fork_unlock_child): Rename from ptmalloc_unlock_all2.
++ Remove outdated comment.
++ (ptmalloc_init): Do not call thread_atfork. Remove
++ thread_atfork_static.
++ * malloc/tst-malloc-fork-deadlock.c: New file.
++ * Makefile (tests): Add tst-malloc-fork-deadlock.
++ (tst-malloc-fork-deadlock): Link against libpthread.
++ * manual/memory.texi (Aligned Memory Blocks): Update safety
++ annotation comments.
++ * sysdeps/nptl/fork.c (__libc_fork): Call
++ __malloc_fork_lock_parent, __malloc_fork_unlock_parent,
++ __malloc_fork_unlock_child.
++ * sysdeps/mach/hurd/fork.c (__fork): Likewise.
++
++2016-03-22 Samuel Thibault <samuel.thibault@ens-lyon.org>
++
++ * malloc/Makefile ($(objpfx)tst-malloc-backtrace,
++ $(objpfx)tst-malloc-thread-exit, $(objpfx)tst-malloc-thread-fail): Use
++ $(shared-thread-library) instead of hardcoding the path to libpthread.
++
++2016-02-19 Florian Weimer <fweimer@redhat.com>
++
++ * sysdeps/generic/malloc-machine.h: Assume mutex_init is always
++ available. Do not define NO_THREADS.
++ * malloc/malloc.c: Do not check NO_THREADS.
++ * malloc/arena.c: Likewise.
++
++2016-05-02 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #20031]
++ * hesiod/hesiod.c (get_txt_records): Return error if TXT record is
++ completely empty.
++
++2016-05-02 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19573]
++ * hesiod/Makefile (libnss_hesiod-routines): Remove hesiod-init.
++ * hesiod/nss_hesiod/hesiod-init.c: Remove file.
++ * hesiod/nss_hesiod/nss_hesiod.h: Likewise.
++ * hesiod/hesiod.h (__hesiod_res_get, __hesiod_res_set): Remove.
++ (hesiod_init, hesiod_end, hesiod_to_bind, hesiod_resolve)
++ (hesiod_free_list): Mark as hidden.
++ * hesiod/hesiod_p (struct hesiod_p): Remove res, free_res,
++ res_set, res_get.
++ * hesiod/hesiod.c: Remove unnecessary forward declarations.
++ (init, __hesiod_res_get, __hesiod_res_set): Remove.
++ (hesiod_init): Remove obsolete res_ninit call.
++ (hesiod_end): Do not free resolver state. Do not invoke callback.
++ (hesiod_bind): Do not call init.
++ (get_txt_records): Use res_mkquery, res_send instead of
++ res_nmkquery, res_nsend.
++ * hesiod/nss_hesiod/hesiod-grp.c (lookup): Call hesiod_init
++ instead of _nss_hesiod_init.
++ (_nss_hesiod_initgroups_dyn): Likewise.
++ * hesiod/nss_hesiod/hesiod-proto.c (lookup): Likewise.
++ * hesiod/nss_hesiod/hesiod-pwd.c (lookup): Likewise.
++ * hesiod/nss_hesiod/hesiod-service.c (lookup): Likewise.
++
++2016-05-02 Florian Weimer <fweimer@redhat.com>
++
++ * hesiod/hesiod.h: Remove RCS keyword.
++ * hesiod/hesiod_p.h: Likewise.
++ * hesiod/hesiod.c: Likewise.
++
++2016-05-04 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19787]
++ * inet/getnameinfo.c (check_sprintf_result): New function.
++ (CHECKED_SNPRINTF): New macro.
++ (gni_host_inet_numeric): Use CHECKED_SNPRINTF to write the scope
++ to the host buffer.
++ (gni_host_local): Use checked_copy to copy the host name.
++ (gni_serv_inet): Use CHECKED_SNPRINTF to write the service name.
++ (gni_serv_local): Use checked_copy to copy the service name.
++ (getnameinfo): Remove unnecessary truncation of result buffers.
++
++2016-05-04 Florian Weimer <fweimer@redhat.com>
++
++ * inet/getnameinfo.c (gni_host_inet_numeric): Return EAI_OVERFLOW
++ in case of inet_ntop failure.
++
++2016-05-04 Florian Weimer <fweimer@redhat.com>
++
++ * inet/getnameinfo.c (gni_host_inet_name): Use temporaries to
++ avoid long lines.
++ (gni_host_inet_numeric): Likewise. Reduce scope of local
++ variables.
++ (gni_host_inet, gni_host_local): Add comment.
++ (gni_host): Add comment. Use temporary to avoid long lines.
++
++2016-04-29 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19642]
++ * inet/getnameinfo.c (gni_host_inet_name, gni_host_inet_numeric)
++ (gni_host_inet, gni_host_local, gni_host, gni_serv_inet)
++ (gni_serv_local, gni_serv): New functions extracted from
++ getnameinfo.
++ (getnameinfo): Call gni_host and gni_serv to perform the
++ processing. Always free scratch buffer.
++
++2016-04-28 Florian Weimer <fweimer@redhat.com>
++
++ * inet/getnameinfo.c (getnameinfo): Do not preserve errno.
++
++2016-03-29 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19837]
++ * nss/nss_db/db-XXX.c (_nss_db_getENTNAME_r): Propagate ERANGE
++ error if parse_line fails.
++
++2016-04-20 Yvan Roux <yvan.roux@linaro.org>
++
++ * stdlib/setenv.c (unsetenv): Fix ambiguous 'else'.
++ * nis/nis_call.c (nis_server_cache_add): Likewise.
++
++2016-04-09 Mike Frysinger <vapier@gentoo.org>
++
++ * sysdeps/i386/configure.ac: Change == to = when calling test.
++ * sysdeps/x86_64/configure.ac: Likewise.
++ * sysdeps/i386/configure: Regenerated.
++ * sysdeps/x86_64/configure: Likewise.
++
++2016-04-01 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19879]
++ CVE-2016-3075
++ * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Do not
++ copy name.
++
++2016-04-01 Stefan Liebler <stli@linux.vnet.ibm.com>
++
++ * sysdeps/s390/bits/link.h: (La_s390_vr) New typedef.
++ (La_s390_32_regs): Append vector register lr_v24-lr_v31.
++ (La_s390_64_regs): Likewise.
++ (La_s390_32_retval): Append vector register lrv_v24.
++ (La_s390_64_retval): Likeweise.
++ * sysdeps/s390/s390-32/dl-trampoline.h (_dl_runtime_profile):
++ Handle extended structs La_s390_32_regs and La_s390_32_retval.
++ * sysdeps/s390/s390-64/dl-trampoline.h (_dl_runtime_profile):
++ Handle extended structs La_s390_64_regs and La_s390_64_retval.
++
++2016-04-01 Stefan Liebler <stli@linux.vnet.ibm.com>
++
++ * sysdeps/s390/s390-32/dl-trampoline.S: Include dl-trampoline.h twice
++ to create a non-vector/vector version for _dl_runtime_resolve and
++ _dl_runtime_profile. Move implementation to ...
++ * sysdeps/s390/s390-32/dl-trampoline.h: ... here.
++ (_dl_runtime_resolve) Save and restore fpr/vrs.
++ (_dl_runtime_profile) Save and restore vrs and fix some issues
++ if _dl_call_pltexit is called.
++ * sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
++ Choose the correct resolver function if running on a machine with vx.
++ * sysdeps/s390/s390-64/dl-trampoline.S: Include dl-trampoline.h twice
++ to create a non-vector/vector version for _dl_runtime_resolve and
++ _dl_runtime_profile. Move implementation to ...
++ * sysdeps/s390/s390-64/dl-trampoline.h: ... here.
++ (_dl_runtime_resolve) Save and restore fpr/vrs.
++ (_dl_runtime_profile) Save and restore vrs and fix some issues
++ * sysdeps/s390/s390-64/dl-machine.h: (elf_machine_runtime_setup):
++ Choose the correct resolver function if running on a machine with vx.
++
++2016-03-25 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19791]
++ * resolv/res_send.c (close_and_return_error): New function.
++ (send_dg): Initialize *resplen2 after reopen failure. Call
++ close_and_return_error for error returns. On error paths without
++ __res_iclose, initialze *resplen2 explicitly. Update comment for
++ successful return.
++
++2016-03-21 Dylan Alex Simon <dylan-sourceware@dylex.net>
++
++ [BZ #19822]
++ * math/Makefile ($(inst_libdir)/libm.so): Write output to $@.tmp and
++ move it to the final $@ location.
++
++2016-03-15 Andreas Schwab <schwab@suse.de>
++
++ [BZ #19257]
++ * resolv/res_init.c (__res_iclose): Use statp->nscount instead of
++ statp->_u._ext.nscount as loop count.
++
++2016-03-11 H.J. Lu <hongjiu.lu@intel.com>
++
++ [BZ #19758]
++ * sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
++ (EXTRA_LD_ENVVARS): Or bit_Prefer_MAP_32BIT_EXEC.
++
++2016-03-11 H.J. Lu <hongjiu.lu@intel.com>
++
++ [BZ #19759]
++ * sysdeps/x86/bits/string.h (_HAVE_STRING_ARCH_mempcpy): New.
++
++2016-03-10 H.J. Lu <hongjiu.lu@intel.com>
++
++ [BZ #19762]
++ * sysdeps/i386/i686/multiarch/bcopy.S (bcopy): Use
++ HAS_ARCH_FEATURE with Fast_Rep_String.
++ * sysdeps/i386/i686/multiarch/bzero.S (__bzero): Likewise.
++ * sysdeps/i386/i686/multiarch/memcpy.S (memcpy): Likewise.
++ * sysdeps/i386/i686/multiarch/memcpy_chk.S (__memcpy_chk):
++ Likewise.
++ * sysdeps/i386/i686/multiarch/memmove_chk.S (__memmove_chk):
++ Likewise.
++ * sysdeps/i386/i686/multiarch/mempcpy.S (__mempcpy): Likewise.
++ * sysdeps/i386/i686/multiarch/mempcpy_chk.S (__mempcpy_chk):
++ Likewise.
++ * sysdeps/i386/i686/multiarch/memset.S (memset): Likewise.
++ * sysdeps/i386/i686/multiarch/memset_chk.S (__memset_chk):
++ Likewise.
++
++2016-03-09 Aurelien Jarno <aurelien@aurel32.net>
++
++ [BZ #19792]
++ * sysdeps/unix/sysv/linux/mips/makecontext.S (__makecontext):
++ Terminate FDE before return label.
++
++2016-03-08 Aurelien Jarno <aurelien@aurel32.net>
++
++ * include/sys/auxv.h: New file.
++
++2016-03-07 Hongjiu Zhang <noctuorare@gmail.com>
++
++ * elf/sln.c (makesymlink): Change struct stat to stat64, and lstat
++ to lstat64.
++
++2016-02-24 Marko Myllynen <myllynen@redhat.com>
++
++ * NEWS (2.23): Fix typo in bug 19048 text.
++
++2016-02-24 Andreas Schwab <schwab@suse.de>
++
++ * math/test-math-isinff.cc (do_test): Only call isinfl and isnanl
++ if !NO_LONG_DOUBLE.
++
++2016-02-22 Roland McGrath <roland@hack.frob.com>
++
++ * sysdeps/arm/nacl/libc.abilist (GLIBC_2.23): Add GLIBC_2.23,
++ fts64_children, fts64_close, fts64_open, fts64_read and fts64_set.
++
++2016-02-22 H.J. Lu <hongjiu.lu@intel.com>
++
++ [BZ #19679]
++ * sysdeps/x86_64/dl-trampoline.S (DL_RUNIME_UNALIGNED_VEC_SIZE):
++ Renamed to ...
++ (DL_RUNTIME_UNALIGNED_VEC_SIZE): This. Set to 8.
++ (DL_RUNIME_RESOLVE_REALIGN_STACK): Renamed to ...
++ (DL_RUNTIME_RESOLVE_REALIGN_STACK): This. Updated.
++ (DL_RUNIME_RESOLVE_REALIGN_STACK): Renamed to ...
++ (DL_RUNTIME_RESOLVE_REALIGN_STACK): This.
++ * sysdeps/x86_64/dl-trampoline.h
++ (DL_RUNIME_RESOLVE_REALIGN_STACK): Renamed to ...
++ (DL_RUNTIME_RESOLVE_REALIGN_STACK): This.
++
2016-02-18 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+ * configure: Regenerated.
* version.h (RELEASE): Set to "stable".
(VERSION): Set to 2.23.
* include/feature.h (__GLIBC_MINOR__): Set to 23.
+diff --git a/NEWS b/NEWS
+index c0276cf..9c1c638 100644
+--- a/NEWS
++++ b/NEWS
+@@ -5,6 +5,33 @@ See the end for copying conditions.
+ Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
+ using `glibc' in the "product" field.
+ \f
++Version 2.23.1
++
++Security related changes:
++
++* The getnetbyname implementation in nss_dns had a potentially unbounded
++ alloca call (in the form of a call to strdupa), leading to a stack
++ overflow (stack exhaustion) and a crash if getnetbyname is invoked
++ on a very long name. (CVE-2016-3075)
++
++* The glob function suffered from a stack-based buffer overflow when it was
++ called with the GLOB_ALTDIRFUNC flag and encountered a long file name.
++ Reported by Alexander Cherepanov. (CVE-2016-1234)
++
++The following bugs are resolved with this release:
++
++ [19679] gcc-4.9.3 C++ exception handling broken due to unaligned stack
++ [19758] Or bit_Prefer_MAP_32BIT_EXEC in EXTRA_LD_ENVVARS
++ [19759] Don't inline mempcpy for x86
++ [19762] Use HAS_ARCH_FEATURE with Fast_Rep_String
++ [19791] Assertion failure in res_query.c with un-connectable name server
++ addresses
++ [19792] MIPS: backtrace yields infinite backtrace with makecontext
++ [19822] libm.so install clobbers old version
++ [19879] network: nss_dns: Stack overflow in getnetbyname implementation
++ (CVE-2016-3075)
++
++\f
+ Version 2.23
+
+ * Unicode 8.0.0 Support: Character encoding, character type info, and
+@@ -38,7 +65,7 @@ Version 2.23
+ unnecessary serialization of memory allocation requests across threads.
+ The defect is now corrected. Users should see a substantial increase in
+ the concurent throughput of allocation requests for applications which
+- trigger this bug. Affected applications typically create create and
++ trigger this bug. Affected applications typically create and
+ destroy threads frequently. (Bug 19048 was reported and analyzed by
+ Ericsson.)
+
diff --git a/configure b/configure
index 06ea87e..8fe5937 100755
--- a/configure
*** and join the community!" "$LINENO" 5
;;
esac
+diff --git a/elf/Makefile b/elf/Makefile
+index 63a5355..c3dc451 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -149,7 +149,7 @@ 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-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error
+ # reldep9
+ ifeq ($(build-hardcoded-path-in-tests),yes)
+ tests += tst-dlopen-aout
+@@ -163,7 +163,8 @@ endif
+ endif
+ ifeq ($(run-built-tests),yes)
+ tests-special += $(objpfx)tst-leaks1-mem.out \
+- $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out
++ $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
++ $(objpfx)tst-ldconfig-X.out
+ endif
+ tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+@@ -1252,3 +1253,9 @@ $(objpfx)tst-prelink-cmp.out: tst-prelink.exp \
+ $(objpfx)tst-prelink-conflict.out
+ cmp $^ > $@; \
+ $(evaluate-test)
++
++$(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
++ $(evaluate-test)
++
++$(objpfx)tst-dlsym-error: $(libdl)
+diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
+index f577759..6d299c1 100644
+--- a/elf/dl-lookup.c
++++ b/elf/dl-lookup.c
+@@ -858,7 +858,6 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
+ if (__glibc_unlikely (current_value.s == NULL))
+ {
+ if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
+- && skip_map == NULL
+ && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
+ {
+ /* We could find no value for a strong reference. */
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 9c6f2ba..467ca82 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -100,7 +100,8 @@ int opt_format = 1;
+ /* Build cache. */
+ static int opt_build_cache = 1;
+
+-/* Generate links. */
++/* Enable symbolic link processing. If set, create or update symbolic
++ links, and remove stale symbolic links. */
+ static int opt_link = 1;
+
+ /* Only process directories specified on the command line. */
+@@ -141,7 +142,7 @@ static const struct argp_option options[] =
+ { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
+ { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
+ { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
+- { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
++ { NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0},
+ { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
+ { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
+ { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
+@@ -800,7 +801,7 @@ search_dir (const struct dir_entry *entry)
+ error (0, errno, _("Cannot stat %s"), file_name);
+
+ /* Remove stale symlinks. */
+- if (strstr (direntry->d_name, ".so."))
++ if (opt_link && strstr (direntry->d_name, ".so."))
+ unlink (real_file_name);
+ continue;
+ }
+diff --git a/elf/sln.c b/elf/sln.c
+index 9d57be2..f52cb9f 100644
+--- a/elf/sln.c
++++ b/elf/sln.c
+@@ -164,11 +164,11 @@ makesymlinks (const char *file)
+ static int
+ makesymlink (const char *src, const char *dest)
+ {
+- struct stat stats;
++ struct stat64 stats;
+ const char *error;
+
+ /* Destination must not be a directory. */
+- if (lstat (dest, &stats) == 0)
++ if (lstat64 (dest, &stats) == 0)
+ {
+ if (S_ISDIR (stats.st_mode))
+ {
+diff --git a/elf/tst-dlsym-error.c b/elf/tst-dlsym-error.c
+new file mode 100644
+index 0000000..fb084c5
+--- /dev/null
++++ b/elf/tst-dlsym-error.c
+@@ -0,0 +1,114 @@
++/* Test error reporting for dlsym, dlvsym failures.
++ 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 <dlfcn.h>
++#include <gnu/lib-names.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++/* Used to disambiguate symbol names. */
++static int counter;
++
++static void
++test_one (void *handle, const char *name, void *(func) (void *, const char *),
++ const char *suffix)
++{
++ ++counter;
++ char symbol[32];
++ snprintf (symbol, sizeof (symbol), "no_such_symbol_%d", counter);
++ char *expected_message;
++ if (asprintf (&expected_message, ": undefined symbol: %s%s",
++ symbol, suffix) < 0)
++ {
++ printf ("error: asprintf: %m\n");
++ abort ();
++ }
++
++ void *addr = func (handle, symbol);
++ if (addr != NULL)
++ {
++ printf ("error: %s: found symbol \"no_such_symbol\"\n", name);
++ abort ();
++ }
++ const char *message = dlerror ();
++ if (message == NULL)
++ {
++ printf ("error: %s: missing error message\n", name);
++ abort ();
++ }
++ const char *message_without_path = strchrnul (message, ':');
++ if (strcmp (message_without_path, expected_message) != 0)
++ {
++ printf ("error: %s: unexpected error message: %s\n", name, message);
++ abort ();
++ }
++ free (expected_message);
++
++ message = dlerror ();
++ if (message != NULL)
++ {
++ printf ("error: %s: unexpected error message: %s\n", name, message);
++ abort ();
++ }
++}
++
++static void
++test_handles (const char *name, void *(func) (void *, const char *),
++ const char *suffix)
++{
++ test_one (RTLD_DEFAULT, name, func, suffix);
++ test_one (RTLD_NEXT, name, func, suffix);
++
++ void *handle = dlopen (LIBC_SO, RTLD_LAZY);
++ if (handle == NULL)
++ {
++ printf ("error: cannot dlopen %s: %s\n", LIBC_SO, dlerror ());
++ abort ();
++ }
++ test_one (handle, name, func, suffix);
++ dlclose (handle);
++}
++
++static void *
++dlvsym_no_such_version (void *handle, const char *name)
++{
++ return dlvsym (handle, name, "NO_SUCH_VERSION");
++}
++
++static void *
++dlvsym_glibc_private (void *handle, const char *name)
++{
++ return dlvsym (handle, name, "GLIBC_PRIVATE");
++}
++
++static int
++do_test (void)
++{
++ test_handles ("dlsym", dlsym, "");
++ test_handles ("dlvsym", dlvsym_no_such_version,
++ ", version NO_SUCH_VERSION");
++ test_handles ("dlvsym", dlvsym_glibc_private,
++ ", version GLIBC_PRIVATE");
++
++ return 0;
++}
++
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+diff --git a/elf/tst-ldconfig-X.sh b/elf/tst-ldconfig-X.sh
+new file mode 100644
+index 0000000..0c122a5
+--- /dev/null
++++ b/elf/tst-ldconfig-X.sh
+@@ -0,0 +1,62 @@
++#!/bin/sh
++# Test that ldconfig -X does not remove stale symbolic links.
++# Copyright (C) 2000-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/>.
++
++set -ex
++
++common_objpfx=$1
++test_wrapper_env=$2
++run_program_env=$3
++
++testroot="${common_objpfx}elf/bug19610-test-directory"
++cleanup () {
++ rm -rf "$testroot"
++}
++trap cleanup 0
++
++rm -rf "$testroot"
++mkdir -p $testroot/lib $testroot/etc
++
++# Relative symbolic link target.
++ln -s libdoesnotexist.so.1.1 $testroot/lib/libdoesnotexist.so.1
++
++# Absolute symbolic link target.
++ln -s $testroot/opt/sw/lib/libdoesnotexist2.so.1.1 $testroot/lib/
++
++errors=0
++check_files () {
++ for name in libdoesnotexist.so.1 libdoesnotexist2.so.1.1 ; do
++ path="$testroot/lib/$name"
++ if test ! -h $path ; then
++ echo "error: missing file: $path"
++ errors=1
++ fi
++ done
++}
++
++check_files
++
++${test_wrapper_env} \
++${run_program_env} \
++${common_objpfx}elf/ldconfig -X -f /dev/null \
++ -C $testroot/etc/ld.so.cache \
++ $testroot/lib
++
++check_files
++
++exit $errors
+diff --git a/hesiod/Makefile b/hesiod/Makefile
+index d68a859..2d1966c 100644
+--- a/hesiod/Makefile
++++ b/hesiod/Makefile
+@@ -28,7 +28,7 @@ extra-libs-others = $(extra-libs)
+ subdir-dirs = nss_hesiod
+ vpath %.c nss_hesiod
+
+-libnss_hesiod-routines := hesiod hesiod-grp hesiod-init hesiod-proto \
++libnss_hesiod-routines := hesiod hesiod-grp hesiod-proto \
+ hesiod-pwd hesiod-service
+ # Build only shared library
+ libnss_hesiod-inhibit-o = $(filter-out .os,$(object-suffixes))
+diff --git a/hesiod/hesiod.c b/hesiod/hesiod.c
+index 657dabe..98ddee3 100644
+--- a/hesiod/hesiod.c
++++ b/hesiod/hesiod.c
+@@ -1,6 +1,19 @@
+-#if defined(LIBC_SCCS) && !defined(lint)
+-static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie Exp $";
+-#endif
++/* Copyright (C) 1997-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/>. */
+
+ /*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+@@ -52,18 +65,9 @@ static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie
+
+ /* Forward */
+
+-int hesiod_init(void **context);
+-void hesiod_end(void *context);
+-char * hesiod_to_bind(void *context, const char *name,
+- const char *type);
+-char ** hesiod_resolve(void *context, const char *name,
+- const char *type);
+-void hesiod_free_list(void *context, char **list);
+-
+ static int parse_config_file(struct hesiod_p *ctx, const char *filename);
+ static char ** get_txt_records(struct hesiod_p *ctx, int class,
+ const char *name);
+-static int init(struct hesiod_p *ctx);
+
+ /* Public */
+
+@@ -82,7 +86,6 @@ hesiod_init(void **context) {
+
+ ctx->LHS = NULL;
+ ctx->RHS = NULL;
+- ctx->res = NULL;
+ /* Set default query classes. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
+@@ -131,11 +134,6 @@ hesiod_init(void **context) {
+ goto cleanup;
+ }
+
+-#if 0
+- if (res_ninit(ctx->res) < 0)
+- goto cleanup;
+-#endif
+-
+ *context = ctx;
+ return (0);
+
+@@ -152,12 +150,8 @@ hesiod_end(void *context) {
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+ int save_errno = errno;
+
+- if (ctx->res)
+- res_nclose(ctx->res);
+ free(ctx->RHS);
+ free(ctx->LHS);
+- if (ctx->res && ctx->free_res)
+- (*ctx->free_res)(ctx->res);
+ free(ctx);
+ __set_errno(save_errno);
+ }
+@@ -232,10 +226,6 @@ hesiod_resolve(void *context, const char *name, const char *type) {
+
+ if (bindname == NULL)
+ return (NULL);
+- if (init(ctx) == -1) {
+- free(bindname);
+- return (NULL);
+- }
+
+ retvec = get_txt_records(ctx, ctx->classes[0], bindname);
+
+@@ -365,13 +355,13 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
+ /*
+ * Construct the query and send it.
+ */
+- n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0,
++ n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0,
+ NULL, qbuf, MAX_HESRESP);
+ if (n < 0) {
+ __set_errno(EMSGSIZE);
+ return (NULL);
+ }
+- n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
++ n = res_send(qbuf, n, abuf, MAX_HESRESP);
+ if (n < 0) {
+ __set_errno(ECONNREFUSED);
+ return (NULL);
+@@ -421,7 +411,7 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
+ cp += INT16SZ + INT32SZ; /* skip the ttl, too */
+ rr.dlen = ns_get16(cp);
+ cp += INT16SZ;
+- if (cp + rr.dlen > eom) {
++ if (rr.dlen == 0 || cp + rr.dlen > eom) {
+ __set_errno(EMSGSIZE);
+ goto cleanup;
+ }
+@@ -464,44 +454,3 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
+ free(list);
+ return (NULL);
+ }
+-
+-struct __res_state *
+-__hesiod_res_get(void *context) {
+- struct hesiod_p *ctx = context;
+-
+- if (!ctx->res) {
+- struct __res_state *res;
+- res = (struct __res_state *)calloc(1, sizeof *res);
+- if (res == NULL)
+- return (NULL);
+- __hesiod_res_set(ctx, res, free);
+- }
+-
+- return (ctx->res);
+-}
+-
+-void
+-__hesiod_res_set(void *context, struct __res_state *res,
+- void (*free_res)(void *)) {
+- struct hesiod_p *ctx = context;
+-
+- if (ctx->res && ctx->free_res) {
+- res_nclose(ctx->res);
+- (*ctx->free_res)(ctx->res);
+- }
+-
+- ctx->res = res;
+- ctx->free_res = free_res;
+-}
+-
+-static int
+-init(struct hesiod_p *ctx) {
+-
+- if (!ctx->res && !__hesiod_res_get(ctx))
+- return (-1);
+-
+- if (__res_maybe_init (ctx->res, 0) == -1)
+- return (-1);
+-
+- return (0);
+-}
+diff --git a/hesiod/hesiod.h b/hesiod/hesiod.h
+index 82fce30..c4f5356 100644
+--- a/hesiod/hesiod.h
++++ b/hesiod/hesiod.h
+@@ -1,3 +1,20 @@
++/* Copyright (C) 1997-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/>. */
++
+ /*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+@@ -19,22 +36,15 @@
+ * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
+ */
+
+-/*
+- * $BINDId: hesiod.h,v 1.7 1999/01/08 19:22:45 vixie Exp $
+- */
+-
+ #ifndef _HESIOD_H_INCLUDED
+ #define _HESIOD_H_INCLUDED
+
+-int hesiod_init (void **context);
+-void hesiod_end (void *context);
++int hesiod_init (void **context) attribute_hidden;
++void hesiod_end (void *context) attribute_hidden;
+ char * hesiod_to_bind (void *context, const char *name,
+- const char *type);
++ const char *type) attribute_hidden;
+ char ** hesiod_resolve (void *context, const char *name,
+- const char *type);
+-void hesiod_free_list (void *context, char **list);
+-struct __res_state * __hesiod_res_get (void *context);
+-void __hesiod_res_set (void *context, struct __res_state *,
+- void (*)(void *));
++ const char *type) attribute_hidden;
++void hesiod_free_list (void *context, char **list) attribute_hidden;
+
+ #endif /*_HESIOD_H_INCLUDED*/
+diff --git a/hesiod/hesiod_p.h b/hesiod/hesiod_p.h
+index 5010d71..1d6d826 100644
+--- a/hesiod/hesiod_p.h
++++ b/hesiod/hesiod_p.h
+@@ -1,3 +1,20 @@
++/* Copyright (C) 1997-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/>. */
++
+ /*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+@@ -20,10 +37,6 @@
+ */
+
+ /*
+- * $BINDId: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $
+- */
+-
+-/*
+ * hesiod_p.h -- private definitions for the hesiod library
+ */
+
+@@ -36,11 +49,6 @@
+ struct hesiod_p {
+ char * LHS; /* normally ".ns" */
+ char * RHS; /* AKA the default hesiod domain */
+- struct __res_state * res; /* resolver context */
+- void (*free_res)(void *);
+- void (*res_set)(struct hesiod_p *, struct __res_state *,
+- void (*)(void *));
+- struct __res_state * (*res_get)(struct hesiod_p *);
+ int classes[2]; /* The class search order. */
+ };
+
+diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c
+index 7e4ecb4..944e5e0 100644
+--- a/hesiod/nss_hesiod/hesiod-grp.c
++++ b/hesiod/nss_hesiod/hesiod-grp.c
+@@ -26,8 +26,6 @@
+ #include <string.h>
+ #include <sys/param.h>
+
+-#include "nss_hesiod.h"
+-
+ /* Get the declaration of the parser function. */
+ #define ENTNAME grent
+ #define STRUCTURE group
+@@ -58,8 +56,7 @@ lookup (const char *name, const char *type, struct group *grp,
+ size_t len;
+ int olderr = errno;
+
+- context = _nss_hesiod_init ();
+- if (context == NULL)
++ if (hesiod_init (&context) < 0)
+ return NSS_STATUS_UNAVAIL;
+
+ list = hesiod_resolve (context, name, type);
+@@ -179,8 +176,7 @@ _nss_hesiod_initgroups_dyn (const char *user, gid_t group, long int *start,
+ gid_t *groups = *groupsp;
+ int save_errno;
+
+- context = _nss_hesiod_init ();
+- if (context == NULL)
++ if (hesiod_init (&context) < 0)
+ return NSS_STATUS_UNAVAIL;
+
+ list = hesiod_resolve (context, user, "grplist");
+diff --git a/hesiod/nss_hesiod/hesiod-init.c b/hesiod/nss_hesiod/hesiod-init.c
+deleted file mode 100644
+index 2315040..0000000
+--- a/hesiod/nss_hesiod/hesiod-init.c
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+- Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 2000.
+-
+- 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 <sys/cdefs.h> /* Needs to come before <hesiod.h>. */
+-#include <hesiod.h>
+-#include <resolv.h>
+-#include <stddef.h>
+-
+-#include "nss_hesiod.h"
+-
+-void *
+-_nss_hesiod_init (void)
+-{
+- void *context;
+-
+- if (hesiod_init (&context) == -1)
+- return NULL;
+-
+- /* Use the default (per-thread) resolver state. */
+- __hesiod_res_set (context, &_res, NULL);
+-
+- return context;
+-}
+diff --git a/hesiod/nss_hesiod/hesiod-proto.c b/hesiod/nss_hesiod/hesiod-proto.c
+index 3c59e73..8a13bba 100644
+--- a/hesiod/nss_hesiod/hesiod-proto.c
++++ b/hesiod/nss_hesiod/hesiod-proto.c
+@@ -25,8 +25,6 @@
+ #include <stdlib.h>
+ #include <string.h>
+
+-#include "nss_hesiod.h"
+-
+ /* Declare a parser for Hesiod protocol entries. Although the format
+ of the entries is identical to those in /etc/protocols, here is no
+ predefined parser for us to use. */
+@@ -68,8 +66,7 @@ lookup (const char *name, const char *type, struct protoent *proto,
+ int found;
+ int olderr = errno;
+
+- context = _nss_hesiod_init ();
+- if (context == NULL)
++ if (hesiod_init (&context) < 0)
+ return NSS_STATUS_UNAVAIL;
+
+ list = hesiod_resolve (context, name, type);
+diff --git a/hesiod/nss_hesiod/hesiod-pwd.c b/hesiod/nss_hesiod/hesiod-pwd.c
+index 1ddf3e3..c119167 100644
+--- a/hesiod/nss_hesiod/hesiod-pwd.c
++++ b/hesiod/nss_hesiod/hesiod-pwd.c
+@@ -24,8 +24,6 @@
+ #include <stdlib.h>
+ #include <string.h>
+
+-#include "nss_hesiod.h"
+-
+ /* Get the declaration of the parser function. */
+ #define ENTNAME pwent
+ #define STRUCTURE passwd
+@@ -56,8 +54,7 @@ lookup (const char *name, const char *type, struct passwd *pwd,
+ size_t len;
+ int olderr = errno;
+
+- context = _nss_hesiod_init ();
+- if (context == NULL)
++ if (hesiod_init (&context) < 0)
+ return NSS_STATUS_UNAVAIL;
+
+ list = hesiod_resolve (context, name, type);
+diff --git a/hesiod/nss_hesiod/hesiod-service.c b/hesiod/nss_hesiod/hesiod-service.c
+index 756345f..2df9cbb 100644
+--- a/hesiod/nss_hesiod/hesiod-service.c
++++ b/hesiod/nss_hesiod/hesiod-service.c
+@@ -25,8 +25,6 @@
+ #include <stdlib.h>
+ #include <string.h>
+
+-#include "nss_hesiod.h"
+-
+ /* Hesiod uses a format for service entries that differs from the
+ traditional format. We therefore declare our own parser. */
+
+@@ -69,8 +67,7 @@ lookup (const char *name, const char *type, const char *protocol,
+ int found;
+ int olderr = errno;
+
+- context = _nss_hesiod_init ();
+- if (context == NULL)
++ if (hesiod_init (&context) < 0)
+ return NSS_STATUS_UNAVAIL;
+
+ list = hesiod_resolve (context, name, type);
+diff --git a/hesiod/nss_hesiod/nss_hesiod.h b/hesiod/nss_hesiod/nss_hesiod.h
+deleted file mode 100644
+index a6ed8ee..0000000
+--- a/hesiod/nss_hesiod/nss_hesiod.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+- Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 2000.
+-
+- 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/>. */
+-
+-/* Initialize a Hesiod context. */
+-extern void *_nss_hesiod_init (void);
+diff --git a/include/printf.h b/include/printf.h
+index c0bd2d2..b12b5dc 100644
+--- a/include/printf.h
++++ b/include/printf.h
+@@ -1,6 +1,7 @@
+ #ifndef _PRINTF_H
+
+ #include <stdio-common/printf.h>
++#include <xlocale.h>
+
+ /* Now define the internal interfaces. */
+ extern int __printf_fphex (FILE *, const struct printf_info *,
+@@ -8,5 +9,8 @@ extern int __printf_fphex (FILE *, const struct printf_info *,
+ extern int __printf_fp (FILE *, const struct printf_info *,
+ const void *const *);
+ libc_hidden_proto (__printf_fp)
++extern int __printf_fp_l (FILE *, locale_t, const struct printf_info *,
++ const void *const *);
++libc_hidden_proto (__printf_fp_l)
+
+ #endif
+diff --git a/include/sys/auxv.h b/include/sys/auxv.h
+new file mode 100644
+index 0000000..dede2c3
+--- /dev/null
++++ b/include/sys/auxv.h
+@@ -0,0 +1 @@
++#include <misc/sys/auxv.h>
+diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
+index 40f67f0..283da55 100644
+--- a/inet/getnameinfo.c
++++ b/inet/getnameinfo.c
+@@ -1,3 +1,21 @@
++/* Convert socket address to string using Name Service Switch modules.
++ Copyright (C) 1997-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/>. */
++
+ /* The Inner Net License, Version 2.00
+
+ The author(s) grant permission for redistribution and use in source and
+@@ -169,20 +187,322 @@ nrl_domainname (void)
+ return domain;
+ };
+
++/* Copy a string to a destination buffer with length checking. Return
++ EAI_OVERFLOW if the buffer is not large enough, and 0 on
++ success. */
++static int
++checked_copy (char *dest, size_t destlen, const char *source)
++{
++ size_t source_length = strlen (source);
++ if (source_length + 1 > destlen)
++ return EAI_OVERFLOW;
++ memcpy (dest, source, source_length + 1);
++ return 0;
++}
+
+-int
+-getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
+- socklen_t hostlen, char *serv, socklen_t servlen,
+- int flags)
++/* Helper function for CHECKED_SNPRINTF below. */
++static int
++check_sprintf_result (int result, size_t destlen)
++{
++ if (result < 0)
++ return EAI_SYSTEM;
++ if ((size_t) result >= destlen)
++ /* If ret == destlen, there was no room for the terminating NUL
++ character. */
++ return EAI_OVERFLOW;
++ return 0;
++}
++
++/* Format a string in the destination buffer. Return 0 on success,
++ EAI_OVERFLOW in case the buffer is too small, or EAI_SYSTEM on any
++ other error. */
++#define CHECKED_SNPRINTF(dest, destlen, format, ...) \
++ check_sprintf_result \
++ (__snprintf (dest, destlen, format, __VA_ARGS__), destlen)
++
++/* Convert host name, AF_INET/AF_INET6 case, name only. */
++static int
++gni_host_inet_name (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *host, socklen_t hostlen, int flags)
+ {
+- int serrno = errno;
+ int herrno;
+ struct hostent th;
+- int ok = 0;
+- struct scratch_buffer tmpbuf;
++ struct hostent *h = NULL;
++ if (sa->sa_family == AF_INET6)
++ {
++ const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
++ while (__gethostbyaddr_r (&sin6p->sin6_addr, sizeof(struct in6_addr),
++ AF_INET6, &th, tmpbuf->data, tmpbuf->length,
++ &h, &herrno))
++ if (herrno == NETDB_INTERNAL && errno == ERANGE)
++ {
++ if (!scratch_buffer_grow (tmpbuf))
++ {
++ __set_h_errno (herrno);
++ return EAI_MEMORY;
++ }
++ }
++ else
++ break;
++ }
++ else
++ {
++ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
++ while (__gethostbyaddr_r (&sinp->sin_addr, sizeof(struct in_addr),
++ AF_INET, &th, tmpbuf->data, tmpbuf->length,
++ &h, &herrno))
++ if (herrno == NETDB_INTERNAL && errno == ERANGE)
++ {
++ if (!scratch_buffer_grow (tmpbuf))
++ {
++ __set_h_errno (herrno);
++ return EAI_MEMORY;
++ }
++ }
++ else
++ break;
++ }
+
+- scratch_buffer_init (&tmpbuf);
++ if (h == NULL)
++ {
++ if (herrno == NETDB_INTERNAL)
++ {
++ __set_h_errno (herrno);
++ return EAI_SYSTEM;
++ }
++ if (herrno == TRY_AGAIN)
++ {
++ __set_h_errno (herrno);
++ return EAI_AGAIN;
++ }
++ }
++
++ if (h)
++ {
++ char *c;
++ if ((flags & NI_NOFQDN)
++ && (c = nrl_domainname ())
++ && (c = strstr (h->h_name, c))
++ && (c != h->h_name) && (*(--c) == '.'))
++ /* Terminate the string after the prefix. */
++ *c = '\0';
++
++#ifdef HAVE_LIBIDN
++ /* If requested, convert from the IDN format. */
++ if (flags & NI_IDN)
++ {
++ int idn_flags = 0;
++ if (flags & NI_IDN_ALLOW_UNASSIGNED)
++ idn_flags |= IDNA_ALLOW_UNASSIGNED;
++ if (flags & NI_IDN_USE_STD3_ASCII_RULES)
++ idn_flags |= IDNA_USE_STD3_ASCII_RULES;
++
++ char *out;
++ int rc = __idna_to_unicode_lzlz (h->h_name, &out,
++ idn_flags);
++ if (rc != IDNA_SUCCESS)
++ {
++ if (rc == IDNA_MALLOC_ERROR)
++ return EAI_MEMORY;
++ if (rc == IDNA_DLOPEN_ERROR)
++ return EAI_SYSTEM;
++ return EAI_IDN_ENCODE;
++ }
++
++ if (out != h->h_name)
++ {
++ h->h_name = strdupa (out);
++ free (out);
++ }
++ }
++#endif
++
++ size_t len = strlen (h->h_name) + 1;
++ if (len > hostlen)
++ return EAI_OVERFLOW;
+
++ memcpy (host, h->h_name, len);
++
++ return 0;
++ }
++
++ return EAI_NONAME;
++}
++
++/* Convert host name, AF_INET/AF_INET6 case, numeric conversion. */
++static int
++gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *host, socklen_t hostlen, int flags)
++{
++ if (sa->sa_family == AF_INET6)
++ {
++ const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
++ if (inet_ntop (AF_INET6, &sin6p->sin6_addr, host, hostlen) == NULL)
++ return EAI_OVERFLOW;
++
++ uint32_t scopeid = sin6p->sin6_scope_id;
++ if (scopeid != 0)
++ {
++ size_t used_hostlen = __strnlen (host, hostlen);
++ /* Location of the scope string in the host buffer. */
++ char *scope_start = host + used_hostlen;
++ size_t scope_length = hostlen - used_hostlen;
++
++ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
++ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
++ {
++ char scopebuf[IFNAMSIZ];
++ if (if_indextoname (scopeid, scopebuf) != NULL)
++ return CHECKED_SNPRINTF
++ (scope_start, scope_length,
++ "%c%s", SCOPE_DELIMITER, scopebuf);
++ }
++ return CHECKED_SNPRINTF
++ (scope_start, scope_length, "%c%u", SCOPE_DELIMITER, scopeid);
++ }
++ }
++ else
++ {
++ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
++ if (inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen) == NULL)
++ return EAI_OVERFLOW;
++ }
++ return 0;
++}
++
++/* Convert AF_INET or AF_INET6 socket address, host part. */
++static int
++gni_host_inet (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *host, socklen_t hostlen, int flags)
++{
++ if (!(flags & NI_NUMERICHOST))
++ {
++ int result = gni_host_inet_name
++ (tmpbuf, sa, addrlen, host, hostlen, flags);
++ if (result != EAI_NONAME)
++ return result;
++ }
++
++ if (flags & NI_NAMEREQD)
++ return EAI_NONAME;
++ else
++ return gni_host_inet_numeric
++ (tmpbuf, sa, addrlen, host, hostlen, flags);
++}
++
++/* Convert AF_LOCAL socket address, host part. */
++static int
++gni_host_local (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *host, socklen_t hostlen, int flags)
++{
++ if (!(flags & NI_NUMERICHOST))
++ {
++ struct utsname utsname;
++ if (uname (&utsname) == 0)
++ return checked_copy (host, hostlen, utsname.nodename);
++ }
++
++ if (flags & NI_NAMEREQD)
++ return EAI_NONAME;
++
++ return checked_copy (host, hostlen, "localhost");
++}
++
++/* Convert the host part of an AF_LOCAK socket address. */
++static int
++gni_host (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *host, socklen_t hostlen, int flags)
++{
++ switch (sa->sa_family)
++ {
++ case AF_INET:
++ case AF_INET6:
++ return gni_host_inet (tmpbuf, sa, addrlen, host, hostlen, flags);
++
++ case AF_LOCAL:
++ return gni_host_local (tmpbuf, sa, addrlen, host, hostlen, flags);
++
++ default:
++ return EAI_FAMILY;
++ }
++}
++
++/* Convert service to string, AF_INET and AF_INET6 variant. */
++static int
++gni_serv_inet (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *serv, socklen_t servlen, int flags)
++{
++ _Static_assert
++ (offsetof (struct sockaddr_in, sin_port)
++ == offsetof (struct sockaddr_in6, sin6_port)
++ && sizeof (((struct sockaddr_in) {}).sin_port) == sizeof (in_port_t)
++ && sizeof (((struct sockaddr_in6) {}).sin6_port) == sizeof (in_port_t),
++ "AF_INET and AF_INET6 port consistency");
++ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
++ if (!(flags & NI_NUMERICSERV))
++ {
++ struct servent *s, ts;
++ int e;
++ while ((e = __getservbyport_r (sinp->sin_port,
++ ((flags & NI_DGRAM)
++ ? "udp" : "tcp"), &ts,
++ tmpbuf->data, tmpbuf->length, &s)))
++ {
++ if (e == ERANGE)
++ {
++ if (!scratch_buffer_grow (tmpbuf))
++ return EAI_MEMORY;
++ }
++ else
++ break;
++ }
++ if (s)
++ return checked_copy (serv, servlen, s->s_name);
++ /* Fall through to numeric conversion. */
++ }
++ return CHECKED_SNPRINTF (serv, servlen, "%d", ntohs (sinp->sin_port));
++}
++
++/* Convert service to string, AF_LOCAL variant. */
++static int
++gni_serv_local (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *serv, socklen_t servlen, int flags)
++{
++ return checked_copy
++ (serv, servlen, ((const struct sockaddr_un *) sa)->sun_path);
++}
++
++/* Convert service to string, dispatching to the implementations
++ above. */
++static int
++gni_serv (struct scratch_buffer *tmpbuf,
++ const struct sockaddr *sa, socklen_t addrlen,
++ char *serv, socklen_t servlen, int flags)
++{
++ switch (sa->sa_family)
++ {
++ case AF_INET:
++ case AF_INET6:
++ return gni_serv_inet (tmpbuf, sa, addrlen, serv, servlen, flags);
++ case AF_LOCAL:
++ return gni_serv_local (tmpbuf, sa, addrlen, serv, servlen, flags);
++ default:
++ return EAI_FAMILY;
++ }
++}
++
++int
++getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
++ socklen_t hostlen, char *serv, socklen_t servlen,
++ int flags)
++{
+ if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
+ #ifdef HAVE_LIBIDN
+ |NI_IDN|NI_IDN_ALLOW_UNASSIGNED|NI_IDN_USE_STD3_ASCII_RULES
+@@ -214,256 +534,30 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
+ return EAI_FAMILY;
+ }
+
+- if (host != NULL && hostlen > 0)
+- switch (sa->sa_family)
+- {
+- case AF_INET:
+- case AF_INET6:
+- if (!(flags & NI_NUMERICHOST))
+- {
+- struct hostent *h = NULL;
+- if (sa->sa_family == AF_INET6)
+- {
+- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
+- sizeof(struct in6_addr),
+- AF_INET6, &th,
+- tmpbuf.data, tmpbuf.length,
+- &h, &herrno))
+- if (herrno == NETDB_INTERNAL && errno == ERANGE)
+- {
+- if (!scratch_buffer_grow (&tmpbuf))
+- {
+- __set_h_errno (herrno);
+- return EAI_MEMORY;
+- }
+- }
+- else
+- break;
+- }
+- else
+- {
+- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
+- sizeof(struct in_addr),
+- AF_INET, &th,
+- tmpbuf.data, tmpbuf.length,
+- &h, &herrno))
+- if (herrno == NETDB_INTERNAL && errno == ERANGE)
+- {
+- if (!scratch_buffer_grow (&tmpbuf))
+- {
+- __set_h_errno (herrno);
+- return EAI_MEMORY;
+- }
+- }
+- else
+- break;
+- }
+-
+- if (h == NULL)
+- {
+- if (herrno == NETDB_INTERNAL)
+- {
+- __set_h_errno (herrno);
+- return EAI_SYSTEM;
+- }
+- if (herrno == TRY_AGAIN)
+- {
+- __set_h_errno (herrno);
+- return EAI_AGAIN;
+- }
+- }
+-
+- if (h)
+- {
+- char *c;
+- if ((flags & NI_NOFQDN)
+- && (c = nrl_domainname ())
+- && (c = strstr (h->h_name, c))
+- && (c != h->h_name) && (*(--c) == '.'))
+- /* Terminate the string after the prefix. */
+- *c = '\0';
+-
+-#ifdef HAVE_LIBIDN
+- /* If requested, convert from the IDN format. */
+- if (flags & NI_IDN)
+- {
+- int idn_flags = 0;
+- if (flags & NI_IDN_ALLOW_UNASSIGNED)
+- idn_flags |= IDNA_ALLOW_UNASSIGNED;
+- if (flags & NI_IDN_USE_STD3_ASCII_RULES)
+- idn_flags |= IDNA_USE_STD3_ASCII_RULES;
+-
+- char *out;
+- int rc = __idna_to_unicode_lzlz (h->h_name, &out,
+- idn_flags);
+- if (rc != IDNA_SUCCESS)
+- {
+- if (rc == IDNA_MALLOC_ERROR)
+- return EAI_MEMORY;
+- if (rc == IDNA_DLOPEN_ERROR)
+- return EAI_SYSTEM;
+- return EAI_IDN_ENCODE;
+- }
+-
+- if (out != h->h_name)
+- {
+- h->h_name = strdupa (out);
+- free (out);
+- }
+- }
+-#endif
+-
+- size_t len = strlen (h->h_name) + 1;
+- if (len > hostlen)
+- return EAI_OVERFLOW;
+-
+- memcpy (host, h->h_name, len);
+-
+- ok = 1;
+- }
+- }
+-
+- if (!ok)
+- {
+- if (flags & NI_NAMEREQD)
+- {
+- __set_errno (serrno);
+- return EAI_NONAME;
+- }
+- else
+- {
+- const char *c;
+- if (sa->sa_family == AF_INET6)
+- {
+- const struct sockaddr_in6 *sin6p;
+- uint32_t scopeid;
+-
+- sin6p = (const struct sockaddr_in6 *) sa;
+-
+- c = inet_ntop (AF_INET6,
+- (const void *) &sin6p->sin6_addr, host, hostlen);
+- scopeid = sin6p->sin6_scope_id;
+- if (scopeid != 0)
+- {
+- /* Buffer is >= IFNAMSIZ+1. */
+- char scopebuf[IFNAMSIZ + 1];
+- char *scopeptr;
+- int ni_numericscope = 0;
+- size_t real_hostlen = __strnlen (host, hostlen);
+- size_t scopelen = 0;
+-
+- scopebuf[0] = SCOPE_DELIMITER;
+- scopebuf[1] = '\0';
+- scopeptr = &scopebuf[1];
+-
+- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
+- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
+- {
+- if (if_indextoname (scopeid, scopeptr) == NULL)
+- ++ni_numericscope;
+- else
+- scopelen = strlen (scopebuf);
+- }
+- else
+- ++ni_numericscope;
+-
+- if (ni_numericscope)
+- scopelen = 1 + __snprintf (scopeptr,
+- (scopebuf
+- + sizeof scopebuf
+- - scopeptr),
+- "%u", scopeid);
+-
+- if (real_hostlen + scopelen + 1 > hostlen)
+- /* Signal the buffer is too small. This is
+- what inet_ntop does. */
+- c = NULL;
+- else
+- memcpy (host + real_hostlen, scopebuf, scopelen + 1);
+- }
+- }
+- else
+- c = inet_ntop (AF_INET,
+- (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
+- host, hostlen);
+- if (c == NULL)
+- return EAI_OVERFLOW;
+- }
+- ok = 1;
+- }
+- break;
+-
+- case AF_LOCAL:
+- if (!(flags & NI_NUMERICHOST))
+- {
+- struct utsname utsname;
+-
+- if (!uname (&utsname))
+- {
+- strncpy (host, utsname.nodename, hostlen);
+- break;
+- };
+- };
+-
+- if (flags & NI_NAMEREQD)
+- {
+- __set_errno (serrno);
+- return EAI_NONAME;
+- }
+-
+- strncpy (host, "localhost", hostlen);
+- break;
++ struct scratch_buffer tmpbuf;
++ scratch_buffer_init (&tmpbuf);
+
+- default:
+- return EAI_FAMILY;
++ if (host != NULL && hostlen > 0)
++ {
++ int result = gni_host (&tmpbuf, sa, addrlen, host, hostlen, flags);
++ if (result != 0)
++ {
++ scratch_buffer_free (&tmpbuf);
++ return result;
++ }
+ }
+
+ if (serv && (servlen > 0))
+- switch (sa->sa_family)
+- {
+- case AF_INET:
+- case AF_INET6:
+- if (!(flags & NI_NUMERICSERV))
+- {
+- struct servent *s, ts;
+- int e;
+- while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
+- ((flags & NI_DGRAM)
+- ? "udp" : "tcp"), &ts,
+- tmpbuf.data, tmpbuf.length, &s)))
+- {
+- if (e == ERANGE)
+- {
+- if (!scratch_buffer_grow (&tmpbuf))
+- return EAI_MEMORY;
+- }
+- else
+- break;
+- }
+- if (s)
+- {
+- strncpy (serv, s->s_name, servlen);
+- break;
+- }
+- }
+-
+- if (__snprintf (serv, servlen, "%d",
+- ntohs (((const struct sockaddr_in *) sa)->sin_port))
+- + 1 > servlen)
+- return EAI_OVERFLOW;
+-
+- break;
+-
+- case AF_LOCAL:
+- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
+- break;
++ {
++ int result = gni_serv (&tmpbuf, sa, addrlen, serv, servlen, flags);
++ if (result != 0)
++ {
++ scratch_buffer_free (&tmpbuf);
++ return result;
++ }
+ }
+
+- if (host && (hostlen > 0))
+- host[hostlen-1] = 0;
+- if (serv && (servlen > 0))
+- serv[servlen-1] = 0;
+- errno = serrno;
++ scratch_buffer_free (&tmpbuf);
+ return 0;
+ }
+ libc_hidden_def (getnameinfo)
+diff --git a/locale/localeinfo.h b/locale/localeinfo.h
+index 5c4e6ef..94627f3 100644
+--- a/locale/localeinfo.h
++++ b/locale/localeinfo.h
+@@ -299,6 +299,27 @@ extern __thread struct __locale_data *const *_nl_current_##category \
+
+ #endif
+
++/* Extract CATEGORY locale's string for ITEM. */
++static inline const char *
++_nl_lookup (locale_t l, int category, int item)
++{
++ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].string;
++}
++
++/* Extract CATEGORY locale's wide string for ITEM. */
++static inline const wchar_t *
++_nl_lookup_wstr (locale_t l, int category, int item)
++{
++ return (wchar_t *) l->__locales[category]
++ ->values[_NL_ITEM_INDEX (item)].wstr;
++}
++
++/* Extract the CATEGORY locale's word for ITEM. */
++static inline uint32_t
++_nl_lookup_word (locale_t l, int category, int item)
++{
++ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].word;
++}
+
+ /* Default search path if no LOCPATH environment variable. */
+ extern const char _nl_default_locale_path[] attribute_hidden;
+diff --git a/localedata/ChangeLog b/localedata/ChangeLog
+index 05ccd90..dd1c2b1 100644
+--- a/localedata/ChangeLog
++++ b/localedata/ChangeLog
+@@ -1,3 +1,10 @@
++2016-02-19 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #19581]
++ * locales/sr_ME (date_fmt): Remove newline.
++ * locales/sr_RS (date_fmt): Likewise.
++ * locales/sr_RS@latin (date_fmt): Likewise.
++
+ 2016-02-08 Mike Frysinger <vapier@gentoo.org>
+
+ * locales/an_ES: Convert to UTF-8 encodings.
+diff --git a/localedata/locales/sr_ME b/localedata/locales/sr_ME
+index 4f243dc..dd68df8 100644
+--- a/localedata/locales/sr_ME
++++ b/localedata/locales/sr_ME
+@@ -119,7 +119,7 @@ am_pm "";""
+ t_fmt_ampm "<U0025><U0054>"
+ date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
+ <U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
+-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
++<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
+ week 7;19971130;4
+ first_weekday 2
+ first_workday 2
+diff --git a/localedata/locales/sr_RS b/localedata/locales/sr_RS
+index 2ae085b..ffea86f 100644
+--- a/localedata/locales/sr_RS
++++ b/localedata/locales/sr_RS
+@@ -300,7 +300,7 @@ am_pm "";""
+ t_fmt_ampm "<U0025><U0054>"
+ date_fmt "<U0025><U0061><U002C><U0020><U0025><U0065><U002E><U0020>/
+ <U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
+-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
++<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
+ week 7;19971130;4
+ first_weekday 2
+ first_workday 2
+diff --git a/localedata/locales/sr_RS@latin b/localedata/locales/sr_RS@latin
+index da6628b..fd10ea6 100644
+--- a/localedata/locales/sr_RS@latin
++++ b/localedata/locales/sr_RS@latin
+@@ -120,7 +120,7 @@ am_pm "";""
+ t_fmt_ampm "<U0025><U0054>"
+ date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
+ <U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
+-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
++<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
+ week 7;19971130;4
+ first_weekday 2
+ first_workday 2
+diff --git a/malloc/Makefile b/malloc/Makefile
+index 360288b..3283f4f 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -29,7 +29,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
+ tst-malloc-usable tst-realloc tst-posix_memalign \
+ tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
+ tst-malloc-backtrace tst-malloc-thread-exit \
+- tst-malloc-thread-fail
++ tst-malloc-thread-fail tst-malloc-fork-deadlock
+ test-srcs = tst-mtrace
+
+ routines = malloc morecore mcheck mtrace obstack \
+@@ -46,12 +46,10 @@ extra-libs-others = $(extra-libs)
+ libmemusage-routines = memusage
+ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
+
+-$(objpfx)tst-malloc-backtrace: $(common-objpfx)nptl/libpthread.so \
+- $(common-objpfx)nptl/libpthread_nonshared.a
+-$(objpfx)tst-malloc-thread-exit: $(common-objpfx)nptl/libpthread.so \
+- $(common-objpfx)nptl/libpthread_nonshared.a
+-$(objpfx)tst-malloc-thread-fail: $(common-objpfx)nptl/libpthread.so \
+- $(common-objpfx)nptl/libpthread_nonshared.a
++$(objpfx)tst-malloc-backtrace: $(shared-thread-library)
++$(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
++$(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
++$(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library)
+
+ # These should be removed by `make clean'.
+ extra-objs = mcheck-init.o libmcheck.a
+diff --git a/malloc/arena.c b/malloc/arena.c
+index 1edb4d4..47715b6 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -130,149 +130,43 @@ int __malloc_initialized = -1;
+
+ /**************************************************************************/
+
+-#ifndef NO_THREADS
+-
+ /* atfork support. */
+
+-static void *(*save_malloc_hook)(size_t __size, const void *);
+-static void (*save_free_hook) (void *__ptr, const void *);
+-static void *save_arena;
+-
+-# ifdef ATFORK_MEM
+-ATFORK_MEM;
+-# endif
+-
+-/* Magic value for the thread-specific arena pointer when
+- malloc_atfork() is in use. */
+-
+-# define ATFORK_ARENA_PTR ((void *) -1)
+-
+-/* The following hooks are used while the `atfork' handling mechanism
+- is active. */
+-
+-static void *
+-malloc_atfork (size_t sz, const void *caller)
+-{
+- void *victim;
+-
+- if (thread_arena == ATFORK_ARENA_PTR)
+- {
+- /* We are the only thread that may allocate at all. */
+- if (save_malloc_hook != malloc_check)
+- {
+- return _int_malloc (&main_arena, sz);
+- }
+- else
+- {
+- if (top_check () < 0)
+- return 0;
+-
+- victim = _int_malloc (&main_arena, sz + 1);
+- return mem2mem_check (victim, sz);
+- }
+- }
+- else
+- {
+- /* Suspend the thread until the `atfork' handlers have completed.
+- By that time, the hooks will have been reset as well, so that
+- mALLOc() can be used again. */
+- (void) mutex_lock (&list_lock);
+- (void) mutex_unlock (&list_lock);
+- return __libc_malloc (sz);
+- }
+-}
+-
+-static void
+-free_atfork (void *mem, const void *caller)
+-{
+- mstate ar_ptr;
+- mchunkptr p; /* chunk corresponding to mem */
+-
+- if (mem == 0) /* free(0) has no effect */
+- return;
+-
+- p = mem2chunk (mem); /* do not bother to replicate free_check here */
+-
+- if (chunk_is_mmapped (p)) /* release mmapped memory. */
+- {
+- munmap_chunk (p);
+- return;
+- }
+-
+- ar_ptr = arena_for_chunk (p);
+- _int_free (ar_ptr, p, thread_arena == ATFORK_ARENA_PTR);
+-}
+-
+-
+-/* Counter for number of times the list is locked by the same thread. */
+-static unsigned int atfork_recursive_cntr;
++/* The following three functions are called around fork from a
++ multi-threaded process. We do not use the general fork handler
++ mechanism to make sure that our handlers are the last ones being
++ called, so that other fork handlers can use the malloc
++ subsystem. */
+
+-/* The following two functions are registered via thread_atfork() to
+- make sure that the mutexes remain in a consistent state in the
+- fork()ed version of a thread. Also adapt the malloc and free hooks
+- temporarily, because the `atfork' handler mechanism may use
+- malloc/free internally (e.g. in LinuxThreads). */
+-
+-static void
+-ptmalloc_lock_all (void)
++void
++internal_function
++__malloc_fork_lock_parent (void)
+ {
+- mstate ar_ptr;
+-
+ if (__malloc_initialized < 1)
+ return;
+
+ /* We do not acquire free_list_lock here because we completely
+- reconstruct free_list in ptmalloc_unlock_all2. */
++ reconstruct free_list in __malloc_fork_unlock_child. */
+
+- if (mutex_trylock (&list_lock))
+- {
+- if (thread_arena == ATFORK_ARENA_PTR)
+- /* This is the same thread which already locks the global list.
+- Just bump the counter. */
+- goto out;
++ (void) mutex_lock (&list_lock);
+
+- /* This thread has to wait its turn. */
+- (void) mutex_lock (&list_lock);
+- }
+- for (ar_ptr = &main_arena;; )
++ for (mstate ar_ptr = &main_arena;; )
+ {
+ (void) mutex_lock (&ar_ptr->mutex);
+ ar_ptr = ar_ptr->next;
+ if (ar_ptr == &main_arena)
+ break;
+ }
+- save_malloc_hook = __malloc_hook;
+- save_free_hook = __free_hook;
+- __malloc_hook = malloc_atfork;
+- __free_hook = free_atfork;
+- /* Only the current thread may perform malloc/free calls now.
+- save_arena will be reattached to the current thread, in
+- ptmalloc_lock_all, so save_arena->attached_threads is not
+- updated. */
+- save_arena = thread_arena;
+- thread_arena = ATFORK_ARENA_PTR;
+-out:
+- ++atfork_recursive_cntr;
+ }
+
+-static void
+-ptmalloc_unlock_all (void)
++void
++internal_function
++__malloc_fork_unlock_parent (void)
+ {
+- mstate ar_ptr;
+-
+ if (__malloc_initialized < 1)
+ return;
+
+- if (--atfork_recursive_cntr != 0)
+- return;
+-
+- /* Replace ATFORK_ARENA_PTR with save_arena.
+- save_arena->attached_threads was not changed in ptmalloc_lock_all
+- and is still correct. */
+- thread_arena = save_arena;
+- __malloc_hook = save_malloc_hook;
+- __free_hook = save_free_hook;
+- for (ar_ptr = &main_arena;; )
++ for (mstate ar_ptr = &main_arena;; )
+ {
+ (void) mutex_unlock (&ar_ptr->mutex);
+ ar_ptr = ar_ptr->next;
+@@ -282,35 +176,23 @@ ptmalloc_unlock_all (void)
+ (void) mutex_unlock (&list_lock);
+ }
+
+-# ifdef __linux__
+-
+-/* In NPTL, unlocking a mutex in the child process after a
+- fork() is currently unsafe, whereas re-initializing it is safe and
+- does not leak resources. Therefore, a special atfork handler is
+- installed for the child. */
+-
+-static void
+-ptmalloc_unlock_all2 (void)
++void
++internal_function
++__malloc_fork_unlock_child (void)
+ {
+- mstate ar_ptr;
+-
+ if (__malloc_initialized < 1)
+ return;
+
+- thread_arena = save_arena;
+- __malloc_hook = save_malloc_hook;
+- __free_hook = save_free_hook;
+-
+- /* Push all arenas to the free list, except save_arena, which is
++ /* Push all arenas to the free list, except thread_arena, which is
+ attached to the current thread. */
+ mutex_init (&free_list_lock);
+- if (save_arena != NULL)
+- ((mstate) save_arena)->attached_threads = 1;
++ if (thread_arena != NULL)
++ thread_arena->attached_threads = 1;
+ free_list = NULL;
+- for (ar_ptr = &main_arena;; )
++ for (mstate ar_ptr = &main_arena;; )
+ {
+ mutex_init (&ar_ptr->mutex);
+- if (ar_ptr != save_arena)
++ if (ar_ptr != thread_arena)
+ {
+ /* This arena is no longer attached to any thread. */
+ ar_ptr->attached_threads = 0;
+@@ -323,15 +205,8 @@ ptmalloc_unlock_all2 (void)
+ }
+
+ mutex_init (&list_lock);
+- atfork_recursive_cntr = 0;
+ }
+
+-# else
+-
+-# define ptmalloc_unlock_all2 ptmalloc_unlock_all
+-# endif
+-#endif /* !NO_THREADS */
+-
+ /* Initialization routine. */
+ #include <string.h>
+ extern char **_environ;
+@@ -400,7 +275,6 @@ ptmalloc_init (void)
+ #endif
+
+ thread_arena = &main_arena;
+- thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
+ const char *s = NULL;
+ if (__glibc_likely (_environ != NULL))
+ {
+@@ -475,14 +349,6 @@ ptmalloc_init (void)
+ __malloc_initialized = 1;
+ }
+
+-/* There are platforms (e.g. Hurd) with a link-time hook mechanism. */
+-#ifdef thread_atfork_static
+-thread_atfork_static (ptmalloc_lock_all, ptmalloc_unlock_all, \
+- ptmalloc_unlock_all2)
+-#endif
+-
+-
+-
+ /* Managing heaps and arenas (for concurrent threads) */
+
+ #if MALLOC_DEBUG > 1
+@@ -831,7 +697,8 @@ _int_new_arena (size_t size)
+ limit is reached). At this point, some arena has to be attached
+ to two threads. We could acquire the arena lock before list_lock
+ to make it less likely that reused_arena picks this new arena,
+- but this could result in a deadlock with ptmalloc_lock_all. */
++ but this could result in a deadlock with
++ __malloc_fork_lock_parent. */
+
+ (void) mutex_lock (&a->mutex);
+
+diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
+new file mode 100644
+index 0000000..b830d3f
+--- /dev/null
++++ b/malloc/malloc-internal.h
+@@ -0,0 +1,32 @@
++/* Internal declarations for malloc, for use within libc.
++ 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; see the file COPYING.LIB. If
++ not, see <http://www.gnu.org/licenses/>. */
++
++#ifndef _MALLOC_PRIVATE_H
++#define _MALLOC_PRIVATE_H
++
++/* Called in the parent process before a fork. */
++void __malloc_fork_lock_parent (void) internal_function attribute_hidden;
++
++/* Called in the parent process after a fork. */
++void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
++
++/* Called in the child process after a fork. */
++void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
++
++
++#endif /* _MALLOC_PRIVATE_H */
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index d20d595..39e4298 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -244,6 +244,7 @@
+ /* For ALIGN_UP et. al. */
+ #include <libc-internal.h>
+
++#include <malloc/malloc-internal.h>
+
+ /*
+ Debugging:
+@@ -1074,10 +1075,6 @@ static void* realloc_check(void* oldmem, size_t bytes,
+ const void *caller);
+ static void* memalign_check(size_t alignment, size_t bytes,
+ const void *caller);
+-#ifndef NO_THREADS
+-static void* malloc_atfork(size_t sz, const void *caller);
+-static void free_atfork(void* mem, const void *caller);
+-#endif
+
+ /* ------------------ MMAP support ------------------ */
+
+diff --git a/malloc/tst-malloc-fork-deadlock.c b/malloc/tst-malloc-fork-deadlock.c
+new file mode 100644
+index 0000000..94549ca
+--- /dev/null
++++ b/malloc/tst-malloc-fork-deadlock.c
+@@ -0,0 +1,220 @@
++/* Test concurrent fork, getline, and fflush (NULL).
++ 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; see the file COPYING.LIB. If
++ not, see <http://www.gnu.org/licenses/>. */
++
++#include <sys/wait.h>
++#include <unistd.h>
++#include <errno.h>
++#include <stdio.h>
++#include <pthread.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <malloc.h>
++#include <time.h>
++#include <string.h>
++#include <signal.h>
++
++static int do_test (void);
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
++
++enum {
++ /* Number of threads which call fork. */
++ fork_thread_count = 4,
++ /* Number of threads which call getline (and, indirectly,
++ malloc). */
++ read_thread_count = 8,
++};
++
++static bool termination_requested;
++
++static void *
++fork_thread_function (void *closure)
++{
++ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
++ {
++ pid_t pid = fork ();
++ if (pid < 0)
++ {
++ printf ("error: fork: %m\n");
++ abort ();
++ }
++ else if (pid == 0)
++ _exit (17);
++
++ int status;
++ if (waitpid (pid, &status, 0) < 0)
++ {
++ printf ("error: waitpid: %m\n");
++ abort ();
++ }
++ if (!WIFEXITED (status) || WEXITSTATUS (status) != 17)
++ {
++ printf ("error: waitpid returned invalid status: %d\n", status);
++ abort ();
++ }
++ }
++ return NULL;
++}
++
++static char *file_to_read;
++
++static void *
++read_thread_function (void *closure)
++{
++ FILE *f = fopen (file_to_read, "r");
++ if (f == NULL)
++ {
++ printf ("error: fopen (%s): %m\n", file_to_read);
++ abort ();
++ }
++
++ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
++ {
++ rewind (f);
++ char *line = NULL;
++ size_t line_allocated = 0;
++ ssize_t ret = getline (&line, &line_allocated, f);
++ if (ret < 0)
++ {
++ printf ("error: getline: %m\n");
++ abort ();
++ }
++ free (line);
++ }
++ fclose (f);
++
++ return NULL;
++}
++
++static void *
++flushall_thread_function (void *closure)
++{
++ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
++ if (fflush (NULL) != 0)
++ {
++ printf ("error: fflush (NULL): %m\n");
++ abort ();
++ }
++ return NULL;
++}
++
++static void
++create_threads (pthread_t *threads, size_t count, void *(*func) (void *))
++{
++ for (size_t i = 0; i < count; ++i)
++ {
++ int ret = pthread_create (threads + i, NULL, func, NULL);
++ if (ret != 0)
++ {
++ errno = ret;
++ printf ("error: pthread_create: %m\n");
++ abort ();
++ }
++ }
++}
++
++static void
++join_threads (pthread_t *threads, size_t count)
++{
++ for (size_t i = 0; i < count; ++i)
++ {
++ int ret = pthread_join (threads[i], NULL);
++ if (ret != 0)
++ {
++ errno = ret;
++ printf ("error: pthread_join: %m\n");
++ abort ();
++ }
++ }
++}
++
++/* Create a file which consists of a single long line, and assigns
++ file_to_read. The hope is that this triggers an allocation in
++ getline which needs a lock. */
++static void
++create_file_with_large_line (void)
++{
++ int fd = create_temp_file ("bug19431-large-line", &file_to_read);
++ if (fd < 0)
++ {
++ printf ("error: create_temp_file: %m\n");
++ abort ();
++ }
++ FILE *f = fdopen (fd, "w+");
++ if (f == NULL)
++ {
++ printf ("error: fdopen: %m\n");
++ abort ();
++ }
++ for (int i = 0; i < 50000; ++i)
++ fputc ('x', f);
++ fputc ('\n', f);
++ if (ferror (f))
++ {
++ printf ("error: fputc: %m\n");
++ abort ();
++ }
++ if (fclose (f) != 0)
++ {
++ printf ("error: fclose: %m\n");
++ abort ();
++ }
++}
++
++static int
++do_test (void)
++{
++ /* Make sure that we do not exceed the arena limit with the number
++ of threads we configured. */
++ if (mallopt (M_ARENA_MAX, 400) == 0)
++ {
++ printf ("error: mallopt (M_ARENA_MAX) failed\n");
++ return 1;
++ }
++
++ /* Leave some room for shutting down all threads gracefully. */
++ int timeout = 3;
++ if (timeout > TIMEOUT)
++ timeout = TIMEOUT - 1;
++
++ create_file_with_large_line ();
++
++ pthread_t fork_threads[fork_thread_count];
++ create_threads (fork_threads, fork_thread_count, fork_thread_function);
++ pthread_t read_threads[read_thread_count];
++ create_threads (read_threads, read_thread_count, read_thread_function);
++ pthread_t flushall_threads[1];
++ create_threads (flushall_threads, 1, flushall_thread_function);
++
++ struct timespec ts = {timeout, 0};
++ if (nanosleep (&ts, NULL))
++ {
++ printf ("error: error: nanosleep: %m\n");
++ abort ();
++ }
++
++ __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
++
++ join_threads (flushall_threads, 1);
++ join_threads (read_threads, read_thread_count);
++ join_threads (fork_threads, fork_thread_count);
++
++ free (file_to_read);
++
++ return 0;
++}
+diff --git a/manual/examples/mkdirent.c b/manual/examples/mkdirent.c
+new file mode 100644
+index 0000000..f8400f4
+--- /dev/null
++++ b/manual/examples/mkdirent.c
+@@ -0,0 +1,42 @@
++/* Example for creating a struct dirent object for use with glob.
++ Copyright (C) 2016 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License
++ as published by the Free Software Foundation; either version 2
++ of the License, or (at your option) any later version.
++
++ This program 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include <dirent.h>
++#include <errno.h>
++#include <stddef.h>
++#include <stdlib.h>
++#include <string.h>
++
++struct dirent *
++mkdirent (const char *name)
++{
++ size_t dirent_size = offsetof (struct dirent, d_name) + 1;
++ size_t name_length = strlen (name);
++ size_t total_size = dirent_size + name_length;
++ if (total_size < dirent_size)
++ {
++ errno = ENOMEM;
++ return NULL;
++ }
++ struct dirent *result = malloc (total_size);
++ if (result == NULL)
++ return NULL;
++ result->d_type = DT_UNKNOWN;
++ result->d_ino = 1; /* Do not skip this entry. */
++ memcpy (result->d_name, name, name_length + 1);
++ return result;
++}
+diff --git a/manual/memory.texi b/manual/memory.texi
+index 700555e..cdeb472 100644
+--- a/manual/memory.texi
++++ b/manual/memory.texi
+@@ -1051,14 +1051,6 @@ systems that do not support @w{ISO C11}.
+ @c _dl_addr_inside_object ok
+ @c determine_info ok
+ @c __rtld_lock_unlock_recursive (dl_load_lock) @aculock
+-@c thread_atfork @asulock @aculock @acsfd @acsmem
+-@c __register_atfork @asulock @aculock @acsfd @acsmem
+-@c lll_lock (__fork_lock) @asulock @aculock
+-@c fork_handler_alloc @asulock @aculock @acsfd @acsmem
+-@c calloc dup @asulock @aculock @acsfd @acsmem
+-@c __linkin_atfork ok
+-@c catomic_compare_and_exchange_bool_acq ok
+-@c lll_unlock (__fork_lock) @aculock
+ @c *_environ @mtsenv
+ @c next_env_entry ok
+ @c strcspn dup ok
+diff --git a/manual/pattern.texi b/manual/pattern.texi
+index d1b9275..565e7eb 100644
+--- a/manual/pattern.texi
++++ b/manual/pattern.texi
+@@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the
+ @code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of
+ this field is @w{@code{struct dirent *(*) (void *)}}.
+
+-This is a GNU extension.
++An implementation of @code{gl_readdir} needs to initialize the following
++members of the @code{struct dirent} object:
++
++@table @code
++@item d_type
++This member should be set to the file type of the entry if it is known.
++Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob}
++function may use the specified file type to avoid callbacks in cases
++where the file type indicates that the data is not required.
++
++@item d_ino
++This member needs to be non-zero, otherwise @code{glob} may skip the
++current entry and call the @code{gl_readdir} callback function again to
++retrieve another entry.
++
++@item d_name
++This member must be set to the name of the entry. It must be
++null-terminated.
++@end table
++
++The example below shows how to allocate a @code{struct dirent} object
++containing a given name.
++
++@smallexample
++@include mkdirent.c.texi
++@end smallexample
++
++The @code{glob} function reads the @code{struct dirent} members listed
++above and makes a copy of the file name in the @code{d_name} member
++immediately after the @code{gl_readdir} callback function returns.
++Future invocations of any of the callback functions may dealloacte or
++reuse the buffer. It is the responsibility of the caller of the
++@code{glob} function to allocate and deallocate the buffer, around the
++call to @code{glob} or using the callback functions. For example, an
++application could allocate the buffer in the @code{gl_readdir} callback
++function, and deallocate it in the @code{gl_closedir} callback function.
++
++The @code{gl_readdir} member is a GNU extension.
+
+ @item gl_opendir
+ The address of an alternative implementation of the @code{opendir}
+diff --git a/math/Makefile b/math/Makefile
+index 7d573a0..6aa87f9 100644
+--- a/math/Makefile
++++ b/math/Makefile
+@@ -100,7 +100,8 @@ $(inst_libdir)/libm.so: $(common-objpfx)format.lds \
+ cat $<; \
+ echo 'GROUP ( $(slibdir)/libm.so$(libm.so-version) ' \
+ 'AS_NEEDED ( $(libdir)/libmvec_nonshared.a $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
+- ) > $@
++ ) > $@.new
++ mv -f $@.new $@
+ endif
+
+ # Rules for the test suite.
+diff --git a/math/test-math-isinff.cc b/math/test-math-isinff.cc
+index 195d753..ecff1dc 100644
+--- a/math/test-math-isinff.cc
++++ b/math/test-math-isinff.cc
+@@ -30,12 +30,17 @@ do_test (void)
+ header fix this test will not compile. */
+ if (isinff (1.0f)
+ || !isinff (INFINITY)
++#ifndef NO_LONG_DOUBLE
+ || isinfl (1.0L)
+ || !isinfl (INFINITY)
++#endif
+ || isnanf (2.0f)
+ || !isnanf (NAN)
++#ifndef NO_LONG_DOUBLE
+ || isnanl (2.0L)
+- || !isnanl (NAN))
++ || !isnanl (NAN)
++#endif
++ )
+ {
+ printf ("FAIL: Failed to call is* functions.\n");
+ exit (1);
+diff --git a/nis/nis_call.c b/nis/nis_call.c
+index 3fa37e4..cb7839a 100644
+--- a/nis/nis_call.c
++++ b/nis/nis_call.c
+@@ -680,16 +680,18 @@ nis_server_cache_add (const_nis_name name, int search_parent,
+ /* Choose which entry should be evicted from the cache. */
+ loc = &nis_server_cache[0];
+ if (*loc != NULL)
+- for (i = 1; i < 16; ++i)
+- if (nis_server_cache[i] == NULL)
+- {
++ {
++ for (i = 1; i < 16; ++i)
++ if (nis_server_cache[i] == NULL)
++ {
++ loc = &nis_server_cache[i];
++ break;
++ }
++ else if ((*loc)->uses > nis_server_cache[i]->uses
++ || ((*loc)->uses == nis_server_cache[i]->uses
++ && (*loc)->expires > nis_server_cache[i]->expires))
+ loc = &nis_server_cache[i];
+- break;
+- }
+- else if ((*loc)->uses > nis_server_cache[i]->uses
+- || ((*loc)->uses == nis_server_cache[i]->uses
+- && (*loc)->expires > nis_server_cache[i]->expires))
+- loc = &nis_server_cache[i];
++ }
+ old = *loc;
+ *loc = new;
+
+diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
+index 03c18d7..125a5e9 100644
+--- a/nss/nss_db/db-XXX.c
++++ b/nss/nss_db/db-XXX.c
+@@ -288,8 +288,8 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
+ }
+ if (err < 0)
+ {
+- H_ERRNO_SET (HOST_NOT_FOUND);
+- status = NSS_STATUS_NOTFOUND;
++ H_ERRNO_SET (NETDB_INTERNAL);
++ status = NSS_STATUS_TRYAGAIN;
+ break;
+ }
+
diff --git a/po/be.po b/po/be.po
index 66d1235..ffb39b4 100644
--- a/po/be.po
#~ msgid "compile-time support for database policy missing"
#~ msgstr "compile-time 支援用於資料庫策略缺少"
+diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c
+index ddf5ec9..5873e08 100644
+--- a/posix/bug-glob2.c
++++ b/posix/bug-glob2.c
+@@ -40,6 +40,17 @@
+ # define PRINTF(fmt, args...)
+ #endif
+
++#define LONG_NAME \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+ static struct
+ {
+@@ -58,6 +69,7 @@ static struct
+ { ".", 3, DT_DIR, 0755 },
+ { "..", 3, DT_DIR, 0755 },
+ { "a", 3, DT_REG, 0644 },
++ { LONG_NAME, 3, DT_REG, 0644 },
+ { "unreadable", 2, DT_DIR, 0111 },
+ { ".", 3, DT_DIR, 0111 },
+ { "..", 3, DT_DIR, 0755 },
+@@ -75,7 +87,7 @@ typedef struct
+ int level;
+ int idx;
+ struct dirent d;
+- char room_for_dirent[NAME_MAX];
++ char room_for_dirent[sizeof (LONG_NAME)];
+ } my_DIR;
+
+
+@@ -193,7 +205,7 @@ my_readdir (void *gdir)
+ return NULL;
+ }
+
+- dir->d.d_ino = dir->idx;
++ dir->d.d_ino = 1; /* glob should not skip this entry. */
+
+ #ifdef _DIRENT_HAVE_D_TYPE
+ dir->d.d_type = filesystem[dir->idx].type;
+diff --git a/posix/glob.c b/posix/glob.c
+index 0c04c3c..ea4b0b6 100644
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -24,7 +24,9 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <stdbool.h>
+ #include <stddef.h>
++#include <stdint.h>
+
+ /* Outcomment the following line for production quality code. */
+ /* #define NDEBUG 1 */
+@@ -57,10 +59,8 @@
+
+ #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+ # include <dirent.h>
+-# define NAMLEN(dirent) strlen((dirent)->d_name)
+ #else
+ # define dirent direct
+-# define NAMLEN(dirent) (dirent)->d_namlen
+ # ifdef HAVE_SYS_NDIR_H
+ # include <sys/ndir.h>
+ # endif
+@@ -75,82 +75,8 @@
+ # endif /* HAVE_VMSDIR_H */
+ #endif
+
+-
+-/* In GNU systems, <dirent.h> defines this macro for us. */
+-#ifdef _D_NAMLEN
+-# undef NAMLEN
+-# define NAMLEN(d) _D_NAMLEN(d)
+-#endif
+-
+-/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+- if the `d_type' member for `struct dirent' is available.
+- HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
+-#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+-/* True if the directory entry D must be of type T. */
+-# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
+-
+-/* True if the directory entry D might be a symbolic link. */
+-# define DIRENT_MIGHT_BE_SYMLINK(d) \
+- ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
+-
+-/* True if the directory entry D might be a directory. */
+-# define DIRENT_MIGHT_BE_DIR(d) \
+- ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
+-
+-#else /* !HAVE_D_TYPE */
+-# define DIRENT_MUST_BE(d, t) false
+-# define DIRENT_MIGHT_BE_SYMLINK(d) true
+-# define DIRENT_MIGHT_BE_DIR(d) true
+-#endif /* HAVE_D_TYPE */
+-
+-/* If the system has the `struct dirent64' type we use it internally. */
+-#if defined _LIBC && !defined COMPILE_GLOB64
+-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+-# define CONVERT_D_NAMLEN(d64, d32)
+-# else
+-# define CONVERT_D_NAMLEN(d64, d32) \
+- (d64)->d_namlen = (d32)->d_namlen;
+-# endif
+-
+-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+-# define CONVERT_D_INO(d64, d32)
+-# else
+-# define CONVERT_D_INO(d64, d32) \
+- (d64)->d_ino = (d32)->d_ino;
+-# endif
+-
+-# ifdef _DIRENT_HAVE_D_TYPE
+-# define CONVERT_D_TYPE(d64, d32) \
+- (d64)->d_type = (d32)->d_type;
+-# else
+-# define CONVERT_D_TYPE(d64, d32)
+-# endif
+-
+-# define CONVERT_DIRENT_DIRENT64(d64, d32) \
+- memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
+- CONVERT_D_NAMLEN (d64, d32) \
+- CONVERT_D_INO (d64, d32) \
+- CONVERT_D_TYPE (d64, d32)
+-#endif
+-
+-
+-#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+-/* Posix does not require that the d_ino field be present, and some
+- systems do not provide it. */
+-# define REAL_DIR_ENTRY(dp) 1
+-#else
+-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+-#endif /* POSIX */
+-
+ #include <stdlib.h>
+ #include <string.h>
+-
+-/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
+-#include <limits.h>
+-#ifndef NAME_MAX
+-# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
+-#endif
+-
+ #include <alloca.h>
+
+ #ifdef _LIBC
+@@ -195,8 +121,111 @@
+ \f
+ static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+
++/* A representation of a directory entry which does not depend on the
++ layout of struct dirent, or the size of ino_t. */
++struct readdir_result
++{
++ const char *name;
++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++ uint8_t type;
++# endif
++ bool skip_entry;
++};
++
++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++/* Initializer based on the d_type member of struct dirent. */
++# define D_TYPE_TO_RESULT(source) (source)->d_type,
++
++/* True if the directory entry D might be a symbolic link. */
++static bool
++readdir_result_might_be_symlink (struct readdir_result d)
++{
++ return d.type == DT_UNKNOWN || d.type == DT_LNK;
++}
++
++/* True if the directory entry D might be a directory. */
++static bool
++readdir_result_might_be_dir (struct readdir_result d)
++{
++ return d.type == DT_DIR || readdir_result_might_be_symlink (d);
++}
++# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
++# define D_TYPE_TO_RESULT(source)
++
++/* If we do not have type information, symbolic links and directories
++ are always a possibility. */
++
++static bool
++readdir_result_might_be_symlink (struct readdir_result d)
++{
++ return true;
++}
++
++static bool
++readdir_result_might_be_dir (struct readdir_result d)
++{
++ return true;
++}
++
++# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
++
++# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
++/* Initializer for skip_entry. POSIX does not require that the d_ino
++ field be present, and some systems do not provide it. */
++# define D_INO_TO_RESULT(source) false,
++# else
++# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
++# endif
++
++/* Construct an initializer for a struct readdir_result object from a
++ struct dirent *. No copy of the name is made. */
++#define READDIR_RESULT_INITIALIZER(source) \
++ { \
++ source->d_name, \
++ D_TYPE_TO_RESULT (source) \
++ D_INO_TO_RESULT (source) \
++ }
++
+ #endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+
++/* Call gl_readdir on STREAM. This macro can be overridden to reduce
++ type safety if an old interface version needs to be supported. */
++#ifndef GL_READDIR
++# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
++#endif
++
++/* Extract name and type from directory entry. No copy of the name is
++ made. If SOURCE is NULL, result name is NULL. Keep in sync with
++ convert_dirent64 below. */
++static struct readdir_result
++convert_dirent (const struct dirent *source)
++{
++ if (source == NULL)
++ {
++ struct readdir_result result = { NULL, };
++ return result;
++ }
++ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
++ return result;
++}
++
++#ifndef COMPILE_GLOB64
++/* Like convert_dirent, but works on struct dirent64 instead. Keep in
++ sync with convert_dirent above. */
++static struct readdir_result
++convert_dirent64 (const struct dirent64 *source)
++{
++ if (source == NULL)
++ {
++ struct readdir_result result = { NULL, };
++ return result;
++ }
++ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
++ return result;
++}
++#endif
++
++
+ #ifndef attribute_hidden
+ # define attribute_hidden
+ #endif
+@@ -1553,56 +1582,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+
+ while (1)
+ {
+- const char *name;
+- size_t len;
+-#if defined _LIBC && !defined COMPILE_GLOB64
+- struct dirent64 *d;
+- union
+- {
+- struct dirent64 d64;
+- char room [offsetof (struct dirent64, d_name[0])
+- + NAME_MAX + 1];
+- }
+- d64buf;
+-
+- if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
+- {
+- struct dirent *d32 = (*pglob->gl_readdir) (stream);
+- if (d32 != NULL)
+- {
+- CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
+- d = &d64buf.d64;
+- }
+- else
+- d = NULL;
+- }
+- else
+- d = __readdir64 (stream);
++ struct readdir_result d;
++ {
++ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
++ d = convert_dirent (GL_READDIR (pglob, stream));
++ else
++ {
++#ifdef COMPILE_GLOB64
++ d = convert_dirent (__readdir (stream));
+ #else
+- struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+- ? ((struct dirent *)
+- (*pglob->gl_readdir) (stream))
+- : __readdir (stream));
++ d = convert_dirent64 (__readdir64 (stream));
+ #endif
+- if (d == NULL)
++ }
++ }
++ if (d.name == NULL)
+ break;
+- if (! REAL_DIR_ENTRY (d))
++ if (d.skip_entry)
+ continue;
+
+ /* If we shall match only directories use the information
+ provided by the dirent call if possible. */
+- if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
++ if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
+ continue;
+
+- name = d->d_name;
+-
+- if (fnmatch (pattern, name, fnm_flags) == 0)
++ if (fnmatch (pattern, d.name, fnm_flags) == 0)
+ {
+ /* If the file we found is a symlink we have to
+ make sure the target file exists. */
+- if (!DIRENT_MIGHT_BE_SYMLINK (d)
+- || link_exists_p (dfd, directory, dirlen, name, pglob,
+- flags))
++ if (!readdir_result_might_be_symlink (d)
++ || link_exists_p (dfd, directory, dirlen, d.name,
++ pglob, flags))
+ {
+ if (cur == names->count)
+ {
+@@ -1622,12 +1631,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ names = newnames;
+ cur = 0;
+ }
+- len = NAMLEN (d);
+- names->name[cur] = (char *) malloc (len + 1);
++ names->name[cur] = strdup (d.name);
+ if (names->name[cur] == NULL)
+ goto memory_error;
+- *((char *) mempcpy (names->name[cur++], name, len))
+- = '\0';
++ ++cur;
+ ++nfound;
+ }
+ }
+diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c
+index 992b997..b7b859b 100644
+--- a/posix/tst-gnuglob.c
++++ b/posix/tst-gnuglob.c
+@@ -211,7 +211,7 @@ my_readdir (void *gdir)
+ return NULL;
+ }
+
+- dir->d.d_ino = dir->idx;
++ dir->d.d_ino = 1; /* glob should not skip this entry. */
+
+ #ifdef _DIRENT_HAVE_D_TYPE
+ dir->d.d_type = filesystem[dir->idx].type;
+diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
+index 3a8e9b1..4720fc8 100644
+--- a/resolv/gethnamaddr.c
++++ b/resolv/gethnamaddr.c
+@@ -70,7 +70,6 @@ static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+ #include <resolv.h>
+ #include <ctype.h>
+ #include <errno.h>
+-#include <syslog.h>
+
+ #define RESOLVSORT
+
+@@ -100,9 +99,6 @@ static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+ #define MAXALIASES 35
+ #define MAXADDRS 35
+
+-static const char AskedForGot[] =
+- "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+-
+ static char *h_addr_ptrs[MAXADDRS + 1];
+
+ static struct hostent host;
+@@ -335,20 +331,12 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
+ * uses many different types in responses that do not
+ * match QTYPE.
+ */
+- if ((_res.options & RES_USE_DNSSEC) == 0) {
+- syslog(LOG_NOTICE|LOG_AUTH,
+- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+- qname, p_class(C_IN), p_type(qtype),
+- p_type(type));
+- }
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(tname, bp) != 0) {
+- syslog(LOG_NOTICE|LOG_AUTH,
+- AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+@@ -397,8 +385,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(host.h_name, bp) != 0) {
+- syslog(LOG_NOTICE|LOG_AUTH,
+- AskedForGot, host.h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+@@ -740,9 +726,6 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
+ _res.options &= ~RES_DNSRCH;
+ _res.options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hname2))) {
+- syslog(LOG_NOTICE|LOG_AUTH,
+- "gethostbyaddr: No A record for %s (verifying [%s])",
+- hname2, inet_ntoa(*((struct in_addr *)addr)));
+ _res.options = old_options;
+ __set_h_errno (HOST_NOT_FOUND);
+ return (NULL);
+@@ -752,9 +735,6 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+- syslog(LOG_NOTICE|LOG_AUTH,
+- "gethostbyaddr: A record of %s != PTR record [%s]",
+- hname2, inet_ntoa(*((struct in_addr *)addr)));
+ __set_h_errno (HOST_NOT_FOUND);
+ return (NULL);
+ }
+diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
+index 27255fd..072104f 100644
+--- a/resolv/nss_dns/dns-canon.c
++++ b/resolv/nss_dns/dns-canon.c
+@@ -103,6 +103,11 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
+
+ ptr += s;
+
++ /* Check that there are enough bytes for the RR
++ metadata. */
++ if (endptr - ptr < 10)
++ goto unavail;
++
+ /* Check whether type and class match. */
+ uint_fast16_t type;
+ NS_GET16 (type, ptr);
+@@ -137,13 +142,25 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
+ if (__ns_get16 (ptr) != ns_c_in)
+ goto unavail;
+
+- /* Also skip over the TTL. */
++ /* Also skip over class and TTL. */
+ ptr += sizeof (uint16_t) + sizeof (uint32_t);
+
+- /* Skip over the data length and data. */
+- ptr += sizeof (uint16_t) + __ns_get16 (ptr);
++ /* Skip over RDATA length and RDATA itself. */
++ uint16_t rdatalen = __ns_get16 (ptr);
++ ptr += sizeof (uint16_t);
++ /* Not enough room for RDATA. */
++ if (endptr - ptr < rdatalen)
++ goto unavail;
++ ptr += rdatalen;
+ }
+ }
++
++ /* Restore original buffer before retry. */
++ if (ansp.ptr != buf)
++ {
++ free (ansp.ptr);
++ ansp.ptr = buf;
++ }
+ }
+
+ out:
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
+index 8599f4c..403a005 100644
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -78,7 +78,6 @@
+ #include <stdlib.h>
+ #include <stddef.h>
+ #include <string.h>
+-#include <sys/syslog.h>
+
+ #include "nsswitch.h"
+
+@@ -99,10 +98,6 @@
+ #endif
+ #define MAXHOSTNAMELEN 256
+
+-static const char AskedForGot[] = "\
+-gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+-
+-
+ /* We need this time later. */
+ typedef union querybuf
+ {
+@@ -139,6 +134,22 @@ extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af,
+ char **canonp);
+ hidden_proto (_nss_dns_gethostbyname3_r)
+
++/* Return the expected RDATA length for an address record type (A or
++ AAAA). */
++static int
++rrtype_to_rdata_length (int type)
++{
++ switch (type)
++ {
++ case T_A:
++ return INADDRSZ;
++ case T_AAAA:
++ return IN6ADDRSZ;
++ default:
++ return -1;
++ }
++}
++
+ enum nss_status
+ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen, int *errnop,
+@@ -751,6 +762,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+ cp += INT32SZ; /* TTL */
+ n = __ns_get16 (cp);
+ cp += INT16SZ; /* len */
++
++ if (end_of_message - cp < n)
++ {
++ /* RDATA extends beyond the end of the packet. */
++ ++had_error;
++ continue;
++ }
++
+ if (__glibc_unlikely (class != C_IN))
+ {
+ /* XXX - debug? syslog? */
+@@ -830,14 +849,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+ have_to_map = 1;
+ else if (__glibc_unlikely (type != qtype))
+ {
+- /* Log a low priority message if we get an unexpected record, but
+- skip it if we are using DNSSEC since it uses many different types
+- in responses that do not match QTYPE. */
+- if ((_res.options & RES_USE_DNSSEC) == 0)
+- syslog (LOG_NOTICE | LOG_AUTH,
+- "gethostby*.getanswer: asked for \"%s %s %s\", "
+- "got type \"%s\"",
+- qname, p_class (C_IN), p_type (qtype), p_type (type));
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+@@ -847,7 +858,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+ case T_PTR:
+ if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
+ {
+- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+@@ -891,10 +901,18 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+ case T_AAAA:
+ if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
+ {
+- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
++
++ /* Stop parsing at a record whose length is incorrect. */
++ if (n != rrtype_to_rdata_length (type))
++ {
++ ++had_error;
++ break;
++ }
++
++ /* Skip records of the wrong type. */
+ if (n != result->h_length)
+ {
+ cp += n;
+@@ -1077,6 +1095,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+ n = __ns_get16 (cp);
+ cp += INT16SZ; /* len */
+
++ if (end_of_message - cp < n)
++ {
++ /* RDATA extends beyond the end of the packet. */
++ ++had_error;
++ continue;
++ }
++
+ if (class != C_IN)
+ {
+ cp += n;
+@@ -1124,32 +1149,25 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+ }
+ continue;
+ }
+-#if 1
+- // We should not see any types other than those explicitly listed
+- // below. Some types sent by server seem missing, though. Just
+- // collect the data for now.
+- if (__glibc_unlikely (type != T_A && type != T_AAAA))
+-#else
+- if (__builtin_expect (type == T_SIG, 0)
+- || __builtin_expect (type == T_KEY, 0)
+- || __builtin_expect (type == T_NXT, 0)
+- || __builtin_expect (type == T_PTR, 0)
+- || __builtin_expect (type == T_DNAME, 0))
+-#endif
+- {
+- /* We don't support DNSSEC yet. For now, ignore the record
+- and send a low priority message to syslog.
+
+- We also don't expect T_PTR or T_DNAME messages. */
+- syslog (LOG_DEBUG | LOG_AUTH,
+- "getaddrinfo*.gaih_getanswer: got type \"%s\"",
+- p_type (type));
++ /* Stop parsing if we encounter a record with incorrect RDATA
++ length. */
++ if (type == T_A || type == T_AAAA)
++ {
++ if (n != rrtype_to_rdata_length (type))
++ {
++ ++had_error;
++ continue;
++ }
++ }
++ else
++ {
++ /* Skip unknown records. */
+ cp += n;
+ continue;
+ }
+- if (type != T_A && type != T_AAAA)
+- abort ();
+
++ assert (type == T_A || type == T_AAAA);
+ if (*pat == NULL)
+ {
+ uintptr_t pad = (-(uintptr_t) buffer
+@@ -1183,12 +1201,6 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+ }
+
+ (*pat)->family = type == T_A ? AF_INET : AF_INET6;
+- if (__builtin_expect ((type == T_A && n != INADDRSZ)
+- || (type == T_AAAA && n != IN6ADDRSZ), 0))
+- {
+- ++had_error;
+- continue;
+- }
+ memcpy ((*pat)->addr, cp, n);
+ cp += n;
+ (*pat)->scopeid = 0;
+diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
+index 2eb2f67..ad6acff 100644
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
+ } net_buffer;
+ querybuf *orig_net_buffer;
+ int anslen;
+- char *qbuf;
+ enum nss_status status;
+
+ if (__res_maybe_init (&_res, 0) == -1)
+ return NSS_STATUS_UNAVAIL;
+
+- qbuf = strdupa (name);
+-
+ net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
+
+- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
++ anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
+ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
+ if (anslen < 0)
+ {
+@@ -348,10 +345,23 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
+ if (n < 0 || res_dnok (bp) == 0)
+ break;
+ cp += n;
++
++ if (end_of_message - cp < 10)
++ {
++ __set_h_errno (NO_RECOVERY);
++ return NSS_STATUS_UNAVAIL;
++ }
++
+ GETSHORT (type, cp);
+ GETSHORT (class, cp);
+ cp += INT32SZ; /* TTL */
+- GETSHORT (n, cp);
++ uint16_t rdatalen;
++ GETSHORT (rdatalen, cp);
++ if (end_of_message - cp < rdatalen)
++ {
++ __set_h_errno (NO_RECOVERY);
++ return NSS_STATUS_UNAVAIL;
++ }
+
+ if (class == C_IN && type == T_PTR)
+ {
+@@ -373,7 +383,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
+ cp += n;
+ return NSS_STATUS_UNAVAIL;
+ }
+- cp += n;
++ cp += rdatalen;
+ if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
+ {
+ *alias_pointer++ = bp;
+@@ -384,6 +394,9 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
+ ++have_answer;
+ }
+ }
++ else
++ /* Skip over unknown record data. */
++ cp += rdatalen;
+ }
+
+ if (have_answer)
+diff --git a/resolv/res_init.c b/resolv/res_init.c
+index e0b6a80..6c951f5 100644
+--- a/resolv/res_init.c
++++ b/resolv/res_init.c
+@@ -594,7 +594,7 @@ __res_iclose(res_state statp, bool free_addr) {
+ statp->_vcsock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+ }
+- for (ns = 0; ns < statp->_u._ext.nscount; ns++)
++ for (ns = 0; ns < statp->nscount; ns++)
+ if (statp->_u._ext.nsaddrs[ns]) {
+ if (statp->_u._ext.nssocks[ns] != -1) {
+ close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 25c19f1..2c0bae1 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -649,6 +649,18 @@ get_nsaddr (res_state statp, int n)
+ return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
+ }
+
++/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
++ is not NULL, and return zero. */
++static int
++__attribute__ ((warn_unused_result))
++close_and_return_error (res_state statp, int *resplen2)
++{
++ __res_iclose(statp, false);
++ if (resplen2 != NULL)
++ *resplen2 = 0;
++ return 0;
++}
++
+ /* The send_vc function is responsible for sending a DNS query over TCP
+ to the nameserver numbered NS from the res_state STATP i.e.
+ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
+@@ -750,8 +762,6 @@ send_vc(res_state statp,
+ u_short len2;
+ u_char *cp;
+
+- if (resplen2 != NULL)
+- *resplen2 = 0;
+ connreset = 0;
+ same_ns:
+ truncating = 0;
+@@ -777,6 +787,8 @@ send_vc(res_state statp,
+ if (statp->_vcsock < 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "socket(vc)", errno);
++ if (resplen2 != NULL)
++ *resplen2 = 0;
+ return (-1);
+ }
+ __set_errno (0);
+@@ -786,8 +798,7 @@ send_vc(res_state statp,
+ : sizeof (struct sockaddr_in6)) < 0) {
+ *terrno = errno;
+ Aerror(statp, stderr, "connect/vc", errno, nsap);
+- __res_iclose(statp, false);
+- return (0);
++ return close_and_return_error (statp, resplen2);
+ }
+ statp->_flags |= RES_F_VC;
+ }
+@@ -810,8 +821,7 @@ send_vc(res_state statp,
+ if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
+ *terrno = errno;
+ Perror(statp, stderr, "write failed", errno);
+- __res_iclose(statp, false);
+- return (0);
++ return close_and_return_error (statp, resplen2);
+ }
+ /*
+ * Receive length & response
+@@ -833,7 +843,6 @@ send_vc(res_state statp,
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read failed", errno);
+- __res_iclose(statp, false);
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+@@ -843,11 +852,13 @@ send_vc(res_state statp,
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+- if (*terrno == ECONNRESET && !connreset) {
+- connreset = 1;
+- goto same_ns;
+- }
+- return (0);
++ if (*terrno == ECONNRESET && !connreset)
++ {
++ __res_iclose (statp, false);
++ connreset = 1;
++ goto same_ns;
++ }
++ return close_and_return_error (statp, resplen2);
+ }
+ int rlen = ntohs (rlen16);
+
+@@ -879,11 +890,11 @@ send_vc(res_state statp,
+ /* Always allocate MAXPACKET, callers expect
+ this specific size. */
+ u_char *newp = malloc (MAXPACKET);
+- if (newp == NULL) {
+- *terrno = ENOMEM;
+- __res_iclose(statp, false);
+- return (0);
+- }
++ if (newp == NULL)
++ {
++ *terrno = ENOMEM;
++ return close_and_return_error (statp, resplen2);
++ }
+ *thisanssizp = MAXPACKET;
+ *thisansp = newp;
+ if (thisansp == ansp2)
+@@ -910,8 +921,7 @@ send_vc(res_state statp,
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ *terrno = EMSGSIZE;
+- __res_iclose(statp, false);
+- return (0);
++ return close_and_return_error (statp, resplen2);
+ }
+
+ cp = *thisansp;
+@@ -922,8 +932,7 @@ send_vc(res_state statp,
+ if (__glibc_unlikely (n <= 0)) {
+ *terrno = errno;
+ Perror(statp, stderr, "read(vc)", errno);
+- __res_iclose(statp, false);
+- return (0);
++ return close_and_return_error (statp, resplen2);
+ }
+ if (__glibc_unlikely (truncating)) {
+ /*
+@@ -1114,7 +1123,11 @@ send_dg(res_state statp,
+ retry_reopen:
+ retval = reopen (statp, terrno, ns);
+ if (retval <= 0)
+- return retval;
++ {
++ if (resplen2 != NULL)
++ *resplen2 = 0;
++ return retval;
++ }
+ retry:
+ evNowTime(&now);
+ evConsTime(&timeout, seconds, 0);
+@@ -1127,8 +1140,6 @@ send_dg(res_state statp,
+ int recvresp2 = buf2 == NULL;
+ pfd[0].fd = EXT(statp).nssocks[ns];
+ pfd[0].events = POLLOUT;
+- if (resplen2 != NULL)
+- *resplen2 = 0;
+ wait:
+ if (need_recompute) {
+ recompute_resend:
+@@ -1136,9 +1147,7 @@ send_dg(res_state statp,
+ if (evCmpTime(finish, now) <= 0) {
+ poll_err_out:
+ Perror(statp, stderr, "poll", errno);
+- err_out:
+- __res_iclose(statp, false);
+- return (0);
++ return close_and_return_error (statp, resplen2);
+ }
+ evSubTime(&timeout, &finish, &now);
+ need_recompute = 0;
+@@ -1185,7 +1194,9 @@ send_dg(res_state statp,
+ }
+
+ *gotsomewhere = 1;
+- return (0);
++ if (resplen2 != NULL)
++ *resplen2 = 0;
++ return 0;
+ }
+ if (n < 0) {
+ if (errno == EINTR)
+@@ -1253,7 +1264,7 @@ send_dg(res_state statp,
+
+ fail_sendmmsg:
+ Perror(statp, stderr, "sendmmsg", errno);
+- goto err_out;
++ return close_and_return_error (statp, resplen2);
+ }
+ }
+ else
+@@ -1271,7 +1282,7 @@ send_dg(res_state statp,
+ if (errno == EINTR || errno == EAGAIN)
+ goto recompute_resend;
+ Perror(statp, stderr, "send", errno);
+- goto err_out;
++ return close_and_return_error (statp, resplen2);
+ }
+ just_one:
+ if (nwritten != 0 || buf2 == NULL || single_request)
+@@ -1349,7 +1360,7 @@ send_dg(res_state statp,
+ goto wait;
+ }
+ Perror(statp, stderr, "recvfrom", errno);
+- goto err_out;
++ return close_and_return_error (statp, resplen2);
+ }
+ *gotsomewhere = 1;
+ if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
+@@ -1360,7 +1371,7 @@ send_dg(res_state statp,
+ (stdout, ";; undersized: %d\n",
+ *thisresplenp));
+ *terrno = EMSGSIZE;
+- goto err_out;
++ return close_and_return_error (statp, resplen2);
+ }
+ if ((recvresp1 || hp->id != anhp->id)
+ && (recvresp2 || hp2->id != anhp->id)) {
+@@ -1409,7 +1420,7 @@ send_dg(res_state statp,
+ ? *thisanssizp : *thisresplenp);
+ /* record the error */
+ statp->_flags |= RES_F_EDNS0ERR;
+- goto err_out;
++ return close_and_return_error (statp, resplen2);
+ }
+ #endif
+ if (!(statp->options & RES_INSECURE2)
+@@ -1461,10 +1472,10 @@ send_dg(res_state statp,
+ goto wait;
+ }
+
+- __res_iclose(statp, false);
+ /* don't retry if called from dig */
+ if (!statp->pfcode)
+- return (0);
++ return close_and_return_error (statp, resplen2);
++ __res_iclose(statp, false);
+ }
+ if (anhp->rcode == NOERROR && anhp->ancount == 0
+ && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
+@@ -1486,6 +1497,8 @@ send_dg(res_state statp,
+ __res_iclose(statp, false);
+ // XXX if we have received one reply we could
+ // XXX use it and not repeat it over TCP...
++ if (resplen2 != NULL)
++ *resplen2 = 0;
+ return (1);
+ }
+ /* Mark which reply we received. */
+@@ -1501,21 +1514,22 @@ send_dg(res_state statp,
+ __res_iclose (statp, false);
+ retval = reopen (statp, terrno, ns);
+ if (retval <= 0)
+- return retval;
++ {
++ if (resplen2 != NULL)
++ *resplen2 = 0;
++ return retval;
++ }
+ pfd[0].fd = EXT(statp).nssocks[ns];
+ }
+ }
+ goto wait;
+ }
+- /*
+- * All is well, or the error is fatal. Signal that the
+- * next nameserver ought not be tried.
+- */
++ /* All is well. We have received both responses (if
++ two responses were requested). */
+ return (resplen);
+- } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+- /* Something went wrong. We can stop trying. */
+- goto err_out;
+- }
++ } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
++ /* Something went wrong. We can stop trying. */
++ return close_and_return_error (statp, resplen2);
+ else {
+ /* poll should not have returned > 0 in this case. */
+ abort ();
+diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
+index 4134f8a..baada9e 100644
+--- a/stdio-common/printf_fp.c
++++ b/stdio-common/printf_fp.c
+@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p)
+ }
+
+ int
+-___printf_fp (FILE *fp,
+- const struct printf_info *info,
+- const void *const *args)
++___printf_fp_l (FILE *fp, locale_t loc,
++ const struct printf_info *info,
++ const void *const *args)
+ {
+ /* The floating-point value to output. */
+ union
+@@ -263,18 +263,19 @@ ___printf_fp (FILE *fp,
+ /* Figure out the decimal point character. */
+ if (info->extra == 0)
+ {
+- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
++ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
++ decimalwc = _nl_lookup_word
++ (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
+ }
+ else
+ {
+- decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
++ decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT);
+ if (*decimal == '\0')
+- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+- decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
++ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
++ decimalwc = _nl_lookup_word (loc, LC_MONETARY,
+ _NL_MONETARY_DECIMAL_POINT_WC);
+ if (decimalwc == L'\0')
+- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
++ decimalwc = _nl_lookup_word (loc, LC_NUMERIC,
+ _NL_NUMERIC_DECIMAL_POINT_WC);
+ }
+ /* The decimal point character must not be zero. */
+@@ -284,9 +285,9 @@ ___printf_fp (FILE *fp,
+ if (info->group)
+ {
+ if (info->extra == 0)
+- grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
++ grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING);
+ else
+- grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
++ grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING);
+
+ if (*grouping <= 0 || *grouping == CHAR_MAX)
+ grouping = NULL;
+@@ -296,19 +297,20 @@ ___printf_fp (FILE *fp,
+ if (wide)
+ {
+ if (info->extra == 0)
+- thousands_sepwc =
+- _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
++ thousands_sepwc = _nl_lookup_word
++ (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
+ else
+ thousands_sepwc =
+- _NL_CURRENT_WORD (LC_MONETARY,
++ _nl_lookup_word (loc, LC_MONETARY,
+ _NL_MONETARY_THOUSANDS_SEP_WC);
+ }
+ else
+ {
+ if (info->extra == 0)
+- thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
++ thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP);
+ else
+- thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
++ thousands_sep = _nl_lookup
++ (loc, LC_MONETARY, MON_THOUSANDS_SEP);
+ }
+
+ if ((wide && thousands_sepwc == L'\0')
+@@ -1171,9 +1173,11 @@ ___printf_fp (FILE *fp,
+ size_t decimal_len;
+ size_t thousands_sep_len;
+ wchar_t *copywc;
+- size_t factor = (info->i18n
+- ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX)
+- : 1);
++ size_t factor;
++ if (info->i18n)
++ factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
++ else
++ factor = 1;
+
+ decimal_len = strlen (decimal);
+
+@@ -1244,8 +1248,18 @@ ___printf_fp (FILE *fp,
+ }
+ return done;
+ }
++ldbl_hidden_def (___printf_fp_l, __printf_fp_l)
++ldbl_strong_alias (___printf_fp_l, __printf_fp_l)
++
++int
++___printf_fp (FILE *fp, const struct printf_info *info,
++ const void *const *args)
++{
++ return ___printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
++}
+ ldbl_hidden_def (___printf_fp, __printf_fp)
+ ldbl_strong_alias (___printf_fp, __printf_fp)
++
+ \f
+ /* Return the number of extra grouping characters that will be inserted
+ into a number with INTDIG_MAX integer digits. */
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index 26fe67a..d978774 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -76,7 +76,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
+ tst-secure-getenv tst-strtod-overflow tst-strtod-round \
+ tst-tininess tst-strtod-underflow tst-tls-atexit \
+ tst-setcontext3 tst-tls-atexit-nodelete \
+- tst-strtol-locale tst-strtod-nan-locale
++ tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l
+ tests-static := tst-secure-getenv
+
+ modules-names = tst-tls-atexit-lib
+@@ -126,7 +126,8 @@ include ../Rules
+
+ ifeq ($(run-built-tests),yes)
+ LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8 \
+- tr_TR.ISO-8859-9
++ tr_TR.ISO-8859-9 tg_TJ.UTF-8 te_IN.UTF-8 bn_IN.UTF-8 \
++ el_GR.UTF-8
+ include ../gen-locales.mk
+
+ $(objpfx)bug-strtod2.out: $(gen-locales)
+@@ -137,6 +138,7 @@ $(objpfx)tst-strtod4.out: $(gen-locales)
+ $(objpfx)tst-strtod5.out: $(gen-locales)
+ $(objpfx)tst-strtol-locale.out: $(gen-locales)
+ $(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
++$(objpfx)tst-strfmon_l.out: $(gen-locales)
+ endif
+
+ # Testdir has to be named stdlib and needs to be writable
+diff --git a/stdlib/setenv.c b/stdlib/setenv.c
+index da61ee0..e66045f 100644
+--- a/stdlib/setenv.c
++++ b/stdlib/setenv.c
+@@ -278,18 +278,20 @@ unsetenv (const char *name)
+ ep = __environ;
+ if (ep != NULL)
+ while (*ep != NULL)
+- if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+- {
+- /* Found it. Remove this pointer by moving later ones back. */
+- char **dp = ep;
+-
+- do
+- dp[0] = dp[1];
+- while (*dp++);
+- /* Continue the loop in case NAME appears again. */
+- }
+- else
+- ++ep;
++ {
++ if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
++ {
++ /* Found it. Remove this pointer by moving later ones back. */
++ char **dp = ep;
++
++ do
++ dp[0] = dp[1];
++ while (*dp++);
++ /* Continue the loop in case NAME appears again. */
++ }
++ else
++ ++ep;
++ }
+
+ UNLOCK;
+
+diff --git a/stdlib/strfmon_l.c b/stdlib/strfmon_l.c
+index b357020..5851a5b 100644
+--- a/stdlib/strfmon_l.c
++++ b/stdlib/strfmon_l.c
+@@ -68,9 +68,6 @@
+ #define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+
+-extern int __printf_fp (FILE *, const struct printf_info *,
+- const void *const *);
+-libc_hidden_proto (__printf_fp)
+ /* This function determines the number of digit groups in the output.
+ The definition is in printf_fp.c. */
+ extern unsigned int __guess_grouping (unsigned int intdig_max,
+@@ -532,7 +529,7 @@ __vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
+ info.extra = 1; /* This means use values from LC_MONETARY. */
+
+ ptr = &fpnum;
+- done = __printf_fp (&f._sbf._f, &info, &ptr);
++ done = __printf_fp_l (&f._sbf._f, loc, &info, &ptr);
+ if (done < 0)
+ return -1;
+
+diff --git a/stdlib/tst-strfmon_l.c b/stdlib/tst-strfmon_l.c
+new file mode 100644
+index 0000000..6841511
+--- /dev/null
++++ b/stdlib/tst-strfmon_l.c
+@@ -0,0 +1,220 @@
++/* Test locale dependence of strfmon_l.
++ 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 <stdbool.h>
++#include <stdio.h>
++#include <monetary.h>
++#include <string.h>
++#include <stdlib.h>
++#include <locale.h>
++
++static const char *const en_us_name = "en_US.ISO-8859-1";
++
++/* Locale value to be used by tests. */
++static locale_t loc;
++static const char *loc_name;
++
++/* Set the global locale to GLOBAL_NAME, and the locale referenced by
++ the loc variable above to LOCAL_NAME. */
++static void
++init_loc (const char *global_name, const char *local_name)
++{
++ loc = newlocale (LC_ALL_MASK, local_name, 0);
++ if (loc == 0)
++ {
++ printf ("error: newlocale (%s): %m\n", local_name);
++ abort ();
++ }
++ loc_name = local_name;
++
++ if (setlocale (LC_ALL, global_name) == NULL)
++ {
++ printf ("error: setlocale (%s): %m\n", global_name);
++ abort ();
++ }
++}
++
++/* Expected strings for a positive or negative value. */
++struct testcase
++{
++ const char *i; /* %i */
++ const char *n; /* %n */
++ const char *i_ungrouped; /* %^i */
++ const char *n_ungrouped; /* %^n */
++};
++
++/* Collected expected strings for both positive and negative
++ values. */
++struct testcase_pair
++{
++ struct testcase positive; /* 1234567.89 */
++ struct testcase negative; /* -1234567.89 */
++};
++
++static bool errors;
++
++/* Test one value using the locale loc. */
++static void
++test_one (const char *format, double value, const char *expected)
++{
++ static char actual[64];
++ int result = strfmon_l (actual, sizeof (actual), loc, format, value);
++ if (result < 0)
++ {
++ printf ("error: locale %s, format \"%s\", value %g: strfmon_l: %m\n",
++ loc_name, format, value);
++ errors = true;
++ }
++ else if (strcmp (actual, expected) != 0)
++ {
++ printf ("error: locale %s, format \"%s\", value %g: mismatch\n",
++ loc_name, format, value);
++ printf ("error: expected: \"%s\"\n", expected);
++ printf ("error: actual: \"%s\"\n", actual);
++ errors = true;
++ }
++}
++
++static void
++test_pair (const struct testcase_pair *pair)
++{
++ double positive = 1234567.89;
++ test_one ("%i", positive, pair->positive.i);
++ test_one ("%n", positive, pair->positive.n);
++ test_one ("%^i", positive, pair->positive.i_ungrouped);
++ test_one ("%^n", positive, pair->positive.n_ungrouped);
++ double negative = -1234567.89;
++ test_one ("%i", negative, pair->negative.i);
++ test_one ("%n", negative, pair->negative.n);
++ test_one ("%^i", negative, pair->negative.i_ungrouped);
++ test_one ("%^n", negative, pair->negative.n_ungrouped);
++}
++
++static const struct testcase_pair en_us =
++ {
++ {
++ "USD 1,234,567.89", "$1,234,567.89",
++ "USD 1234567.89", "$1234567.89"
++ },
++ {
++ "-USD 1,234,567.89", "-$1,234,567.89",
++ "-USD 1234567.89", "-$1234567.89"
++ }
++ };
++
++static void
++test_en_us (const char *other_name)
++{
++ init_loc (other_name, en_us_name);
++ test_pair (&en_us);
++ freelocale (loc);
++}
++
++struct locale_pair
++{
++ const char *locale_name;
++ struct testcase_pair pair;
++};
++
++static const struct locale_pair tests[] =
++ {
++ {
++ "de_DE.UTF-8",
++ {
++ {
++ "1.234.567,89 EUR", "1.234.567,89 \u20ac",
++ "1234567,89 EUR", "1234567,89 \u20ac"
++ },
++ {
++ "-1.234.567,89 EUR", "-1.234.567,89 \u20ac",
++ "-1234567,89 EUR", "-1234567,89 \u20ac"
++ }
++ },
++ },
++ {
++ "tg_TJ.UTF-8",
++ {
++ {
++ "1 234 567.89 TJS", "1 234 567.89 \u0440\u0443\u0431",
++ "1234567.89 TJS", "1234567.89 \u0440\u0443\u0431"
++ },
++ {
++ "-1 234 567.89 TJS", "-1 234 567.89 \u0440\u0443\u0431",
++ "-1234567.89 TJS", "-1234567.89 \u0440\u0443\u0431"
++ }
++ }
++ },
++ {
++ "te_IN.UTF-8",
++ {
++ {
++ "INR12,34,567.89", "\u20b912,34,567.89",
++ "INR1234567.89", "\u20b91234567.89"
++ },
++ {
++ "-INR12,34,567.89", "-\u20b912,34,567.89",
++ "-INR1234567.89", "-\u20b91234567.89"
++ }
++ }
++ },
++ {
++ "bn_IN.UTF-8",
++ {
++ {
++ "INR 12,345,67.89", "\u20b9 12,345,67.89",
++ "INR 1234567.89", "\u20b9 1234567.89"
++ },
++ {
++ "-INR 12,345,67.89", "-\u20b9 12,345,67.89",
++ "-INR 1234567.89", "-\u20b9 1234567.89"
++ }
++ }
++ },
++ {
++ "el_GR.UTF-8",
++ {
++ {
++ "1.234.567,89EUR", "1.234.567,89\u20ac",
++ "1234567,89EUR", "1234567,89\u20ac"
++ },
++ {
++ "-EUR1.234.567,89", "-\u20ac1.234.567,89",
++ "-EUR1234567,89", "-\u20ac1234567,89",
++ }
++ }
++ },
++ {}
++ };
++
++static int
++do_test (void)
++{
++ for (const struct locale_pair *test = tests;
++ test->locale_name != NULL; ++test)
++ {
++ init_loc (en_us_name, test->locale_name);
++ test_pair (&test->pair);
++ freelocale (loc);
++ test_en_us (test->locale_name);
++ }
++
++ return errors;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
+index 561441e..0560510 100644
+--- a/sysdeps/arm/nacl/libc.abilist
++++ b/sysdeps/arm/nacl/libc.abilist
+@@ -1834,3 +1834,9 @@ GLIBC_2.22 wprintf F
+ GLIBC_2.22 write F
+ GLIBC_2.22 writev F
+ GLIBC_2.22 wscanf F
++GLIBC_2.23 GLIBC_2.23 A
++GLIBC_2.23 fts64_children F
++GLIBC_2.23 fts64_close F
++GLIBC_2.23 fts64_open F
++GLIBC_2.23 fts64_read F
++GLIBC_2.23 fts64_set F
+diff --git a/sysdeps/generic/malloc-machine.h b/sysdeps/generic/malloc-machine.h
+index 1ed2d50..71b95c2 100644
+--- a/sysdeps/generic/malloc-machine.h
++++ b/sysdeps/generic/malloc-machine.h
+@@ -22,25 +22,6 @@
+
+ #include <atomic.h>
+
+-#ifndef mutex_init /* No threads, provide dummy macros */
+-
+-# define NO_THREADS
+-
+-/* The mutex functions used to do absolutely nothing, i.e. lock,
+- trylock and unlock would always just return 0. However, even
+- without any concurrently active threads, a mutex can be used
+- legitimately as an `in use' flag. To make the code that is
+- protected by a mutex async-signal safe, these macros would have to
+- be based on atomic test-and-set operations, for example. */
+-typedef int mutex_t;
+-
+-# define mutex_init(m) (*(m) = 0)
+-# define mutex_lock(m) ({ *(m) = 1; 0; })
+-# define mutex_trylock(m) (*(m) ? 1 : ((*(m) = 1), 0))
+-# define mutex_unlock(m) (*(m) = 0)
+-
+-#endif /* !defined mutex_init */
+-
+ #ifndef atomic_full_barrier
+ # define atomic_full_barrier() __asm ("" ::: "memory")
+ #endif
+diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure
+index 9515719..5b55c5a 100644
+--- a/sysdeps/i386/configure
++++ b/sysdeps/i386/configure
+@@ -72,7 +72,7 @@ rm -f conftest*
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_mpx" >&5
+ $as_echo "$libc_cv_asm_mpx" >&6; }
+-if test $libc_cv_asm_mpx == yes; then
++if test $libc_cv_asm_mpx = yes; then
+ $as_echo "#define HAVE_MPX_SUPPORT 1" >>confdefs.h
+
+ fi
+diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac
+index f8f9e44..19ef33f 100644
+--- a/sysdeps/i386/configure.ac
++++ b/sysdeps/i386/configure.ac
+@@ -41,7 +41,7 @@ else
+ libc_cv_asm_mpx=no
+ fi
+ rm -f conftest*])
+-if test $libc_cv_asm_mpx == yes; then
++if test $libc_cv_asm_mpx = yes; then
+ AC_DEFINE(HAVE_MPX_SUPPORT)
+ fi
+
+diff --git a/sysdeps/i386/i686/multiarch/bcopy.S b/sysdeps/i386/i686/multiarch/bcopy.S
+index d5b408d..ce6661b 100644
+--- a/sysdeps/i386/i686/multiarch/bcopy.S
++++ b/sysdeps/i386/i686/multiarch/bcopy.S
+@@ -36,7 +36,7 @@ ENTRY(bcopy)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__bcopy_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__bcopy_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/bzero.S b/sysdeps/i386/i686/multiarch/bzero.S
+index 3bad417..738ca69 100644
+--- a/sysdeps/i386/i686/multiarch/bzero.S
++++ b/sysdeps/i386/i686/multiarch/bzero.S
+@@ -31,7 +31,7 @@ ENTRY(__bzero)
+ HAS_CPU_FEATURE (SSE2)
+ jz 2f
+ LOAD_FUNC_GOT_EAX ( __bzero_sse2)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__bzero_sse2_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/memcpy.S b/sysdeps/i386/i686/multiarch/memcpy.S
+index 27913ea..652b5a2 100644
+--- a/sysdeps/i386/i686/multiarch/memcpy.S
++++ b/sysdeps/i386/i686/multiarch/memcpy.S
+@@ -38,7 +38,7 @@ ENTRY(memcpy)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memcpy_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memcpy_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/memcpy_chk.S b/sysdeps/i386/i686/multiarch/memcpy_chk.S
+index 39bc3c2..0eee32c 100644
+--- a/sysdeps/i386/i686/multiarch/memcpy_chk.S
++++ b/sysdeps/i386/i686/multiarch/memcpy_chk.S
+@@ -39,7 +39,7 @@ ENTRY(__memcpy_chk)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memcpy_chk_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memcpy_chk_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/memmove_chk.S b/sysdeps/i386/i686/multiarch/memmove_chk.S
+index c27892d..a29bbc9 100644
+--- a/sysdeps/i386/i686/multiarch/memmove_chk.S
++++ b/sysdeps/i386/i686/multiarch/memmove_chk.S
+@@ -36,7 +36,7 @@ ENTRY(__memmove_chk)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memmove_chk_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memmove_chk_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/mempcpy.S b/sysdeps/i386/i686/multiarch/mempcpy.S
+index 141ff2e..b46f3fc 100644
+--- a/sysdeps/i386/i686/multiarch/mempcpy.S
++++ b/sysdeps/i386/i686/multiarch/mempcpy.S
+@@ -38,7 +38,7 @@ ENTRY(__mempcpy)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__mempcpy_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__mempcpy_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/mempcpy_chk.S b/sysdeps/i386/i686/multiarch/mempcpy_chk.S
+index 2788b66..30f3629 100644
+--- a/sysdeps/i386/i686/multiarch/mempcpy_chk.S
++++ b/sysdeps/i386/i686/multiarch/mempcpy_chk.S
+@@ -39,7 +39,7 @@ ENTRY(__mempcpy_chk)
+ HAS_CPU_FEATURE (SSSE3)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__mempcpy_chk_ssse3)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__mempcpy_chk_ssse3_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/memset.S b/sysdeps/i386/i686/multiarch/memset.S
+index 268df0c..14180e4 100644
+--- a/sysdeps/i386/i686/multiarch/memset.S
++++ b/sysdeps/i386/i686/multiarch/memset.S
+@@ -31,7 +31,7 @@ ENTRY(memset)
+ HAS_CPU_FEATURE (SSE2)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memset_sse2)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memset_sse2_rep)
+ 2: ret
+diff --git a/sysdeps/i386/i686/multiarch/memset_chk.S b/sysdeps/i386/i686/multiarch/memset_chk.S
+index d18b53f..d73f202 100644
+--- a/sysdeps/i386/i686/multiarch/memset_chk.S
++++ b/sysdeps/i386/i686/multiarch/memset_chk.S
+@@ -31,7 +31,7 @@ ENTRY(__memset_chk)
+ HAS_CPU_FEATURE (SSE2)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memset_chk_sse2)
+- HAS_CPU_FEATURE (Fast_Rep_String)
++ HAS_ARCH_FEATURE (Fast_Rep_String)
+ jz 2f
+ LOAD_FUNC_GOT_EAX (__memset_chk_sse2_rep)
+ 2: ret
+diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
+index ad09fd7..2e8b59e 100644
+--- a/sysdeps/mach/hurd/fork.c
++++ b/sysdeps/mach/hurd/fork.c
+@@ -26,6 +26,7 @@
+ #include <assert.h>
+ #include "hurdmalloc.h" /* XXX */
+ #include <tls.h>
++#include <malloc/malloc-internal.h>
+
+ #undef __fork
+
+@@ -107,6 +108,12 @@ __fork (void)
+ /* Run things that prepare for forking before we create the task. */
+ RUN_HOOK (_hurd_fork_prepare_hook, ());
+
++ /* Acquire malloc locks. This needs to come last because fork
++ handlers may use malloc, and the libio list lock has an
++ indirect malloc dependency as well (via the getdelim
++ function). */
++ __malloc_fork_lock_parent ();
++
+ /* Lock things that want to be locked before we fork. */
+ {
+ void *const *p;
+@@ -604,6 +611,9 @@ __fork (void)
+ nthreads * sizeof (*threads));
+ }
+
++ /* Release malloc locks. */
++ __malloc_fork_unlock_parent ();
++
+ /* Run things that want to run in the parent to restore it to
+ normality. Usually prepare hooks and parent hooks are
+ symmetrical: the prepare hook arrests state in some way for the
+@@ -655,6 +665,9 @@ __fork (void)
+ /* Forking clears the trace flag. */
+ __sigemptyset (&_hurdsig_traced);
+
++ /* Release malloc locks. */
++ __malloc_fork_unlock_child ();
++
+ /* Run things that want to run in the child task to set up. */
+ RUN_HOOK (_hurd_fork_child_hook, ());
+
+diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
+index 27f8d52..1a68cbd 100644
+--- a/sysdeps/nptl/fork.c
++++ b/sysdeps/nptl/fork.c
+@@ -31,7 +31,7 @@
+ #include <fork.h>
+ #include <arch-fork.h>
+ #include <futex-internal.h>
+-
++#include <malloc/malloc-internal.h>
+
+ static void
+ fresetlockfiles (void)
+@@ -111,6 +111,11 @@ __libc_fork (void)
+
+ _IO_list_lock ();
+
++ /* Acquire malloc locks. This needs to come last because fork
++ handlers may use malloc, and the libio list lock has an indirect
++ malloc dependency as well (via the getdelim function). */
++ __malloc_fork_lock_parent ();
++
+ #ifndef NDEBUG
+ pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
+ #endif
+@@ -168,6 +173,9 @@ __libc_fork (void)
+ # endif
+ #endif
+
++ /* Release malloc locks. */
++ __malloc_fork_unlock_child ();
++
+ /* Reset the file list. These are recursive mutexes. */
+ fresetlockfiles ();
+
+@@ -209,6 +217,9 @@ __libc_fork (void)
+ /* Restore the PID value. */
+ THREAD_SETMEM (THREAD_SELF, pid, parentpid);
+
++ /* Release malloc locks, parent process variant. */
++ __malloc_fork_unlock_parent ();
++
+ /* We execute this even if the 'fork' call failed. */
+ _IO_list_unlock ();
+
+diff --git a/sysdeps/s390/bits/link.h b/sysdeps/s390/bits/link.h
+index 2ef7f44..e27ed67 100644
+--- a/sysdeps/s390/bits/link.h
++++ b/sysdeps/s390/bits/link.h
+@@ -19,6 +19,9 @@
+ # error "Never include <bits/link.h> directly; use <link.h> instead."
+ #endif
+
++#if defined HAVE_S390_VX_ASM_SUPPORT
++typedef char La_s390_vr[16];
++#endif
+
+ #if __ELF_NATIVE_CLASS == 32
+
+@@ -32,6 +35,16 @@ typedef struct La_s390_32_regs
+ uint32_t lr_r6;
+ double lr_fp0;
+ double lr_fp2;
++# if defined HAVE_S390_VX_ASM_SUPPORT
++ La_s390_vr lr_v24;
++ La_s390_vr lr_v25;
++ La_s390_vr lr_v26;
++ La_s390_vr lr_v27;
++ La_s390_vr lr_v28;
++ La_s390_vr lr_v29;
++ La_s390_vr lr_v30;
++ La_s390_vr lr_v31;
++# endif
+ } La_s390_32_regs;
+
+ /* Return values for calls from PLT on s390-32. */
+@@ -40,6 +53,9 @@ typedef struct La_s390_32_retval
+ uint32_t lrv_r2;
+ uint32_t lrv_r3;
+ double lrv_fp0;
++# if defined HAVE_S390_VX_ASM_SUPPORT
++ La_s390_vr lrv_v24;
++# endif
+ } La_s390_32_retval;
+
+
+@@ -77,6 +93,16 @@ typedef struct La_s390_64_regs
+ double lr_fp2;
+ double lr_fp4;
+ double lr_fp6;
++# if defined HAVE_S390_VX_ASM_SUPPORT
++ La_s390_vr lr_v24;
++ La_s390_vr lr_v25;
++ La_s390_vr lr_v26;
++ La_s390_vr lr_v27;
++ La_s390_vr lr_v28;
++ La_s390_vr lr_v29;
++ La_s390_vr lr_v30;
++ La_s390_vr lr_v31;
++# endif
+ } La_s390_64_regs;
+
+ /* Return values for calls from PLT on s390-64. */
+@@ -84,6 +110,9 @@ typedef struct La_s390_64_retval
+ {
+ uint64_t lrv_r2;
+ double lrv_fp0;
++# if defined HAVE_S390_VX_ASM_SUPPORT
++ La_s390_vr lrv_v24;
++# endif
+ } La_s390_64_retval;
+
+
+diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
+index 14bde3b..ec0ae4a 100644
+--- a/sysdeps/s390/s390-32/dl-machine.h
++++ b/sysdeps/s390/s390-32/dl-machine.h
+@@ -89,6 +89,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ {
+ extern void _dl_runtime_resolve (Elf32_Word);
+ extern void _dl_runtime_profile (Elf32_Word);
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ extern void _dl_runtime_resolve_vx (Elf32_Word);
++ extern void _dl_runtime_profile_vx (Elf32_Word);
++#endif
++
+
+ if (l->l_info[DT_JMPREL] && lazy)
+ {
+@@ -116,7 +121,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ end in this function. */
+ if (__glibc_unlikely (profile))
+ {
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ if (GLRO(dl_hwcap) & HWCAP_S390_VX)
++ got[2] = (Elf32_Addr) &_dl_runtime_profile_vx;
++ else
++ got[2] = (Elf32_Addr) &_dl_runtime_profile;
++#else
+ got[2] = (Elf32_Addr) &_dl_runtime_profile;
++#endif
+
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
+@@ -125,9 +137,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ GL(dl_profile_map) = l;
+ }
+ else
+- /* This function will get called to fix up the GOT entry indicated by
+- the offset on the stack, and then jump to the resolved address. */
+- got[2] = (Elf32_Addr) &_dl_runtime_resolve;
++ {
++ /* This function will get called to fix up the GOT entry indicated by
++ the offset on the stack, and then jump to the resolved address. */
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ if (GLRO(dl_hwcap) & HWCAP_S390_VX)
++ got[2] = (Elf32_Addr) &_dl_runtime_resolve_vx;
++ else
++ got[2] = (Elf32_Addr) &_dl_runtime_resolve;
++#else
++ got[2] = (Elf32_Addr) &_dl_runtime_resolve;
++#endif
++ }
+ }
+
+ return lazy;
+diff --git a/sysdeps/s390/s390-32/dl-trampoline.S b/sysdeps/s390/s390-32/dl-trampoline.S
+index 1645610..859183c 100644
+--- a/sysdeps/s390/s390-32/dl-trampoline.S
++++ b/sysdeps/s390/s390-32/dl-trampoline.S
+@@ -16,130 +16,18 @@
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+-/* This code is used in dl-runtime.c to call the `fixup' function
+- and then redirect to the address it returns. */
+-
+-/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+- * with the following linkage:
+- * r2 - r6 : parameter registers
+- * f0, f2 : floating point parameter registers
+- * 24(r15), 28(r15) : PLT arguments PLT1, PLT2
+- * 96(r15) : additional stack parameters
+- * The normal clobber rules for function calls apply:
+- * r0 - r5 : call clobbered
+- * r6 - r13 : call saved
+- * r14 : return address (call clobbered)
+- * r15 : stack pointer (call saved)
+- * f4, f6 : call saved
+- * f0 - f3, f5, f7 - f15 : call clobbered
+- */
+-
+ #include <sysdep.h>
+
+ .text
+- .globl _dl_runtime_resolve
+- .type _dl_runtime_resolve, @function
+- cfi_startproc
+- .align 16
+-_dl_runtime_resolve:
+- stm %r2,%r5,32(%r15) # save registers
+- st %r14,8(%r15)
+- cfi_offset (r14, -88)
+- lr %r0,%r15 # create stack frame
+- ahi %r15,-96
+- cfi_adjust_cfa_offset (96)
+- st 0,0(%r15)
+- lm %r2,%r3,120(%r15) # load args saved by PLT
+- basr %r1,0
+-0: l %r14,1f-0b(%r1)
+- bas %r14,0(%r14,%r1) # call resolver
+- lr %r1,%r2 # function addr returned in r2
+- ahi %r15,96 # remove stack frame
+- cfi_adjust_cfa_offset (-96)
+- l %r14,8(15) # restore registers
+- lm %r2,%r5,32(%r15)
+- br %r1
+-1: .long _dl_fixup - 0b
+- cfi_endproc
+- .size _dl_runtime_resolve, .-_dl_runtime_resolve
+-
+-
+-#ifndef PROF
+- .globl _dl_runtime_profile
+- .type _dl_runtime_profile, @function
+- cfi_startproc
+- .align 16
+-_dl_runtime_profile:
+- stm %r2,%r6,32(%r15) # save registers
+- std %f0,56(%r15)
+- std %f2,64(%r15)
+- st %r6,8(%r15)
+- st %r12,12(%r15)
+- st %r14,16(%r15)
+- cfi_offset (r6, -64)
+- cfi_offset (f0, -40)
+- cfi_offset (f2, -32)
+- cfi_offset (r12, -84)
+- cfi_offset (r14, -80)
+- lr %r12,%r15 # create stack frame
+- cfi_def_cfa_register (12)
+- ahi %r15,-96
+- st %r12,0(%r15)
+- lm %r2,%r3,24(%r12) # load arguments saved by PLT
+- lr %r4,%r14 # return address as third parameter
+- basr %r1,0
+-0: l %r14,6f-0b(%r1)
+- la %r5,32(%r12) # pointer to struct La_s390_32_regs
+- la %r6,20(%r12) # long int * framesize
+- bas %r14,0(%r14,%r1) # call resolver
+- lr %r1,%r2 # function addr returned in r2
+- icm %r0,15,20(%r12) # load & test framesize
+- jnm 2f
+-
+- lm %r2,%r6,32(%r12)
+- ld %f0,56(%r12)
+- ld %f2,64(%r12)
+- lr %r15,%r12 # remove stack frame
+- cfi_def_cfa_register (15)
+- l %r14,16(%r15) # restore registers
+- l %r12,12(%r15)
+- br %r1 # tail-call to the resolved function
+-
+- cfi_def_cfa_register (12)
+-2: jz 4f # framesize == 0 ?
+- ahi %r0,7 # align framesize to 8
+- lhi %r2,-8
+- nr %r0,%r2
+- slr %r15,%r0 # make room for framesize bytes
+- st %r12,0(%r15)
+- la %r2,96(%r15)
+- la %r3,96(%r12)
+- srl %r0,3
+-3: mvc 0(8,%r2),0(%r3) # copy additional parameters
+- la %r2,8(%r2)
+- la %r3,8(%r3)
+- brct %r0,3b
+-4: lm %r2,%r6,32(%r12) # load register parameters
+- ld %f0,56(%r12)
+- ld %f2,64(%r12)
+- basr %r14,%r1 # call resolved function
+- stm %r2,%r3,72(%r12)
+- std %f0,80(%r12)
+- lm %r2,%r3,24(%r12) # load arguments saved by PLT
+- basr %r1,0
+-5: l %r14,7f-5b(%r1)
+- la %r4,32(%r12) # pointer to struct La_s390_32_regs
+- la %r5,72(%r12) # pointer to struct La_s390_32_retval
+- basr %r14,%r1 # call _dl_call_pltexit
+-
+- lr %r15,%r12 # remove stack frame
+- cfi_def_cfa_register (15)
+- l %r14,16(%r15) # restore registers
+- l %r12,12(%r15)
+- br %r14
+-
+-6: .long _dl_profile_fixup - 0b
+-7: .long _dl_call_pltexit - 5b
+- cfi_endproc
+- .size _dl_runtime_profile, .-_dl_runtime_profile
++/* Create variant of _dl_runtime_resolve/profile for machines before z13.
++ No vector registers are saved/restored. */
++#include <dl-trampoline.h>
++
++#if defined HAVE_S390_VX_ASM_SUPPORT
++/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
++ The vector registers are saved/restored, too.*/
++# define _dl_runtime_resolve _dl_runtime_resolve_vx
++# define _dl_runtime_profile _dl_runtime_profile_vx
++# define RESTORE_VRS
++# include <dl-trampoline.h>
+ #endif
+diff --git a/sysdeps/s390/s390-32/dl-trampoline.h b/sysdeps/s390/s390-32/dl-trampoline.h
+new file mode 100644
+index 0000000..086449f
+--- /dev/null
++++ b/sysdeps/s390/s390-32/dl-trampoline.h
+@@ -0,0 +1,231 @@
++/* PLT trampolines. s390 version.
++ 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 code is used in dl-runtime.c to call the `fixup' function
++ and then redirect to the address it returns. */
++
++/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
++ * with the following linkage:
++ * r2 - r6 : parameter registers
++ * f0, f2 : floating point parameter registers
++ * v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
++ * 24(r15), 28(r15) : PLT arguments PLT1, PLT2
++ * 96(r15) : additional stack parameters
++ * The normal clobber rules for function calls apply:
++ * r0 - r5 : call clobbered
++ * r6 - r13 : call saved
++ * r14 : return address (call clobbered)
++ * r15 : stack pointer (call saved)
++ * f4, f6 : call saved
++ * f0 - f3, f5, f7 - f15 : call clobbered
++ * v0 - v3, v5, v7 - v15 : bytes 0-7 overlap with fprs: call clobbered
++ bytes 8-15: call clobbered
++ * v4, v6 : bytes 0-7 overlap with f4, f6: call saved
++ bytes 8-15: call clobbered
++ * v16 - v31 : call clobbered
++ */
++
++
++ .globl _dl_runtime_resolve
++ .type _dl_runtime_resolve, @function
++ cfi_startproc
++ .align 16
++_dl_runtime_resolve:
++ stm %r2,%r5,32(%r15) # save registers
++ cfi_offset (r2, -64)
++ cfi_offset (r3, -60)
++ cfi_offset (r4, -56)
++ cfi_offset (r5, -52)
++ std %f0,56(%r15)
++ cfi_offset (f0, -40)
++ std %f2,64(%r15)
++ cfi_offset (f2, -32)
++ st %r14,8(%r15)
++ cfi_offset (r14, -88)
++ lr %r0,%r15
++ lm %r2,%r3,24(%r15) # load args saved by PLT
++#ifdef RESTORE_VRS
++ ahi %r15,-224 # create stack frame
++ cfi_adjust_cfa_offset (224)
++ .machine push
++ .machine "z13"
++ .machinemode "zarch_nohighgprs"
++ vstm %v24,%v31,96(%r15) # store call-clobbered vr arguments
++ cfi_offset (v24, -224)
++ cfi_offset (v25, -208)
++ cfi_offset (v26, -192)
++ cfi_offset (v27, -176)
++ cfi_offset (v28, -160)
++ cfi_offset (v29, -144)
++ cfi_offset (v30, -128)
++ cfi_offset (v31, -112)
++ .machine pop
++#else
++ ahi %r15,-96 # create stack frame
++ cfi_adjust_cfa_offset (96)
++#endif
++ st %r0,0(%r15) # write backchain
++ basr %r1,0
++0: l %r14,1f-0b(%r1)
++ bas %r14,0(%r14,%r1) # call _dl_fixup
++ lr %r1,%r2 # function addr returned in r2
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ .machinemode "zarch_nohighgprs"
++ vlm %v24,%v31,96(%r15) # restore vector registers
++ .machine pop
++ ahi %r15,224 # remove stack frame
++ cfi_adjust_cfa_offset (-224)
++#else
++ ahi %r15,96 # remove stack frame
++ cfi_adjust_cfa_offset (-96)
++#endif
++ l %r14,8(15) # restore registers
++ ld %f0,56(%r15)
++ ld %f2,64(%r15)
++ lm %r2,%r5,32(%r15)
++ br %r1
++1: .long _dl_fixup - 0b
++ cfi_endproc
++ .size _dl_runtime_resolve, .-_dl_runtime_resolve
++
++
++#ifndef PROF
++ .globl _dl_runtime_profile
++ .type _dl_runtime_profile, @function
++ cfi_startproc
++ .align 16
++_dl_runtime_profile:
++ st %r12,12(%r15) # r12 is used as backup of r15
++ cfi_offset (r12, -84)
++ st %r14,16(%r15)
++ cfi_offset (r14, -80)
++ lr %r12,%r15 # backup stack pointer
++ cfi_def_cfa_register (12)
++ ahi %r15,-264 # create stack frame:
++ # 96 + sizeof(La_s390_32_regs)
++ st %r12,0(%r15) # save backchain
++
++ stm %r2,%r6,96(%r15) # save registers
++ cfi_offset (r2, -264) # + r6 needed as arg for
++ cfi_offset (r3, -260) # _dl_profile_fixup
++ cfi_offset (r4, -256)
++ cfi_offset (r5, -252)
++ cfi_offset (r6, -248)
++ std %f0,120(%r15)
++ cfi_offset (f0, -240)
++ std %f2,128(%r15)
++ cfi_offset (f2, -232)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ .machinemode "zarch_nohighgprs"
++ vstm %v24,%v31,136(%r15) # store call-clobbered vr arguments
++ cfi_offset (v24, -224)
++ cfi_offset (v25, -208)
++ cfi_offset (v26, -192)
++ cfi_offset (v27, -176)
++ cfi_offset (v28, -160)
++ cfi_offset (v29, -144)
++ cfi_offset (v30, -128)
++ cfi_offset (v31, -112)
++ .machine pop
++#endif
++
++ lm %r2,%r3,24(%r12) # load arguments saved by PLT
++ lr %r4,%r14 # return address as third parameter
++ basr %r1,0
++0: l %r14,6f-0b(%r1)
++ la %r5,96(%r15) # pointer to struct La_s390_32_regs
++ la %r6,20(%r12) # long int * framesize
++ bas %r14,0(%r14,%r1) # call resolver
++ lr %r1,%r2 # function addr returned in r2
++ ld %f0,120(%r15) # restore call-clobbered arg fprs
++ ld %f2,128(%r15)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ .machinemode "zarch_nohighgprs"
++ vlm %v24,%v31,136(%r15) # restore call-clobbered arg vrs
++ .machine pop
++#endif
++ icm %r0,15,20(%r12) # load & test framesize
++ jnm 2f
++
++ lm %r2,%r6,96(%r15) # framesize < 0 means no pltexit call
++ # so we can do a tail call without
++ # copying the arg overflow area
++ lr %r15,%r12 # remove stack frame
++ cfi_def_cfa_register (15)
++ l %r14,16(%r15) # restore registers
++ l %r12,12(%r15)
++ br %r1 # tail-call to the resolved function
++
++ cfi_def_cfa_register (12)
++2: la %r4,96(%r15) # pointer to struct La_s390_32_regs
++ st %r4,32(%r12)
++ jz 4f # framesize == 0 ?
++ ahi %r0,7 # align framesize to 8
++ lhi %r2,-8
++ nr %r0,%r2
++ slr %r15,%r0 # make room for framesize bytes
++ st %r12,0(%r15) # save backchain
++ la %r2,96(%r15)
++ la %r3,96(%r12)
++ srl %r0,3
++3: mvc 0(8,%r2),0(%r3) # copy additional parameters
++ la %r2,8(%r2)
++ la %r3,8(%r3)
++ brct %r0,3b
++4: lm %r2,%r6,0(%r4) # load register parameters
++ basr %r14,%r1 # call resolved function
++ stm %r2,%r3,40(%r12) # store return values r2, r3, f0
++ std %f0,48(%r12) # to struct La_s390_32_retval
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vst %v24,56(%r12) # store return value v24
++ .machine pop
++#endif
++ lm %r2,%r4,24(%r12) # r2, r3: load arguments saved by PLT
++ # r4: pointer to struct La_s390_32_regs
++ basr %r1,0
++5: l %r14,7f-5b(%r1)
++ la %r5,40(%r12) # pointer to struct La_s390_32_retval
++ bas %r14,0(%r14,%r1) # call _dl_call_pltexit
++
++ lr %r15,%r12 # remove stack frame
++ cfi_def_cfa_register (15)
++ l %r14,16(%r15) # restore registers
++ l %r12,12(%r15)
++ lm %r2,%r3,40(%r15) # restore return values
++ ld %f0,48(%r15)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vl %v24,56(%r15) # restore return value v24
++ .machine pop
++#endif
++ br %r14
++
++6: .long _dl_profile_fixup - 0b
++7: .long _dl_call_pltexit - 5b
++ cfi_endproc
++ .size _dl_runtime_profile, .-_dl_runtime_profile
++#endif
+diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
+index cb81aaf..9ee7c92 100644
+--- a/sysdeps/s390/s390-64/dl-machine.h
++++ b/sysdeps/s390/s390-64/dl-machine.h
+@@ -26,6 +26,7 @@
+ #include <sys/param.h>
+ #include <string.h>
+ #include <link.h>
++#include <sysdeps/s390/dl-procinfo.h>
+ #include <dl-irel.h>
+
+ #define ELF_MACHINE_IRELATIVE R_390_IRELATIVE
+@@ -78,6 +79,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ {
+ extern void _dl_runtime_resolve (Elf64_Word);
+ extern void _dl_runtime_profile (Elf64_Word);
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ extern void _dl_runtime_resolve_vx (Elf64_Word);
++ extern void _dl_runtime_profile_vx (Elf64_Word);
++#endif
+
+ if (l->l_info[DT_JMPREL] && lazy)
+ {
+@@ -105,7 +110,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ end in this function. */
+ if (__glibc_unlikely (profile))
+ {
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ if (GLRO(dl_hwcap) & HWCAP_S390_VX)
++ got[2] = (Elf64_Addr) &_dl_runtime_profile_vx;
++ else
++ got[2] = (Elf64_Addr) &_dl_runtime_profile;
++#else
+ got[2] = (Elf64_Addr) &_dl_runtime_profile;
++#endif
+
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
+@@ -114,9 +126,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+ GL(dl_profile_map) = l;
+ }
+ else
+- /* This function will get called to fix up the GOT entry indicated by
+- the offset on the stack, and then jump to the resolved address. */
+- got[2] = (Elf64_Addr) &_dl_runtime_resolve;
++ {
++ /* This function will get called to fix up the GOT entry indicated by
++ the offset on the stack, and then jump to the resolved address. */
++#if defined HAVE_S390_VX_ASM_SUPPORT
++ if (GLRO(dl_hwcap) & HWCAP_S390_VX)
++ got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx;
++ else
++ got[2] = (Elf64_Addr) &_dl_runtime_resolve;
++#else
++ got[2] = (Elf64_Addr) &_dl_runtime_resolve;
++#endif
++ }
+ }
+
+ return lazy;
+diff --git a/sysdeps/s390/s390-64/dl-trampoline.S b/sysdeps/s390/s390-64/dl-trampoline.S
+index 6919ed0..1b0c9e2 100644
+--- a/sysdeps/s390/s390-64/dl-trampoline.S
++++ b/sysdeps/s390/s390-64/dl-trampoline.S
+@@ -16,126 +16,18 @@
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+-/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+- * with the following linkage:
+- * r2 - r6 : parameter registers
+- * f0, f2, f4, f6 : floating point parameter registers
+- * 48(r15), 56(r15) : PLT arguments PLT1, PLT2
+- * 160(r15) : additional stack parameters
+- * The normal clobber rules for function calls apply:
+- * r0 - r5 : call clobbered
+- * r6 - r13 : call saved
+- * r14 : return address (call clobbered)
+- * r15 : stack pointer (call saved)
+- * f1, f3, f5, f7 : call saved
+- * f0 - f3, f5, f7 - f15 : call clobbered
+- */
+-
+ #include <sysdep.h>
+
+ .text
+- .globl _dl_runtime_resolve
+- .type _dl_runtime_resolve, @function
+- cfi_startproc
+- .align 16
+-_dl_runtime_resolve:
+- stmg %r2,%r5,64(15) # save call-clobbered argument registers
+- stg %r14,96(15)
+- cfi_offset (r14, -64)
+- lgr %r0,%r15
+- aghi %r15,-160 # create stack frame
+- cfi_adjust_cfa_offset (160)
+- stg %r0,0(%r15) # write backchain
+- lmg %r2,%r3,208(%r15)# load args saved by PLT
+- brasl %r14,_dl_fixup # call fixup
+- lgr %r1,%r2 # function addr returned in r2
+- aghi %r15,160 # remove stack frame
+- cfi_adjust_cfa_offset (-160)
+- lg %r14,96(15) # restore registers
+- lmg %r2,%r5,64(15)
+- br %r1
+- cfi_endproc
+- .size _dl_runtime_resolve, .-_dl_runtime_resolve
+-
+-
+-#ifndef PROF
+- .globl _dl_runtime_profile
+- .type _dl_runtime_profile, @function
+- cfi_startproc
+- .align 16
+-_dl_runtime_profile:
+- stmg %r2,%r6,64(%r15) # save call-clobbered arg regs
+- std %f0,104(%r15) # + r6 needed as arg for
+- std %f2,112(%r15) # _dl_profile_fixup
+- std %f4,120(%r15)
+- std %f6,128(%r15)
+- stg %r12,24(%r15) # r12 is used as backup of r15
+- stg %r14,32(%r15)
+- cfi_offset (r6, -96)
+- cfi_offset (f0, -56)
+- cfi_offset (f2, -48)
+- cfi_offset (f4, -40)
+- cfi_offset (f6, -32)
+- cfi_offset (r12, -136)
+- cfi_offset (r14, -128)
+- lgr %r12,%r15 # backup stack pointer
+- cfi_def_cfa_register (12)
+- aghi %r15,-160 # create stack frame
+- stg %r12,0(%r15) # save backchain
+- lmg %r2,%r3,48(%r12) # load arguments saved by PLT
+- lgr %r4,%r14 # return address as third parameter
+- la %r5,64(%r12) # pointer to struct La_s390_32_regs
+- la %r6,40(%r12) # long int * framesize
+- brasl %r14,_dl_profile_fixup # call resolver
+- lgr %r1,%r2 # function addr returned in r2
+- lg %r0,40(%r12) # load framesize
+- ltgr %r0,%r0
+- jnm 1f
+-
+- lmg %r2,%r6,64(%r12) # framesize < 0 means no pltexit call
+- ld %f0,104(%r12) # so we can do a tail call without
+- ld %f2,112(%r12) # copying the arg overflow area
+- ld %f4,120(%r12)
+- ld %f6,128(%r12)
+-
+- lgr %r15,%r12 # remove stack frame
+- cfi_def_cfa_register (15)
+- lg %r14,32(%r15) # restore registers
+- lg %r12,24(%r15)
+- br %r1 # tail-call to resolved function
+-
+- cfi_def_cfa_register (12)
+-1: jz 4f # framesize == 0 ?
+- aghi %r0,7 # align framesize to 8
+- nill %r0,0xfff8
+- slgr %r15,%r0 # make room for framesize bytes
+- stg %r12,0(%r15)
+- la %r2,160(%r15)
+- la %r3,160(%r12)
+- srlg %r0,%r0,3
+-3: mvc 0(8,%r2),0(%r3) # copy additional parameters
+- la %r2,8(%r2)
+- la %r3,8(%r3)
+- brctg %r0,3b
+-4: lmg %r2,%r6,64(%r12) # load register parameters
+- ld %f0,104(%r12) # restore call-clobbered arg regs
+- ld %f2,112(%r12)
+- ld %f4,120(%r12)
+- ld %f6,128(%r12)
+- basr %r14,%r1 # call resolved function
+- stg %r2,136(%r12)
+- std %f0,144(%r12)
+- lmg %r2,%r3,48(%r12) # load arguments saved by PLT
+- la %r4,32(%r12) # pointer to struct La_s390_32_regs
+- la %r5,72(%r12) # pointer to struct La_s390_32_retval
+- brasl %r14,_dl_call_pltexit
+-
+- lgr %r15,%r12 # remove stack frame
+- cfi_def_cfa_register (15)
+- lg %r14,32(%r15) # restore registers
+- lg %r12,24(%r15)
+- br %r14
+-
+- cfi_endproc
+- .size _dl_runtime_profile, .-_dl_runtime_profile
++/* Create variant of _dl_runtime_resolve/profile for machines before z13.
++ No vector registers are saved/restored. */
++#include <dl-trampoline.h>
++
++#if defined HAVE_S390_VX_ASM_SUPPORT
++/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
++ The vector registers are saved/restored, too.*/
++# define _dl_runtime_resolve _dl_runtime_resolve_vx
++# define _dl_runtime_profile _dl_runtime_profile_vx
++# define RESTORE_VRS
++# include <dl-trampoline.h>
+ #endif
+diff --git a/sysdeps/s390/s390-64/dl-trampoline.h b/sysdeps/s390/s390-64/dl-trampoline.h
+new file mode 100644
+index 0000000..33ea3de
+--- /dev/null
++++ b/sysdeps/s390/s390-64/dl-trampoline.h
+@@ -0,0 +1,225 @@
++/* PLT trampolines. s390x version.
++ 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/>. */
++
++/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
++ * with the following linkage:
++ * r2 - r6 : parameter registers
++ * f0, f2, f4, f6 : floating point parameter registers
++ * v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
++ * 48(r15), 56(r15) : PLT arguments PLT1, PLT2
++ * 160(r15) : additional stack parameters
++ * The normal clobber rules for function calls apply:
++ * r0 - r5 : call clobbered
++ * r6 - r13 : call saved
++ * r14 : return address (call clobbered)
++ * r15 : stack pointer (call saved)
++ * f0 - f7 : call clobbered
++ * f8 - f15 : call saved
++ * v0 - v7 : bytes 0-7 overlap with f0-f7: call clobbered
++ bytes 8-15: call clobbered
++ * v8 - v15 : bytes 0-7 overlap with f8-f15: call saved
++ bytes 8-15: call clobbered
++ * v16 - v31 : call clobbered
++ */
++
++ .globl _dl_runtime_resolve
++ .type _dl_runtime_resolve, @function
++ cfi_startproc
++ .align 16
++_dl_runtime_resolve:
++ stmg %r2,%r5,64(%r15) # save call-clobbered argument registers
++ cfi_offset (r2, -96)
++ cfi_offset (r3, -88)
++ cfi_offset (r4, -80)
++ cfi_offset (r5, -72)
++ std %f0,104(%r15)
++ cfi_offset (f0, -56)
++ std %f2,112(%r15)
++ cfi_offset (f2, -48)
++ std %f4,120(%r15)
++ cfi_offset (f4, -40)
++ std %f6,128(%r15)
++ cfi_offset (f6, -32)
++ stg %r14,96(15)
++ cfi_offset (r14, -64)
++ lmg %r2,%r3,48(%r15) # load args for fixup saved by PLT
++ lgr %r0,%r15
++#ifdef RESTORE_VRS
++ aghi %r15,-288 # create stack frame
++ cfi_adjust_cfa_offset (288)
++ .machine push
++ .machine "z13"
++ vstm %v24,%v31,160(%r15)# store call-clobbered vector argument registers
++ cfi_offset (v24, -288)
++ cfi_offset (v25, -272)
++ cfi_offset (v26, -256)
++ cfi_offset (v27, -240)
++ cfi_offset (v28, -224)
++ cfi_offset (v29, -208)
++ cfi_offset (v30, -192)
++ cfi_offset (v31, -176)
++ .machine pop
++#else
++ aghi %r15,-160 # create stack frame
++ cfi_adjust_cfa_offset (160)
++#endif
++ stg %r0,0(%r15) # write backchain
++ brasl %r14,_dl_fixup # call _dl_fixup
++ lgr %r1,%r2 # function addr returned in r2
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vlm %v24,%v31,160(%r15)# restore vector registers
++ .machine pop
++ aghi %r15,288 # remove stack frame
++ cfi_adjust_cfa_offset (-288)
++#else
++ aghi %r15,160 # remove stack frame
++ cfi_adjust_cfa_offset (-160)
++#endif
++ lg %r14,96(%r15) # restore registers
++ ld %f0,104(%r15)
++ ld %f2,112(%r15)
++ ld %f4,120(%r15)
++ ld %f6,128(%r15)
++ lmg %r2,%r5,64(%r15)
++ br %r1
++ cfi_endproc
++ .size _dl_runtime_resolve, .-_dl_runtime_resolve
++
++
++#ifndef PROF
++ .globl _dl_runtime_profile
++ .type _dl_runtime_profile, @function
++ cfi_startproc
++ .align 16
++_dl_runtime_profile:
++ stg %r12,24(%r15) # r12 is used as backup of r15
++ cfi_offset (r12, -136)
++ stg %r14,32(%r15)
++ cfi_offset (r14, -128)
++ lgr %r12,%r15 # backup stack pointer
++ cfi_def_cfa_register (12)
++ aghi %r15,-360 # create stack frame:
++ # 160 + sizeof(La_s390_64_regs)
++ stg %r12,0(%r15) # save backchain
++
++ stmg %r2,%r6,160(%r15) # save call-clobbered arg regs
++ cfi_offset (r2, -360) # + r6 needed as arg for
++ cfi_offset (r3, -352) # _dl_profile_fixup
++ cfi_offset (r4, -344)
++ cfi_offset (r5, -336)
++ cfi_offset (r6, -328)
++ std %f0,200(%r15)
++ cfi_offset (f0, -320)
++ std %f2,208(%r15)
++ cfi_offset (f2, -312)
++ std %f4,216(%r15)
++ cfi_offset (f4, -304)
++ std %f6,224(%r15)
++ cfi_offset (f6, -296)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vstm %v24,%v31,232(%r15) # store call-clobbered vector arguments
++ cfi_offset (v24, -288)
++ cfi_offset (v25, -272)
++ cfi_offset (v26, -256)
++ cfi_offset (v27, -240)
++ cfi_offset (v28, -224)
++ cfi_offset (v29, -208)
++ cfi_offset (v30, -192)
++ cfi_offset (v31, -176)
++ .machine pop
++#endif
++ lmg %r2,%r3,48(%r12) # load arguments saved by PLT
++ lgr %r4,%r14 # return address as third parameter
++ la %r5,160(%r15) # pointer to struct La_s390_64_regs
++ la %r6,40(%r12) # long int * framesize
++ brasl %r14,_dl_profile_fixup # call resolver
++ lgr %r1,%r2 # function addr returned in r2
++ ld %f0,200(%r15) # restore call-clobbered arg fprs
++ ld %f2,208(%r15)
++ ld %f4,216(%r15)
++ ld %f6,224(%r15)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vlm %v24,%v31,232(%r15) # restore call-clobbered arg vrs
++ .machine pop
++#endif
++ lg %r0,40(%r12) # load framesize
++ ltgr %r0,%r0
++ jnm 1f
++
++ lmg %r2,%r6,160(%r15) # framesize < 0 means no pltexit call
++ # so we can do a tail call without
++ # copying the arg overflow area
++ lgr %r15,%r12 # remove stack frame
++ cfi_def_cfa_register (15)
++ lg %r14,32(%r15) # restore registers
++ lg %r12,24(%r15)
++ br %r1 # tail-call to resolved function
++
++ cfi_def_cfa_register (12)
++1: la %r4,160(%r15) # pointer to struct La_s390_64_regs
++ stg %r4,64(%r12)
++ jz 4f # framesize == 0 ?
++ aghi %r0,7 # align framesize to 8
++ nill %r0,0xfff8
++ slgr %r15,%r0 # make room for framesize bytes
++ stg %r12,0(%r15) # save backchain
++ la %r2,160(%r15)
++ la %r3,160(%r12)
++ srlg %r0,%r0,3
++3: mvc 0(8,%r2),0(%r3) # copy additional parameters
++ la %r2,8(%r2) # depending on framesize
++ la %r3,8(%r3)
++ brctg %r0,3b
++4: lmg %r2,%r6,0(%r4) # restore call-clobbered arg gprs
++ basr %r14,%r1 # call resolved function
++ stg %r2,72(%r12) # store return values r2, f0
++ std %f0,80(%r12) # to struct La_s390_64_retval
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vst %v24,88(%r12) # store return value v24
++ .machine pop
++#endif
++ lmg %r2,%r4,48(%r12) # r2, r3: load arguments saved by PLT
++ # r4: pointer to struct La_s390_64_regs
++ la %r5,72(%r12) # pointer to struct La_s390_64_retval
++ brasl %r14,_dl_call_pltexit
++
++ lgr %r15,%r12 # remove stack frame
++ cfi_def_cfa_register (15)
++ lg %r14,32(%r15) # restore registers
++ lg %r12,24(%r15)
++ lg %r2,72(%r15) # restore return values
++ ld %f0,80(%r15)
++#ifdef RESTORE_VRS
++ .machine push
++ .machine "z13"
++ vl %v24,88(%r15) # restore return value v24
++ .machine pop
++#endif
++ br %r14 # Jump back to caller
++
++ cfi_endproc
++ .size _dl_runtime_profile, .-_dl_runtime_profile
++#endif
+diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c
+index b4fcd1a..802c957 100644
+--- a/sysdeps/unix/sysv/linux/i386/glob64.c
++++ b/sysdeps/unix/sysv/linux/i386/glob64.c
+@@ -1,3 +1,21 @@
++/* Two glob variants with 64-bit support, for dirent64 and __olddirent64.
++ Copyright (C) 1998-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 <dirent.h>
+ #include <glob.h>
+ #include <sys/stat.h>
+@@ -38,11 +56,15 @@ int __old_glob64 (const char *__pattern, int __flags,
+
+ #undef dirent
+ #define dirent __old_dirent64
++#undef GL_READDIR
++# define GL_READDIR(pglob, stream) \
++ ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
+ #undef __readdir
+ #define __readdir(dirp) __old_readdir64 (dirp)
+ #undef glob
+ #define glob(pattern, flags, errfunc, pglob) \
+ __old_glob64 (pattern, flags, errfunc, pglob)
++#define convert_dirent __old_convert_dirent
+ #define glob_in_dir __old_glob_in_dir
+ #define GLOB_ATTRIBUTE attribute_compat_text_section
+
+diff --git a/sysdeps/unix/sysv/linux/mips/makecontext.S b/sysdeps/unix/sysv/linux/mips/makecontext.S
+index 66600c7..3196554 100644
+--- a/sysdeps/unix/sysv/linux/mips/makecontext.S
++++ b/sysdeps/unix/sysv/linux/mips/makecontext.S
+@@ -153,6 +153,11 @@ NESTED (__makecontext, FRAMESZ, ra)
+ #endif
+ jr ra
+
++ /* We need to terminate the FDE to stop unwinding if backtrace was
++ called within a context created by makecontext. */
++ cfi_endproc
++ nop
++
+ 99:
+ #ifdef __PIC__
+ move gp, s1
+@@ -186,6 +191,8 @@ NESTED (__makecontext, FRAMESZ, ra)
+ 1:
+ lb zero, (zero)
+ b 1b
++
++ cfi_startproc
+ PSEUDO_END (__makecontext)
+
+ weak_alias (__makecontext, makecontext)
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
+index c9db5ea..a759934 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
++++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
+@@ -33,7 +33,7 @@
+ case 21: \
+ if (memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \
+ GLRO(dl_x86_cpu_features).feature[index_Prefer_MAP_32BIT_EXEC] \
+- = bit_Prefer_MAP_32BIT_EXEC; \
++ |= bit_Prefer_MAP_32BIT_EXEC; \
+ break;
+
+ /* Extra unsecure variables. The names are all stuffed in a single
+diff --git a/sysdeps/x86/bits/string.h b/sysdeps/x86/bits/string.h
+index e4e019f..8dfce05 100644
+--- a/sysdeps/x86/bits/string.h
++++ b/sysdeps/x86/bits/string.h
+@@ -23,6 +23,9 @@
+ /* Use the unaligned string inline ABI. */
+ #define _STRING_INLINE_unaligned 1
+
++/* Don't inline mempcpy into memcpy as x86 has an optimized mempcpy. */
++#define _HAVE_STRING_ARCH_mempcpy 1
++
+ /* Enable inline functions only for i486 or better when compiling for
+ ia32. */
+ #if !defined __x86_64__ && (defined __i486__ || defined __pentium__ \
+diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
+index 67ed5ba..cc47b88 100644
+--- a/sysdeps/x86_64/Makefile
++++ b/sysdeps/x86_64/Makefile
+@@ -60,7 +60,7 @@ $(objpfx)tst-audit3: $(objpfx)tst-auditmod3a.so
+ $(objpfx)tst-audit3.out: $(objpfx)tst-auditmod3b.so
+ tst-audit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod3b.so
+
+-$(objpfx)tst-audit4: $(objpfx)tst-auditmod4a.so
++$(objpfx)tst-audit4: $(objpfx)tst-audit4-aux.o $(objpfx)tst-auditmod4a.so
+ $(objpfx)tst-audit4.out: $(objpfx)tst-auditmod4b.so
+ tst-audit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod4b.so
+
+@@ -77,12 +77,12 @@ $(objpfx)tst-audit7: $(objpfx)tst-auditmod7a.so
+ $(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so
+ tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so
+
+-$(objpfx)tst-audit10: $(objpfx)tst-auditmod10a.so
++$(objpfx)tst-audit10: $(objpfx)tst-audit10-aux.o $(objpfx)tst-auditmod10a.so
+ $(objpfx)tst-audit10.out: $(objpfx)tst-auditmod10b.so
+ tst-audit10-ENV = LD_AUDIT=$(objpfx)tst-auditmod10b.so
+
+ AVX-CFLAGS=-mavx -mno-vzeroupper
+-CFLAGS-tst-audit4.c += $(AVX-CFLAGS)
++CFLAGS-tst-audit4-aux.c += $(AVX-CFLAGS)
+ CFLAGS-tst-auditmod4a.c += $(AVX-CFLAGS)
+ CFLAGS-tst-auditmod4b.c += $(AVX-CFLAGS)
+ CFLAGS-tst-auditmod6b.c += $(AVX-CFLAGS)
+@@ -90,7 +90,7 @@ CFLAGS-tst-auditmod6c.c += $(AVX-CFLAGS)
+ CFLAGS-tst-auditmod7b.c += $(AVX-CFLAGS)
+ ifeq (yes,$(config-cflags-avx512))
+ AVX512-CFLAGS = -mavx512f
+-CFLAGS-tst-audit10.c += $(AVX512-CFLAGS)
++CFLAGS-tst-audit10-aux.c += $(AVX512-CFLAGS)
+ CFLAGS-tst-auditmod10a.c += $(AVX512-CFLAGS)
+ CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS)
+ endif
+diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure
+index c72b9d3..88fbfe4 100644
+--- a/sysdeps/x86_64/configure
++++ b/sysdeps/x86_64/configure
+@@ -24,7 +24,7 @@ rm -f conftest*
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_avx512" >&5
+ $as_echo "$libc_cv_asm_avx512" >&6; }
+-if test $libc_cv_asm_avx512 == yes; then
++if test $libc_cv_asm_avx512 = yes; then
+ $as_echo "#define HAVE_AVX512_ASM_SUPPORT 1" >>confdefs.h
+
+ fi
+@@ -77,7 +77,7 @@ rm -f conftest*
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_mpx" >&5
+ $as_echo "$libc_cv_asm_mpx" >&6; }
+-if test $libc_cv_asm_mpx == yes; then
++if test $libc_cv_asm_mpx = yes; then
+ $as_echo "#define HAVE_MPX_SUPPORT 1" >>confdefs.h
+
+ fi
+diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac
+index 37b1059..b39309e 100644
+--- a/sysdeps/x86_64/configure.ac
++++ b/sysdeps/x86_64/configure.ac
+@@ -13,7 +13,7 @@ else
+ libc_cv_asm_avx512=no
+ fi
+ rm -f conftest*])
+-if test $libc_cv_asm_avx512 == yes; then
++if test $libc_cv_asm_avx512 = yes; then
+ AC_DEFINE(HAVE_AVX512_ASM_SUPPORT)
+ fi
+
+@@ -37,7 +37,7 @@ else
+ libc_cv_asm_mpx=no
+ fi
+ rm -f conftest*])
+-if test $libc_cv_asm_mpx == yes; then
++if test $libc_cv_asm_mpx = yes; then
+ AC_DEFINE(HAVE_MPX_SUPPORT)
+ fi
+
+diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
+index 9fb6b13..39b8771 100644
+--- a/sysdeps/x86_64/dl-trampoline.S
++++ b/sysdeps/x86_64/dl-trampoline.S
+@@ -33,15 +33,19 @@
+ # define DL_STACK_ALIGNMENT 8
+ #endif
+
+-#ifndef DL_RUNIME_UNALIGNED_VEC_SIZE
+-/* The maximum size of unaligned vector load and store. */
+-# define DL_RUNIME_UNALIGNED_VEC_SIZE 16
++#ifndef DL_RUNTIME_UNALIGNED_VEC_SIZE
++/* The maximum size in bytes of unaligned vector load and store in the
++ dynamic linker. Since SSE optimized memory/string functions with
++ aligned SSE register load and store are used in the dynamic linker,
++ we must set this to 8 so that _dl_runtime_resolve_sse will align the
++ stack before calling _dl_fixup. */
++# define DL_RUNTIME_UNALIGNED_VEC_SIZE 8
+ #endif
+
+ /* True if _dl_runtime_resolve should align stack to VEC_SIZE bytes. */
+-#define DL_RUNIME_RESOLVE_REALIGN_STACK \
++#define DL_RUNTIME_RESOLVE_REALIGN_STACK \
+ (VEC_SIZE > DL_STACK_ALIGNMENT \
+- && VEC_SIZE > DL_RUNIME_UNALIGNED_VEC_SIZE)
++ && VEC_SIZE > DL_RUNTIME_UNALIGNED_VEC_SIZE)
+
+ /* Align vector register save area to 16 bytes. */
+ #define REGISTER_SAVE_VEC_OFF 0
+@@ -76,7 +80,7 @@
+ #ifdef HAVE_AVX512_ASM_SUPPORT
+ # define VEC_SIZE 64
+ # define VMOVA vmovdqa64
+-# if DL_RUNIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
++# if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
+ # define VMOV vmovdqa64
+ # else
+ # define VMOV vmovdqu64
+@@ -100,7 +104,7 @@ strong_alias (_dl_runtime_profile_avx, _dl_runtime_profile_avx512)
+
+ #define VEC_SIZE 32
+ #define VMOVA vmovdqa
+-#if DL_RUNIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
++#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
+ # define VMOV vmovdqa
+ #else
+ # define VMOV vmovdqu
+@@ -119,7 +123,7 @@ strong_alias (_dl_runtime_profile_avx, _dl_runtime_profile_avx512)
+ /* movaps/movups is 1-byte shorter. */
+ #define VEC_SIZE 16
+ #define VMOVA movaps
+-#if DL_RUNIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
++#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT
+ # define VMOV movaps
+ #else
+ # define VMOV movups
+diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
+index f419183..b90836a 100644
+--- a/sysdeps/x86_64/dl-trampoline.h
++++ b/sysdeps/x86_64/dl-trampoline.h
+@@ -30,7 +30,7 @@
+ #undef REGISTER_SAVE_AREA
+ #undef LOCAL_STORAGE_AREA
+ #undef BASE
+-#if DL_RUNIME_RESOLVE_REALIGN_STACK
++#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ # define REGISTER_SAVE_AREA (REGISTER_SAVE_AREA_RAW + 8)
+ /* Local stack area before jumping to function address: RBX. */
+ # define LOCAL_STORAGE_AREA 8
+@@ -57,7 +57,7 @@
+ cfi_startproc
+ _dl_runtime_resolve:
+ cfi_adjust_cfa_offset(16) # Incorporate PLT
+-#if DL_RUNIME_RESOLVE_REALIGN_STACK
++#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ # if LOCAL_STORAGE_AREA != 8
+ # error LOCAL_STORAGE_AREA must be 8
+ # endif
+@@ -146,7 +146,7 @@ _dl_runtime_resolve:
+ VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 5)(%rsp), %VEC(5)
+ VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 6)(%rsp), %VEC(6)
+ VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 7)(%rsp), %VEC(7)
+-#if DL_RUNIME_RESOLVE_REALIGN_STACK
++#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ mov %RBX_LP, %RSP_LP
+ cfi_def_cfa_register(%rsp)
+ movq (%rsp), %rbx
+diff --git a/sysdeps/x86_64/tst-audit10-aux.c b/sysdeps/x86_64/tst-audit10-aux.c
+new file mode 100644
+index 0000000..992a16c
+--- /dev/null
++++ b/sysdeps/x86_64/tst-audit10-aux.c
+@@ -0,0 +1,41 @@
++/* Test case for preserved AVX512 registers in dynamic linker, -mavx512f part.
++ Copyright (C) 2012-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 <immintrin.h>
++#include <stdlib.h>
++#include <string.h>
++
++int
++tst_audit10_aux (void)
++{
++#ifdef __AVX512F__
++ extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
++ __m512i, __m512i, __m512i, __m512i);
++
++ __m512i zmm = _mm512_setzero_si512 ();
++ __m512i ret = audit_test (zmm, zmm, zmm, zmm, zmm, zmm, zmm, zmm);
++
++ zmm = _mm512_set1_epi64 (0x12349876);
++
++ if (memcmp (&zmm, &ret, sizeof (ret)))
++ abort ();
++ return 0;
++#else /* __AVX512F__ */
++ return 77;
++#endif /* __AVX512F__ */
++}
+diff --git a/sysdeps/x86_64/tst-audit10.c b/sysdeps/x86_64/tst-audit10.c
+index d104341..0df2275 100644
+--- a/sysdeps/x86_64/tst-audit10.c
++++ b/sysdeps/x86_64/tst-audit10.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 2012-2016 Free Software Foundation, Inc.
++/* Test case for preserved AVX512 registers in dynamic linker.
++ Copyright (C) 2012-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
+@@ -15,17 +16,14 @@
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+-/* Test case for x86-64 preserved registers in dynamic linker. */
+-
+-#ifdef __AVX512F__
+-#include <stdlib.h>
+-#include <string.h>
+ #include <cpuid.h>
+-#include <immintrin.h>
++
++int tst_audit10_aux (void);
+
+ static int
+ avx512_enabled (void)
+ {
++#ifdef bit_AVX512F
+ unsigned int eax, ebx, ecx, edx;
+
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0
+@@ -40,34 +38,20 @@ avx512_enabled (void)
+
+ /* Verify that ZMM, YMM and XMM states are enabled. */
+ return (eax & 0xe6) == 0xe6;
++#else
++ return 0;
++#endif
+ }
+
+-
+-extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
+- __m512i, __m512i, __m512i, __m512i);
+ static int
+ do_test (void)
+ {
+ /* Run AVX512 test only if AVX512 is supported. */
+ if (avx512_enabled ())
+- {
+- __m512i zmm = _mm512_setzero_si512 ();
+- __m512i ret = audit_test (zmm, zmm, zmm, zmm, zmm, zmm, zmm, zmm);
+-
+- zmm = _mm512_set1_epi64 (0x12349876);
+-
+- if (memcmp (&zmm, &ret, sizeof (ret)))
+- abort ();
+- }
+- return 0;
+-}
+-#else
+-static int
+-do_test (void)
+-{
+- return 0;
++ return tst_audit10_aux ();
++ else
++ return 77;
+ }
+-#endif
+
+ #define TEST_FUNCTION do_test ()
+ #include "../../test-skeleton.c"
+diff --git a/sysdeps/x86_64/tst-audit4-aux.c b/sysdeps/x86_64/tst-audit4-aux.c
+new file mode 100644
+index 0000000..a1aeb65
+--- /dev/null
++++ b/sysdeps/x86_64/tst-audit4-aux.c
+@@ -0,0 +1,39 @@
++/* Test case for preserved AVX registers in dynamic linker, -mavx part.
++ Copyright (C) 2009-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 <immintrin.h>
++#include <stdlib.h>
++#include <string.h>
++
++extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
++ __m256i, __m256i, __m256i, __m256i);
++
++int
++tst_audit4_aux (void)
++{
++#ifdef __AVX__
++ __m256i ymm = _mm256_setzero_si256 ();
++ __m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
++ ymm = _mm256_set1_epi32 (0x12349876);
++ if (memcmp (&ymm, &ret, sizeof (ret)))
++ abort ();
++ return 0;
++#else /* __AVX__ */
++ return 77;
++#endif /* __AVX__ */
++}
+diff --git a/sysdeps/x86_64/tst-audit4.c b/sysdeps/x86_64/tst-audit4.c
+index 44d5123..d8e2ab1 100644
+--- a/sysdeps/x86_64/tst-audit4.c
++++ b/sysdeps/x86_64/tst-audit4.c
+@@ -1,11 +1,24 @@
+-/* Test case for x86-64 preserved registers in dynamic linker. */
++/* Test case for preserved AVX registers in dynamic linker.
++ Copyright (C) 2009-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/>. */
+
+-#ifdef __AVX__
+-#include <stdlib.h>
+-#include <string.h>
+ #include <cpuid.h>
+-#include <immintrin.h>
+
++int tst_audit4_aux (void);
+
+ static int
+ avx_enabled (void)
+@@ -22,31 +35,15 @@ avx_enabled (void)
+ return (eax & 6) == 6;
+ }
+
+-
+-extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
+- __m256i, __m256i, __m256i, __m256i);
+ static int
+ do_test (void)
+ {
+ /* Run AVX test only if AVX is supported. */
+ if (avx_enabled ())
+- {
+- __m256i ymm = _mm256_setzero_si256 ();
+- __m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
+-
+- ymm = _mm256_set1_epi32 (0x12349876);
+- if (memcmp (&ymm, &ret, sizeof (ret)))
+- abort ();
+- }
+- return 0;
+-}
+-#else
+-static int
+-do_test (void)
+-{
+- return 0;
++ return tst_audit4_aux ();
++ else
++ return 77;
+ }
+-#endif
+
+ #define TEST_FUNCTION do_test ()
+ #include "../../test-skeleton.c"