Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update.
2001-09-08  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-close.c (_dl_close): If object has no r_list (i.e., wasn't
	loaded directly) determine length if l_initfini list by iterating
	over its elements.  Minor optimizations.
	* elf/dl-deps.c (_dl_map_object_deps): Always add own map to l_initfini
	for dependency objects.
	If object was already loaded check whether any of the dependencies
	is already on the relocation dependency list.  If yes, remove the
	latter.  Minor optimizations.
	* elf/dl-lookup.c (add_dependency): Add check for self reference of
	maps here.  Search l_initfini list only if the object was loaded
	directly and not only as a dependency.
	(_dl_lookup_symbol): Add relocation dependency also if object
	is not in global scope.  Remove test for self-reference here.
	(_dl_lookup_versioned_symbol): Likewise.
	* elf/dl-object (_dl_new_object): Cleanup.  Initialize dont_free
	element of first name record.
	* elf/loadtest.c: Add some more test to recognize early if an object
	wasn't unloaded.
	* elf/Makefile: Add rules to build and run reldep5.
	* elf/reldep5.c: New file.
	* elf/reldepmod5.c: New file.
	* elf/reldepmod6.c: New file.

	* elf/reldep2.c: Fix typo.

	* elf/dl-object.c (_dl_new_object): Initialize l_scope and l_scope_max.
  • Loading branch information
Ulrich Drepper committed Sep 8, 2001
1 parent 5a21d30 commit c4bb124
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 96 deletions.
29 changes: 28 additions & 1 deletion ChangeLog
@@ -1,8 +1,35 @@
2001-09-08 Ulrich Drepper <drepper@redhat.com>

* elf/dl-close.c (_dl_close): If object has no r_list (i.e., wasn't
loaded directly) determine length if l_initfini list by iterating
over its elements. Minor optimizations.
* elf/dl-deps.c (_dl_map_object_deps): Always add own map to l_initfini
for dependency objects.
If object was already loaded check whether any of the dependencies
is already on the relocation dependency list. If yes, remove the
latter. Minor optimizations.
* elf/dl-lookup.c (add_dependency): Add check for self reference of
maps here. Search l_initfini list only if the object was loaded
directly and not only as a dependency.
(_dl_lookup_symbol): Add relocation dependency also if object
is not in global scope. Remove test for self-reference here.
(_dl_lookup_versioned_symbol): Likewise.
* elf/dl-object (_dl_new_object): Cleanup. Initialize dont_free
element of first name record.
* elf/loadtest.c: Add some more test to recognize early if an object
wasn't unloaded.
* elf/Makefile: Add rules to build and run reldep5.
* elf/reldep5.c: New file.
* elf/reldepmod5.c: New file.
* elf/reldepmod6.c: New file.

* elf/reldep2.c: Fix typo.

2001-09-07 Ulrich Drepper <drepper@redhat.com>

