diff --git a/aarch64-sigstksz.patch b/aarch64-sigstksz.patch
new file mode 100644
index 0000000..a405f0c
--- /dev/null
+++ b/aarch64-sigstksz.patch
@@ -0,0 +1,62 @@
+ [BZ #16850]
+ * sysdeps/unix/sysv/linux/aarch64/bits/sigstack.h: New file.
+
+Index: glibc-2.21/sysdeps/unix/sysv/linux/aarch64/bits/sigstack.h
+===================================================================
+--- /dev/null
++++ glibc-2.21/sysdeps/unix/sysv/linux/aarch64/bits/sigstack.h
+@@ -0,0 +1,54 @@
++/* sigstack, sigaltstack definitions.
++ Copyright (C) 2015 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ . */
++
++#ifndef _SIGNAL_H
++# error "Never include this file directly. Use instead"
++#endif
++
++
++/* Structure describing a signal stack (obsolete). */
++struct sigstack
++ {
++ void *ss_sp; /* Signal stack pointer. */
++ int ss_onstack; /* Nonzero if executing on this stack. */
++ };
++
++
++/* Possible values for `ss_flags.'. */
++enum
++{
++ SS_ONSTACK = 1,
++#define SS_ONSTACK SS_ONSTACK
++ SS_DISABLE
++#define SS_DISABLE SS_DISABLE
++};
++
++/* Minimum stack size for a signal handler. */
++#define MINSIGSTKSZ 5120
++
++/* System default stack size. */
++#define SIGSTKSZ 16384
++
++
++/* Alternate, preferred interface. */
++typedef struct sigaltstack
++ {
++ void *ss_sp;
++ int ss_flags;
++ size_t ss_size;
++ } stack_t;
diff --git a/glibc-testsuite.changes b/glibc-testsuite.changes
index 7805886..286bb78 100644
--- a/glibc-testsuite.changes
+++ b/glibc-testsuite.changes
@@ -1,3 +1,19 @@
+-------------------------------------------------------------------
+Thu Apr 2 08:11:20 UTC 2015 - schwab@suse.de
+
+- aarch64-sigstksz.patch: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+
+-------------------------------------------------------------------
+Mon Mar 30 09:04:49 UTC 2015 - schwab@suse.de
+
+- powerpc-software-sqrt.patch: Fix powerpc software sqrt (BZ #17964, BZ
+ #17967)
+- nss-separate-state-getXXent.patch: Separate internal state between
+ getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+- static-tls-dtv-limit.patch: Fix DTV race, assert, DTV_SURPLUS Static TLS
+ limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621,
+ BZ #17628)
+
-------------------------------------------------------------------
Mon Mar 9 13:05:32 UTC 2015 - schwab@suse.de
diff --git a/glibc-testsuite.spec b/glibc-testsuite.spec
index 93f2fa1..b6ba37f 100644
--- a/glibc-testsuite.spec
+++ b/glibc-testsuite.spec
@@ -235,8 +235,14 @@ Patch306: glibc-fix-double-loopback.diff
Patch1000: htm-tabort.patch
# PATCH-FIX-UPSTREAM Fix value of O_TMPFILE for architectures with non-default O_DIRECTORY (BZ #17912)
Patch1001: o-tmpfile.patch
-# PATH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
+# PATCH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
Patch1002: memcpy-chk-non-SSE2.patch
+# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
+Patch1003: pthread-mutexattr-gettype-kind.patch
+# PATCH-FIX-UPSTREAM Fix powerpc software sqrt (BZ #17964, BZ #17967)
+Patch1004: powerpc-software-sqrt.patch
+# PATCH-FIX-UPSTREAM Fix DTV race, assert, DTV_SURPLUS Static TLS limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621, BZ #17628)
+Patch1005: static-tls-dtv-limit.patch
###
# Patches awaiting upstream approval
@@ -251,10 +257,12 @@ Patch2003: abort-no-flush.patch
Patch2005: glibc-memset-nontemporal.diff
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
Patch2006: ibm93x-redundant-shift-si.patch
-# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
-Patch2007: pthread-mutexattr-gettype-kind.patch
# PATCH-FIX-UPSTREAM Rewrite handling of nameserver configuration in resolver
-Patch2008: resolv-nameserver-handling.patch
+Patch2007: resolv-nameserver-handling.patch
+# PATCH-FIX-UPSTREAM Separate internal state between getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+Patch2008: nss-separate-state-getXXent.patch
+# PATCH-FIX-UPSTREAM aarch64: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+Patch2009: aarch64-sigstksz.patch
# Non-glibc patches
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
@@ -458,6 +466,9 @@ rm nscd/s-stamp
%patch1000 -p1
%patch1001 -p1
%patch1002 -p1
+%patch1003 -p1
+%patch1004 -p1
+%patch1005 -p1
%patch2000 -p1
%patch2002 -p1
@@ -466,6 +477,7 @@ rm nscd/s-stamp
%patch2006 -p1
%patch2007 -p1
%patch2008 -p1
+%patch2009 -p1
%patch3000
diff --git a/glibc-utils.changes b/glibc-utils.changes
index 7805886..286bb78 100644
--- a/glibc-utils.changes
+++ b/glibc-utils.changes
@@ -1,3 +1,19 @@
+-------------------------------------------------------------------
+Thu Apr 2 08:11:20 UTC 2015 - schwab@suse.de
+
+- aarch64-sigstksz.patch: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+
+-------------------------------------------------------------------
+Mon Mar 30 09:04:49 UTC 2015 - schwab@suse.de
+
+- powerpc-software-sqrt.patch: Fix powerpc software sqrt (BZ #17964, BZ
+ #17967)
+- nss-separate-state-getXXent.patch: Separate internal state between
+ getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+- static-tls-dtv-limit.patch: Fix DTV race, assert, DTV_SURPLUS Static TLS
+ limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621,
+ BZ #17628)
+
-------------------------------------------------------------------
Mon Mar 9 13:05:32 UTC 2015 - schwab@suse.de
diff --git a/glibc-utils.spec b/glibc-utils.spec
index a02a571..4d14ed7 100644
--- a/glibc-utils.spec
+++ b/glibc-utils.spec
@@ -234,8 +234,14 @@ Patch306: glibc-fix-double-loopback.diff
Patch1000: htm-tabort.patch
# PATCH-FIX-UPSTREAM Fix value of O_TMPFILE for architectures with non-default O_DIRECTORY (BZ #17912)
Patch1001: o-tmpfile.patch
-# PATH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
+# PATCH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
Patch1002: memcpy-chk-non-SSE2.patch
+# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
+Patch1003: pthread-mutexattr-gettype-kind.patch
+# PATCH-FIX-UPSTREAM Fix powerpc software sqrt (BZ #17964, BZ #17967)
+Patch1004: powerpc-software-sqrt.patch
+# PATCH-FIX-UPSTREAM Fix DTV race, assert, DTV_SURPLUS Static TLS limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621, BZ #17628)
+Patch1005: static-tls-dtv-limit.patch
###
# Patches awaiting upstream approval
@@ -250,10 +256,12 @@ Patch2003: abort-no-flush.patch
Patch2005: glibc-memset-nontemporal.diff
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
Patch2006: ibm93x-redundant-shift-si.patch
-# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
-Patch2007: pthread-mutexattr-gettype-kind.patch
# PATCH-FIX-UPSTREAM Rewrite handling of nameserver configuration in resolver
-Patch2008: resolv-nameserver-handling.patch
+Patch2007: resolv-nameserver-handling.patch
+# PATCH-FIX-UPSTREAM Separate internal state between getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+Patch2008: nss-separate-state-getXXent.patch
+# PATCH-FIX-UPSTREAM aarch64: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+Patch2009: aarch64-sigstksz.patch
# Non-glibc patches
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
@@ -458,6 +466,9 @@ rm nscd/s-stamp
%patch1000 -p1
%patch1001 -p1
%patch1002 -p1
+%patch1003 -p1
+%patch1004 -p1
+%patch1005 -p1
%patch2000 -p1
%patch2002 -p1
@@ -466,6 +477,7 @@ rm nscd/s-stamp
%patch2006 -p1
%patch2007 -p1
%patch2008 -p1
+%patch2009 -p1
%patch3000
diff --git a/glibc.changes b/glibc.changes
index 7805886..286bb78 100644
--- a/glibc.changes
+++ b/glibc.changes
@@ -1,3 +1,19 @@
+-------------------------------------------------------------------
+Thu Apr 2 08:11:20 UTC 2015 - schwab@suse.de
+
+- aarch64-sigstksz.patch: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+
+-------------------------------------------------------------------
+Mon Mar 30 09:04:49 UTC 2015 - schwab@suse.de
+
+- powerpc-software-sqrt.patch: Fix powerpc software sqrt (BZ #17964, BZ
+ #17967)
+- nss-separate-state-getXXent.patch: Separate internal state between
+ getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+- static-tls-dtv-limit.patch: Fix DTV race, assert, DTV_SURPLUS Static TLS
+ limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621,
+ BZ #17628)
+
-------------------------------------------------------------------
Mon Mar 9 13:05:32 UTC 2015 - schwab@suse.de
diff --git a/glibc.spec b/glibc.spec
index 171f596..f7d1dbf 100644
--- a/glibc.spec
+++ b/glibc.spec
@@ -235,8 +235,14 @@ Patch306: glibc-fix-double-loopback.diff
Patch1000: htm-tabort.patch
# PATCH-FIX-UPSTREAM Fix value of O_TMPFILE for architectures with non-default O_DIRECTORY (BZ #17912)
Patch1001: o-tmpfile.patch
-# PATH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
+# PATCH-FIX-UPSTREAM Fix __memcpy_chk on non-SSE2 CPUs (BZ #17949)
Patch1002: memcpy-chk-non-SSE2.patch
+# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
+Patch1003: pthread-mutexattr-gettype-kind.patch
+# PATCH-FIX-UPSTREAM Fix powerpc software sqrt (BZ #17964, BZ #17967)
+Patch1004: powerpc-software-sqrt.patch
+# PATCH-FIX-UPSTREAM Fix DTV race, assert, DTV_SURPLUS Static TLS limit, and nptl_db garbage (bsc#919678, BZ #17090, BZ #17620, BZ #17621, BZ #17628)
+Patch1005: static-tls-dtv-limit.patch
###
# Patches awaiting upstream approval
@@ -251,10 +257,12 @@ Patch2003: abort-no-flush.patch
Patch2005: glibc-memset-nontemporal.diff
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
Patch2006: ibm93x-redundant-shift-si.patch
-# PATCH-FIX-UPSTREAM Filter out PTHREAD_MUTEX_NO_ELISION_NP bit in pthread_mutexattr_gettype (BZ #15790)
-Patch2007: pthread-mutexattr-gettype-kind.patch
# PATCH-FIX-UPSTREAM Rewrite handling of nameserver configuration in resolver
-Patch2008: resolv-nameserver-handling.patch
+Patch2007: resolv-nameserver-handling.patch
+# PATCH-FIX-UPSTREAM Separate internal state between getXXent and getXXbyYY NSS calls (bsc#918187, BZ #18007)
+Patch2008: nss-separate-state-getXXent.patch
+# PATCH-FIX-UPSTREAM aarch64: Increase MINSIGSTKSZ and SIGSTKSZ (BZ #16850)
+Patch2009: aarch64-sigstksz.patch
# Non-glibc patches
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
@@ -458,6 +466,9 @@ rm nscd/s-stamp
%patch1000 -p1
%patch1001 -p1
%patch1002 -p1
+%patch1003 -p1
+%patch1004 -p1
+%patch1005 -p1
%patch2000 -p1
%patch2002 -p1
@@ -466,6 +477,7 @@ rm nscd/s-stamp
%patch2006 -p1
%patch2007 -p1
%patch2008 -p1
+%patch2009 -p1
%patch3000
diff --git a/nss-separate-state-getXXent.patch b/nss-separate-state-getXXent.patch
new file mode 100644
index 0000000..10b4dea
--- /dev/null
+++ b/nss-separate-state-getXXent.patch
@@ -0,0 +1,715 @@
+ [BZ #18007]
+ * nis/nss_compat/compat-grp.c (internal_endgrent): Add parameter
+ needent, call nss_endgrent only if non-zero.
+ (_nss_compat_endgrent): Pass non-zero.
+ (_nss_compat_getgrnam_r, _nss_compat_getgrgid_r): Pass zero.
+ * nis/nss_compat/compat-pwd.c (internal_endpwent): Add parameter
+ needent, call nss_endpwent only if non-zero.
+ (_nss_compat_endpwent): Pass non-zero.
+ (_nss_compat_getpwnam_r, _nss_compat_getpwuid_r): Pass zero.
+ * nis/nss_compat/compat-spwd.c (internal_setspent): Add parameter
+ needent, call nss_setspent only if non-zero.
+ (_nss_compat_setspent): Pass non-zero.
+ (internal_endspent): Add parameter needent, call nss_endspent only
+ if non-zero.
+ (_nss_compat_endspent, _nss_compat_getspent_r): Pass non-zero.
+ (_nss_compat_getspnam_r): Pass zero.
+ * nss/nss_files/files-XXX.c (position, last_use, keep_stream):
+ Remove. All uses removed.
+ (internal_setent): Remove parameter stayopen, add parameter
+ stream. Use it instead of global variable.
+ (CONCAT(_nss_files_set,ENTNAME)): Pass global stream.
+ (internal_endent, internal_getent): Add parameter stream. Use it
+ instead of global variable.
+ (CONCAT(_nss_files_end,ENTNAME))
+ (CONCAT(_nss_files_get,ENTNAME_r)): Pass global stream.
+ (_nss_files_get##name##_r): Pass local stream. Remove locking.
+ * nss/nss_files/files-alias.c (position, last_use): Remove. All
+ uses removed.
+ (internal_setent, internal_endent): Add parameter stream. Use it
+ instead of global variable.
+ (_nss_files_setaliasent, _nss_files_endaliasent): Pass global
+ stream.
+ (get_next_alias): Add parameter stream.
+ (_nss_files_getaliasent_r): Pass global stream.
+ (_nss_files_getaliasbyname_r): Pass local stream. Remove locking.
+ * nss/nss_files/files-hosts.c (_nss_files_gethostbyname3_r)
+ (_nss_files_gethostbyname4_r): Pass local stream to
+ internal_setent, internal_getent and internal_endent. Remove
+ locking.
+
+Index: glibc-2.21/nis/nss_compat/compat-grp.c
+===================================================================
+--- glibc-2.21.orig/nis/nss_compat/compat-grp.c
++++ glibc-2.21/nis/nss_compat/compat-grp.c
+@@ -192,9 +192,9 @@ _nss_compat_setgrent (int stayopen)
+
+
+ static enum nss_status
+-internal_endgrent (ent_t *ent)
++internal_endgrent (ent_t *ent, int needent)
+ {
+- if (nss_endgrent)
++ if (needent && nss_endgrent)
+ nss_endgrent ();
+
+ if (ent->stream != NULL)
+@@ -222,7 +222,7 @@ _nss_compat_endgrent (void)
+
+ __libc_lock_lock (lock);
+
+- result = internal_endgrent (&ext_ent);
++ result = internal_endgrent (&ext_ent, 1);
+
+ __libc_lock_unlock (lock);
+
+@@ -532,7 +532,7 @@ _nss_compat_getgrnam_r (const char *name
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
+
+- internal_endgrent (&ent);
++ internal_endgrent (&ent, 0);
+
+ return result;
+ }
+@@ -661,7 +661,7 @@ _nss_compat_getgrgid_r (gid_t gid, struc
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
+
+- internal_endgrent (&ent);
++ internal_endgrent (&ent, 0);
+
+ return result;
+ }
+Index: glibc-2.21/nis/nss_compat/compat-pwd.c
+===================================================================
+--- glibc-2.21.orig/nis/nss_compat/compat-pwd.c
++++ glibc-2.21/nis/nss_compat/compat-pwd.c
+@@ -309,9 +309,9 @@ _nss_compat_setpwent (int stayopen)
+
+
+ static enum nss_status
+-internal_endpwent (ent_t *ent)
++internal_endpwent (ent_t *ent, int needent)
+ {
+- if (nss_endpwent)
++ if (needent && nss_endpwent)
+ nss_endpwent ();
+
+ if (ent->stream != NULL)
+@@ -346,7 +346,7 @@ _nss_compat_endpwent (void)
+
+ __libc_lock_lock (lock);
+
+- result = internal_endpwent (&ext_ent);
++ result = internal_endpwent (&ext_ent, 1);
+
+ __libc_lock_unlock (lock);
+
+@@ -871,7 +871,7 @@ _nss_compat_getpwnam_r (const char *name
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
+
+- internal_endpwent (&ent);
++ internal_endpwent (&ent, 0);
+
+ return result;
+ }
+@@ -1110,7 +1110,7 @@ _nss_compat_getpwuid_r (uid_t uid, struc
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
+
+- internal_endpwent (&ent);
++ internal_endpwent (&ent, 0);
+
+ return result;
+ }
+Index: glibc-2.21/nis/nss_compat/compat-spwd.c
+===================================================================
+--- glibc-2.21.orig/nis/nss_compat/compat-spwd.c
++++ glibc-2.21/nis/nss_compat/compat-spwd.c
+@@ -169,7 +169,7 @@ copy_spwd_changes (struct spwd *dest, st
+ }
+
+ static enum nss_status
+-internal_setspent (ent_t *ent, int stayopen)
++internal_setspent (ent_t *ent, int stayopen, int needent)
+ {
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+@@ -239,7 +239,7 @@ internal_setspent (ent_t *ent, int stayo
+
+ give_spwd_free (&ent->pwd);
+
+- if (status == NSS_STATUS_SUCCESS && nss_setspent)
++ if (needent && status == NSS_STATUS_SUCCESS && nss_setspent)
+ ent->setent_status = nss_setspent (stayopen);
+
+ return status;
+@@ -256,7 +256,7 @@ _nss_compat_setspent (int stayopen)
+ if (ni == NULL)
+ init_nss_interface ();
+
+- result = internal_setspent (&ext_ent, stayopen);
++ result = internal_setspent (&ext_ent, stayopen, 1);
+
+ __libc_lock_unlock (lock);
+
+@@ -265,9 +265,9 @@ _nss_compat_setspent (int stayopen)
+
+
+ static enum nss_status
+-internal_endspent (ent_t *ent)
++internal_endspent (ent_t *ent, int needent)
+ {
+- if (nss_endspent)
++ if (needent && nss_endspent)
+ nss_endspent ();
+
+ if (ent->stream != NULL)
+@@ -303,7 +303,7 @@ _nss_compat_endspent (void)
+
+ __libc_lock_lock (lock);
+
+- result = internal_endspent (&ext_ent);
++ result = internal_endspent (&ext_ent, 1);
+
+ __libc_lock_unlock (lock);
+
+@@ -658,7 +658,7 @@ _nss_compat_getspent_r (struct spwd *pwd
+ init_nss_interface ();
+
+ if (ext_ent.stream == NULL)
+- result = internal_setspent (&ext_ent, 1);
++ result = internal_setspent (&ext_ent, 1, 1);
+
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop);
+@@ -830,12 +830,12 @@ _nss_compat_getspnam_r (const char *name
+
+ __libc_lock_unlock (lock);
+
+- result = internal_setspent (&ent, 0);
++ result = internal_setspent (&ent, 0, 0);
+
+ if (result == NSS_STATUS_SUCCESS)
+ result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop);
+
+- internal_endspent (&ent);
++ internal_endspent (&ent, 0);
+
+ return result;
+ }
+Index: glibc-2.21/nss/nss_files/files-XXX.c
+===================================================================
+--- glibc-2.21.orig/nss/nss_files/files-XXX.c
++++ glibc-2.21/nss/nss_files/files-XXX.c
+@@ -63,21 +63,18 @@ __libc_lock_define_initialized (static,
+ /* Maintenance of the shared stream open on the database file. */
+
+ static FILE *stream;
+-static fpos_t position;
+-static enum { nouse, getent, getby } last_use;
+-static int keep_stream;
+
+ /* Open database file if not already opened. */
+ static enum nss_status
+-internal_setent (int stayopen)
++internal_setent (FILE **stream)
+ {
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+- if (stream == NULL)
++ if (*stream == NULL)
+ {
+- stream = fopen (DATAFILE, "rce");
++ *stream = fopen (DATAFILE, "rce");
+
+- if (stream == NULL)
++ if (*stream == NULL)
+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+@@ -90,7 +87,7 @@ internal_setent (int stayopen)
+ int result;
+ int flags;
+
+- result = flags = fcntl (fileno (stream), F_GETFD, 0);
++ result = flags = fcntl (fileno (*stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ # ifdef O_CLOEXEC
+@@ -100,15 +97,15 @@ internal_setent (int stayopen)
+ # endif
+ {
+ flags |= FD_CLOEXEC;
+- result = fcntl (fileno (stream), F_SETFD, flags);
++ result = fcntl (fileno (*stream), F_SETFD, flags);
+ }
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+- fclose (stream);
+- stream = NULL;
++ fclose (*stream);
++ *stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
+@@ -116,11 +113,7 @@ internal_setent (int stayopen)
+ }
+ }
+ else
+- rewind (stream);
+-
+- /* Remember STAYOPEN flag. */
+- if (stream != NULL)
+- keep_stream |= stayopen;
++ rewind (*stream);
+
+ return status;
+ }
+@@ -134,16 +127,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stay
+
+ __libc_lock_lock (lock);
+
+- status = internal_setent (stayopen);
+-
+- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
+- {
+- fclose (stream);
+- stream = NULL;
+- status = NSS_STATUS_UNAVAIL;
+- }
+-
+- last_use = getent;
++ status = internal_setent (&stream);
+
+ __libc_lock_unlock (lock);
+
+@@ -153,12 +137,12 @@ CONCAT(_nss_files_set,ENTNAME) (int stay
+
+ /* Close the database file. */
+ static void
+-internal_endent (void)
++internal_endent (FILE **stream)
+ {
+- if (stream != NULL)
++ if (*stream != NULL)
+ {
+- fclose (stream);
+- stream = NULL;
++ fclose (*stream);
++ *stream = NULL;
+ }
+ }
+
+@@ -169,10 +153,7 @@ CONCAT(_nss_files_end,ENTNAME) (void)
+ {
+ __libc_lock_lock (lock);
+
+- internal_endent ();
+-
+- /* Reset STAYOPEN flag. */
+- keep_stream = 0;
++ internal_endent (&stream);
+
+ __libc_lock_unlock (lock);
+
+@@ -227,7 +208,7 @@ get_contents (char *linebuf, size_t len,
+
+ /* Parsing the database file into `struct STRUCTURE' data structures. */
+ static enum nss_status
+-internal_getent (struct STRUCTURE *result,
++internal_getent (FILE *stream, struct STRUCTURE *result,
+ char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO
+ EXTRA_ARGS_DECL)
+ {
+@@ -300,45 +281,14 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct
+ {
+ int save_errno = errno;
+
+- status = internal_setent (0);
++ status = internal_setent (&stream);
+
+ __set_errno (save_errno);
+-
+- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
+- {
+- fclose (stream);
+- stream = NULL;
+- status = NSS_STATUS_UNAVAIL;
+- }
+ }
+
+ if (status == NSS_STATUS_SUCCESS)
+- {
+- /* If the last use was not by the getent function we need the
+- position the stream. */
+- if (last_use != getent)
+- {
+- if (fsetpos (stream, &position) < 0)
+- status = NSS_STATUS_UNAVAIL;
+- else
+- last_use = getent;
+- }
+-
+- if (status == NSS_STATUS_SUCCESS)
+- {
+- status = internal_getent (result, buffer, buflen, errnop
+- H_ERRNO_ARG EXTRA_ARGS_VALUE);
+-
+- /* Remember this position if we were successful. If the
+- operation failed we give the user a chance to repeat the
+- operation (perhaps the buffer was too small). */
+- if (status == NSS_STATUS_SUCCESS)
+- fgetpos (stream, &position);
+- else
+- /* We must make sure we reposition the stream the next call. */
+- last_use = nouse;
+- }
+- }
++ status = internal_getent (stream, result, buffer, buflen, errnop
++ H_ERRNO_ARG EXTRA_ARGS_VALUE);
+
+ __libc_lock_unlock (lock);
+
+@@ -364,27 +314,20 @@ _nss_files_get##name##_r (proto,
+ size_t buflen, int *errnop H_ERRNO_PROTO) \
+ { \
+ enum nss_status status; \
++ FILE *stream = NULL; \
+ \
+- __libc_lock_lock (lock); \
+- \
+- /* Reset file pointer to beginning or open file. */ \
+- status = internal_setent (keep_stream); \
++ /* Open file. */ \
++ status = internal_setent (&stream); \
+ \
+ if (status == NSS_STATUS_SUCCESS) \
+ { \
+- /* Tell getent function that we have repositioned the file pointer. */ \
+- last_use = getby; \
+- \
+- while ((status = internal_getent (result, buffer, buflen, errnop \
++ while ((status = internal_getent (stream, result, buffer, buflen, errnop \
+ H_ERRNO_ARG EXTRA_ARGS_VALUE)) \
+ == NSS_STATUS_SUCCESS) \
+ { break_if_match } \
+ \
+- if (! keep_stream) \
+- internal_endent (); \
++ internal_endent (&stream); \
+ } \
+ \
+- __libc_lock_unlock (lock); \
+- \
+ return status; \
+ }
+Index: glibc-2.21/nss/nss_files/files-alias.c
+===================================================================
+--- glibc-2.21.orig/nss/nss_files/files-alias.c
++++ glibc-2.21/nss/nss_files/files-alias.c
+@@ -36,20 +36,18 @@ __libc_lock_define_initialized (static,
+ /* Maintenance of the shared stream open on the database file. */
+
+ static FILE *stream;
+-static fpos_t position;
+-static enum { nouse, getent, getby } last_use;
+
+
+ static enum nss_status
+-internal_setent (void)
++internal_setent (FILE **stream)
+ {
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+- if (stream == NULL)
++ if (*stream == NULL)
+ {
+- stream = fopen ("/etc/aliases", "rce");
++ *stream = fopen ("/etc/aliases", "rce");
+
+- if (stream == NULL)
++ if (*stream == NULL)
+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+@@ -62,7 +60,7 @@ internal_setent (void)
+ int result;
+ int flags;
+
+- result = flags = fcntl (fileno (stream), F_GETFD, 0);
++ result = flags = fcntl (fileno (*stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ # ifdef O_CLOEXEC
+@@ -72,14 +70,14 @@ internal_setent (void)
+ # endif
+ {
+ flags |= FD_CLOEXEC;
+- result = fcntl (fileno (stream), F_SETFD, flags);
++ result = fcntl (fileno (*stream), F_SETFD, flags);
+ }
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+- fclose (stream);
++ fclose (*stream);
+ stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+@@ -88,7 +86,7 @@ internal_setent (void)
+ }
+ }
+ else
+- rewind (stream);
++ rewind (*stream);
+
+ return status;
+ }
+@@ -102,16 +100,7 @@ _nss_files_setaliasent (void)
+
+ __libc_lock_lock (lock);
+
+- status = internal_setent ();
+-
+- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
+- {
+- fclose (stream);
+- stream = NULL;
+- status = NSS_STATUS_UNAVAIL;
+- }
+-
+- last_use = getent;
++ status = internal_setent (&stream);
+
+ __libc_lock_unlock (lock);
+
+@@ -121,12 +110,12 @@ _nss_files_setaliasent (void)
+
+ /* Close the database file. */
+ static void
+-internal_endent (void)
++internal_endent (FILE **stream)
+ {
+- if (stream != NULL)
++ if (*stream != NULL)
+ {
+- fclose (stream);
+- stream = NULL;
++ fclose (*stream);
++ *stream = NULL;
+ }
+ }
+
+@@ -137,7 +126,7 @@ _nss_files_endaliasent (void)
+ {
+ __libc_lock_lock (lock);
+
+- internal_endent ();
++ internal_endent (&stream);
+
+ __libc_lock_unlock (lock);
+
+@@ -146,7 +135,7 @@ _nss_files_endaliasent (void)
+
+ /* Parsing the database file into `struct aliasent' data structures. */
+ static enum nss_status
+-get_next_alias (const char *match, struct aliasent *result,
++get_next_alias (FILE *stream, const char *match, struct aliasent *result,
+ char *buffer, size_t buflen, int *errnop)
+ {
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+@@ -397,35 +386,16 @@ _nss_files_getaliasent_r (struct aliasen
+
+ /* Be prepared that the set*ent function was not called before. */
+ if (stream == NULL)
+- status = internal_setent ();
++ status = internal_setent (&stream);
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+- /* If the last use was not by the getent function we need the
+- position the stream. */
+- if (last_use != getent)
+- {
+- if (fsetpos (stream, &position) < 0)
+- status = NSS_STATUS_UNAVAIL;
+- else
+- last_use = getent;
+- }
+-
+- if (status == NSS_STATUS_SUCCESS)
+- {
+- result->alias_local = 1;
++ result->alias_local = 1;
+
+- /* Read lines until we get a definite result. */
+- do
+- status = get_next_alias (NULL, result, buffer, buflen, errnop);
+- while (status == NSS_STATUS_RETURN);
+-
+- /* If we successfully read an entry remember this position. */
+- if (status == NSS_STATUS_SUCCESS)
+- fgetpos (stream, &position);
+- else
+- last_use = nouse;
+- }
++ /* Read lines until we get a definite result. */
++ do
++ status = get_next_alias (stream, NULL, result, buffer, buflen, errnop);
++ while (status == NSS_STATUS_RETURN);
+ }
+
+ __libc_lock_unlock (lock);
+@@ -440,6 +410,7 @@ _nss_files_getaliasbyname_r (const char
+ {
+ /* Return next entry in host file. */
+ enum nss_status status = NSS_STATUS_SUCCESS;
++ FILE *stream = NULL;
+
+ if (name == NULL)
+ {
+@@ -447,11 +418,8 @@ _nss_files_getaliasbyname_r (const char
+ return NSS_STATUS_UNAVAIL;
+ }
+
+- __libc_lock_lock (lock);
+-
+- /* Open the stream or rest it. */
+- status = internal_setent ();
+- last_use = getby;
++ /* Open the stream. */
++ status = internal_setent (&stream);
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+@@ -459,13 +427,11 @@ _nss_files_getaliasbyname_r (const char
+
+ /* Read lines until we get a definite result. */
+ do
+- status = get_next_alias (name, result, buffer, buflen, errnop);
++ status = get_next_alias (stream, name, result, buffer, buflen, errnop);
+ while (status == NSS_STATUS_RETURN);
+ }
+
+- internal_endent ();
+-
+- __libc_lock_unlock (lock);
++ internal_endent (&stream);
+
+ return status;
+ }
+Index: glibc-2.21/nss/nss_files/files-hosts.c
+===================================================================
+--- glibc-2.21.orig/nss/nss_files/files-hosts.c
++++ glibc-2.21/nss/nss_files/files-hosts.c
+@@ -115,14 +115,13 @@ _nss_files_gethostbyname3_r (const char
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp, char **canonp)
+ {
++ FILE *stream = NULL;
+ uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data);
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+- __libc_lock_lock (lock);
+-
+- /* Reset file pointer to beginning or open file. */
+- enum nss_status status = internal_setent (keep_stream);
++ /* Open file. */
++ enum nss_status status = internal_setent (&stream);
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+@@ -130,10 +129,7 @@ _nss_files_gethostbyname3_r (const char
+ addresses to IPv6 addresses really the right thing to do? */
+ int flags = ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0);
+
+- /* Tell getent function that we have repositioned the file pointer. */
+- last_use = getby;
+-
+- while ((status = internal_getent (result, buffer, buflen, errnop,
++ while ((status = internal_getent (stream, result, buffer, buflen, errnop,
+ herrnop, af, flags))
+ == NSS_STATUS_SUCCESS)
+ {
+@@ -160,7 +156,7 @@ _nss_files_gethostbyname3_r (const char
+ bufferend = (char *) &result->h_aliases[naliases + 1];
+
+ again:
+- while ((status = internal_getent (&tmp_result_buf, tmp_buffer,
++ while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer,
+ tmp_buflen, errnop, herrnop, af,
+ flags))
+ == NSS_STATUS_SUCCESS)
+@@ -336,15 +332,12 @@ _nss_files_gethostbyname3_r (const char
+ free (tmp_buffer);
+ }
+
+- if (! keep_stream)
+- internal_endent ();
++ internal_endent (&stream);
+ }
+
+ if (canonp && status == NSS_STATUS_SUCCESS)
+ *canonp = result->h_name;
+
+- __libc_lock_unlock (lock);
+-
+ return status;
+ }
+
+@@ -373,16 +366,13 @@ _nss_files_gethostbyname4_r (const char
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp)
+ {
+- __libc_lock_lock (lock);
++ FILE *stream = NULL;
+
+- /* Reset file pointer to beginning or open file. */
+- enum nss_status status = internal_setent (keep_stream);
++ /* Open file. */
++ enum nss_status status = internal_setent (&stream);
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+- /* Tell getent function that we have repositioned the file pointer. */
+- last_use = getby;
+-
+ bool any = false;
+ bool got_canon = false;
+ while (1)
+@@ -394,7 +384,7 @@ _nss_files_gethostbyname4_r (const char
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ struct hostent result;
+- status = internal_getent (&result, buffer, buflen, errnop,
++ status = internal_getent (stream, &result, buffer, buflen, errnop,
+ herrnop, AF_UNSPEC, 0);
+ if (status != NSS_STATUS_SUCCESS)
+ break;
+@@ -470,8 +460,7 @@ _nss_files_gethostbyname4_r (const char
+ status = NSS_STATUS_SUCCESS;
+ }
+
+- if (! keep_stream)
+- internal_endent ();
++ internal_endent (&stream);
+ }
+ else if (status == NSS_STATUS_TRYAGAIN)
+ {
+@@ -484,7 +473,5 @@ _nss_files_gethostbyname4_r (const char
+ *herrnop = NO_DATA;
+ }
+
+- __libc_lock_unlock (lock);
+-
+ return status;
+ }
diff --git a/powerpc-software-sqrt.patch b/powerpc-software-sqrt.patch
new file mode 100644
index 0000000..d86b73f
--- /dev/null
+++ b/powerpc-software-sqrt.patch
@@ -0,0 +1,117 @@
+2015-02-13 Joseph Myers
+
+ [BZ #17967]
+ * sysdeps/powerpc/fpu/e_sqrtf.c (__slow_ieee754_sqrtf): Use
+ __builtin_fmaf instead of relying on contraction of a * b + c.
+
+2015-02-12 Joseph Myers
+
+ [BZ #17964]
+ * sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Use
+ __builtin_fma instead of relying on contraction of a * b + c.
+
+Index: glibc-2.21/sysdeps/powerpc/fpu/e_sqrt.c
+===================================================================
+--- glibc-2.21.orig/sysdeps/powerpc/fpu/e_sqrt.c
++++ glibc-2.21/sysdeps/powerpc/fpu/e_sqrt.c
+@@ -99,38 +99,41 @@ __slow_ieee754_sqrt (double x)
+ /* Here we have three Newton-Raphson iterations each of a
+ division and a square root and the remainder of the
+ argument reduction, all interleaved. */
+- sd = -(sg * sg - sx);
++ sd = -__builtin_fma (sg, sg, -sx);
+ fsgi = (xi0 + 0x40000000) >> 1 & 0x7ff00000;
+ sy2 = sy + sy;
+- sg = sy * sd + sg; /* 16-bit approximation to sqrt(sx). */
++ sg = __builtin_fma (sy, sd, sg); /* 16-bit approximation to
++ sqrt(sx). */
+
+ /* schedule the INSERT_WORDS (fsg, fsgi, 0) to get separation
+ between the store and the load. */
+ INSERT_WORDS (fsg, fsgi, 0);
+ iw_u.parts.msw = fsgi;
+ iw_u.parts.lsw = (0);
+- e = -(sy * sg - almost_half);
+- sd = -(sg * sg - sx);
++ e = -__builtin_fma (sy, sg, -almost_half);
++ sd = -__builtin_fma (sg, sg, -sx);
+ if ((xi0 & 0x7ff00000) == 0)
+ goto denorm;
+- sy = sy + e * sy2;
+- sg = sg + sy * sd; /* 32-bit approximation to sqrt(sx). */
++ sy = __builtin_fma (e, sy2, sy);
++ sg = __builtin_fma (sy, sd, sg); /* 32-bit approximation to
++ sqrt(sx). */
+ sy2 = sy + sy;
+ /* complete the INSERT_WORDS (fsg, fsgi, 0) operation. */
+ fsg = iw_u.value;
+- e = -(sy * sg - almost_half);
+- sd = -(sg * sg - sx);
+- sy = sy + e * sy2;
++ e = -__builtin_fma (sy, sg, -almost_half);
++ sd = -__builtin_fma (sg, sg, -sx);
++ sy = __builtin_fma (e, sy2, sy);
+ shx = sx * fsg;
+- sg = sg + sy * sd; /* 64-bit approximation to sqrt(sx),
+- but perhaps rounded incorrectly. */
++ sg = __builtin_fma (sy, sd, sg); /* 64-bit approximation to
++ sqrt(sx), but perhaps
++ rounded incorrectly. */
+ sy2 = sy + sy;
+ g = sg * fsg;
+- e = -(sy * sg - almost_half);
+- d = -(g * sg - shx);
+- sy = sy + e * sy2;
++ e = -__builtin_fma (sy, sg, -almost_half);
++ d = -__builtin_fma (g, sg, -shx);
++ sy = __builtin_fma (e, sy2, sy);
+ fesetenv_register (fe);
+- return g + sy * d;
++ return __builtin_fma (sy, d, g);
+ denorm:
+ /* For denormalised numbers, we normalise, calculate the
+ square root, and return an adjusted result. */
+Index: glibc-2.21/sysdeps/powerpc/fpu/e_sqrtf.c
+===================================================================
+--- glibc-2.21.orig/sysdeps/powerpc/fpu/e_sqrtf.c
++++ glibc-2.21/sysdeps/powerpc/fpu/e_sqrtf.c
+@@ -87,26 +87,28 @@ __slow_ieee754_sqrtf (float x)
+ /* Here we have three Newton-Raphson iterations each of a
+ division and a square root and the remainder of the
+ argument reduction, all interleaved. */
+- sd = -(sg * sg - sx);
++ sd = -__builtin_fmaf (sg, sg, -sx);
+ fsgi = (xi + 0x40000000) >> 1 & 0x7f800000;
+ sy2 = sy + sy;
+- sg = sy * sd + sg; /* 16-bit approximation to sqrt(sx). */
+- e = -(sy * sg - almost_half);
++ sg = __builtin_fmaf (sy, sd, sg); /* 16-bit approximation to
++ sqrt(sx). */
++ e = -__builtin_fmaf (sy, sg, -almost_half);
+ SET_FLOAT_WORD (fsg, fsgi);
+- sd = -(sg * sg - sx);
+- sy = sy + e * sy2;
++ sd = -__builtin_fmaf (sg, sg, -sx);
++ sy = __builtin_fmaf (e, sy2, sy);
+ if ((xi & 0x7f800000) == 0)
+ goto denorm;
+ shx = sx * fsg;
+- sg = sg + sy * sd; /* 32-bit approximation to sqrt(sx),
+- but perhaps rounded incorrectly. */
++ sg = __builtin_fmaf (sy, sd, sg); /* 32-bit approximation to
++ sqrt(sx), but perhaps
++ rounded incorrectly. */
+ sy2 = sy + sy;
+ g = sg * fsg;
+- e = -(sy * sg - almost_half);
+- d = -(g * sg - shx);
+- sy = sy + e * sy2;
++ e = -__builtin_fmaf (sy, sg, -almost_half);
++ d = -__builtin_fmaf (g, sg, -shx);
++ sy = __builtin_fmaf (e, sy2, sy);
+ fesetenv_register (fe);
+- return g + sy * d;
++ return __builtin_fmaf (sy, d, g);
+ denorm:
+ /* For denormalised numbers, we normalise, calculate the
+ square root, and return an adjusted result. */
diff --git a/static-tls-dtv-limit.patch b/static-tls-dtv-limit.patch
new file mode 100644
index 0000000..209153f
--- /dev/null
+++ b/static-tls-dtv-limit.patch
@@ -0,0 +1,641 @@
+2015-03-17 Alexandre Oliva
+
+ [BZ #17090]
+ [BZ #17620]
+ [BZ #17621]
+ [BZ #17628]
+ * NEWS: Update.
+ * elf/dl-tls.c (_dl_update_slotinfo): Clean up outdated DTV
+ entries with Static TLS too. Skip entries past the end of the
+ allocated DTV, from Alan Modra.
+ (tls_get_addr_tail): Update to glibc_likely/unlikely. Move
+ Static TLS DTV entry set up from...
+ (_dl_allocate_tls_init): ... here (fix modid assertion), ...
+ * elf/dl-reloc.c (_dl_nothread_init_static_tls): ... here...
+ * nptl/allocatestack.c (init_one_static_tls): ... and here...
+ * elf/dlopen.c (dl_open_worker): Drop l_tls_modid upper bound
+ for Static TLS.
+ * elf/tlsdeschtab.h (map_generation): Return size_t. Check
+ that the slot we find is associated with the given map before
+ using its generation count.
+ * nptl_db/db_info.c: Include ldsodefs.h.
+ (rtld_global, dtv_slotinfo_list, dtv_slotinfo): New typedefs.
+ * nptl_db/structs.def (DB_RTLD_VARIABLE): New macro.
+ (DB_MAIN_VARIABLE, DB_RTLD_GLOBAL_FIELD): Likewise.
+ (link_map::l_tls_offset): New struct field.
+ (dtv_t::counter): Likewise.
+ (rtld_global): New struct.
+ (_rtld_global): New rtld variable.
+ (dl_tls_dtv_slotinfo_list): New rtld global field.
+ (dtv_slotinfo_list): New struct.
+ (dtv_slotinfo): Likewise.
+ * nptl_db/td_symbol_list.c: Drop gnu/lib-names.h include.
+ (td_lookup): Rename to...
+ (td_mod_lookup): ... this. Use new mod parameter instead of
+ LIBPTHREAD_SO.
+ * nptl_db/td_thr_tlsbase.c: Include link.h.
+ (dtv_slotinfo_list, dtv_slotinfo): New functions.
+ (td_thr_tlsbase): Check DTV generation. Compute Static TLS
+ addresses even if the DTV is out of date or missing them.
+ * nptl_db/fetch-value.c (_td_locate_field): Do not refuse to
+ index zero-length arrays.
+ * nptl_db/thread_dbP.h: Include gnu/lib-names.h.
+ (td_lookup): Make it a macro implemented in terms of...
+ (td_mod_lookup): ... this declaration.
+ * nptl_db/db-symbols.awk (DB_RTLD_VARIABLE): Override.
+ (DB_MAIN_VARIABLE): Likewise.
+
+Index: glibc-2.21/elf/dl-open.c
+===================================================================
+--- glibc-2.21.orig/elf/dl-open.c
++++ glibc-2.21/elf/dl-open.c
+@@ -533,17 +533,7 @@ TLS generation counter wrapped! Please
+ && imap->l_tls_blocksize > 0)
+ {
+ /* For static TLS we have to allocate the memory here and
+- now. This includes allocating memory in the DTV. But we
+- cannot change any DTV other than our own. So, if we
+- cannot guarantee that there is room in the DTV we don't
+- even try it and fail the load.
+-
+- XXX We could track the minimum DTV slots allocated in
+- all threads. */
+- if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
+- _dl_signal_error (0, "dlopen", NULL, N_("\
+-cannot load any more object with static TLS"));
+-
++ now, but we can delay updating the DTV. */
+ imap->l_need_tls_init = 0;
+ #ifdef SHARED
+ /* Update the slot information data for at least the
+Index: glibc-2.21/elf/dl-reloc.c
+===================================================================
+--- glibc-2.21.orig/elf/dl-reloc.c
++++ glibc-2.21/elf/dl-reloc.c
+@@ -136,12 +136,6 @@ _dl_nothread_init_static_tls (struct lin
+ # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+ #endif
+
+- /* Fill in the DTV slot so that a later LD/GD access will find it. */
+- dtv_t *dtv = THREAD_DTV ();
+- assert (map->l_tls_modid <= dtv[-1].counter);
+- dtv[map->l_tls_modid].pointer.val = dest;
+- dtv[map->l_tls_modid].pointer.is_static = true;
+-
+ /* Initialize the memory. */
+ memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+ '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+Index: glibc-2.21/elf/dl-tls.c
+===================================================================
+--- glibc-2.21.orig/elf/dl-tls.c
++++ glibc-2.21/elf/dl-tls.c
+@@ -493,17 +493,14 @@ _dl_allocate_tls_init (void *result)
+ assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
+ maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+
++ dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
++ dtv[map->l_tls_modid].pointer.is_static = false;
++
+ if (map->l_tls_offset == NO_TLS_OFFSET
+ || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
+- {
+- /* For dynamically loaded modules we simply store
+- the value indicating deferred allocation. */
+- dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+- dtv[map->l_tls_modid].pointer.is_static = false;
+- continue;
+- }
++ continue;
+
+- assert (map->l_tls_modid == cnt);
++ assert (map->l_tls_modid == total + cnt);
+ assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
+ #if TLS_TCB_AT_TP
+ assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
+@@ -515,8 +512,6 @@ _dl_allocate_tls_init (void *result)
+ #endif
+
+ /* Copy the initialization image and clear the BSS part. */
+- dtv[map->l_tls_modid].pointer.val = dest;
+- dtv[map->l_tls_modid].pointer.is_static = true;
+ memset (__mempcpy (dest, map->l_tls_initimage,
+ map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+@@ -679,13 +674,16 @@ _dl_update_slotinfo (unsigned long int r
+ struct link_map *map = listp->slotinfo[cnt].map;
+ if (map == NULL)
+ {
+- /* If this modid was used at some point the memory
+- might still be allocated. */
+- if (! dtv[total + cnt].pointer.is_static
+- && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
++ if (dtv[-1].counter >= total + cnt)
+ {
+- free (dtv[total + cnt].pointer.val);
++ /* If this modid was used at some point the memory
++ might still be allocated. */
++ if (! dtv[total + cnt].pointer.is_static
++ && (dtv[total + cnt].pointer.val
++ != TLS_DTV_UNALLOCATED))
++ free (dtv[total + cnt].pointer.val);
+ dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
++ dtv[total + cnt].pointer.is_static = false;
+ }
+
+ continue;
+@@ -718,10 +716,8 @@ _dl_update_slotinfo (unsigned long int r
+ memalign and not malloc. */
+ free (dtv[modid].pointer.val);
+
+- /* This module is loaded dynamically- We defer memory
+- allocation. */
+- dtv[modid].pointer.is_static = false;
+ dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
++ dtv[modid].pointer.is_static = false;
+
+ if (modid == req_modid)
+ the_map = map;
+@@ -759,13 +755,12 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t
+ the_map = listp->slotinfo[idx].map;
+ }
+
+- again:
+ /* Make sure that, if a dlopen running in parallel forces the
+ variable into static storage, we'll wait until the address in the
+ static TLS block is set up, and use that. If we're undecided
+ yet, make sure we make the decision holding the lock as well. */
+- if (__builtin_expect (the_map->l_tls_offset
+- != FORCED_DYNAMIC_TLS_OFFSET, 0))
++ if (__glibc_unlikely (the_map->l_tls_offset
++ != FORCED_DYNAMIC_TLS_OFFSET))
+ {
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
+ if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
+@@ -773,22 +768,28 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t
+ the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+ }
+- else
++ else if (__glibc_likely (the_map->l_tls_offset
++ != FORCED_DYNAMIC_TLS_OFFSET))
+ {
++#if TLS_TCB_AT_TP
++ void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
++#elif TLS_DTV_AT_TP
++ void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
++#else
++# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
++#endif
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+- if (__builtin_expect (the_map->l_tls_offset
+- != FORCED_DYNAMIC_TLS_OFFSET, 1))
+- {
+- void *p = dtv[GET_ADDR_MODULE].pointer.val;
+- if (__glibc_unlikely (p == TLS_DTV_UNALLOCATED))
+- goto again;
+
+- return (char *) p + GET_ADDR_OFFSET;
+- }
++ dtv[GET_ADDR_MODULE].pointer.is_static = true;
++ dtv[GET_ADDR_MODULE].pointer.val = p;
++
++ return (char *) p + GET_ADDR_OFFSET;
+ }
++ else
++ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+ }
+ void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
+- dtv[GET_ADDR_MODULE].pointer.is_static = false;
++ assert (!dtv[GET_ADDR_MODULE].pointer.is_static);
+
+ return (char *) p + GET_ADDR_OFFSET;
+ }
+Index: glibc-2.21/elf/tlsdeschtab.h
+===================================================================
+--- glibc-2.21.orig/elf/tlsdeschtab.h
++++ glibc-2.21/elf/tlsdeschtab.h
+@@ -42,7 +42,7 @@ eq_tlsdesc (void *p, void *q)
+ return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
+ }
+
+-inline static int
++inline static size_t
+ map_generation (struct link_map *map)
+ {
+ size_t idx = map->l_tls_modid;
+@@ -58,7 +58,7 @@ map_generation (struct link_map *map)
+ we can assume that, if the generation count is zero, we
+ still haven't determined the generation count for this
+ module. */
+- if (listp->slotinfo[idx].gen)
++ if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
+ return listp->slotinfo[idx].gen;
+ else
+ break;
+Index: glibc-2.21/nptl/allocatestack.c
+===================================================================
+--- glibc-2.21.orig/nptl/allocatestack.c
++++ glibc-2.21/nptl/allocatestack.c
+@@ -1190,7 +1190,6 @@ __nptl_setxid (struct xid_command *cmdp)
+ static inline void __attribute__((always_inline))
+ init_one_static_tls (struct pthread *curp, struct link_map *map)
+ {
+- dtv_t *dtv = GET_DTV (TLS_TPADJ (curp));
+ # if TLS_TCB_AT_TP
+ void *dest = (char *) curp - map->l_tls_offset;
+ # elif TLS_DTV_AT_TP
+@@ -1199,11 +1198,9 @@ init_one_static_tls (struct pthread *cur
+ # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+ # endif
+
+- /* Fill in the DTV slot so that a later LD/GD access will find it. */
+- dtv[map->l_tls_modid].pointer.val = dest;
+- dtv[map->l_tls_modid].pointer.is_static = true;
+-
+- /* Initialize the memory. */
++ /* We cannot delay the initialization of the Static TLS area, since
++ it can be accessed with LE or IE, but since the DTV is only used
++ by GD and LD, we can delay its update to avoid a race. */
+ memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+ '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+ }
+Index: glibc-2.21/nptl_db/db-symbols.awk
+===================================================================
+--- glibc-2.21.orig/nptl_db/db-symbols.awk
++++ glibc-2.21/nptl_db/db-symbols.awk
+@@ -2,6 +2,8 @@
+ # we've just built. It checks for all the symbols used in td_symbol_list.
+
+ BEGIN {
++%define DB_RTLD_VARIABLE(name) /* Nothing. */
++%define DB_MAIN_VARIABLE(name) /* Nothing. */
+ %define DB_LOOKUP_NAME(idx, name) required[STRINGIFY (name)] = 1;
+ %define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) th_unique[STRINGIFY (name)] = 1;
+ %include "db-symbols.h"
+Index: glibc-2.21/nptl_db/db_info.c
+===================================================================
+--- glibc-2.21.orig/nptl_db/db_info.c
++++ glibc-2.21/nptl_db/db_info.c
+@@ -21,6 +21,7 @@
+ #include
+ #include "thread_dbP.h"
+ #include
++#include
+
+ typedef struct pthread pthread;
+ typedef struct pthread_key_struct pthread_key_struct;
+@@ -37,6 +38,9 @@ typedef struct
+ } dtv;
+
+ typedef struct link_map link_map;
++typedef struct rtld_global rtld_global;
++typedef struct dtv_slotinfo_list dtv_slotinfo_list;
++typedef struct dtv_slotinfo dtv_slotinfo;
+
+ /* Actually static in nptl/init.c, but we only need it for typeof. */
+ extern bool __nptl_initial_report_events;
+Index: glibc-2.21/nptl_db/fetch-value.c
+===================================================================
+--- glibc-2.21.orig/nptl_db/fetch-value.c
++++ glibc-2.21/nptl_db/fetch-value.c
+@@ -69,7 +69,8 @@ _td_locate_field (td_thragent_t *ta,
+ }
+ }
+
+- if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
++ if (idx != 0 && DB_DESC_NELEM (desc) != 0
++ && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
+ /* This is an internal indicator to callers with nonzero IDX
+ that the IDX value is too big. */
+ return TD_NOAPLIC;
+Index: glibc-2.21/nptl_db/structs.def
+===================================================================
+--- glibc-2.21.orig/nptl_db/structs.def
++++ glibc-2.21/nptl_db/structs.def
+@@ -22,6 +22,28 @@
+ # define STRUCTS_DEF_DEFAULTS 1
+ #endif
+
++#ifndef DB_RTLD_VARIABLE
++# define DB_RTLD_VARIABLE(name) DB_VARIABLE (name)
++#endif
++
++#ifndef DB_MAIN_VARIABLE
++# define DB_MAIN_VARIABLE(name) DB_VARIABLE (name)
++#endif
++
++#ifndef DB_RTLD_GLOBAL_FIELD
++# if !IS_IN (libpthread)
++# define DB_RTLD_GLOBAL_FIELD(field) \
++ DB_STRUCT_FIELD (rtld_global, _##field) \
++ DB_MAIN_VARIABLE (_##field)
++# elif defined SHARED
++# define DB_RTLD_GLOBAL_FIELD(field) \
++ DB_STRUCT_FIELD (rtld_global, _##field)
++# else
++# define DB_RTLD_GLOBAL_FIELD(field) \
++ DB_MAIN_VARIABLE (_##field)
++# endif
++#endif /* DB_RTLD_GLOBAL_FIELD */
++
+ DB_STRUCT (pthread)
+ DB_STRUCT_FIELD (pthread, list)
+ DB_STRUCT_FIELD (pthread, report_events)
+@@ -70,14 +92,31 @@ DB_STRUCT (pthread_key_data_level2)
+ DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data)
+
+ DB_STRUCT_FIELD (link_map, l_tls_modid)
++DB_STRUCT_FIELD (link_map, l_tls_offset)
+
+ DB_STRUCT_ARRAY_FIELD (dtv, dtv)
+ #define pointer_val pointer.val /* Field of anonymous struct in dtv_t. */
+ DB_STRUCT_FIELD (dtv_t, pointer_val)
++DB_STRUCT_FIELD (dtv_t, counter)
+ #if !IS_IN (libpthread) || TLS_TCB_AT_TP
+ DB_STRUCT_FIELD (pthread, dtvp)
+ #endif
+
++#if !(IS_IN (libpthread) && !defined SHARED)
++DB_STRUCT (rtld_global)
++DB_RTLD_VARIABLE (_rtld_global)
++#endif
++DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
++
++DB_STRUCT (dtv_slotinfo_list)
++DB_STRUCT_FIELD (dtv_slotinfo_list, len)
++DB_STRUCT_FIELD (dtv_slotinfo_list, next)
++DB_STRUCT_ARRAY_FIELD (dtv_slotinfo_list, slotinfo)
++
++DB_STRUCT (dtv_slotinfo)
++DB_STRUCT_FIELD (dtv_slotinfo, gen)
++DB_STRUCT_FIELD (dtv_slotinfo, map)
++
+ #ifdef STRUCTS_DEF_DEFAULTS
+ # undef DB_STRUCT_ARRAY_FIELD
+ # undef DB_ARRAY_VARIABLE
+Index: glibc-2.21/nptl_db/td_symbol_list.c
+===================================================================
+--- glibc-2.21.orig/nptl_db/td_symbol_list.c
++++ glibc-2.21/nptl_db/td_symbol_list.c
+@@ -18,7 +18,6 @@
+ . */
+
+ #include
+-#include
+ #include "thread_dbP.h"
+
+ static const char *symbol_list_arr[] =
+@@ -41,12 +40,12 @@ td_symbol_list (void)
+
+
+ ps_err_e
+-td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
++td_mod_lookup (struct ps_prochandle *ps, const char *mod,
++ int idx, psaddr_t *sym_addr)
+ {
+ ps_err_e result;
+ assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
+- result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx],
+- sym_addr);
++ result = ps_pglobal_lookup (ps, mod, symbol_list_arr[idx], sym_addr);
+
+ #ifdef HAVE_ASM_GLOBAL_DOT_NAME
+ /* For PowerPC, 64-bit uses dot symbols but 32-bit does not.
+Index: glibc-2.21/nptl_db/td_thr_tlsbase.c
+===================================================================
+--- glibc-2.21.orig/nptl_db/td_thr_tlsbase.c
++++ glibc-2.21/nptl_db/td_thr_tlsbase.c
+@@ -17,14 +17,118 @@
+ . */
+
+ #include "thread_dbP.h"
++#include
+
++/* Get the DTV slotinfo list head entry from the dynamic loader state
++ into *LISTHEAD. */
++static td_err_e
++dtv_slotinfo_list (td_thragent_t *ta,
++ psaddr_t *listhead)
++{
++ td_err_e err;
++ psaddr_t head;
++
++ if (ta->ta_addr__rtld_global == 0
++ && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
++ &ta->ta_addr__rtld_global) != PS_OK)
++ ta->ta_addr__rtld_global = (void*)-1;
++
++ if (ta->ta_addr__rtld_global != (void*)-1)
++ {
++ err = DB_GET_FIELD (head, ta, ta->ta_addr__rtld_global,
++ rtld_global, _dl_tls_dtv_slotinfo_list, 0);
++ if (err != TD_OK)
++ return err;
++ }
++ else
++ {
++ if (ta->ta_addr__dl_tls_dtv_slotinfo_list == 0
++ && td_mod_lookup (ta->ph, NULL, SYM__dl_tls_dtv_slotinfo_list,
++ &ta->ta_addr__dl_tls_dtv_slotinfo_list) != PS_OK)
++ return TD_ERR;
++
++ err = _td_fetch_value (ta, ta->ta_var__dl_tls_dtv_slotinfo_list,
++ SYM_DESC__dl_tls_dtv_slotinfo_list,
++ 0, ta->ta_addr__dl_tls_dtv_slotinfo_list, &head);
++ if (err != TD_OK)
++ return err;
++ }
++
++ *listhead = head;
++ return TD_OK;
++}
++
++/* Get the address of the DTV slotinfo entry for MODID into
++ *DTVSLOTINFO. */
++static td_err_e
++dtv_slotinfo (td_thragent_t *ta,
++ unsigned long int modid,
++ psaddr_t *dtvslotinfo)
++{
++ td_err_e err;
++ psaddr_t slot, temp;
++ size_t slbase = 0;
++
++ err = dtv_slotinfo_list (ta, &slot);
++ if (err != TD_OK)
++ return err;
++
++ while (slot)
++ {
++ /* Get the number of entries in this list entry's array. */
++ err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list, len, 0);
++ if (err != TD_OK)
++ return err;
++ size_t len = (uintptr_t)temp;
++
++ /* Did we find the list entry for modid? */
++ if (modid < slbase + len)
++ break;
++
++ /* We didn't, so get the next list entry. */
++ slbase += len;
++ err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list,
++ next, 0);
++ if (err != TD_OK)
++ return err;
++ slot = temp;
++ }
++
++ /* We reached the end of the list and found nothing. */
++ if (!slot)
++ return TD_ERR;
++
++ /* Take the slotinfo for modid from the list entry. */
++ err = DB_GET_FIELD_ADDRESS (temp, ta, slot, dtv_slotinfo_list,
++ slotinfo, modid - slbase);
++ if (err != TD_OK)
++ return err;
++ slot = temp;
++
++ *dtvslotinfo = slot;
++ return TD_OK;
++}
++
++/* Return in *BASE the base address of the TLS block for MODID within
++ TH.
++
++ It should return success and yield the correct pointer in any
++ circumstance where the TLS block for the module and thread
++ requested has already been initialized.
++
++ It should fail with TD_TLSDEFER only when the thread could not
++ possibly have observed any values in that TLS block. That way, the
++ debugger can fall back to showing initial values from the PT_TLS
++ segment (and refusing attempts to mutate) for the TD_TLSDEFER case,
++ and never fail to make the values the program will actually see
++ available to the user of the debugger. */
+ td_err_e
+ td_thr_tlsbase (const td_thrhandle_t *th,
+ unsigned long int modid,
+ psaddr_t *base)
+ {
+ td_err_e err;
+- psaddr_t dtv, dtvslot, dtvptr;
++ psaddr_t dtv, dtvslot, dtvptr, temp;
+
+ if (modid < 1)
+ return TD_NOTLS;
+@@ -50,11 +154,75 @@ td_thr_tlsbase (const td_thrhandle_t *th
+ return TD_TLSDEFER;
+ }
+
++ err = dtv_slotinfo (th->th_ta_p, modid, &temp);
++ if (err != TD_OK)
++ return err;
++
++ psaddr_t slot;
++ err = DB_GET_STRUCT (slot, th->th_ta_p, temp, dtv_slotinfo);
++ if (err != TD_OK)
++ return err;
++
++ /* Take the link_map from the slotinfo. */
++ psaddr_t map;
++ err = DB_GET_FIELD_LOCAL (map, th->th_ta_p, slot, dtv_slotinfo, map, 0);
++ if (err != TD_OK)
++ return err;
++ if (!map)
++ return TD_ERR;
++
++ /* Ok, the modid is good, now find out what DTV generation it
++ requires. */
++ err = DB_GET_FIELD_LOCAL (temp, th->th_ta_p, slot, dtv_slotinfo, gen, 0);
++ if (err != TD_OK)
++ return err;
++ size_t modgen = (uintptr_t)temp;
++
+ /* Get the DTV pointer from the thread descriptor. */
+ err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
+ if (err != TD_OK)
+ return err;
+
++ psaddr_t dtvgenloc;
++ /* Get the DTV generation count at dtv[0].counter. */
++ err = DB_GET_FIELD_ADDRESS (dtvgenloc, th->th_ta_p, dtv, dtv, dtv, 0);
++ if (err != TD_OK)
++ return err;
++ err = DB_GET_FIELD (temp, th->th_ta_p, dtvgenloc, dtv_t, counter, 0);
++ if (err != TD_OK)
++ return err;
++ size_t dtvgen = (uintptr_t)temp;
++
++ /* Is the DTV current enough? */
++ if (dtvgen < modgen)
++ {
++ try_static_tls:
++ /* If the module uses Static TLS, we're still good. */
++ err = DB_GET_FIELD (temp, th->th_ta_p, map, link_map, l_tls_offset, 0);
++ if (err != TD_OK)
++ return err;
++ ptrdiff_t tlsoff = (uintptr_t)temp;
++
++ if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
++ && tlsoff != NO_TLS_OFFSET)
++ {
++ psaddr_t tp = pd;
++
++#if TLS_TCB_AT_TP
++ dtvptr = tp - tlsoff;
++#elif TLS_DTV_AT_TP
++ dtvptr = tp + tlsoff + TLS_PRE_TCB_SIZE;
++#else
++# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
++#endif
++
++ *base = dtvptr;
++ return TD_OK;
++ }
++
++ return TD_TLSDEFER;
++ }
++
+ /* Find the corresponding entry in the DTV. */
+ err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
+ if (err != TD_OK)
+@@ -68,7 +236,7 @@ td_thr_tlsbase (const td_thrhandle_t *th
+ /* It could be that the memory for this module is not allocated for
+ the given thread. */
+ if ((uintptr_t) dtvptr & 1)
+- return TD_TLSDEFER;
++ goto try_static_tls;
+
+ *base = dtvptr;
+ return TD_OK;
+Index: glibc-2.21/nptl_db/thread_dbP.h
+===================================================================
+--- glibc-2.21.orig/nptl_db/thread_dbP.h
++++ glibc-2.21/nptl_db/thread_dbP.h
+@@ -29,6 +29,7 @@
+ #include "thread_db.h"
+ #include "../nptl/pthreadP.h" /* This is for *_BITMASK only. */
+ #include
++#include
+
+ /* Indeces for the symbol names. */
+ enum
+@@ -139,11 +140,11 @@ ta_ok (const td_thragent_t *ta)
+ }
+
+
+-/* Internal wrapper around ps_pglobal_lookup. */
+-extern ps_err_e td_lookup (struct ps_prochandle *ps,
+- int idx, psaddr_t *sym_addr) attribute_hidden;
+-
+-
++/* Internal wrappers around ps_pglobal_lookup. */
++extern ps_err_e td_mod_lookup (struct ps_prochandle *ps, const char *modname,
++ int idx, psaddr_t *sym_addr) attribute_hidden;
++#define td_lookup(ps, idx, sym_addr) \
++ td_mod_lookup ((ps), LIBPTHREAD_SO, (idx), (sym_addr))
+
+
+ /* Store in psaddr_t VAR the address of inferior's symbol NAME. */