]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-libc.c
Undo feature selection for ftruncate.
[thirdparty/glibc.git] / elf / dl-libc.c
CommitLineData
b3fc5f84 1/* Handle loading and unloading shared objects for internal libc purposes.
22c83193 2 Copyright (C) 1999-2002,2004,2005,2006,2009 Free Software Foundation, Inc.
b3fc5f84
UD
3 This file is part of the GNU C Library.
4 Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
b3fc5f84
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
b3fc5f84 15
41bdb6e2
AJ
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
b3fc5f84
UD
20
21#include <dlfcn.h>
22#include <stdlib.h>
23#include <ldsodefs.h>
24
9dcafc55
UD
25extern int __libc_argc attribute_hidden;
26extern char **__libc_argv attribute_hidden;
27
28extern char **__environ;
29
b3fc5f84
UD
30/* The purpose of this file is to provide wrappers around the dynamic
31 linker error mechanism (similar to dlopen() et al in libdl) which
32 are usable from within libc. Generally we want to throw away the
33 string that dlerror() would return and just pass back a null pointer
34 for errors. This also lets the rest of libc not know about the error
35 handling mechanism.
36
37 Much of this code came from gconv_dl.c with slight modifications. */
38
39static int
40internal_function
41dlerror_run (void (*operate) (void *), void *args)
42{
8e17ea58
UD
43 const char *objname;
44 const char *last_errstring = NULL;
74780cf6 45 bool malloced;
b3fc5f84 46
74780cf6
UD
47 (void) GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
48 operate, args);
b3fc5f84 49
74780cf6
UD
50 int result = last_errstring != NULL;
51 if (result && malloced)
8e17ea58 52 free ((char *) last_errstring);
b3fc5f84
UD
53
54 return result;
55}
56
57/* These functions are called by dlerror_run... */
58
59struct do_dlopen_args
60{
61 /* Argument to do_dlopen. */
62 const char *name;
3c857306
UD
63 /* Opening mode. */
64 int mode;
b3fc5f84
UD
65
66 /* Return from do_dlopen. */
67 struct link_map *map;
68};
69
70struct do_dlsym_args
71{
72 /* Arguments to do_dlsym. */
73 struct link_map *map;
74 const char *name;
75
76 /* Return values of do_dlsym. */
c0282c06 77 lookup_t loadbase;
b3fc5f84
UD
78 const ElfW(Sym) *ref;
79};
80
81static void
82do_dlopen (void *ptr)
83{
84 struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
85 /* Open and relocate the shared object. */
9dcafc55
UD
86 args->map = GLRO(dl_open) (args->name, args->mode, NULL, __LM_ID_CALLER,
87 __libc_argc, __libc_argv, __environ);
b3fc5f84
UD
88}
89
90static void
91do_dlsym (void *ptr)
92{
93 struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
94 args->ref = NULL;
021723ab
UD
95 args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
96 args->map->l_local_scope, NULL, 0,
97 DL_LOOKUP_RETURN_NEWEST, NULL);
b3fc5f84
UD
98}
99
100static void
101do_dlclose (void *ptr)
102{
9dcafc55 103 GLRO(dl_close) ((struct link_map *) ptr);
b3fc5f84
UD
104}
105
81b215af
UD
106/* This code is to support __libc_dlopen from __libc_dlopen'ed shared
107 libraries. We need to ensure the statically linked __libc_dlopen
108 etc. functions are used instead of the dynamically loaded. */
109struct dl_open_hook
110{
111 void *(*dlopen_mode) (const char *name, int mode);
112 void *(*dlsym) (void *map, const char *name);
113 int (*dlclose) (void *map);
114};
115
116#ifdef SHARED
117extern struct dl_open_hook *_dl_open_hook;
118libc_hidden_proto (_dl_open_hook);
9dcafc55 119struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
81b215af
UD
120libc_hidden_data_def (_dl_open_hook);
121#else
122static void
123do_dlsym_private (void *ptr)
124{
125 lookup_t l;
126 struct r_found_version vers;
127 vers.name = "GLIBC_PRIVATE";
128 vers.hidden = 1;
9dcafc55 129 /* vers.hash = _dl_elf_hash (vers.name); */
81b215af 130 vers.hash = 0x0963cf85;
81b215af
UD
131 vers.filename = NULL;
132
133 struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
134 args->ref = NULL;
021723ab 135 l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
c0a777e8 136 args->map->l_scope, &vers, 0, 0, NULL);
81b215af
UD
137 args->loadbase = l;
138}
139
140static struct dl_open_hook _dl_open_hook =
141 {
142 .dlopen_mode = __libc_dlopen_mode,
143 .dlsym = __libc_dlsym,
144 .dlclose = __libc_dlclose
145 };
146#endif
147
b3fc5f84
UD
148/* ... and these functions call dlerror_run. */
149
150void *
3c857306 151__libc_dlopen_mode (const char *name, int mode)
b3fc5f84
UD
152{
153 struct do_dlopen_args args;
3c857306
UD
154 args.name = name;
155 args.mode = mode;
b3fc5f84 156
81b215af
UD
157#ifdef SHARED
158 if (__builtin_expect (_dl_open_hook != NULL, 0))
159 return _dl_open_hook->dlopen_mode (name, mode);
b3fc5f84 160 return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
81b215af
UD
161#else
162 if (dlerror_run (do_dlopen, &args))
163 return NULL;
164
790b6c7a
UD
165 __libc_register_dl_open_hook (args.map);
166 __libc_register_dlfcn_hook (args.map);
167 return (void *) args.map;
168#endif
169}
170libc_hidden_def (__libc_dlopen_mode)
171
172#ifndef SHARED
173void *
174__libc_dlsym_private (struct link_map *map, const char *name)
175{
81b215af 176 struct do_dlsym_args sargs;
790b6c7a
UD
177 sargs.map = map;
178 sargs.name = name;
81b215af
UD
179
180 if (! dlerror_run (do_dlsym_private, &sargs))
790b6c7a
UD
181 return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref);
182 return NULL;
183}
81b215af 184
790b6c7a
UD
185void
186__libc_register_dl_open_hook (struct link_map *map)
187{
188 struct dl_open_hook **hook;
189
190 hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook");
191 if (hook != NULL)
192 *hook = &_dl_open_hook;
b3fc5f84 193}
790b6c7a 194#endif
b3fc5f84
UD
195
196void *
3c857306 197__libc_dlsym (void *map, const char *name)
b3fc5f84
UD
198{
199 struct do_dlsym_args args;
3c857306
UD
200 args.map = map;
201 args.name = name;
b3fc5f84 202
81b215af
UD
203#ifdef SHARED
204 if (__builtin_expect (_dl_open_hook != NULL, 0))
205 return _dl_open_hook->dlsym (map, name);
206#endif
b3fc5f84 207 return (dlerror_run (do_dlsym, &args) ? NULL
b511d8fc 208 : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
b3fc5f84 209}
9d79e037 210libc_hidden_def (__libc_dlsym)
b3fc5f84
UD
211
212int
3c857306 213__libc_dlclose (void *map)
b3fc5f84 214{
81b215af
UD
215#ifdef SHARED
216 if (__builtin_expect (_dl_open_hook != NULL, 0))
217 return _dl_open_hook->dlclose (map);
218#endif
3c857306 219 return dlerror_run (do_dlclose, map);
b3fc5f84 220}
9d79e037 221libc_hidden_def (__libc_dlclose)
752a2a50
UD
222
223
c877418f 224libc_freeres_fn (free_mem)
752a2a50
UD
225{
226 struct link_map *l;
f55727ca
UD
227 struct r_search_path_elem *d;
228
229 /* Remove all search directories. */
d6b5d570 230 d = GL(dl_all_dirs);
c31e278f 231 while (d != GLRO(dl_init_all_dirs))
f55727ca
UD
232 {
233 struct r_search_path_elem *old = d;
234 d = d->next;
235 free (old);
236 }
752a2a50
UD
237
238 /* Remove all additional names added to the objects. */
22c83193 239 for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
c0f62c56
UD
240 for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
241 {
242 struct libname_list *lnp = l->l_libname->next;
243
244 l->l_libname->next = NULL;
245
246 while (lnp != NULL)
247 {
248 struct libname_list *old = lnp;
249 lnp = lnp->next;
250 if (! old->dont_free)
752a2a50 251 free (old);
c0f62c56
UD
252 }
253 }
752a2a50 254}