aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-lookup.c')
-rw-r--r--elf/dl-lookup.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 39b3a3d013..4603761383 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -1,5 +1,5 @@
/* Look up a symbol in the loaded objects.
- Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003 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
@@ -90,17 +90,34 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
unsigned int i;
int result = 0;
- /* Avoid self-references. */
+ /* Avoid self-references and references to objects which cannot be
+ unloaded anyway. */
if (undef_map == map)
return 0;
+ /* Make sure nobody can unload the object while we are at it. */
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
+
/* Don't create cross-reference between modules which are
dynamically loaded by the same dlopen() call. */
if (undef_map->l_opencount == 0 && map->l_opencount == 0)
- return 0;
+ goto out;
- /* Make sure nobody can unload the object while we are at it. */
- __rtld_lock_lock_recursive (GL(dl_load_lock));
+ /* Avoid references to objects which cannot be unloaded anyway. */
+ if (map->l_type != lt_loaded
+ || (map->l_flags_1 & DF_1_NODELETE) != 0)
+ goto out;
+
+ /* If the object with the undefined reference cannot be removed ever
+ just make sure the same is true for the object which contains the
+ definition. */
+ if (undef_map->l_type != lt_loaded
+ || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
+ {
+ ++map->l_opencount;
+ map->l_flags |= DF_1_NODELETE;
+ goto out;
+ }
/* Determine whether UNDEF_MAP already has a reference to MAP. First
look in the normal dependencies. */