fgetws implementation.
[kopensolaris-gnu/glibc.git] / elf / dl-close.c
index a260539..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
@@ -103,17 +103,17 @@ _dl_close (struct link_map *map)
          if (imap->l_global)
            {
              /* This object is in the global scope list.  Remove it.  */
-             unsigned int cnt = _dl_main_searchlist->r_nlist;
+             int cnt = _dl_main_searchlist->r_nlist;
 
              do
                --cnt;
              while (_dl_main_searchlist->r_list[cnt] != imap);
-             while (cnt < _dl_main_searchlist->r_nlist)
-               {
-                 _dl_main_searchlist->r_list[0]
-                   = _dl_main_searchlist->r_list[1];
-                 ++cnt;
-               }
+
+             /* 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;
            }
 
@@ -140,7 +140,7 @@ _dl_close (struct link_map *map)
 
          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);
 
          /* This name always is allocated.  */
@@ -165,12 +165,31 @@ _dl_close (struct link_map *map)
          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 ();