Update.
authorUlrich Drepper <drepper@redhat.com>
Mon, 3 Apr 2000 03:51:04 +0000 (03:51 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 3 Apr 2000 03:51:04 +0000 (03:51 +0000)
2000-04-02  Ulrich Drepper  <drepper@redhat.com>

* elf/dl-fini.c (_dl_fini): Increment j counter after swapping in
element at this position.

* elf/Versions [ld.so] (GLIBC_2.2): Export _dl_load_lock.
* elf/link.h (struct link_map): Add l_reldepsmax, l_reldepsact, and
l_reldeps elements.
* elf/dl-lookup.c (add_dependency): New function.
(_dl_lookup_symbol): Use it whenever symbol was found in a global,
dynamically loaded object.
(_dl_lookup_symbol_skip): Likewise.
(_dl_lookup_versioned_symbol): Likewise.
(_dl_lookup_versioned_symbol_skip): Likewise.
* elf/dl-open.c: Don't define _dl_load_lock here...
* elf/rtld.c: ...but here...
* elf/dl-support.c: ...and here.
* elf/dl-close.c (_dl_close): Close also dependent objects introduce
through relocation.
* elf/dl-fini.c (_dl_fini): Also take dependencies introduced through
relocations.
* dlfcn/Makefile (glrefmain.out): Test is not expected to fail
anymore.
* dlfcn/glrefmain.c: Add one more debug message.

* Makeconfig (preprocess-versions): Don't add $(CPPFLAGS) to compiler
command line.
* Makerules (sysd-versions): Use ( ) instead of { }.

* elf/dl-load.c: Use __builtin_expect to signal that compiler should
optimize for the non-debugging case.
* elf/dl-lookup.c: Likewise.
* sysdeps/generic/libc-start.c: Likewise.

14 files changed:
ChangeLog
Makeconfig
Makerules
dlfcn/glrefmain.c
elf/Versions
elf/dl-close.c
elf/dl-fini.c
elf/dl-load.c
elf/dl-lookup.c
elf/dl-open.c
elf/dl-support.c
elf/link.h
elf/rtld.c
sysdeps/generic/libc-start.c

index 4e585d1..7775af3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2000-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/dl-fini.c (_dl_fini): Increment j counter after swapping in
+       element at this position.
+
+       * elf/Versions [ld.so] (GLIBC_2.2): Export _dl_load_lock.
+       * elf/link.h (struct link_map): Add l_reldepsmax, l_reldepsact, and
+       l_reldeps elements.
+       * elf/dl-lookup.c (add_dependency): New function.
+       (_dl_lookup_symbol): Use it whenever symbol was found in a global,
+       dynamically loaded object.
+       (_dl_lookup_symbol_skip): Likewise.
+       (_dl_lookup_versioned_symbol): Likewise.
+       (_dl_lookup_versioned_symbol_skip): Likewise.
+       * elf/dl-open.c: Don't define _dl_load_lock here...
+       * elf/rtld.c: ...but here...
+       * elf/dl-support.c: ...and here.
+       * elf/dl-close.c (_dl_close): Close also dependent objects introduce
+       through relocation.
+       * elf/dl-fini.c (_dl_fini): Also take dependencies introduced through
+       relocations.
+       * dlfcn/Makefile (glrefmain.out): Test is not expected to fail
+       anymore.
+       * dlfcn/glrefmain.c: Add one more debug message.
+
+       * Makeconfig (preprocess-versions): Don't add $(CPPFLAGS) to compiler
+       command line.
+       * Makerules (sysd-versions): Use ( ) instead of { }.
+
+       * elf/dl-load.c: Use __builtin_expect to signal that compiler should
+       optimize for the non-debugging case.
+       * elf/dl-lookup.c: Likewise.
+       * sysdeps/generic/libc-start.c: Likewise.
+
 2000-04-02  Roland McGrath  <roland@baalperazim.frob.com>
 
        * sysdeps/mach/hurd/i386/init-first.c: Replace PIC #ifdefs with SHARED.
index 70b933c..8ae477a 100644 (file)
@@ -674,7 +674,7 @@ ifeq (yes, $(build-shared))
 # %ifdef et al based on config.h settings or other %include'd files.
 define preprocess-versions
 sed 's/#.*$$//;s/^[    ]*%/#/' \
-| $(CC) $(CPPFLAGS) -E -undef -include $(common-objpfx)config.h -x c - \
+| $(CC) -E -undef -include $(common-objpfx)config.h -x c - \
 | sed 's/#.*$$//;/^[   ]*$$/d'
 endef
 
index 28fc884..731ad0e 100644 (file)
--- a/Makerules
+++ b/Makerules
@@ -306,13 +306,13 @@ $(common-objpfx)sysd-versions: $(common-objpfx)Versions.all \
                               $(wildcard $(all-subdirs:%=$(..)%/Versions)) \
                               $(wildcard $(sysdirs:%=%/Versions)) \
                               $(sysd-versions-force)
-       { echo 'sysd-versions-subdirs = $(all-subdirs) $(config-sysdirs)' ; \
+       ( echo 'sysd-versions-subdirs = $(all-subdirs) $(config-sysdirs)' ; \
          cat $(filter-out $< $(word 2,$^) $(sysd-versions-force),$^) \
          | $(preprocess-versions) \
          | LC_ALL=C $(AWK) -v buildroot=$(common-objpfx) -v defsfile=$< \
                            -v move_if_change='$(move-if-change)' \
                            -f $(word 2,$^); \
-       } > $@T
+       ) > $@T
        mv -f $@T $@
 endif # avoid-generated
 endif # $(versioning) = yes
index 32854b1..efb080a 100644 (file)
@@ -70,6 +70,9 @@ do_test (void)
 
   dlclose (d2);
 
+  puts ("glreflib2 also closed");
+  fflush (stdout);
+
   return 0;
 }
 
