aboutsummaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2010-11-03 09:23:08 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2010-11-03 09:23:08 +0000
commitb8fc1b23bebaee0002c434e99caf75e324710ddf (patch)
tree32512f3bc1869db4dad1920d6d6d20fa63b1d63e /libexec
parent8908d48d82353d54926e0d11340e0603a73e3344 (diff)
Notes
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c15
-rw-r--r--libexec/rtld-elf/rtld.h1
2 files changed, 14 insertions, 2 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 8bc8692a9229..f1ffc3e3e4df 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1275,8 +1275,11 @@ init_dag(Obj_Entry *root)
{
DoneList donelist;
+ if (root->dag_inited)
+ return;
donelist_init(&donelist);
init_dag1(root, root, &donelist);
+ root->dag_inited = true;
}
static void
@@ -2045,8 +2048,16 @@ dlopen(const char *name, int mode)
}
} else {
- /* Bump the reference counts for objects on this DAG. */
- ref_dag(obj);
+ /*
+ * Bump the reference counts for objects on this DAG. If
+ * this is the first dlopen() call for the object that was
+ * already loaded as a dependency, initialize the dag
+ * starting at it.
+ */
+ if (obj->dl_refcount == 1)
+ init_dag(obj);
+ else
+ ref_dag(obj);
if (ld_tracing)
goto trace;
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index 6bae2f034b70..faa84e2d5acc 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry {
bool ref_nodel : 1; /* Refcount increased to prevent dlclose */
bool init_scanned: 1; /* Object is already on init list. */
bool on_fini_list: 1; /* Object is already on fini list. */
+ bool dag_inited : 1; /* Object has its DAG initialized. */
struct link_map linkmap; /* For GDB and dlinfo() */
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */