*
*/
+/* We need to do this early, because stdio.h includes the header files
+ that handle _GNU_SOURCE and other similar macros. Defining it later
+ is simply too late, because those headers are protected from re-
+ inclusion. */
+#ifdef __linux
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE /* make sure dladdr is declared */
+# endif
+#endif
+
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/dso.h>
#else
#ifdef HAVE_DLFCN_H
-
-#ifdef __linux
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE /* make sure dladdr is declared */
+# ifdef __osf__
+# define __EXTENSIONS__
+# endif
+# include <dlfcn.h>
+# define HAVE_DLINFO 1
+# if defined(_AIX) || defined(__CYGWIN__) || \
+ defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
+ (defined(__osf__) && !defined(RTLD_NEXT)) || \
+ (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
+ defined(__ANDROID__)
+# undef HAVE_DLINFO
# endif
-#endif
-#include <dlfcn.h>
#endif
/* Part of the hack in "dlfcn_load" ... */
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",
dlfcn_merger,
NULL, /* init */
NULL, /* finish */
- dlfcn_pathbyaddr
+ dlfcn_pathbyaddr,
+ dlfcn_globallookup
};
DSO_METHOD *DSO_METHOD_dlfcn(void)
ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
goto err;
}
- if(!sk_push(dso->meth_data, (char *)ptr))
+ if(!sk_void_push(dso->meth_data, (char *)ptr))
{
DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR);
goto err;
DSOerr(DSO_F_DLFCN_UNLOAD,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
- if(sk_num(dso->meth_data) < 1)
+ if(sk_void_num(dso->meth_data) < 1)
return(1);
- ptr = (void *)sk_pop(dso->meth_data);
+ ptr = sk_void_pop(dso->meth_data);
if(ptr == NULL)
{
DSOerr(DSO_F_DLFCN_UNLOAD,DSO_R_NULL_HANDLE);
/* Should push the value back onto the stack in
* case of a retry. */
- sk_push(dso->meth_data, (char *)ptr);
+ sk_void_push(dso->meth_data, ptr);
return(0);
}
/* For now I'm not aware of any errors associated with dlclose() */
DSOerr(DSO_F_DLFCN_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
return(NULL);
}
- if(sk_num(dso->meth_data) < 1)
+ if(sk_void_num(dso->meth_data) < 1)
{
DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_STACK_ERROR);
return(NULL);
}
- ptr = (void *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
+ ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if(ptr == NULL)
{
DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_NULL_HANDLE);
static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
{
void *ptr;
- DSO_FUNC_TYPE sym, *tsym = &sym;
+ union {
+ DSO_FUNC_TYPE sym;
+ void *dlret;
+ } u;
if((dso == NULL) || (symname == NULL))
{
DSOerr(DSO_F_DLFCN_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
return(NULL);
}
- if(sk_num(dso->meth_data) < 1)
+ if(sk_void_num(dso->meth_data) < 1)
{
DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_STACK_ERROR);
return(NULL);
}
- ptr = (void *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
+ ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if(ptr == NULL)
{
DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_NULL_HANDLE);
return(NULL);
}
- *(void **)(tsym) = dlsym(ptr, symname);
- if(sym == NULL)
+ u.dlret = dlsym(ptr, symname);
+ if(u.dlret == NULL)
{
DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE);
ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
return(NULL);
}
- return(sym);
+ return u.sym;
}
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);
{
int spec2len, len;
- spec2len = (filespec2 ? strlen(filespec2) : 0);
+ spec2len = strlen(filespec2);
len = spec2len + (filespec1 ? strlen(filespec1) : 0);
if(filespec2 && filespec2[spec2len - 1] == '/')
return(merged);
}
+#ifdef OPENSSL_SYS_MACOSX
+#define DSO_ext ".dylib"
+#define DSO_extlen 6
+#else
+#define DSO_ext ".so"
+#define DSO_extlen 3
+#endif
+
+
static char *dlfcn_name_converter(DSO *dso, const char *filename)
{
char *translated;
transform = (strstr(filename, "/") == NULL);
if(transform)
{
- /* We will convert this to "%s.so" or "lib%s.so" */
- rsize += 3; /* The length of ".so" */
+ /* We will convert this to "%s.so" or "lib%s.so" etc */
+ rsize += DSO_extlen; /* The length of ".so" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
rsize += 3; /* The length of "lib" */
}
if(transform)
{
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
- sprintf(translated, "lib%s.so", filename);
+ sprintf(translated, "lib%s" DSO_ext, filename);
else
- sprintf(translated, "%s.so", filename);
+ sprintf(translated, "%s" DSO_ext, filename);
}
else
sprintf(translated, "%s", filename);
}
#ifdef __sgi
-#if 0
+/*
This is a quote from IRIX manual for dladdr(3c):
<dlfcn.h> does not contain a prototype for dladdr or definition of
part of the IRIX compatibility guarantee; however, there is no future
intention to change this interface, so on a practical level, the code
below is safe to use on IRIX.
-#endif
+*/
#include <rld_interface.h>
#ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
#define _RLD_INTERFACE_DLFCN_H_DLADDR
v = _rld_new_interface(_RLD_DLADDR,address,dl);
return (int)v;
}
-#endif
+#endif /* __sgi */
static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
{
+#ifdef HAVE_DLINFO
Dl_info dli;
int len;
- if (addr == NULL) addr = dlfcn_pathbyaddr;
+ if (addr == NULL)
+ {
+ union { int(*f)(void*,char*,int); void *p; } t =
+ { dlfcn_pathbyaddr };
+ addr = t.p;
+ }
if (dladdr(addr,&dli))
{
return len;
}
- ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror());
+ ERR_add_error_data(2, "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 */