index 791fcee..26fd7d6 100644 (file)
@@ -52,7 +52,7 @@ ld.so {
     _dl_dst_count; _dl_dst_substitute;
   }
   GLIBC_2.2 {
-    _dl_init;
+    _dl_init; _dl_load_lock;
 
     # this is defined in ld.so and overridden by libc
     _dl_init_first;
index a301479..a58e8f8 100644 (file)
@@ -43,8 +43,10 @@ internal_function
 _dl_close (void *_map)
 {
   struct link_map **list;
+  struct link_map **rellist;
   struct link_map *map = _map;
-  unsigned nsearchlist;
+  unsigned int nsearchlist;
+  unsigned int nrellist;
   unsigned int i;
 
   if (map->l_opencount == 0)
@@ -65,6 +67,9 @@ _dl_close (void *_map)
   list = map->l_searchlist.r_list;
   nsearchlist = map->l_searchlist.r_nlist;
 
+  rellist = map->l_reldeps;
+  nrellist = map->l_reldepsact;
+
   /* Call all termination functions at once.  */
   for (i = 0; i < nsearchlist; ++i)
     {
@@ -192,6 +197,16 @@ _dl_close (void *_map)
        }
     }
 
+  /* Now we can perhaps also remove the modules for which we had
+     dependencies because of symbol lookup.  */
+  if (rellist != NULL)
+    {
+      while (nrellist-- > 0)
+       _dl_close (rellist[nrellist]);
+
+      free (rellist);
+    }
+
   free (list);
 
   if (_dl_global_scope_alloc != 0
index 61dedd5..fd22bc0 100644 (file)
@@ -87,18 +87,41 @@ _dl_fini (void)
                    memmove (&maps[j] + 1,
                             &maps[j],
                             (k - j) * sizeof (struct link_map *));
-                   maps[j] = here;
+                   maps[j++] = here;
 
                    break;
                  }
                else
                  ++runp;
            }
+
+         if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
+           {
+             unsigned int m = maps[k]->l_reldepsact;
+             struct link_map **relmaps = maps[k]->l_reldeps;
+
+             while (m-- > 0)
+               {
+                 if (relmaps[m] == l)
+                   {
+                     struct link_map *here = maps[k];
+
+                     /* Move it now.  */
+                     memmove (&maps[j] + 1,
+                              &maps[j],
+                              (k - j) * sizeof (struct link_map *));
+                     maps[j] = here;
+
+                     break;
+                   }
+
+               }
+           }
        }
     }
 
   /* `maps' now contains the objects in the right order.  Now call the
-     destructors.  We have the process this array from the front.  */
+     destructors.  We have to process this array from the front.  */
   for (i = 0; i < nloaded; ++i)
     {
       l = maps[i];
index 5d1463b..e57de81 100644 (file)
@@ -748,7 +748,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
       }
 
   /* Print debugging message.  */
-  if (_dl_debug_files)
+  if (__builtin_expect (_dl_debug_files, 0))
     _dl_debug_message (1, "file=", name, ";  generating link map\n", NULL);
 
   /* Read the header directly.  */
