mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-10 19:30:10 +00:00
_dl_fini: Rewrite to use VLA instead of extend_alloca
In this case, extend_alloca is used to work around the lack of deallocation on scope exit. A VLA is automatically deallocated in this way, so it is the more fitting approach. To implement this, it is necessary to eliminate the goto. In addition, this change eliminates the trivially-true assert; the assert is always skipped if nloaded > 0. * elf/dl-fini.c (_dl_fini): Rewrite to use variable-length array instead of extend_alloca. Change control flow to avoid a goto. Remove assert which is trivially always true.
This commit is contained in:
parent
2145f97cee
commit
58acfe6fa7
@ -1,3 +1,9 @@
|
|||||||
|
2015-10-29 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
* elf/dl-fini.c (_dl_fini): Rewrite to use variable-length array
|
||||||
|
instead of extend_alloca. Change control flow to avoid a goto.
|
||||||
|
Remove assert which is trivially always true.
|
||||||
|
|
||||||
2015-10-28 Joseph Myers <joseph@codesourcery.com>
|
2015-10-28 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
[BZ #16068]
|
[BZ #16068]
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
License along with the GNU C Library; if not, see
|
License along with the GNU C Library; if not, see
|
||||||
<http://www.gnu.org/licenses/>. */
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <alloca.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
@ -140,8 +139,6 @@ _dl_fini (void)
|
|||||||
using `dlopen' there are possibly several other modules with its
|
using `dlopen' there are possibly several other modules with its
|
||||||
dependencies to be taken into account. Therefore we have to start
|
dependencies to be taken into account. Therefore we have to start
|
||||||
determining the order of the modules once again from the beginning. */
|
determining the order of the modules once again from the beginning. */
|
||||||
struct link_map **maps = NULL;
|
|
||||||
size_t maps_size = 0;
|
|
||||||
|
|
||||||
/* We run the destructors of the main namespaces last. As for the
|
/* We run the destructors of the main namespaces last. As for the
|
||||||
other namespaces, we pick run the destructors in them in reverse
|
other namespaces, we pick run the destructors in them in reverse
|
||||||
@ -155,7 +152,6 @@ _dl_fini (void)
|
|||||||
/* Protect against concurrent loads and unloads. */
|
/* Protect against concurrent loads and unloads. */
|
||||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||||
|
|
||||||
unsigned int nmaps = 0;
|
|
||||||
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
|
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
|
||||||
/* No need to do anything for empty namespaces or those used for
|
/* No need to do anything for empty namespaces or those used for
|
||||||
auditing DSOs. */
|
auditing DSOs. */
|
||||||
@ -164,26 +160,12 @@ _dl_fini (void)
|
|||||||
|| GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
|
|| GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
goto out;
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||||
|
|
||||||
/* XXX Could it be (in static binaries) that there is no object
|
|
||||||
loaded? */
|
|
||||||
assert (ns != LM_ID_BASE || nloaded > 0);
|
|
||||||
|
|
||||||
/* Now we can allocate an array to hold all the pointers and copy
|
|
||||||
the pointers in. */
|
|
||||||
if (maps_size < nloaded * sizeof (struct link_map *))
|
|
||||||
{
|
|
||||||
if (maps_size == 0)
|
|
||||||
{
|
|
||||||
maps_size = nloaded * sizeof (struct link_map *);
|
|
||||||
maps = (struct link_map **) alloca (maps_size);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
maps = (struct link_map **)
|
{
|
||||||
extend_alloca (maps, maps_size,
|
/* Now we can allocate an array to hold all the pointers and
|
||||||
nloaded * sizeof (struct link_map *));
|
copy the pointers in. */
|
||||||
}
|
struct link_map *maps[nloaded];
|
||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct link_map *l;
|
struct link_map *l;
|
||||||
@ -198,31 +180,32 @@ _dl_fini (void)
|
|||||||
l->l_idx = i;
|
l->l_idx = i;
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
/* Bump l_direct_opencount of all objects so that they are
|
/* Bump l_direct_opencount of all objects so that they
|
||||||
not dlclose()ed from underneath us. */
|
are not dlclose()ed from underneath us. */
|
||||||
++l->l_direct_opencount;
|
++l->l_direct_opencount;
|
||||||
}
|
}
|
||||||
assert (ns != LM_ID_BASE || i == nloaded);
|
assert (ns != LM_ID_BASE || i == nloaded);
|
||||||
assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
|
assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
|
||||||
nmaps = i;
|
unsigned int nmaps = i;
|
||||||
|
|
||||||
/* Now we have to do the sorting. */
|
/* Now we have to do the sorting. */
|
||||||
_dl_sort_fini (maps, nmaps, NULL, ns);
|
_dl_sort_fini (maps, nmaps, NULL, ns);
|
||||||
|
|
||||||
/* We do not rely on the linked list of loaded object anymore from
|
/* We do not rely on the linked list of loaded object anymore
|
||||||
this point on. We have our own list here (maps). The various
|
from this point on. We have our own list here (maps). The
|
||||||
members of this list cannot vanish since the open count is too
|
various members of this list cannot vanish since the open
|
||||||
high and will be decremented in this loop. So we release the
|
count is too high and will be decremented in this loop. So
|
||||||
lock so that some code which might be called from a destructor
|
we release the lock so that some code which might be called
|
||||||
can directly or indirectly access the lock. */
|
from a destructor can directly or indirectly access the
|
||||||
out:
|
lock. */
|
||||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||||
|
|
||||||
/* 'maps' now contains the objects in the right order. Now call the
|
/* 'maps' now contains the objects in the right order. Now
|
||||||
destructors. We have to process this array from the front. */
|
call the destructors. We have to process this array from
|
||||||
|
the front. */
|
||||||
for (i = 0; i < nmaps; ++i)
|
for (i = 0; i < nmaps; ++i)
|
||||||
{
|
{
|
||||||
l = maps[i];
|
struct link_map *l = maps[i];
|
||||||
|
|
||||||
if (l->l_init_called)
|
if (l->l_init_called)
|
||||||
{
|
{
|
||||||
@ -254,7 +237,8 @@ _dl_fini (void)
|
|||||||
|
|
||||||
/* Next try the old-style destructor. */
|
/* Next try the old-style destructor. */
|
||||||
if (l->l_info[DT_FINI] != NULL)
|
if (l->l_info[DT_FINI] != NULL)
|
||||||
DL_CALL_DT_FINI(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
|
DL_CALL_DT_FINI
|
||||||
|
(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
@ -278,6 +262,7 @@ _dl_fini (void)
|
|||||||
--l->l_direct_opencount;
|
--l->l_direct_opencount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
if (! do_audit && GLRO(dl_naudit) > 0)
|
if (! do_audit && GLRO(dl_naudit) > 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user