OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [dl/] [dl-close.c] - Blame information for rev 158

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Close a shared object opened by `_dl_open'.
2
   Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
 
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
 
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
 
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
19
 
20
#include <assert.h>
21
#include <dlfcn.h>
22
#include <libintl.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <bits/libc-lock.h>
26
#include <ldsodefs.h>
27
#include <sys/types.h>
28
#include <sys/mman.h>
29
 
30
 
31
/* Type of the constructor functions.  */
32
typedef void (*fini_t) (void);
33
 
34
 
35
void
36
internal_function
37
_dl_close (void *_map)
38
{
39
  struct reldep_list
40
  {
41
    struct link_map **rellist;
42
    unsigned int nrellist;
43
    struct reldep_list *next;
44
  } *reldeps = NULL;
45
  struct link_map **list;
46
  struct link_map *map = _map;
47
  unsigned int i;
48
  unsigned int *new_opencount;
49
 
50
  /* First see whether we can remove the object at all.  */
51
  if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
52
      && map->l_init_called)
53
    /* Nope.  Do nothing.  */
54
    return;
55
 
56
  if (__builtin_expect (map->l_opencount, 1) == 0)
57
    _dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
58
 
59
  /* Acquire the lock.  */
60
#ifdef HAVE_DD_LOCK
61
    __lock_acquire(_dl_load_lock);
62
#endif
63
 
64
 
65
  /* Decrement the reference count.  */
66
  if (map->l_opencount > 1 || map->l_type != lt_loaded)
67
    {
68
      /* There are still references to this object.  Do nothing more.  */
69
      if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
70
        _dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
71
                          map->l_name, map->l_opencount);
72
 
73
      /* One decrement the object itself, not the dependencies.  */
74
      --map->l_opencount;
75
 
76
#ifdef HAVE_DD_LOCK
77
        __lock_release(_dl_load_lock);
78
#endif
79
 
80
      return;
81
    }
82
 
83
  list = map->l_initfini;
84
 
85
  /* Compute the new l_opencount values.  */
86
  i = map->l_searchlist.r_nlist;
87
  if (__builtin_expect (i == 0, 0))
88
    /* This can happen if we handle relocation dependencies for an
89
       object which wasn't loaded directly.  */
90
    for (i = 1; list[i] != NULL; ++i)
91
      ;
92
 
93
  new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
94
 
95
  for (i = 0; list[i] != NULL; ++i)
96
    {
97
      list[i]->l_idx = i;
98
      new_opencount[i] = list[i]->l_opencount;
99
    }
100
  --new_opencount[0];
101
  for (i = 1; list[i] != NULL; ++i)
102
    if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
103
        /* Decrement counter.  */
104
        && --new_opencount[i] == 0
105
        /* Test whether this object was also loaded directly.  */
106
        && list[i]->l_searchlist.r_list != NULL)
107
      {
108
        /* In this case we have the decrement all the dependencies of
109
           this object.  They are all in MAP's dependency list.  */
110
        unsigned int j;
111
        struct link_map **dep_list = list[i]->l_searchlist.r_list;
112
 
113
        for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
114
          if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
115
              || ! dep_list[j]->l_init_called)
116
            {
117
              assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
118
              --new_opencount[dep_list[j]->l_idx];
119
            }
120
      }
121
  assert (new_opencount[0] == 0);
122
 
123
  /* Call all termination functions at once.  */
124
  for (i = 0; list[i] != NULL; ++i)
125
    {
126
      struct link_map *imap = list[i];
127
      if (new_opencount[i] == 0 && imap->l_type == lt_loaded
128
          && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
129
          && (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called)
130
          /* Skip any half-cooked objects that were never initialized.  */
131
          && imap->l_init_called)
132
        {
133
          /* When debugging print a message first.  */
134
          if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
135
            _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
136
 
137
          /* Call its termination function.  */
138
          if (imap->l_info[DT_FINI_ARRAY] != NULL)
139
            {
140
              ElfW(Addr) *array =
141
                (ElfW(Addr) *) (imap->l_addr
142
                                + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
143
              unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
144
                                 / sizeof (ElfW(Addr)));
145
              unsigned int cnt;
146
 
147
              for (cnt = 0; cnt < sz; ++cnt)
148
                ((fini_t) (imap->l_addr + array[cnt])) ();
149
            }
150
 
151
          /* Next try the old-style destructor.  */
152
          if (imap->l_info[DT_FINI] != NULL)
153
            (*(void (*) (void)) DL_DT_FINI_ADDRESS
154
              (imap, (void *) imap->l_addr
155
                     + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
156
        }
157
      else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
158
        {
159
          /* The object is still used.  But the object we are unloading
160
             right now is responsible for loading it and therefore we
161
             have the search list of the current object in its scope.
162
             Remove it.  */
163
          struct r_scope_elem **runp = imap->l_scope;
164
 
165
          while (*runp != NULL)
166
            if (*runp == &map->l_searchlist)
167
              {
168
                /* Copy all later elements.  */
169
                while ((runp[0] = runp[1]) != NULL)
170
                  ++runp;
171
                break;
172
              }
173
          else
174
            ++runp;
175
        }
176
 
177
      /* Store the new l_opencount value.  */
178
      imap->l_opencount = new_opencount[i];
179
      /* Just a sanity check.  */
180
      assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
181
    }
182
 
183
  /* Notify the debugger we are about to remove some loaded objects.  */
184
  _r_debug.r_state = RT_DELETE;
185
  _dl_debug_state ();
186
 
187
  /* Check each element of the search list to see if all references to
188
     it are gone.  */
189
  for (i = 0; list[i] != NULL; ++i)
190
    {
191
      struct link_map *imap = list[i];
192
      if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
193
        {
194
          struct libname_list *lnp;
195
 
196
          /* That was the last reference, and this was a dlopen-loaded
197
             object.  We can unmap it.  */
198
          if (__builtin_expect (imap->l_global, 0))
199
            {
200
              /* This object is in the global scope list.  Remove it.  */
201
              unsigned int cnt = _dl_main_searchlist->r_nlist;
202
 
203
              do
204
                --cnt;
205
              while (_dl_main_searchlist->r_list[cnt] != imap);
206
 
207
              /* The object was already correctly registered.  */
208
              while (++cnt < _dl_main_searchlist->r_nlist)
209
                _dl_main_searchlist->r_list[cnt - 1]
210
                  = _dl_main_searchlist->r_list[cnt];
211
 
212
              --_dl_main_searchlist->r_nlist;
213
            }
214
 
215
          /* We can unmap all the maps at once.  We determined the
216
             start address and length when we loaded the object and
217
             the `munmap' call does the rest.  */
