summaryrefslogtreecommitdiffstats
path: root/main/libc0.9.32/0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch
blob: d406f030d65f41a20b2d76d0beea944322ce75a0 (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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
From 521807eb4d18c5e693f91ad53cb277c76aab8686 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Thu, 24 Mar 2011 13:24:32 +0200
Subject: [PATCH] libdl: rudimentary locking for dlopen/dlsym/dlclose
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This implements big-dlfcn lock to allow multithreaded usage of
dlopen/dlsym/dlclose. We should really clean up the dl code so
we can use more fine grained locking or even RCU where appropriate.
But at least we won't crash now.

Signed-off-by: Timo Teräs <timo.teras@iki.fi>
---
 TODO               |    1 +
 ldso/libdl/libdl.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/TODO b/TODO
index ae305a5..95cabd5 100644
--- a/TODO
+++ b/TODO
@@ -101,6 +101,7 @@ TODO list for AFTER the uClibc 1.0.0 release:
     *) run 'nm -D --size-sort -t d libuClibc-0.9.26.so' and work on the
 	biggest things (i.e. stuff at the end of the list) to make
 	them smaller.
+    *) Fix dlopen/dlsym/dlclose locking to more fine grained or use RCU
     <more wishlist items here>
 
 
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 68cd579..e007f54 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <string.h> /* Needed for 'strstr' prototype' */
 #include <stdbool.h>
+#include <bits/uClibc_mutex.h>
 
 #ifdef __UCLIBC_HAS_TLS__
 #include <tls.h>
@@ -44,6 +45,10 @@
 extern void _dl_add_to_slotinfo(struct link_map  *l);
 #endif
 
+/* TODO: get rid of global lock and use more finegrained locking, or
+ * perhaps RCU for the global structures */
+__UCLIBC_MUTEX_STATIC(_dl_mutex, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
 #ifdef SHARED
 # if defined(USE_TLS) && USE_TLS
 # include <dl-tls.h>
@@ -271,7 +276,7 @@ void dl_cleanup(void)
 	}
 }
 
-void *dlopen(const char *libname, int flag)
+static void *do_dlopen(const char *libname, int flag)
 {
 	struct elf_resolve *tpnt, *tfrom;
 	struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
@@ -605,7 +610,18 @@ oops:
 	return NULL;
 }
 
-void *dlsym(void *vhandle, const char *name)
+void *dlopen(const char *libname, int flag)
+{
+	void *ret;
+
+	__UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+	ret = do_dlopen(libname, flag);
+	__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+	return ret;
+}
+
+static void *do_dlsym(void *vhandle, const char *name, void *caller_address)
 {
 	struct elf_resolve *tpnt, *tfrom;
 	struct dyn_elf *handle;
@@ -653,7 +669,7 @@ void *dlsym(void *vhandle, const char *name)
 		 * dynamic loader itself, as it doesn't know
 		 * how to properly treat it.
 		 */
-		from = (ElfW(Addr)) __builtin_return_address(0);
+		from = (ElfW(Addr)) caller_address;
 
 		tfrom = NULL;
 		for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
@@ -690,6 +706,17 @@ out:
 	return ret;
 }
 
+void *dlsym(void *vhandle, const char *name)
+{
+	void *ret;
+
+	__UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+	ret = do_dlsym(vhandle, name, __builtin_return_address(0));
+	__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+	return ret;
+}
+
 #if 0
 void *dlvsym(void *vhandle, const char *name, const char *version)
 {
@@ -957,7 +984,13 @@ static int do_dlclose(void *vhandle, int need_fini)
 
 int dlclose(void *vhandle)
 {
-	return do_dlclose(vhandle, 1);
+	int ret;
+
+	__UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+	ret = do_dlclose(vhandle, 1);
+	__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+	return ret;
 }
 
 char *dlerror(void)
@@ -1004,7 +1037,7 @@ int dlinfo(void)
 	return 0;
 }
 
-int dladdr(const void *__address, Dl_info * __info)
+static int do_dladdr(const void *__address, Dl_info * __info)
 {
 	struct elf_resolve *pelf;
 	struct elf_resolve *rpnt;
@@ -1108,3 +1141,14 @@ int dladdr(const void *__address, Dl_info * __info)
 	}
 }
 #endif
+
+int dladdr(const void *__address, Dl_info * __info)
+{
+	int ret;
+
+	__UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+	ret = do_dladdr(__address, __info);
+	__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+	return ret;
+}
-- 
1.7.1