File ld-prelink-unique.diff of Package glibc

2010-03-23  Jakub Jelinek  <jakub@redhat.com>

	* elf/dl-lookup.c (do_lookup_x): If tab->entries is NULL,
	but tab->size != 0, just unlock and goto success, without
	allocating anything or entering anything into the hash table.
	(_dl_debug_bindings): Temporarily set tab->entries to NULL
	around do_lookup_x in undef_map->l_local_scope[0].

--- libc/elf/dl-lookup.c.jj	2009-12-16 00:10:37.000000000 +0100
+++ libc/elf/dl-lookup.c	2010-03-23 11:03:45.850560036 +0100
@@ -1,5 +1,6 @@
 /* Look up a symbol in the loaded objects.
-   Copyright (C) 1995-2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1995-2005, 2006, 2007, 2009, 2010
+   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
@@ -414,6 +415,20 @@ do_lookup_x (const char *undef_name, uin
 		  assert (!RTLD_CHECK_FOREIGN_CALL);
 #endif
 
+#ifdef SHARED
+		  /* If tab->entries is NULL, but tab->size is not, it means
+		     this is the second, conflict finding, lookup for
+		     LD_TRACE_PRELINKING in _dl_debug_bindings.  Don't
+		     allocate anything and don't enter anything into the
+		     hash table.  */
+		  if (__builtin_expect (tab->size, 0))
+		    {
+		      assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
+		      __rtld_lock_unlock_recursive (tab->lock);
+		      goto success;
+		    }
+#endif
+
 #define INITIAL_NUNIQUE_SYM_TABLE 31
 		  size = INITIAL_NUNIQUE_SYM_TABLE;
 		  entries = calloc (sizeof (struct unique_sym), size);
@@ -917,13 +932,17 @@ _dl_debug_bindings (const char *undef_na
 	{
 	  const uint_fast32_t new_hash = dl_new_hash (undef_name);
 	  unsigned long int old_hash = 0xffffffff;
+	  struct unique_sym *saved_entries
+	    = GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries;
 
+	  GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL;
 	  do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
 		       undef_map->l_local_scope[0], 0, version, 0, NULL,
 		       type_class, undef_map);
 
 	  if (val.s != value->s || val.m != value->m)
 	    conflict = 1;
+	  GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries;
 	}
 
       if (value->s)
openSUSE Build Service is sponsored by