@@ -1046,7 +1046,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 
   l->l_entry += l->l_addr;
 
-  if (_dl_debug_files)
+  if (__builtin_expect (_dl_debug_files, 0))
     {
       const size_t nibbles = sizeof (void *) * 2;
       char buf1[nibbles + 1];
@@ -1182,7 +1182,8 @@ open_path (const char *name, size_t namelen, int preloaded,
 
       /* If we are debugging the search for libraries print the path
         now if it hasn't happened now.  */
-      if (_dl_debug_libs && current_what != this_dir->what)
+      if (__builtin_expect (_dl_debug_libs, 0)
+         && current_what != this_dir->what)
        {
          current_what = this_dir->what;
          print_search_path (dirs, current_what, this_dir->where);
@@ -1202,7 +1203,7 @@ open_path (const char *name, size_t namelen, int preloaded,
             - buf);
 
          /* Print name we try if this is wanted.  */
-         if (_dl_debug_libs)
+         if (__builtin_expect (_dl_debug_libs, 0))
            _dl_debug_message (1, "  trying file=", buf, "\n", NULL);
 
          fd = __open (buf, O_RDONLY);
@@ -1316,7 +1317,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
     }
 
   /* Display information if we are debugging.  */
-  if (_dl_debug_files && loader != NULL)
+  if (__builtin_expect (_dl_debug_files, 0) && loader != NULL)
     _dl_debug_message (1, "\nfile=", name, ";  needed by ",
                       loader->l_name[0] ? loader->l_name : _dl_argv[0],
                       "\n", NULL);
@@ -1327,7 +1328,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 
       size_t namelen = strlen (name) + 1;
 
-      if (_dl_debug_libs)
+      if (__builtin_expect (_dl_debug_libs, 0))
        _dl_debug_message (1, "find library=", name, "; searching\n", NULL);
 
       fd = -1;
@@ -1411,7 +1412,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
        fd = open_path (name, namelen, preloaded, rtld_search_dirs, &realname);
 
       /* Add another newline when we a tracing the library loading.  */
-      if (_dl_debug_libs)
+      if (__builtin_expect (_dl_debug_libs, 0))
         _dl_debug_message (1, "\n", NULL);
     }
   else
index 702fd3b..7ac8770 100644 (file)
    Boston, MA 02111-1307, USA.  */
 
 #include <alloca.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <ldsodefs.h>
 #include "dl-hash.h"
 #include <dl-machine.h>
+#include <bits/libc-lock.h>
 
 #include <assert.h>
 
@@ -59,6 +61,15 @@ struct sym_val
 /* Statistics function.  */
 unsigned long int _dl_num_relocations;
 
+/* During the program run we must not modify the global data of
+   loaded shared object simultanously in two threads.  Therefore we
+   protect `_dl_open' and `_dl_close' in dl-close.c.
+
+   This must be a recursive lock since the initializer function of
+   the loaded object might as well require a call to this function.
+   At this time it is not anymore a problem to modify the tables.  */
+__libc_lock_define (extern, _dl_load_lock)
+
 
 /* We have two different situations when looking up a simple: with or
    without versioning.  gcc is not able to optimize a single function
@@ -70,6 +81,105 @@ unsigned long int _dl_num_relocations;
 #include "do-lookup.h"
 
 
+/* Add extra dependency on MAP to UNDEF_MAP.  */
+static int
+add_dependency (struct link_map *undef_map, struct link_map *map)
+{
+  struct link_map **list;
+  unsigned act;
+  unsigned int i;
+  int result = 0;
+
+  /* Make sure nobody can unload the object while we are at it.  */
+  __libc_lock_lock (_dl_load_lock);
+
+  /* Determine whether UNDEF_MAP already has a reference to MAP.  First
+     look in the normal dependencies.  */
+  list = undef_map->l_searchlist.r_list;
+  act = undef_map->l_searchlist.r_nlist;
+
+  for (i = 0; i < act; ++i)
+    if (list[i] == map)
+      break;
+
+  if (__builtin_expect (i, act) == act)
+    {
+      /* No normal dependency.  See whether we already had to add it
+        to the special list of dynamic dependencies.  */
+      list = undef_map->l_reldeps;
+      act = undef_map->l_reldepsact;
+
+      for (i = 0; i < act; ++i)
+       if (list[i] == map)
+         break;
+
+      if (i == act)
+       {
+         /* The object is not yet in the dependency list.  Before we add
+            it make sure just one more time the object we are about to
+            reference is still available.  There is a brief period in
+            which the object could have been removed since we found the
+            definition.  */
+         struct link_map *runp = _dl_loaded;
+
+         while (runp != NULL && runp != map)
+           runp = runp->l_next;
+
+         if (runp != NULL)
+           {
+             /* The object is still available.  Add the reference now.  */
+             if (act >= undef_map->l_reldepsmax)
+               {
+                 /* Allocate more memory for the dependency list.  Since
+                    this can never happen during the startup phase we can
+                    use `realloc'.  */
+                 void *newp;
+
+                 undef_map->l_reldepsmax += 5;
+                 newp = realloc (undef_map->l_reldeps,
+                                 undef_map->l_reldepsmax);
+
+                 if (__builtin_expect (newp != NULL, 1))
+                   undef_map->l_reldeps = (struct link_map **) newp;
+                 else
+                   /* Correct the addition.  */
+                   undef_map->l_reldepsmax -= 5;
+               }
+
+             /* If we didn't manage to allocate memory for the list this
+                is no fatal mistake.  We simply increment the use counter
+                of the referenced object and don't record the dependencies.
+                This means this increment can never be reverted and the
+                object will never be unloaded.  This is semantically the
+                correct behaviour.  */
+             if (act < undef_map->l_reldepsmax)
+               undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
+
+             /* And increment the counter in the referenced object.  */
+             ++map->l_opencount;
+
+             /* Display information if we are debugging.  */
+             if (__builtin_expect (_dl_debug_files, 0))
+               _dl_debug_message (1, "\nfile=",
+                                  map->l_name[0] ? map->l_name : _dl_argv[0],
+                                  ";  needed by ",
+                                  undef_map->l_name[0]
+                                  ? undef_map->l_name : _dl_argv[0],
+                                  " (relocation dependency)\n\n", NULL);
+           }
+         else
+           /* Whoa, that was bad luck.  We have to search again.  */
+           result = -1;
+       }
+    }
+
+  /* Release the lock.  */
+  __libc_lock_unlock (_dl_load_lock);
+
+  return result;
+}
+
+
 /* Search loaded objects' symbol tables for a definition of the symbol
    UNDEF_NAME.  */
 
@@ -90,7 +200,24 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
   for (scope = symbol_scope; *scope; ++scope)
     if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
                   *scope, 0, NULL, reloc_type))
