Last dso_dlfcn.c check-in said "Use Dl_info only on systems where it is
[openssl.git] / crypto / dso / dso_dlfcn.c
index 6d6ee758ef2197589b8afb4d803976955f0714e0..d36e0b0f3aa8acea7bec7632a4687a5e372ab2ca 100644 (file)
@@ -78,8 +78,13 @@ DSO_METHOD *DSO_METHOD_dlfcn(void)
 #else
 
 #ifdef HAVE_DLFCN_H
-
-#include <dlfcn.h>
+# include <dlfcn.h>
+# define HAVE_DLINFO 1
+# if defined(_AIX) || defined(__CYGWIN__) || \
+     defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
+     (defined(__OpenBSD__) && !defined(RTLD_SELF))
+#  undef HAVE_DLINFO
+# endif
 #endif
 
 /* Part of the hack in "dlfcn_load" ... */
@@ -99,6 +104,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename);
 static char *dlfcn_merger(DSO *dso, const char *filespec1,
        const char *filespec2);
 static int dlfcn_pathbyaddr(void *addr,char *path,int sz);
+static void *dlfcn_globallookup(const char *name);
 
 static DSO_METHOD dso_meth_dlfcn = {
        "OpenSSL 'dlfcn' shared library method",
@@ -116,7 +122,8 @@ static DSO_METHOD dso_meth_dlfcn = {
        dlfcn_merger,
        NULL, /* init */
        NULL, /* finish */
-       dlfcn_pathbyaddr
+       dlfcn_pathbyaddr,
+       dlfcn_globallookup
        };
 
 DSO_METHOD *DSO_METHOD_dlfcn(void)
@@ -291,13 +298,12 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
                }
        /* If the first file specification is a rooted path, it rules.
           same goes if the second file specification is missing. */
-       if (!filespec2 || filespec1[0] == '/')
+       if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/'))
                {
                merged = OPENSSL_malloc(strlen(filespec1) + 1);
                if(!merged)
                        {
-                       DSOerr(DSO_F_DLFCN_MERGER,
-                               ERR_R_MALLOC_FAILURE);
+                       DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
                        return(NULL);
                        }
                strcpy(merged, filespec1);
@@ -323,7 +329,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
                {
                int spec2len, len;
 
-               spec2len = (filespec2 ? strlen(filespec2) : 0);
+               spec2len = strlen(filespec2);
                len = spec2len + (filespec1 ? strlen(filespec1) : 0);
 
                if(filespec2 && filespec2[spec2len - 1] == '/')
@@ -420,6 +426,7 @@ static int dladdr(void *address, Dl_info *dl)
 
 static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
        {
+#ifdef HAVE_DLINFO
        Dl_info dli;
        int len;
 
@@ -441,6 +448,20 @@ static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
                }
 
        ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror());
+#endif
        return -1;
        }
+
+static void *dlfcn_globallookup(const char *name)
+       {
+       void *ret = NULL,*handle = dlopen(NULL,RTLD_LAZY);
+       
+       if (handle)
+               {
+               ret = dlsym(handle,name);
+               dlclose(handle);
+               }
+
+       return ret;
+       }
 #endif /* DSO_DLFCN */