* include/link.h (struct link_map): Add l_scope_mem and l_scope_max
elements. Change l_scope to be a pointer only.
* elf/dl-object.c (_dl_new_ojbect): Initialize l_scope and l_scope_max.
* elf/dl-object.c (_dl_new_object): Initialize l_scope and l_scope_max.
* elf/dl-open.c (dl_open_worker): If dependency wasn't just opened
here add searchlist of newly open file to the dependency's scope.
* elf/dl-close.c (_dl_close): If dependency is used otherwise remove
Expand Down
10 changes: 8 additions & 2 deletions elf/Makefile
Expand Up @@ -55,6 +55,7 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
nodlopenmod.c nodelete.c nodelmod1.c nodelmod2.c \
nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h \
reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \
reldepmod5.c reldepmod6.c \
reldep4mod1.c reldep4mod2.c reldep4mod3.c reldep4mod4.c \
nextmod1.c nextmod2.c pathoptobj.c tst-pathopt.sh \
neededobj1.c neededobj2.c neededobj3.c neededobj4.c \
Expand Down Expand Up @@ -106,7 +107,7 @@ tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
reldep reldep2 reldep3 reldep4 $(tests-nodelete-$(have-z-nodelete)) \
$(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \
neededtest3 neededtest4 unload2 lateglobal initfirst global \
restest2 next dblload dblunload
restest2 next dblload dblunload reldep5
test-srcs = tst-pathopt
tests-vis-yes = vismain
tests-nodelete-yes = nodelete
Expand All @@ -122,7 +123,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
neededobj1 neededobj2 neededobj3 neededobj4 \
neededobj5 neededobj6 firstobj globalmod1 \
unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \
dblloadmod1 dblloadmod2 dblloadmod3
dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6
modules-vis-yes = vismod1 vismod2 vismod3
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
modules-nodlopen-yes = nodlopenmod
Expand Down Expand Up @@ -285,6 +286,8 @@ $(objpfx)reldep4mod1.so: $(objpfx)reldep4mod3.so
$(objpfx)reldep4mod2.so: $(objpfx)reldep4mod4.so
$(objpfx)dblloadmod1.so: $(objpfx)dblloadmod3.so
$(objpfx)dblloadmod2.so: $(objpfx)dblloadmod3.so
$(objpfx)reldepmod5.so: $(objpfx)reldepmod2.so
$(objpfx)reldepmod6.so: $(objpfx)reldepmod2.so

# filtmod1.so has a special rule
$(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
Expand Down Expand Up @@ -423,3 +426,6 @@ $(objpfx)dblload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so

$(objpfx)dblunload: $(libdl)
$(objpfx)dblunload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so

$(objpfx)reldep5: $(libdl)
$(objpfx)reldep5.out: $(objpfx)reldepmod5.so $(objpfx)reldepmod5.so
24 changes: 13 additions & 11 deletions elf/dl-close.c
Expand Up @@ -48,7 +48,8 @@ _dl_close (void *_map)
unsigned int *new_opencount;

/* First see whether we can remove the object at all. */
if ((map->l_flags_1 & DF_1_NODELETE) && map->l_init_called)
if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
&& map->l_init_called)
/* Nope. Do nothing. */
return;

Expand All @@ -63,14 +64,8 @@ _dl_close (void *_map)
{
/* There are still references to this object. Do nothing more. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
{
char buf[20];

buf[sizeof buf - 1] = '\0';

_dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
map->l_name, map->l_opencount);
}
_dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
map->l_name, map->l_opencount);

/* One decrement the object itself, not the dependencies. */
--map->l_opencount;
Expand All @@ -82,8 +77,15 @@ _dl_close (void *_map)
list = map->l_initfini;

/* Compute the new l_opencount values. */
new_opencount = (unsigned int *) alloca (map->l_searchlist.r_nlist
* sizeof (unsigned int));
i = map->l_searchlist.r_nlist;
if (__builtin_expect (i == 0, 0))
/* This can happen if we handle relocation dependencies for an
object which wasn't loaded directly. */
for (i = 1; list[i] != NULL; ++i)
;

new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));

