1295016Sjkim/* dso_dlfcn.c */
2280304Sjkim/*
3280304Sjkim * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
4280304Sjkim * 2000.
568651Skris */
668651Skris/* ====================================================================
768651Skris * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
868651Skris *
968651Skris * Redistribution and use in source and binary forms, with or without
1068651Skris * modification, are permitted provided that the following conditions
1168651Skris * are met:
1268651Skris *
1368651Skris * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
1568651Skris *
1668651Skris * 2. Redistributions in binary form must reproduce the above copyright
1768651Skris *    notice, this list of conditions and the following disclaimer in
1868651Skris *    the documentation and/or other materials provided with the
1968651Skris *    distribution.
2068651Skris *
2168651Skris * 3. All advertising materials mentioning features or use of this
2268651Skris *    software must display the following acknowledgment:
2368651Skris *    "This product includes software developed by the OpenSSL Project
2468651Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2568651Skris *
2668651Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2768651Skris *    endorse or promote products derived from this software without
2868651Skris *    prior written permission. For written permission, please contact
2968651Skris *    licensing@OpenSSL.org.
3068651Skris *
3168651Skris * 5. Products derived from this software may not be called "OpenSSL"
3268651Skris *    nor may "OpenSSL" appear in their names without prior written
3368651Skris *    permission of the OpenSSL Project.
3468651Skris *
3568651Skris * 6. Redistributions of any form whatsoever must retain the following
3668651Skris *    acknowledgment:
3768651Skris *    "This product includes software developed by the OpenSSL Project
3868651Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3968651Skris *
4068651Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4168651Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4268651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4368651Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4468651Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4568651Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4668651Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4768651Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4868651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4968651Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5068651Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5168651Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5268651Skris * ====================================================================
5368651Skris *
5468651Skris * This product includes cryptographic software written by Eric Young
5568651Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5668651Skris * Hudson (tjh@cryptsoft.com).
5768651Skris *
5868651Skris */
5968651Skris
60280304Sjkim/*
61280304Sjkim * We need to do this early, because stdio.h includes the header files that
62280304Sjkim * handle _GNU_SOURCE and other similar macros.  Defining it later is simply
63280304Sjkim * too late, because those headers are protected from re- inclusion.
64280304Sjkim */
65276864Sjkim#ifndef _GNU_SOURCE
66280304Sjkim# define _GNU_SOURCE            /* make sure dladdr is declared */
67238405Sjkim#endif
68238405Sjkim
6968651Skris#include <stdio.h>
7068651Skris#include "cryptlib.h"
7168651Skris#include <openssl/dso.h>
7268651Skris
7368651Skris#ifndef DSO_DLFCN
7468651SkrisDSO_METHOD *DSO_METHOD_dlfcn(void)
75280304Sjkim{
76280304Sjkim    return NULL;
77280304Sjkim}
7868651Skris#else
7968651Skris
80280304Sjkim# ifdef HAVE_DLFCN_H
81280304Sjkim#  ifdef __osf__
82280304Sjkim#   define __EXTENSIONS__
83280304Sjkim#  endif
84280304Sjkim#  include <dlfcn.h>
85280304Sjkim#  define HAVE_DLINFO 1
86280304Sjkim#  if defined(_AIX) || defined(__CYGWIN__) || \
87238405Sjkim     defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
88238405Sjkim     (defined(__osf__) && !defined(RTLD_NEXT))     || \
89238405Sjkim     (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
90280304Sjkim        defined(__ANDROID__)
91280304Sjkim#   undef HAVE_DLINFO
92280304Sjkim#  endif
93238405Sjkim# endif
9468651Skris
9568651Skris/* Part of the hack in "dlfcn_load" ... */
96280304Sjkim# define DSO_MAX_TRANSLATED_SIZE 256
9768651Skris
98109998Smarkmstatic int dlfcn_load(DSO *dso);
9968651Skrisstatic int dlfcn_unload(DSO *dso);
10068651Skrisstatic void *dlfcn_bind_var(DSO *dso, const char *symname);
10168651Skrisstatic DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
102280304Sjkim# if 0
10368651Skrisstatic int dlfcn_unbind(DSO *dso, char *symname, void *symptr);
10468651Skrisstatic int dlfcn_init(DSO *dso);
10568651Skrisstatic int dlfcn_finish(DSO *dso);
106109998Smarkmstatic long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg);
107280304Sjkim# endif
108109998Smarkmstatic char *dlfcn_name_converter(DSO *dso, const char *filename);
109160814Ssimonstatic char *dlfcn_merger(DSO *dso, const char *filespec1,
110280304Sjkim                          const char *filespec2);
111280304Sjkimstatic int dlfcn_pathbyaddr(void *addr, char *path, int sz);
112238405Sjkimstatic void *dlfcn_globallookup(const char *name);
11368651Skris
11468651Skrisstatic DSO_METHOD dso_meth_dlfcn = {
115280304Sjkim    "OpenSSL 'dlfcn' shared library method",
116280304Sjkim    dlfcn_load,
117280304Sjkim    dlfcn_unload,
118280304Sjkim    dlfcn_bind_var,
119280304Sjkim    dlfcn_bind_func,
12068651Skris/* For now, "unbind" doesn't exist */
121280304Sjkim# if 0
122280304Sjkim    NULL,                       /* unbind_var */
123280304Sjkim    NULL,                       /* unbind_func */
124280304Sjkim# endif
125280304Sjkim    NULL,                       /* ctrl */
126280304Sjkim    dlfcn_name_converter,
127280304Sjkim    dlfcn_merger,
128280304Sjkim    NULL,                       /* init */
129280304Sjkim    NULL,                       /* finish */
130280304Sjkim    dlfcn_pathbyaddr,
131280304Sjkim    dlfcn_globallookup
132280304Sjkim};
13368651Skris
13468651SkrisDSO_METHOD *DSO_METHOD_dlfcn(void)
135280304Sjkim{
136280304Sjkim    return (&dso_meth_dlfcn);
137280304Sjkim}
13868651Skris
139280304Sjkim/*
140280304Sjkim * Prior to using the dlopen() function, we should decide on the flag we
141280304Sjkim * send. There's a few different ways of doing this and it's a messy
142280304Sjkim * venn-diagram to match up which platforms support what. So as we don't have
143280304Sjkim * autoconf yet, I'm implementing a hack that could be hacked further
144280304Sjkim * relatively easily to deal with cases as we find them. Initially this is to
145280304Sjkim * cope with OpenBSD.
146280304Sjkim */
147280304Sjkim# if defined(__OpenBSD__) || defined(__NetBSD__)
148280304Sjkim#  ifdef DL_LAZY
149280304Sjkim#   define DLOPEN_FLAG DL_LAZY
150280304Sjkim#  else
151280304Sjkim#   ifdef RTLD_NOW
152280304Sjkim#    define DLOPEN_FLAG RTLD_NOW
153280304Sjkim#   else
154280304Sjkim#    define DLOPEN_FLAG 0
155280304Sjkim#   endif
156280304Sjkim#  endif
157280304Sjkim# else
158280304Sjkim#  ifdef OPENSSL_SYS_SUNOS
159280304Sjkim#   define DLOPEN_FLAG 1
160280304Sjkim#  else
161280304Sjkim#   define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */
162280304Sjkim#  endif
163280304Sjkim# endif
16468651Skris
165280304Sjkim/*
166280304Sjkim * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
167280304Sjkim * (void*) returned from dlopen().
16868651Skris */
16968651Skris
170109998Smarkmstatic int dlfcn_load(DSO *dso)
171280304Sjkim{
172280304Sjkim    void *ptr = NULL;
173280304Sjkim    /* See applicable comments in dso_dl.c */
174280304Sjkim    char *filename = DSO_convert_filename(dso, NULL);
175280304Sjkim    int flags = DLOPEN_FLAG;
17668651Skris
177280304Sjkim    if (filename == NULL) {
178280304Sjkim        DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
179280304Sjkim        goto err;
180280304Sjkim    }
181280304Sjkim# ifdef RTLD_GLOBAL
182280304Sjkim    if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
183280304Sjkim        flags |= RTLD_GLOBAL;
184280304Sjkim# endif
185280304Sjkim    ptr = dlopen(filename, flags);
186280304Sjkim    if (ptr == NULL) {
187280304Sjkim        DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
188280304Sjkim        ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
189280304Sjkim        goto err;
190280304Sjkim    }
191280304Sjkim    if (!sk_void_push(dso->meth_data, (char *)ptr)) {
192280304Sjkim        DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
193280304Sjkim        goto err;
194280304Sjkim    }
195280304Sjkim    /* Success */
196280304Sjkim    dso->loaded_filename = filename;
197280304Sjkim    return (1);
198280304Sjkim err:
199280304Sjkim    /* Cleanup! */
200280304Sjkim    if (filename != NULL)
201280304Sjkim        OPENSSL_free(filename);
202280304Sjkim    if (ptr != NULL)
203280304Sjkim        dlclose(ptr);
204280304Sjkim    return (0);
205109998Smarkm}
20668651Skris
20768651Skrisstatic int dlfcn_unload(DSO *dso)
208280304Sjkim{
209280304Sjkim    void *ptr;
210280304Sjkim    if (dso == NULL) {
211280304Sjkim        DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
212280304Sjkim        return (0);
213280304Sjkim    }
214280304Sjkim    if (sk_void_num(dso->meth_data) < 1)
215280304Sjkim        return (1);
216280304Sjkim    ptr = sk_void_pop(dso->meth_data);
217280304Sjkim    if (ptr == NULL) {
218280304Sjkim        DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
219280304Sjkim        /*
220280304Sjkim         * Should push the value back onto the stack in case of a retry.
221280304Sjkim         */
222280304Sjkim        sk_void_push(dso->meth_data, ptr);
223280304Sjkim        return (0);
224280304Sjkim    }
225280304Sjkim    /* For now I'm not aware of any errors associated with dlclose() */
226280304Sjkim    dlclose(ptr);
227280304Sjkim    return (1);
228280304Sjkim}
22968651Skris
23068651Skrisstatic void *dlfcn_bind_var(DSO *dso, const char *symname)
231280304Sjkim{
232280304Sjkim    void *ptr, *sym;
23368651Skris
234280304Sjkim    if ((dso == NULL) || (symname == NULL)) {
235280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
236280304Sjkim        return (NULL);
237280304Sjkim    }
238280304Sjkim    if (sk_void_num(dso->meth_data) < 1) {
239280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_STACK_ERROR);
240280304Sjkim        return (NULL);
241280304Sjkim    }
242280304Sjkim    ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
243280304Sjkim    if (ptr == NULL) {
244280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_NULL_HANDLE);
245280304Sjkim        return (NULL);
246280304Sjkim    }
247280304Sjkim    sym = dlsym(ptr, symname);
248280304Sjkim    if (sym == NULL) {
249280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_SYM_FAILURE);
250280304Sjkim        ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
251280304Sjkim        return (NULL);
252280304Sjkim    }
253280304Sjkim    return (sym);
254280304Sjkim}
25568651Skris
25668651Skrisstatic DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
257280304Sjkim{
258280304Sjkim    void *ptr;
259280304Sjkim    union {
260280304Sjkim        DSO_FUNC_TYPE sym;
261280304Sjkim        void *dlret;
262280304Sjkim    } u;
26368651Skris
264280304Sjkim    if ((dso == NULL) || (symname == NULL)) {
265280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
266280304Sjkim        return (NULL);
267280304Sjkim    }
268280304Sjkim    if (sk_void_num(dso->meth_data) < 1) {
269280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
270280304Sjkim        return (NULL);
271280304Sjkim    }
272280304Sjkim    ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
273280304Sjkim    if (ptr == NULL) {
274280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
275280304Sjkim        return (NULL);
276280304Sjkim    }
277280304Sjkim    u.dlret = dlsym(ptr, symname);
278280304Sjkim    if (u.dlret == NULL) {
279280304Sjkim        DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
280280304Sjkim        ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
281280304Sjkim        return (NULL);
282280304Sjkim    }
283280304Sjkim    return u.sym;
284280304Sjkim}
28568651Skris
286160814Ssimonstatic char *dlfcn_merger(DSO *dso, const char *filespec1,
287280304Sjkim                          const char *filespec2)
288280304Sjkim{
289280304Sjkim    char *merged;
290160814Ssimon
291280304Sjkim    if (!filespec1 && !filespec2) {
292280304Sjkim        DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);
293280304Sjkim        return (NULL);
294280304Sjkim    }
295280304Sjkim    /*
296280304Sjkim     * If the first file specification is a rooted path, it rules. same goes
297280304Sjkim     * if the second file specification is missing.
298280304Sjkim     */
299280304Sjkim    if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
300280304Sjkim        merged = OPENSSL_malloc(strlen(filespec1) + 1);
301280304Sjkim        if (!merged) {
302280304Sjkim            DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
303280304Sjkim            return (NULL);
304280304Sjkim        }
305280304Sjkim        strcpy(merged, filespec1);
306280304Sjkim    }
307280304Sjkim    /*
308280304Sjkim     * If the first file specification is missing, the second one rules.
309280304Sjkim     */
310280304Sjkim    else if (!filespec1) {
311280304Sjkim        merged = OPENSSL_malloc(strlen(filespec2) + 1);
312280304Sjkim        if (!merged) {
313280304Sjkim            DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
314280304Sjkim            return (NULL);
315280304Sjkim        }
316280304Sjkim        strcpy(merged, filespec2);
317280304Sjkim    } else {
318280304Sjkim        /*
319280304Sjkim         * This part isn't as trivial as it looks.  It assumes that the
320280304Sjkim         * second file specification really is a directory, and makes no
321280304Sjkim         * checks whatsoever.  Therefore, the result becomes the
322280304Sjkim         * concatenation of filespec2 followed by a slash followed by
323280304Sjkim         * filespec1.
324280304Sjkim         */
325280304Sjkim        int spec2len, len;
326160814Ssimon
327280304Sjkim        spec2len = strlen(filespec2);
328280304Sjkim        len = spec2len + strlen(filespec1);
329160814Ssimon
330280304Sjkim        if (spec2len && filespec2[spec2len - 1] == '/') {
331280304Sjkim            spec2len--;
332280304Sjkim            len--;
333280304Sjkim        }
334280304Sjkim        merged = OPENSSL_malloc(len + 2);
335280304Sjkim        if (!merged) {
336280304Sjkim            DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
337280304Sjkim            return (NULL);
338280304Sjkim        }
339280304Sjkim        strcpy(merged, filespec2);
340280304Sjkim        merged[spec2len] = '/';
341280304Sjkim        strcpy(&merged[spec2len + 1], filespec1);
342280304Sjkim    }
343280304Sjkim    return (merged);
344280304Sjkim}
345160814Ssimon
346280304Sjkim# ifdef OPENSSL_SYS_MACOSX
347280304Sjkim#  define DSO_ext ".dylib"
348280304Sjkim#  define DSO_extlen 6
349280304Sjkim# else
350280304Sjkim#  define DSO_ext ".so"
351280304Sjkim#  define DSO_extlen 3
352280304Sjkim# endif
353205128Ssimon
354109998Smarkmstatic char *dlfcn_name_converter(DSO *dso, const char *filename)
355280304Sjkim{
356280304Sjkim    char *translated;
357280304Sjkim    int len, rsize, transform;
358109998Smarkm
359280304Sjkim    len = strlen(filename);
360280304Sjkim    rsize = len + 1;
361280304Sjkim    transform = (strstr(filename, "/") == NULL);
362280304Sjkim    if (transform) {
363280304Sjkim        /* We will convert this to "%s.so" or "lib%s.so" etc */
364280304Sjkim        rsize += DSO_extlen;    /* The length of ".so" */
365280304Sjkim        if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
366280304Sjkim            rsize += 3;         /* The length of "lib" */
367280304Sjkim    }
368280304Sjkim    translated = OPENSSL_malloc(rsize);
369280304Sjkim    if (translated == NULL) {
370280304Sjkim        DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
371280304Sjkim        return (NULL);
372280304Sjkim    }
373280304Sjkim    if (transform) {
374280304Sjkim        if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
375280304Sjkim            sprintf(translated, "lib%s" DSO_ext, filename);
376280304Sjkim        else
377280304Sjkim            sprintf(translated, "%s" DSO_ext, filename);
378280304Sjkim    } else
379280304Sjkim        sprintf(translated, "%s", filename);
380280304Sjkim    return (translated);
381280304Sjkim}
38268651Skris
383280304Sjkim# ifdef __sgi
384280304Sjkim/*-
385238405SjkimThis is a quote from IRIX manual for dladdr(3c):
386238405Sjkim
387238405Sjkim     <dlfcn.h> does not contain a prototype for dladdr or definition of
388238405Sjkim     Dl_info.  The #include <dlfcn.h>  in the SYNOPSIS line is traditional,
389238405Sjkim     but contains no dladdr prototype and no IRIX library contains an
390238405Sjkim     implementation.  Write your own declaration based on the code below.
391238405Sjkim
392238405Sjkim     The following code is dependent on internal interfaces that are not
393238405Sjkim     part of the IRIX compatibility guarantee; however, there is no future
394238405Sjkim     intention to change this interface, so on a practical level, the code
395238405Sjkim     below is safe to use on IRIX.
396238405Sjkim*/
397280304Sjkim#  include <rld_interface.h>
398280304Sjkim#  ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
399280304Sjkim#   define _RLD_INTERFACE_DLFCN_H_DLADDR
400238405Sjkimtypedef struct Dl_info {
401280304Sjkim    const char *dli_fname;
402280304Sjkim    void *dli_fbase;
403280304Sjkim    const char *dli_sname;
404280304Sjkim    void *dli_saddr;
405280304Sjkim    int dli_version;
406280304Sjkim    int dli_reserved1;
407280304Sjkim    long dli_reserved[4];
408238405Sjkim} Dl_info;
409280304Sjkim#  else
410238405Sjkimtypedef struct Dl_info Dl_info;
411280304Sjkim#  endif
412280304Sjkim#  define _RLD_DLADDR             14
413238405Sjkim
414238405Sjkimstatic int dladdr(void *address, Dl_info *dl)
415238405Sjkim{
416280304Sjkim    void *v;
417280304Sjkim    v = _rld_new_interface(_RLD_DLADDR, address, dl);
418280304Sjkim    return (int)v;
419238405Sjkim}
420280304Sjkim# endif                         /* __sgi */
421238405Sjkim
422280304Sjkimstatic int dlfcn_pathbyaddr(void *addr, char *path, int sz)
423280304Sjkim{
424280304Sjkim# ifdef HAVE_DLINFO
425280304Sjkim    Dl_info dli;
426280304Sjkim    int len;
427238405Sjkim
428280304Sjkim    if (addr == NULL) {
429280304Sjkim        union {
430280304Sjkim            int (*f) (void *, char *, int);
431280304Sjkim            void *p;
432280304Sjkim        } t = {
433280304Sjkim            dlfcn_pathbyaddr
434280304Sjkim        };
435280304Sjkim        addr = t.p;
436280304Sjkim    }
437238405Sjkim
438280304Sjkim    if (dladdr(addr, &dli)) {
439280304Sjkim        len = (int)strlen(dli.dli_fname);
440280304Sjkim        if (sz <= 0)
441280304Sjkim            return len + 1;
442280304Sjkim        if (len >= sz)
443280304Sjkim            len = sz - 1;
444280304Sjkim        memcpy(path, dli.dli_fname, len);
445280304Sjkim        path[len++] = 0;
446280304Sjkim        return len;
447280304Sjkim    }
448238405Sjkim
449280304Sjkim    ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());
450280304Sjkim# endif
451280304Sjkim    return -1;
452280304Sjkim}
453238405Sjkim
454238405Sjkimstatic void *dlfcn_globallookup(const char *name)
455280304Sjkim{
456280304Sjkim    void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
457238405Sjkim
458280304Sjkim    if (handle) {
459280304Sjkim        ret = dlsym(handle, name);
460280304Sjkim        dlclose(handle);
461280304Sjkim    }
462280304Sjkim
463280304Sjkim    return ret;
464280304Sjkim}
465280304Sjkim#endif                          /* DSO_DLFCN */
466