]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dso/dso_dlfcn.c
Remove several unused undocumented functions.
[thirdparty/openssl.git] / crypto / dso / dso_dlfcn.c
CommitLineData
0f113f3e
MC
1/*
2 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
3 * 2000.
8f4fac7f
GT
4 */
5/* ====================================================================
6 * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
0f113f3e 13 * notice, this list of conditions and the following disclaimer.
8f4fac7f
GT
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
0f113f3e
MC
59/*
60 * We need to do this early, because stdio.h includes the header files that
61 * handle _GNU_SOURCE and other similar macros. Defining it later is simply
62 * too late, because those headers are protected from re- inclusion.
63 */
c1844095 64#ifndef _GNU_SOURCE
0f113f3e 65# define _GNU_SOURCE /* make sure dladdr is declared */
3ecbd099
RL
66#endif
67
73decf59 68#include "dso_locl.h"
8f4fac7f 69
38186bfd 70#ifdef DSO_DLFCN
8f4fac7f 71
0f113f3e
MC
72# ifdef HAVE_DLFCN_H
73# ifdef __osf__
74# define __EXTENSIONS__
75# endif
76# include <dlfcn.h>
77# define HAVE_DLINFO 1
78# if defined(_AIX) || defined(__CYGWIN__) || \
73133962 79 defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
afb41913 80 (defined(__osf__) && !defined(RTLD_NEXT)) || \
7a4ec19a 81 (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
0f113f3e
MC
82 defined(__ANDROID__)
83# undef HAVE_DLINFO
84# endif
73133962 85# endif
8f4fac7f 86
b9e63915 87/* Part of the hack in "dlfcn_load" ... */
0f113f3e 88# define DSO_MAX_TRANSLATED_SIZE 256
b9e63915 89
51c8dc37 90static int dlfcn_load(DSO *dso);
8f4fac7f 91static int dlfcn_unload(DSO *dso);
e9a68cfb 92static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
51c8dc37 93static char *dlfcn_name_converter(DSO *dso, const char *filename);
cbecb3ac 94static char *dlfcn_merger(DSO *dso, const char *filespec1,
0f113f3e 95 const char *filespec2);
c6cb42e4 96static void *dlfcn_globallookup(const char *name);
8f4fac7f
GT
97
98static DSO_METHOD dso_meth_dlfcn = {
0f113f3e
MC
99 "OpenSSL 'dlfcn' shared library method",
100 dlfcn_load,
101 dlfcn_unload,
0f113f3e 102 dlfcn_bind_func,
0f113f3e
MC
103 NULL, /* ctrl */
104 dlfcn_name_converter,
105 dlfcn_merger,
106 NULL, /* init */
107 NULL, /* finish */
0f113f3e
MC
108 dlfcn_globallookup
109};
8f4fac7f 110
38186bfd 111DSO_METHOD *DSO_METHOD_openssl(void)
0f113f3e 112{
38186bfd 113 return &dso_meth_dlfcn;
0f113f3e
MC
114}
115
116/*
117 * Prior to using the dlopen() function, we should decide on the flag we
118 * send. There's a few different ways of doing this and it's a messy
119 * venn-diagram to match up which platforms support what. So as we don't have
120 * autoconf yet, I'm implementing a hack that could be hacked further
121 * relatively easily to deal with cases as we find them. Initially this is to
122 * cope with OpenBSD.
123 */
124# if defined(__OpenBSD__) || defined(__NetBSD__)
125# ifdef DL_LAZY
126# define DLOPEN_FLAG DL_LAZY
127# else
128# ifdef RTLD_NOW
129# define DLOPEN_FLAG RTLD_NOW
130# else
131# define DLOPEN_FLAG 0
132# endif
133# endif
134# else
135# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */
136# endif
1a797ac6 137
0f113f3e
MC
138/*
139 * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
140 * (void*) returned from dlopen().
8f4fac7f
GT
141 */
142
51c8dc37 143static int dlfcn_load(DSO *dso)
0f113f3e
MC
144{
145 void *ptr = NULL;
146 /* See applicable comments in dso_dl.c */
147 char *filename = DSO_convert_filename(dso, NULL);
148 int flags = DLOPEN_FLAG;
149
150 if (filename == NULL) {
151 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
152 goto err;
153 }
154# ifdef RTLD_GLOBAL
155 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
156 flags |= RTLD_GLOBAL;
157# endif
158 ptr = dlopen(filename, flags);
159 if (ptr == NULL) {
160 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
161 ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
162 goto err;
163 }
164 if (!sk_void_push(dso->meth_data, (char *)ptr)) {
165 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
166 goto err;
167 }
168 /* Success */
169 dso->loaded_filename = filename;
170 return (1);
171 err:
172 /* Cleanup! */
b548a1f1 173 OPENSSL_free(filename);
0f113f3e
MC
174 if (ptr != NULL)
175 dlclose(ptr);
176 return (0);
51c8dc37 177}
8f4fac7f
GT
178
179static int dlfcn_unload(DSO *dso)
0f113f3e
MC
180{
181 void *ptr;
182 if (dso == NULL) {
183 DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
184 return (0);
185 }
186 if (sk_void_num(dso->meth_data) < 1)
187 return (1);
188 ptr = sk_void_pop(dso->meth_data);
189 if (ptr == NULL) {
190 DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
191 /*
192 * Should push the value back onto the stack in case of a retry.
193 */
194 sk_void_push(dso->meth_data, ptr);
195 return (0);
196 }
197 /* For now I'm not aware of any errors associated with dlclose() */
198 dlclose(ptr);
199 return (1);
200}
8f4fac7f 201
e9a68cfb 202static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
0f113f3e
MC
203{
204 void *ptr;
205 union {
206 DSO_FUNC_TYPE sym;
207 void *dlret;
208 } u;
209
210 if ((dso == NULL) || (symname == NULL)) {
211 DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
212 return (NULL);
213 }
214 if (sk_void_num(dso->meth_data) < 1) {
215 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
216 return (NULL);
217 }
218 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
219 if (ptr == NULL) {
220 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
221 return (NULL);
222 }
223 u.dlret = dlsym(ptr, symname);
224 if (u.dlret == NULL) {
225 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
226 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
227 return (NULL);
228 }
229 return u.sym;
230}
8f4fac7f 231
cbecb3ac 232static char *dlfcn_merger(DSO *dso, const char *filespec1,
0f113f3e
MC
233 const char *filespec2)
234{
235 char *merged;
236
237 if (!filespec1 && !filespec2) {
238 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);
239 return (NULL);
240 }
241 /*
242 * If the first file specification is a rooted path, it rules. same goes
243 * if the second file specification is missing.
244 */
245 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
a89c9a0d 246 merged = OPENSSL_strdup(filespec1);
90945fa3 247 if (merged == NULL) {
0f113f3e
MC
248 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
249 return (NULL);
250 }
0f113f3e
MC
251 }
252 /*
253 * If the first file specification is missing, the second one rules.
254 */
255 else if (!filespec1) {
a89c9a0d 256 merged = OPENSSL_strdup(filespec2);
90945fa3 257 if (merged == NULL) {
0f113f3e
MC
258 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
259 return (NULL);
260 }
b7573c59 261 } else {
0f113f3e
MC
262 /*
263 * This part isn't as trivial as it looks. It assumes that the
264 * second file specification really is a directory, and makes no
265 * checks whatsoever. Therefore, the result becomes the
266 * concatenation of filespec2 followed by a slash followed by
267 * filespec1.
268 */
0f113f3e
MC
269 int spec2len, len;
270
271 spec2len = strlen(filespec2);
b7573c59 272 len = spec2len + strlen(filespec1);
0f113f3e 273
b7573c59 274 if (spec2len && filespec2[spec2len - 1] == '/') {
0f113f3e
MC
275 spec2len--;
276 len--;
277 }
278 merged = OPENSSL_malloc(len + 2);
90945fa3 279 if (merged == NULL) {
0f113f3e
MC
280 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
281 return (NULL);
282 }
283 strcpy(merged, filespec2);
284 merged[spec2len] = '/';
285 strcpy(&merged[spec2len + 1], filespec1);
286 }
287 return (merged);
288}
4a620922 289
51c8dc37 290static char *dlfcn_name_converter(DSO *dso, const char *filename)
0f113f3e
MC
291{
292 char *translated;
293 int len, rsize, transform;
294
295 len = strlen(filename);
296 rsize = len + 1;
297 transform = (strstr(filename, "/") == NULL);
298 if (transform) {
299 /* We will convert this to "%s.so" or "lib%s.so" etc */
e987f9f2 300 rsize += strlen(DSO_EXTENSION); /* The length of ".so" */
0f113f3e
MC
301 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
302 rsize += 3; /* The length of "lib" */
303 }
304 translated = OPENSSL_malloc(rsize);
305 if (translated == NULL) {
306 DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
307 return (NULL);
308 }
309 if (transform) {
310 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
e987f9f2 311 sprintf(translated, "lib%s" DSO_EXTENSION, filename);
0f113f3e 312 else
e987f9f2 313 sprintf(translated, "%s" DSO_EXTENSION, filename);
0f113f3e
MC
314 } else
315 sprintf(translated, "%s", filename);
316 return (translated);
317}
318
319# ifdef __sgi
23a22b4c 320/*-
7ed87653
AP
321This is a quote from IRIX manual for dladdr(3c):
322
323 <dlfcn.h> does not contain a prototype for dladdr or definition of
324 Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,
325 but contains no dladdr prototype and no IRIX library contains an
326 implementation. Write your own declaration based on the code below.
327
328 The following code is dependent on internal interfaces that are not
329 part of the IRIX compatibility guarantee; however, there is no future
330 intention to change this interface, so on a practical level, the code
331 below is safe to use on IRIX.
c8e1edaa 332*/
0f113f3e
MC
333# include <rld_interface.h>
334# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
335# define _RLD_INTERFACE_DLFCN_H_DLADDR
7ed87653 336typedef struct Dl_info {
0f113f3e
MC
337 const char *dli_fname;
338 void *dli_fbase;
339 const char *dli_sname;
340 void *dli_saddr;
341 int dli_version;
342 int dli_reserved1;
343 long dli_reserved[4];
7ed87653 344} Dl_info;
0f113f3e 345# else
7ed87653 346typedef struct Dl_info Dl_info;
0f113f3e
MC
347# endif
348# define _RLD_DLADDR 14
7ed87653
AP
349
350static int dladdr(void *address, Dl_info *dl)
351{
0f113f3e
MC
352 void *v;
353 v = _rld_new_interface(_RLD_DLADDR, address, dl);
354 return (int)v;
355}
356# endif /* __sgi */
357
c6cb42e4 358static void *dlfcn_globallookup(const char *name)
0f113f3e
MC
359{
360 void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
361
362 if (handle) {
363 ret = dlsym(handle, name);
364 dlclose(handle);
365 }
366
367 return ret;
368}
369#endif /* DSO_DLFCN */