]>
Commit | Line | Data |
---|---|---|
b3fc5f84 | 1 | /* Handle loading and unloading shared objects for internal libc purposes. |
d6b5d570 | 2 | Copyright (C) 1999, 2000, 2001, 2002 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 | ||
25 | /* The purpose of this file is to provide wrappers around the dynamic | |
26 | linker error mechanism (similar to dlopen() et al in libdl) which | |
27 | are usable from within libc. Generally we want to throw away the | |
28 | string that dlerror() would return and just pass back a null pointer | |
29 | for errors. This also lets the rest of libc not know about the error | |
30 | handling mechanism. | |
31 | ||
32 | Much of this code came from gconv_dl.c with slight modifications. */ | |
33 | ||
34 | static int | |
35 | internal_function | |
36 | dlerror_run (void (*operate) (void *), void *args) | |
37 | { | |
8e17ea58 UD |
38 | const char *objname; |
39 | const char *last_errstring = NULL; | |
b3fc5f84 UD |
40 | int result; |
41 | ||
8e17ea58 | 42 | (void) _dl_catch_error (&objname, &last_errstring, operate, args); |
b3fc5f84 UD |
43 | |
44 | result = last_errstring != NULL; | |
ca3c0135 | 45 | if (result && last_errstring != _dl_out_of_memory) |
8e17ea58 | 46 | free ((char *) last_errstring); |
b3fc5f84 UD |
47 | |
48 | return result; | |
49 | } | |
50 | ||
51 | /* These functions are called by dlerror_run... */ | |
52 | ||
53 | struct do_dlopen_args | |
54 | { | |
55 | /* Argument to do_dlopen. */ | |
56 | const char *name; | |
57 | ||
58 | /* Return from do_dlopen. */ | |
59 | struct link_map *map; | |
60 | }; | |
61 | ||
62 | struct do_dlsym_args | |
63 | { | |
64 | /* Arguments to do_dlsym. */ | |
65 | struct link_map *map; | |
66 | const char *name; | |
67 | ||
68 | /* Return values of do_dlsym. */ | |
c0282c06 | 69 | lookup_t loadbase; |
b3fc5f84 UD |
70 | const ElfW(Sym) *ref; |
71 | }; | |
72 | ||
73 | static void | |
74 | do_dlopen (void *ptr) | |
75 | { | |
76 | struct do_dlopen_args *args = (struct do_dlopen_args *) ptr; | |
77 | /* Open and relocate the shared object. */ | |
78 | args->map = _dl_open (args->name, RTLD_LAZY, NULL); | |
79 | } | |
80 | ||
81 | static void | |
82 | do_dlsym (void *ptr) | |
83 | { | |
84 | struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; | |
85 | args->ref = NULL; | |
06535ae9 | 86 | args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref, |
f9f2a150 UD |
87 | args->map->l_local_scope, 0, |
88 | DL_LOOKUP_RETURN_NEWEST); | |
b3fc5f84 UD |
89 | } |
90 | ||
91 | static void | |
92 | do_dlclose (void *ptr) | |
93 | { | |
53308042 | 94 | _dl_close ((struct link_map *) ptr); |
b3fc5f84 UD |
95 | } |
96 | ||
97 | /* ... and these functions call dlerror_run. */ | |
98 | ||
99 | void * | |
100 | __libc_dlopen (const char *__name) | |
101 | { | |
102 | struct do_dlopen_args args; | |
103 | args.name = __name; | |
104 | ||
105 | return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map); | |
106 | } | |
107 | ||
108 | void * | |
109 | __libc_dlsym (void *__map, const char *__name) | |
110 | { | |
111 | struct do_dlsym_args args; | |
112 | args.map = __map; | |
113 | args.name = __name; | |
114 | ||
115 | return (dlerror_run (do_dlsym, &args) ? NULL | |
b511d8fc | 116 | : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref))); |
b3fc5f84 UD |
117 | } |
118 | ||
119 | int | |
120 | __libc_dlclose (void *__map) | |
121 | { | |
122 | return dlerror_run (do_dlclose, __map); | |
123 | } | |
752a2a50 UD |
124 | |
125 | ||
126 | static void | |
127 | free_mem (void) | |
128 | { | |
129 | struct link_map *l; | |
f55727ca UD |
130 | struct r_search_path_elem *d; |
131 | ||
132 | /* Remove all search directories. */ | |
d6b5d570 UD |
133 | d = GL(dl_all_dirs); |
134 | while (d != GL(dl_init_all_dirs)) | |
f55727ca UD |
135 | { |
136 | struct r_search_path_elem *old = d; | |
137 | d = d->next; | |
138 | free (old); | |
139 | } | |
752a2a50 UD |
140 | |
141 | /* Remove all additional names added to the objects. */ | |
d6b5d570 | 142 | for (l = GL(dl_loaded); l != NULL; l = l->l_next) |
752a2a50 UD |
143 | { |
144 | struct libname_list *lnp = l->l_libname->next; | |
145 | ||
146 | l->l_libname->next = NULL; | |
147 | ||
148 | while (lnp != NULL) | |
149 | { | |
150 | struct libname_list *old = lnp; | |
151 | lnp = lnp->next; | |
152 | if (! old->dont_free) | |
153 | free (old); | |
154 | } | |
155 | } | |
156 | } | |
157 | text_set_element (__libc_subfreeres, free_mem); |