From d6f647d0471d6e82b51ed49f8241749e1fef7c8684abf2919f94690e2fd4ad77 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Wed, 1 Apr 2015 09:51:42 +0000 Subject: [PATCH] Accepting request 293890 from home:Andreas_Schwab:Factory - 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) OBS-URL: https://build.opensuse.org/request/show/293890 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=398 --- glibc-testsuite.changes | 11 + glibc-testsuite.spec | 17 +- glibc-utils.changes | 11 + glibc-utils.spec | 17 +- glibc.changes | 11 + glibc.spec | 17 +- nss-separate-state-getXXent.patch | 715 ++++++++++++++++++++++++++++++ powerpc-software-sqrt.patch | 117 +++++ static-tls-dtv-limit.patch | 641 ++++++++++++++++++++++++++ 9 files changed, 1545 insertions(+), 12 deletions(-) create mode 100644 nss-separate-state-getXXent.patch create mode 100644 powerpc-software-sqrt.patch create mode 100644 static-tls-dtv-limit.patch diff --git a/glibc-testsuite.changes b/glibc-testsuite.changes index 7805886..cde2af6 100644 --- a/glibc-testsuite.changes +++ b/glibc-testsuite.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +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..381bc6a 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,10 @@ 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 # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -458,6 +464,9 @@ rm nscd/s-stamp %patch1000 -p1 %patch1001 -p1 %patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 %patch2000 -p1 %patch2002 -p1 diff --git a/glibc-utils.changes b/glibc-utils.changes index 7805886..cde2af6 100644 --- a/glibc-utils.changes +++ b/glibc-utils.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +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..73335dc 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,10 @@ 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 # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -458,6 +464,9 @@ rm nscd/s-stamp %patch1000 -p1 %patch1001 -p1 %patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 %patch2000 -p1 %patch2002 -p1 diff --git a/glibc.changes b/glibc.changes index 7805886..cde2af6 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +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..65c74e0 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,10 @@ 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 # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -458,6 +464,9 @@ rm nscd/s-stamp %patch1000 -p1 %patch1001 -p1 %patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 %patch2000 -p1 %patch2002 -p1 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. */