1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <dlfcn.h>
22: #include <stdlib.h>
23: #include <ldsodefs.h>
24:
25: extern int __libc_argc attribute_hidden;
26: extern char **__libc_argv attribute_hidden;
27:
28: extern char **__environ;
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39: static int
40: internal_function
41: dlerror_run (void (*operate) (void *), void *args)
42: {
43: const char *objname;
44: const char *last_errstring = NULL;
45: bool malloced;
46:
47: (void) GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
48: operate, args);
49:
50: int result = last_errstring != NULL;
51: if (result && malloced)
52: free ((char *) last_errstring);
53:
54: return result;
55: }
56:
57:
58:
59: struct do_dlopen_args
60: {
61:
62: const char *name;
63:
64: int mode;
65:
66:
67: struct link_map *map;
68: };
69:
70: struct do_dlsym_args
71: {
72:
73: struct link_map *map;
74: const char *name;
75:
76:
77: lookup_t loadbase;
78: const ElfW(Sym) *ref;
79: };
80:
81: static void
82: do_dlopen (void *ptr)
83: {
84: struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
85:
86: args->map = GLRO(dl_open) (args->name, args->mode, NULL, __LM_ID_CALLER,
87: __libc_argc, __libc_argv, __environ);
88: }
89:
90: static void
91: do_dlsym (void *ptr)
92: {
93: struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
94: args->ref = NULL;
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);
98: }
99:
100: static void
101: do_dlclose (void *ptr)
102: {
103: GLRO(dl_close) ((struct link_map *) ptr);
104: }
105:
106:
107:
108:
109: struct 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
117: extern struct dl_open_hook *_dl_open_hook;
118: libc_hidden_proto (_dl_open_hook);
119: struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
120: libc_hidden_data_def (_dl_open_hook);
121: #else
122: static void
123: do_dlsym_private (void *ptr)
124: {
125: lookup_t l;
126: struct r_found_version vers;
127: vers.name = "GLIBC_PRIVATE";
128: vers.hidden = 1;
129:
130: vers.hash = 0x0963cf85;
131: vers.filename = NULL;
132:
133: struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
134: args->ref = NULL;
135: l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
136: args->map->l_scope, &vers, 0, 0, NULL);
137: args->loadbase = l;
138: }
139:
140: static 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:
148:
149:
150: void *
151: __libc_dlopen_mode (const char *name, int mode)
152: {
153: struct do_dlopen_args args;
154: args.name = name;
155: args.mode = mode;
156:
157: #ifdef SHARED
158: if (__builtin_expect (_dl_open_hook != NULL, 0))
159: return _dl_open_hook->dlopen_mode (name, mode);
160: return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
161: #else
162: if (dlerror_run (do_dlopen, &args))
163: return NULL;
164:
165: __libc_register_dl_open_hook (args.map);
166: __libc_register_dlfcn_hook (args.map);
167: return (void *) args.map;
168: #endif
169: }
170: libc_hidden_def (__libc_dlopen_mode)
171:
172: #ifndef SHARED
173: void *
174: __libc_dlsym_private (struct link_map *map, const char *name)
175: {
176: struct do_dlsym_args sargs;
177: sargs.map = map;
178: sargs.name = name;
179:
180: if (! dlerror_run (do_dlsym_private, &sargs))
181: return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref);
182: return NULL;
183: }
184:
185: void
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;
193: }
194: #endif
195:
196: void *
197: __libc_dlsym (void *map, const char *name)
198: {
199: struct do_dlsym_args args;
200: args.map = map;
201: args.name = name;
202:
203: #ifdef SHARED
204: if (__builtin_expect (_dl_open_hook != NULL, 0))
205: return _dl_open_hook->dlsym (map, name);
206: #endif
207: return (dlerror_run (do_dlsym, &args) ? NULL
208: : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
209: }
210: libc_hidden_def (__libc_dlsym)
211:
212: int
213: __libc_dlclose (void *map)
214: {
215: #ifdef SHARED
216: if (__builtin_expect (_dl_open_hook != NULL, 0))
217: return _dl_open_hook->dlclose (map);
218: #endif
219: return dlerror_run (do_dlclose, map);
220: }
221: libc_hidden_def (__libc_dlclose)
222:
223:
224: libc_freeres_fn (free_mem)
225: {
226: struct link_map *l;
227: struct r_search_path_elem *d;
228:
229:
230: d = GL(dl_all_dirs);
231: while (d != GLRO(dl_init_all_dirs))
232: {
233: struct r_search_path_elem *old = d;
234: d = d->next;
235: free (old);
236: }
237:
238:
239: for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
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)
251: free (old);
252: }
253: }
254: }