for (i = 0; list[i] != NULL; ++i)
{
list[i]->l_idx = i;
Expand Down
34 changes: 30 additions & 4 deletions elf/dl-deps.c
Expand Up @@ -448,11 +448,13 @@ _dl_map_object_deps (struct link_map *map,
{
needed[nneeded++] = NULL;

l->l_initfini = malloc (nneeded * sizeof needed[0]);
l->l_initfini = (struct link_map **)
malloc ((nneeded + 1) * sizeof needed[0]);
if (l->l_initfini == NULL)
_dl_signal_error (ENOMEM, map->l_name, NULL,
N_("cannot allocate dependency list"));
memcpy (l->l_initfini, needed, nneeded * sizeof needed[0]);
l->l_initfini[0] = l;
memcpy (&l->l_initfini[1], needed, nneeded * sizeof needed[0]);
}

/* If we have no auxiliary objects just go on to the next map. */
Expand All @@ -462,7 +464,7 @@ _dl_map_object_deps (struct link_map *map,
while (runp != NULL && runp->done);
}

out:
out:
if (errno == 0 && errno_saved != 0)
__set_errno (errno_saved);

Expand All @@ -489,7 +491,7 @@ _dl_map_object_deps (struct link_map *map,

for (nlist = 0, runp = known; runp; runp = runp->next)
{
if (trace_mode && runp->map->l_faked)
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
/* This can happen when we trace the loading. */
--map->l_searchlist.r_nlist;
else
Expand All @@ -500,6 +502,30 @@ _dl_map_object_deps (struct link_map *map,
runp->map->l_reserved = 0;
}

/* Maybe we can remove some relocation dependencies now. */
assert (map->l_searchlist.r_list[0] == map);
for (i = 0; i < map->l_reldepsact; ++i)
{
unsigned int j;

for (j = 1; j < nlist; ++j)
if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
{
/* A direct or transitive dependency is also on the list
of relocation dependencies. Remove the latter. */
--map->l_reldeps[i]->l_opencount;

for (j = i + 1; j < map->l_reldepsact; ++j)
map->l_reldeps[j - 1] = map->l_reldeps[j];

--map->l_reldepsact;

/* Account for the '++i' performed by the 'for'. */
--i;
break;
}
}

/* Now determine the order in which the initialization has to happen. */
memcpy (map->l_initfini, map->l_searchlist.r_list,
nlist * sizeof (struct link_map *));
Expand Down
142 changes: 70 additions & 72 deletions elf/dl-lookup.c
Expand Up @@ -79,92 +79,94 @@ internal_function
add_dependency (struct link_map *undef_map, struct link_map *map)
{
struct link_map **list;
struct link_map *runp;
unsigned int act;
unsigned int i;
int result = 0;

/* Avoid self-references. */
if (undef_map == map)
return 0;

/* Make sure nobody can unload the object while we are at it. */
__libc_lock_lock_recursive (_dl_load_lock);

/* Determine whether UNDEF_MAP already has a reference to MAP. First
look in the normal dependencies. */
list = undef_map->l_initfini;

for (i = 0; list[i] != NULL; ++i)
if (list[i] == map)
break;

if (__builtin_expect (list[i] == NULL, 1))
if (undef_map->l_searchlist.r_list != NULL)
{
/* 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;
list = undef_map->l_initfini;

for (i = 0; i < act; ++i)
for (i = 0; list[i] != NULL; ++i)
if (list[i] == map)
break;
goto out;
}

/* 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;

if (i == act)
for (i = 0; i < act; ++i)
if (list[i] == map)
goto out;

/* 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. */
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 (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
{
/* 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 (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
{
/* 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
* sizeof(struct link_map *));

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 (__builtin_expect (act < undef_map->l_reldepsmax, 1))
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_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\
\nfile=%s; needed by %s (relocation dependency)\n\n",
map->l_name[0] ? map->l_name : _dl_argv[0],
undef_map->l_name[0]
? undef_map->l_name : _dl_argv[0]);
}
/* 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
* sizeof (struct link_map *));

if (__builtin_expect (newp != NULL, 1))
undef_map->l_reldeps = (struct link_map **) newp;
else
/* Whoa, that was bad luck. We have to search again. */
result = -1;
/* 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 (__builtin_expect (act < undef_map->l_reldepsmax, 1))
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_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\
\nfile=%s; needed by %s (relocation dependency)\n\n",
map->l_name[0] ? map->l_name : _dl_argv[0],
undef_map->l_name[0]
? undef_map->l_name : _dl_argv[0]);
}
else
/* Whoa, that was bad luck. We have to search again. */
result = -1;

out:
/* Release the lock. */
__libc_lock_unlock_recursive (_dl_load_lock);

Expand Down Expand Up @@ -212,8 +214,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
&& current_value.m->l_global
&& undef_map != current_value.m
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
Expand Down Expand Up @@ -395,8 +395,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
&& current_value.m->l_global
&& undef_map != current_value.m
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
Expand Down
12 changes: 8 additions & 4 deletions elf/dl-object.c
Expand Up @@ -37,14 +37,18 @@ _dl_new_object (char *realname, const char *libname, int type,
struct link_map *l;
int idx;
size_t libname_len = strlen (libname) + 1;
struct link_map *new = calloc (sizeof *new, 1);
struct libname_list *newname = malloc (sizeof *newname + libname_len);
if (! new || ! newname)
struct link_map *new;
struct libname_list *newname;

new = (struct link_map *) calloc (sizeof *new, 1);
newname = (struct libname_list *) malloc (sizeof *newname + libname_len);
if (new == NULL || newname == NULL)
return NULL;

new->l_name = realname;
newname->name = memcpy (newname + 1, libname, libname_len);
newname->name = (char *) memcpy (newname + 1, libname, libname_len);
newname->next = NULL;
newname->dont_free = 0;
new->l_libname = newname;
new->l_type = type;
new->l_loader = loader;
Expand Down

0 comments on commit c4bb124

Please sign in to comment.