Fix caller information of NSS modules
[platform/upstream/glibc.git] / elf / dl-libc.c
1 /* Handle loading and unloading shared objects for internal libc purposes.
2    Copyright (C) 1999-2002,2004-2006,2009,2010,2011
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #include <dlfcn.h>
23 #include <stdlib.h>
24 #include <ldsodefs.h>
25
26 extern int __libc_argc attribute_hidden;
27 extern char **__libc_argv attribute_hidden;
28
29 extern char **__environ;
30
31 /* The purpose of this file is to provide wrappers around the dynamic
32    linker error mechanism (similar to dlopen() et al in libdl) which
33    are usable from within libc.  Generally we want to throw away the
34    string that dlerror() would return and just pass back a null pointer
35    for errors.  This also lets the rest of libc not know about the error
36    handling mechanism.
37
38    Much of this code came from gconv_dl.c with slight modifications. */
39
40 static int
41 internal_function
42 dlerror_run (void (*operate) (void *), void *args)
43 {
44   const char *objname;
45   const char *last_errstring = NULL;
46   bool malloced;
47
48   (void) GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
49                                operate, args);
50
51   int result = last_errstring != NULL;
52   if (result && malloced)
53     free ((char *) last_errstring);
54
55   return result;
56 }
57
58 /* These functions are called by dlerror_run... */
59
60 struct do_dlopen_args
61 {
62   /* Argument to do_dlopen.  */
63   const char *name;
64   /* Opening mode.  */
65   int mode;
66   /* This is the caller of the dlopen() function.  */
67   const void *caller_dlopen;
68
69   /* Return from do_dlopen.  */
70   struct link_map *map;
71 };
72
73 struct do_dlsym_args
74 {
75   /* Arguments to do_dlsym.  */
76   struct link_map *map;
77   const char *name;
78
79   /* Return values of do_dlsym.  */
80   lookup_t loadbase;
81   const ElfW(Sym) *ref;
82 };
83
84 static void
85 do_dlopen (void *ptr)
86 {
87   struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
88   /* Open and relocate the shared object.  */
89   args->map = GLRO(dl_open) (args->name, args->mode, args->caller_dlopen,
90                              __LM_ID_CALLER, __libc_argc, __libc_argv,
91                              __environ);
92 }
93
94 static void
95 do_dlsym (void *ptr)
96 {
97   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
98   args->ref = NULL;
99   args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
100                                              args->map->l_local_scope, NULL, 0,
101                                              DL_LOOKUP_RETURN_NEWEST, NULL);
102 }
103
104 static void
105 do_dlclose (void *ptr)
106 {
107   GLRO(dl_close) ((struct link_map *) ptr);
108 }
109
110 /* This code is to support __libc_dlopen from __libc_dlopen'ed shared
111    libraries.  We need to ensure the statically linked __libc_dlopen
112    etc. functions are used instead of the dynamically loaded.  */
113 struct dl_open_hook
114 {
115   void *(*dlopen_mode) (const char *name, int mode);
116   void *(*dlsym) (void *map, const char *name);
117   int (*dlclose) (void *map);
118 };
119
120 #ifdef SHARED
121 extern struct dl_open_hook *_dl_open_hook;
122 libc_hidden_proto (_dl_open_hook);
123 struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
124 libc_hidden_data_def (_dl_open_hook);
125 #else
126 static void
127 do_dlsym_private (void *ptr)
128 {
129   lookup_t l;
130   struct r_found_version vers;
131   vers.name = "GLIBC_PRIVATE";
132   vers.hidden = 1;
133   /* vers.hash = _dl_elf_hash (vers.name);  */
134   vers.hash = 0x0963cf85;
135   vers.filename = NULL;
136
137   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
138   args->ref = NULL;
139   l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
140                                 args->map->l_scope, &vers, 0, 0, NULL);
141   args->loadbase = l;
142 }
143
144 static struct dl_open_hook _dl_open_hook =
145   {
146     .dlopen_mode = __libc_dlopen_mode,
147     .dlsym = __libc_dlsym,
148     .dlclose = __libc_dlclose
149   };
150 #endif
151
152 /* ... and these functions call dlerror_run. */
153
154 void *
155 __libc_dlopen_mode (const char *name, int mode)
156 {
157   struct do_dlopen_args args;
158   args.name = name;
159   args.mode = mode;
160   args.caller_dlopen = RETURN_ADDRESS (0);
161
162 #ifdef SHARED
163   if (__builtin_expect (_dl_open_hook != NULL, 0))
164     return _dl_open_hook->dlopen_mode (name, mode);
165   return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
166 #else
167   if (dlerror_run (do_dlopen, &args))
168     return NULL;
169
170   __libc_register_dl_open_hook (args.map);
171   __libc_register_dlfcn_hook (args.map);
172   return (void *) args.map;
173 #endif
174 }
175 libc_hidden_def (__libc_dlopen_mode)
176
177 #ifndef SHARED
178 void *
179 __libc_dlsym_private (struct link_map *map, const char *name)
180 {
181   struct do_dlsym_args sargs;
182   sargs.map = map;
183   sargs.name = name;
184
185   if (! dlerror_run (do_dlsym_private, &sargs))
186     return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref);
187   return NULL;
188 }
189
190 void
191 __libc_register_dl_open_hook (struct link_map *map)
192 {
193   struct dl_open_hook **hook;
194
195   hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook");
196   if (hook != NULL)
197     *hook = &_dl_open_hook;
198 }
199 #endif
200
201 void *
202 __libc_dlsym (void *map, const char *name)
203 {
204   struct do_dlsym_args args;
205   args.map = map;
206   args.name = name;
207
208 #ifdef SHARED
209   if (__builtin_expect (_dl_open_hook != NULL, 0))
210     return _dl_open_hook->dlsym (map, name);
211 #endif
212   return (dlerror_run (do_dlsym, &args) ? NULL
213           : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
214 }
215 libc_hidden_def (__libc_dlsym)
216
217 int
218 __libc_dlclose (void *map)
219 {
220 #ifdef SHARED
221   if (__builtin_expect (_dl_open_hook != NULL, 0))
222     return _dl_open_hook->dlclose (map);
223 #endif
224   return dlerror_run (do_dlclose, map);
225 }
226 libc_hidden_def (__libc_dlclose)
227
228
229 static bool __libc_freeres_fn_section
230 free_slotinfo (struct dtv_slotinfo_list **elemp)
231 {
232   size_t cnt;
233
234   if (*elemp == NULL)
235     /* Nothing here, all is removed (or there never was anything).  */
236     return true;
237
238   if (!free_slotinfo (&(*elemp)->next))
239     /* We cannot free the entry.  */
240     return false;
241
242   /* That cleared our next pointer for us.  */
243
244   for (cnt = 0; cnt < (*elemp)->len; ++cnt)
245     if ((*elemp)->slotinfo[cnt].map != NULL)
246       /* Still used.  */
247       return false;
248
249   /* We can remove the list element.  */
250   free (*elemp);
251   *elemp = NULL;
252
253   return true;
254 }
255
256
257 libc_freeres_fn (free_mem)
258 {
259   struct link_map *l;
260   struct r_search_path_elem *d;
261
262   /* Remove all search directories.  */
263   d = GL(dl_all_dirs);
264   while (d != GLRO(dl_init_all_dirs))
265     {
266       struct r_search_path_elem *old = d;
267       d = d->next;
268       free (old);
269     }
270
271   for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
272     {
273       /* Remove all additional names added to the objects.  */
274       for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
275         {
276           struct libname_list *lnp = l->l_libname->next;
277
278           l->l_libname->next = NULL;
279
280           while (lnp != NULL)
281             {
282               struct libname_list *old = lnp;
283               lnp = lnp->next;
284               if (! old->dont_free)
285                 free (old);
286             }
287         }
288
289       if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
290           && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
291               // XXX Check whether we need NS-specific initial_searchlist
292               == GLRO(dl_initial_searchlist).r_nlist))
293         {
294           /* All object dynamically loaded by the program are unloaded.  Free
295              the memory allocated for the global scope variable.  */
296           struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
297
298           /* Put the old map in.  */
299           GL(dl_ns)[ns]._ns_main_searchlist->r_list
300             // XXX Check whether we need NS-specific initial_searchlist
301             = GLRO(dl_initial_searchlist).r_list;
302           /* Signal that the original map is used.  */
303           GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
304
305           /* Now free the old map.  */
306           free (old);
307         }
308     }
309
310   if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL)
311     {
312       /* Free the memory allocated for the dtv slotinfo array.  We can do
313          this only if all modules which used this memory are unloaded.  */
314 #ifdef SHARED
315       if (GL(dl_initial_dtv) == NULL)
316         /* There was no initial TLS setup, it was set up later when
317            it used the normal malloc.  */
318         free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
319       else
320 #endif
321         /* The first element of the list does not have to be deallocated.
322            It was allocated in the dynamic linker (i.e., with a different
323            malloc), and in the static library it's in .bss space.  */
324         free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
325     }
326
327   void *scope_free_list = GL(dl_scope_free_list);
328   GL(dl_scope_free_list) = NULL;
329   free (scope_free_list);
330 }