fgetws implementation.
[kopensolaris-gnu/glibc.git] / elf / dl-close.c
index 94978ed..a738b11 100644 (file)
@@ -1,5 +1,5 @@
 /* Close a shared object opened by `_dl_open'.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 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
@@ -57,8 +57,8 @@ _dl_close (struct link_map *map)
       return;
     }
 
-  list = map->l_searchlist;
-  nsearchlist = map->l_nsearchlist;
+  list = map->l_searchlist.r_list;
+  nsearchlist = map->l_searchlist.r_nlist;
 
   /* Call all termination functions at once.  */
   for (i = 0; i < nsearchlist; ++i)
@@ -103,21 +103,23 @@ _dl_close (struct link_map *map)
          if (imap->l_global)
            {
              /* This object is in the global scope list.  Remove it.  */
-             struct link_map **tail = _dl_global_scope_end;
+             int cnt = _dl_main_searchlist->r_nlist;
+
              do
-               --tail;
-             while (*tail != imap);
-             while (tail < _dl_global_scope_end)
-               {
-                 tail[0] = tail[1];
-                 ++tail;
-               }
-             --_dl_global_scope_end;
+               --cnt;
+             while (_dl_main_searchlist->r_list[cnt] != imap);
+
+             /* The object was already correctly registered.  */
+             while (++cnt < _dl_main_searchlist->r_nlist)
+               _dl_main_searchlist->r_list[cnt - 1]
+                 = _dl_main_searchlist->r_list[cnt];
+
+             --_dl_main_searchlist->r_nlist;
            }
 
          /* We can unmap all the maps at once.  We determined the
-            length when we loaded the object and `munmap' call does
-            the rest.  */
+            start address and length when we loaded the object and
+            the `munmap' call does the rest.  */
          __munmap ((void *) imap->l_map_start,
                    imap->l_map_end - imap->l_map_start);
 
@@ -135,16 +137,15 @@ _dl_close (struct link_map *map)
 #endif
          if (imap->l_next)
            imap->l_next->l_prev = imap->l_prev;
-         if (imap->l_searchlist && imap->l_searchlist != list)
-           free (imap->l_searchlist);
 
          if (imap->l_versions != NULL)
            free (imap->l_versions);
-         if (imap->l_origin != NULL)
+         if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
            free ((char *) imap->l_origin);
 
-         /* These names always is allocated.  */
+         /* This name always is allocated.  */
          free (imap->l_name);
+         /* Remove the list with all the names of the shared object.  */
          lnp = imap->l_libname;
          do
            {
@@ -154,12 +155,41 @@ _dl_close (struct link_map *map)
            }
          while (lnp != NULL);
 
+         /* Remove the searchlists.  */
+         if (imap->l_searchlist.r_duplist != imap->l_searchlist.r_list)
+           {
+             /* If a r_list exists there always also is a r_duplist.  */
+             assert (imap->l_searchlist.r_list != NULL);
+             free (imap->l_searchlist.r_duplist);
+           }
+         if (imap != map && imap->l_searchlist.r_list != NULL)
+           free (imap->l_searchlist.r_list);
+
+         if (imap->l_phdr_allocated)
+           free ((void *) imap->l_phdr);
+
          free (imap);
        }
     }
 
   free (list);
 
+  if (_dl_global_scope_alloc != 0
+      && _dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist)
+    {
+      /* All object dynamically loaded by the program are unloaded.  Free
+        the memory allocated for the global scope variable.  */
+      struct link_map **old = _dl_main_searchlist->r_list;
+
+      /* Put the old map in.  */
+      _dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
+      /* Signal that the original map is used.  */
+      _dl_global_scope_alloc = 0;
+
+      /* Now free the old map.  */
+      free (old);
+    }
+
   /* Notify the debugger those objects are finalized and gone.  */
   _r_debug.r_state = RT_CONSISTENT;
   _dl_debug_state ();