-      break;
+      {
+       /* We have to check whether this would bind UNDEF_MAP to an object
+          in the global scope which was dynamically loaded.  In this case
+          we have to prevent the latter from being unloaded unless the
+          UNDEF_MAP object is also unloaded.  */
+       if (current_value.m->l_global
+           && (__builtin_expect (current_value.m->l_type, lt_library)
+               == lt_loaded)
+           && undef_map != current_value.m
+           /* Add UNDEF_MAP to the dependencies.  */
+           && add_dependency (undef_map, current_value.m) < 0)
+         /* Something went wrong.  Perhaps the object we tried to reference
+            was just removed.  Try finding another definition.  */
+         return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
+                                   reloc_type);
+
+       break;
+      }
 
   if (current_value.s == NULL)
     {
@@ -104,7 +231,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
       return 0;
     }
 
-  if (_dl_debug_bindings)
+  if (__builtin_expect (_dl_debug_bindings, 0))
     _dl_debug_message (1, "binding file ",
                       (reference_name && reference_name[0]
                        ? reference_name
@@ -143,13 +270,47 @@ _dl_lookup_symbol_skip (const char *undef_name,
   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
     assert (i < (*scope)->r_nduplist);
 
-  if (i >= (*scope)->r_nlist
-      || ! do_lookup (undef_name, undef_map, hash, *ref, &current_value,
-                     *scope, i, skip_map, 0))
+  if (i < (*scope)->r_nlist
+      && do_lookup (undef_name, undef_map, hash, *ref, &current_value,
+                   *scope, i, skip_map, 0))
+    {
+      /* We have to check whether this would bind UNDEF_MAP to an object
+        in the global scope which was dynamically loaded.  In this case
+        we have to prevent the latter from being unloaded unless the
+        UNDEF_MAP object is also unloaded.  */
+      if (current_value.m->l_global
+         && (__builtin_expect (current_value.m->l_type, lt_library)
+             == lt_loaded)
+         && undef_map != current_value.m
+         /* Add UNDEF_MAP to the dependencies.  */
+         && add_dependency (undef_map, current_value.m) < 0)
+       /* Something went wrong.  Perhaps the object we tried to reference
+          was just removed.  Try finding another definition.  */
+       return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
+                                      symbol_scope, skip_map);
+    }
+  else
     while (*++scope)
       if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
                     *scope, 0, skip_map, 0))
