summaryrefslogtreecommitdiffstats
path: root/main/libc0.9.32/libdl.patch
blob: ead6a6ad19f75731419679bf12fc7ea5192cb2bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 95a0650..91aa926 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -544,11 +544,19 @@ static void *do_dlopen(const char *libname, int flag)
 	 * to the GOT tables.  We need to do this in reverse order so that COPY
 	 * directives work correctly */
 
-	/* Get the tail of the list */
-	for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
+	/* Extend the global scope by adding the local scope of the dlopened DSO.
+	 * But only if it's not there. It can happen under certain cases that the
+	 * DSO had refcount = 0, but was already loaded. (NODELETE flag is set, or
+	 * it is pulled in via both NEEDED dependency and explicit dlopen()). */
+	for (ls = &_dl_loaded_modules->symbol_scope; ; ls = ls->next) {
+		if (ls == &dyn_chain->dyn->symbol_scope)
+			break;
+		if (ls->next == NULL) {
+			ls->next = &dyn_chain->dyn->symbol_scope;
+			break;
+		}
+	}
 
-	/* Extend the global scope by adding the local scope of the dlopened DSO. */
-	ls->next = &dyn_chain->dyn->symbol_scope;
 #ifdef __mips__
 	/*
 	 * Relocation of the GOT entries for MIPS have to be done