218
          DL_UNMAP (imap);
219
 
220
          /* Finally, unlink the data structure and free it.  */
221
#ifdef SHARED
222
          /* We will unlink the first object only if this is a statically
223
             linked program.  */
224
          assert (imap->l_prev != NULL);
225
          imap->l_prev->l_next = imap->l_next;
226
#else
227
          if (imap->l_prev != NULL)
228
            imap->l_prev->l_next = imap->l_next;
229
          else
230
            _dl_loaded = imap->l_next;
231
#endif
232
          --_dl_nloaded;
233
          if (imap->l_next)
234
            imap->l_next->l_prev = imap->l_prev;
235
 
236
          if (imap->l_versions != NULL)
237
            free (imap->l_versions);
238
          if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
239
            free ((char *) imap->l_origin);
240
 
241
          /* If the object has relocation dependencies save this
242
             information for latter.  */
243
          if (__builtin_expect (imap->l_reldeps != NULL, 0))
244
            {
245
              struct reldep_list *newrel;
246
 
247
              newrel = (struct reldep_list *) alloca (sizeof (*reldeps));
248
              newrel->rellist = imap->l_reldeps;
249
              newrel->nrellist = imap->l_reldepsact;
250
              newrel->next = reldeps;
251
 
252
              reldeps = newrel;
253
            }
254
 
255
          /* This name always is allocated.  */
256
          free (imap->l_name);
257
          /* Remove the list with all the names of the shared object.  */
258
          lnp = imap->l_libname;
259
          do
260
            {
261
              struct libname_list *this = lnp;
262
              lnp = lnp->next;
263
              if (!this->dont_free)
264
                free (this);
265
            }
266
          while (lnp != NULL);
267
 
268
          /* Remove the searchlists.  */
269
          if (imap != map)
270
              free (imap->l_initfini);
271
 
272
          /* Remove the scope array if we allocated it.  */
273
          if (imap->l_scope != imap->l_scope_mem)
274
            free (imap->l_scope);
275
 
276
          if (imap->l_phdr_allocated)
277
            free ((void *) imap->l_phdr);
278
 
279
          if (imap->l_rpath_dirs.dirs != (void *) -1)
280
            free (imap->l_rpath_dirs.dirs);
281
          if (imap->l_runpath_dirs.dirs != (void *) -1)
282
            free (imap->l_runpath_dirs.dirs);
283
 
284
          free (imap);
285
        }
286
    }
287
 
288
  /* Notify the debugger those objects are finalized and gone.  */
289
  _r_debug.r_state = RT_CONSISTENT;
290
  _dl_debug_state ();
291
 
292
  /* Now we can perhaps also remove the modules for which we had
293
     dependencies because of symbol lookup.  */
294
  while (__builtin_expect (reldeps != NULL, 0))
295
    {
296
      while (reldeps->nrellist-- > 0)
297
        _dl_close (reldeps->rellist[reldeps->nrellist]);
298
 
299
      free (reldeps->rellist);
300
 
301
      reldeps = reldeps->next;
302
    }
303
 
304
  free (list);
305
 
306
  /* Release the lock.  */
307
#ifdef HAVE_DD_LOCK
308
    __lock_release(_dl_load_lock);
309
#endif
310
 
311
 
312
}
313
 
314
 
315
static void
316
free_mem (void)
317
{
318
  if (__builtin_expect (_dl_global_scope_alloc, 0) != 0
319
      && _dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist)
320
    {
321
      /* All object dynamically loaded by the program are unloaded.  Free
322
         the memory allocated for the global scope variable.  */
323
      struct link_map **old = _dl_main_searchlist->r_list;
324
 
325
      /* Put the old map in.  */
326
      _dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
327
      /* Signal that the original map is used.  */
328
      _dl_global_scope_alloc = 0;
329
 
330
      /* Now free the old map.  */
331
      free (old);
332
    }
333
}
334
text_set_element (__libc_subfreeres, free_mem);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.