-       break;
+       {
+         /* We have to check whether this would bind UNDEF_MAP to an object
+            in the global scope which was dynamically loaded.  In this case
+            we have to prevent the latter from being unloaded unless the
+            UNDEF_MAP object is also unloaded.  */
+         if (current_value.m->l_global
+             && (__builtin_expect (current_value.m->l_type, lt_library)
+                 == lt_loaded)
+             && undef_map != current_value.m
+             /* Add UNDEF_MAP to the dependencies.  */
+             && add_dependency (undef_map, current_value.m) < 0)
+           /* Something went wrong.  Perhaps the object we tried to reference
+              was just removed.  Try finding another definition.  */
+           return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
+                                          symbol_scope, skip_map);
+
+         break;
+       }
 
   if (current_value.s == NULL)
     {
@@ -157,7 +318,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
       return 0;
     }
 
-  if (_dl_debug_bindings)
+  if (__builtin_expect (_dl_debug_bindings, 0))
     _dl_debug_message (1, "binding file ",
                       (reference_name && reference_name[0]
                        ? reference_name
@@ -198,7 +359,25 @@ _dl_lookup_versioned_symbol (const char *undef_name,
                                     &current_value, *scope, 0, version, NULL,
                                     reloc_type);
       if (res > 0)
-       break;
+       {
+         /* We have to check whether this would bind UNDEF_MAP to an object
+            in the global scope which was dynamically loaded.  In this case
+            we have to prevent the latter from being unloaded unless the
+            UNDEF_MAP object is also unloaded.  */
+         if (current_value.m->l_global
+             && (__builtin_expect (current_value.m->l_type, lt_library)
+                 == lt_loaded)
+             && undef_map != current_value.m
+             /* Add UNDEF_MAP to the dependencies.  */
+             && add_dependency (undef_map, current_value.m) < 0)
+           /* Something went wrong.  Perhaps the object we tried to reference
+              was just removed.  Try finding another definition.  */
+           return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
+                                               symbol_scope, version,
+                                               reloc_type);
+
+         break;
+       }
 
       if (res < 0)
        {
@@ -232,7 +411,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
       return 0;
     }
 
-  if (_dl_debug_bindings)
+  if (__builtin_expect (_dl_debug_bindings, 0))
     _dl_debug_message (1, "binding file ",
                       (reference_name && reference_name[0]
                        ? reference_name
@@ -271,15 +450,49 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
     assert (i < (*scope)->r_nduplist);
 
-  if (i >= (*scope)->r_nlist
-      || ! do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                               &current_value, *scope, i, version, skip_map,
-                               0))
+  if (i < (*scope)->r_nlist
+      && do_lookup_versioned (undef_name, undef_map, hash, *ref,
+                             &current_value, *scope, i, version, skip_map, 0))
+    {
+      /* We have to check whether this would bind UNDEF_MAP to an object
+        in the global scope which was dynamically loaded.  In this case
+        we have to prevent the latter from being unloaded unless the
+        UNDEF_MAP object is also unloaded.  */
+      if (current_value.m->l_global
+         && (__builtin_expect (current_value.m->l_type, lt_library)
+             == lt_loaded)
+         && undef_map != current_value.m
+         /* Add UNDEF_MAP to the dependencies.  */
+         && add_dependency (undef_map, current_value.m) < 0)
+       /* Something went wrong.  Perhaps the object we tried to reference
+          was just removed.  Try finding another definition.  */
+       return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, ref,
+                                                symbol_scope, version,
+                                                skip_map);
+    }
+  else
     while (*++scope)
       if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
                               &current_value, *scope, 0, version, skip_map,
                               0))
-       break;
+       {
+         /* We have to check whether this would bind UNDEF_MAP to an object
+            in the global scope which was dynamically loaded.  In this case
+            we have to prevent the latter from being unloaded unless the
+            UNDEF_MAP object is also unloaded.  */
+         if (current_value.m->l_global
+             && (__builtin_expect (current_value.m->l_type, lt_library)
+                 == lt_loaded)
+             && undef_map != current_value.m
+             /* Add UNDEF_MAP to the dependencies.  */
+             && add_dependency (undef_map, current_value.m) < 0)
+           /* Something went wrong.  Perhaps the object we tried to reference
+              was just removed.  Try finding another definition.  */
+           return _dl_lookup_versioned_symbol_skip (undef_name, undef_map,
+                                                    ref, symbol_scope,
+                                                    version, skip_map);
+         break;
+       }
 
   if (current_value.s == NULL)
     {
@@ -298,7 +511,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
       return 0;
     }
 
