From f6bfeb3fce1dd949de73a4b91112f31c3d853369 Mon Sep 17 00:00:00 2001
From: "Yury G. Kudryashov" <urkud.urkud@gmail.com>
Date: Wed, 24 Aug 2011 20:22:27 +0000
Subject: [PATCH] Apply glibc-elf-localscope patch from OpenSUSE

This fixes a lot of crashes in KDE background processes

svn path=/nixpkgs/branches/stdenv-updates/; revision=28796
---
 .../glibc-2.12/glibc-elf-localscope.patch     | 82 +++++++++++++++++++
 .../libraries/glibc-2.13/common.nix           |  2 +
 2 files changed, 84 insertions(+)
 create mode 100644 pkgs/development/libraries/glibc-2.12/glibc-elf-localscope.patch

diff --git a/pkgs/development/libraries/glibc-2.12/glibc-elf-localscope.patch b/pkgs/development/libraries/glibc-2.12/glibc-elf-localscope.patch
new file mode 100644
index 00000000000..98f7f81087b
--- /dev/null
+++ b/pkgs/development/libraries/glibc-2.12/glibc-elf-localscope.patch
@@ -0,0 +1,82 @@
+diff -ru a/elf/dl-close.c b/elf/dl-close.c
+--- a/elf/dl-close.c	2011-02-04 00:35:03.000000000 +0100
++++ b/elf/dl-close.c	2011-02-22 02:16:12.367883000 +0100
+@@ -180,24 +186,28 @@
+       /* Signal the object is still needed.  */
+       l->l_idx = IDX_STILL_USED;
+ 
++#define mark_used(dmap) \
++  do {								\
++    if ((dmap)->l_idx != IDX_STILL_USED)			\
++      {								\
++	assert ((dmap)->l_idx >= 0 && (dmap)->l_idx < nloaded);	\
++								\
++	if (!used[(dmap)->l_idx])				\
++	  {							\
++	    used[(dmap)->l_idx] = 1;				\
++	    if ((dmap)->l_idx - 1 < done_index)			\
++	      done_index = (dmap)->l_idx - 1;			\
++	  }							\
++      }								\
++  } while (0)
++
+       /* Mark all dependencies as used.  */
+       if (l->l_initfini != NULL)
+ 	{
+ 	  struct link_map **lp = &l->l_initfini[1];
+ 	  while (*lp != NULL)
+ 	    {
+-	      if ((*lp)->l_idx != IDX_STILL_USED)
+-		{
+-		  assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
+-
+-		  if (!used[(*lp)->l_idx])
+-		    {
+-		      used[(*lp)->l_idx] = 1;
+-		      if ((*lp)->l_idx - 1 < done_index)
+-			done_index = (*lp)->l_idx - 1;
+-		    }
+-		}
+-
++	      mark_used(*lp);
+ 	      ++lp;
+ 	    }
+ 	}
+@@ -206,19 +216,25 @@
+ 	for (unsigned int j = 0; j < l->l_reldeps->act; ++j)
+ 	  {
+ 	    struct link_map *jmap = l->l_reldeps->list[j];
+-
+-	    if (jmap->l_idx != IDX_STILL_USED)
+-	      {
+-		assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
+-
+-		if (!used[jmap->l_idx])
+-		  {
+-		    used[jmap->l_idx] = 1;
+-		    if (jmap->l_idx - 1 < done_index)
+-		      done_index = jmap->l_idx - 1;
+-		  }
+-	      }
++	    mark_used(jmap);
+ 	  }
++      /* And the same for owners of our scopes; normally, our last
++	 scope provider would render us unused, but this can be
++	 prevented by the NODELETE flag. */
++      if (__builtin_expect(l->l_type == lt_loaded
++	                   && (l->l_flags_1 & DF_1_NODELETE), 0))
++	for (size_t cnt = 0; l->l_scope[cnt] != NULL; ++cnt)
++	  /* This relies on l_scope[] entries being always set either
++	     to its own l_symbolic_searchlist address, or some map's
++	     l_searchlist address.  */
++	  if (l->l_scope[cnt] != &l->l_symbolic_searchlist)
++	    {
++	      struct link_map *ls = (struct link_map *)
++		((char *) l->l_scope[cnt]
++		 - offsetof (struct link_map, l_searchlist));
++	      assert (ls->l_ns == nsid);
++	      mark_used(ls);
++	    }
+     }
+ 
+   /* Sort the entries.  */
diff --git a/pkgs/development/libraries/glibc-2.13/common.nix b/pkgs/development/libraries/glibc-2.13/common.nix
index 460deb1019b..c6ea06cc117 100644
--- a/pkgs/development/libraries/glibc-2.13/common.nix
+++ b/pkgs/development/libraries/glibc-2.13/common.nix
@@ -74,6 +74,8 @@ stdenv.mkDerivation ({
     /* Allow nixos and nix handle the locale-archive. */
     ./nix-locale-archive.patch
 
+    /* Without this patch many KDE binaries crash. */
+    ./glibc-elf-localscope.patch
   ];
 
   postPatch = ''