| Index: openssl/crypto/dso/dso_dlfcn.c
|
| ===================================================================
|
| --- openssl/crypto/dso/dso_dlfcn.c (revision 105093)
|
| +++ openssl/crypto/dso/dso_dlfcn.c (working copy)
|
| @@ -56,6 +56,16 @@
|
| *
|
| */
|
|
|
| +/* 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>
|
| @@ -68,7 +78,17 @@
|
| #else
|
|
|
| #ifdef HAVE_DLFCN_H
|
| -#include <dlfcn.h>
|
| +# 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))
|
| +# undef HAVE_DLINFO
|
| +# endif
|
| #endif
|
|
|
| /* Part of the hack in "dlfcn_load" ... */
|
| @@ -87,6 +107,8 @@
|
| 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",
|
| @@ -103,7 +125,9 @@
|
| dlfcn_name_converter,
|
| dlfcn_merger,
|
| NULL, /* init */
|
| - NULL /* finish */
|
| + NULL, /* finish */
|
| + dlfcn_pathbyaddr,
|
| + dlfcn_globallookup
|
| };
|
|
|
| DSO_METHOD *DSO_METHOD_dlfcn(void)
|
| @@ -163,7 +187,7 @@
|
| 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;
|
| @@ -188,15 +212,15 @@
|
| 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() */
|
| @@ -213,12 +237,12 @@
|
| 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);
|
| @@ -247,12 +271,12 @@
|
| 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);
|
| @@ -281,13 +305,12 @@
|
| }
|
| /* 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);
|
| @@ -313,7 +336,7 @@
|
| {
|
| int spec2len, len;
|
|
|
| - spec2len = (filespec2 ? strlen(filespec2) : 0);
|
| + spec2len = strlen(filespec2);
|
| len = spec2len + (filespec1 ? strlen(filespec1) : 0);
|
|
|
| if(filespec2 && filespec2[spec2len - 1] == '/')
|
| @@ -378,4 +401,83 @@
|
| return(translated);
|
| }
|
|
|
| +#ifdef __sgi
|
| +/*
|
| +This is a quote from IRIX manual for dladdr(3c):
|
| +
|
| + <dlfcn.h> does not contain a prototype for dladdr or definition of
|
| + Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,
|
| + but contains no dladdr prototype and no IRIX library contains an
|
| + implementation. Write your own declaration based on the code below.
|
| +
|
| + The following code is dependent on internal interfaces that are not
|
| + 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.
|
| +*/
|
| +#include <rld_interface.h>
|
| +#ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
|
| +#define _RLD_INTERFACE_DLFCN_H_DLADDR
|
| +typedef struct Dl_info {
|
| + const char * dli_fname;
|
| + void * dli_fbase;
|
| + const char * dli_sname;
|
| + void * dli_saddr;
|
| + int dli_version;
|
| + int dli_reserved1;
|
| + long dli_reserved[4];
|
| +} Dl_info;
|
| +#else
|
| +typedef struct Dl_info Dl_info;
|
| +#endif
|
| +#define _RLD_DLADDR 14
|
| +
|
| +static int dladdr(void *address, Dl_info *dl)
|
| +{
|
| + void *v;
|
| + v = _rld_new_interface(_RLD_DLADDR,address,dl);
|
| + return (int)v;
|
| +}
|
| +#endif /* __sgi */
|
| +
|
| +static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
|
| + {
|
| +#ifdef HAVE_DLINFO
|
| + Dl_info dli;
|
| + int len;
|
| +
|
| + if (addr == NULL)
|
| + {
|
| + union { int(*f)(void*,char*,int); void *p; } t =
|
| + { dlfcn_pathbyaddr };
|
| + addr = t.p;
|
| + }
|
| +
|
| + if (dladdr(addr,&dli))
|
| + {
|
| + len = (int)strlen(dli.dli_fname);
|
| + if (sz <= 0) return len+1;
|
| + if (len >= sz) len=sz-1;
|
| + memcpy(path,dli.dli_fname,len);
|
| + path[len++]=0;
|
| + return len;
|
| + }
|
| +
|
| + 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 */
|
|
|