-  if (_dl_debug_bindings)
+  if (__builtin_expect (_dl_debug_bindings, 0))
     _dl_debug_message (1, "binding file ",
                       (reference_name && reference_name[0]
                        ? reference_name
index f110a51..15ed24f 100644 (file)
@@ -63,7 +63,7 @@ static void show_scope (struct link_map *new);
    This must be a recursive lock since the initializer function of
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
-__libc_lock_define_initialized_recursive (, _dl_load_lock)
+__libc_lock_define (extern, _dl_load_lock)
 
 extern size_t _dl_platformlen;
 
index 8201ced..68973cc 100644 (file)
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <ldsodefs.h>
 #include <dl-machine.h>
+#include <bits/libc-lock.h>
 
 extern char *__progname;
 char **_dl_argv = &__progname; /* This is checked for some error messages.  */
@@ -81,6 +82,15 @@ struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist;
 /* Nonzero during startup.  */
 int _dl_starting_up = 1;
 
+/* During the program run we must not modify the global data of
+   loaded shared object simultanously in two threads.  Therefore we
+   protect `_dl_open' and `_dl_close' in dl-close.c.
+
+   This must be a recursive lock since the initializer function of
+   the loaded object might as well require a call to this function.
+   At this time it is not anymore a problem to modify the tables.  */
+__libc_lock_define_initialized_recursive (, _dl_load_lock)
+
 
 static void non_dynamic_init (void) __attribute__ ((unused));
 
index e4c2fea..0588b52 100644 (file)
@@ -208,6 +208,11 @@ struct link_map
 
     /* List of object in order of the init and fini calls.  */
     struct link_map **l_initfini;
+
+    /* List of the dependencies introduced through symbol binding.  */
+    unsigned int l_reldepsmax;
+    unsigned int l_reldepsact;
+    struct link_map **l_reldeps;
   };
 
 #endif /* link.h */
index 562e44a..24968f8 100644 (file)
@@ -27,6 +27,7 @@
 #include <entry.h>
 #include <fpu_control.h>
 #include <hp-timing.h>
+#include <bits/libc-lock.h>
 #include "dynamic-link.h"
 #include "dl-librecon.h"
 
@@ -105,6 +106,15 @@ struct r_scope_elem _dl_initial_searchlist;
 /* Array which is used when looking up in the global scope.  */
 struct r_scope_elem *_dl_global_scope[2];
 
+/* During the program run we must not modify the global data of
+   loaded shared object simultanously in two threads.  Therefore we
+   protect `_dl_open' and `_dl_close' in dl-close.c.
+
+   This must be a recursive lock since the initializer function of
+   the loaded object might as well require a call to this function.
+   At this time it is not anymore a problem to modify the tables.  */
+__libc_lock_define_initialized_recursive (, _dl_load_lock)
+
 /* Set nonzero during loading and initialization of executable and
    libraries, cleared before the executable's entry point runs.  This
    must not be initialized to nonzero, because the unused dynamic
index 6fabb7c..fe4966c 100644 (file)
@@ -56,11 +56,11 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
 
   /* Some security at this point.  Prevent starting a SUID binary where
      the standard file descriptors are not opened.  */
-  if (__libc_enable_secure)
+  if (__builtin_expect (__libc_enable_secure, 0))
     check_standard_fds ();
 
   /* Register the destructor of the dynamic linker if there is any.  */
-  if (rtld_fini != NULL)
+  if (__builtin_expect (rtld_fini != NULL, 1))
     atexit (rtld_fini);
 
   /* Call the initializer of the libc.  This is only needed here if we
@@ -76,14 +76,14 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
 
   /* Call the initializer of the program, if any.  */
 #ifdef SHARED
-  if (_dl_debug_impcalls)
+  if (__builtin_expect (_dl_debug_impcalls, 0))
     _dl_debug_message (1, "\ninitialize program: ", argv[0], "\n\n", NULL);
 #endif
   if (init)
     (*init) ();
 
 #ifdef SHARED
-  if (_dl_debug_impcalls)
+  if (__builtin_expect (_dl_debug_impcalls, 0))
     _dl_debug_message (1, "\ntransferring control: ", argv[0], "\n\n", NULL);
 #endif