diff options
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c')
| -rw-r--r-- | Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c | 135 |
1 files changed, 120 insertions, 15 deletions
diff --git a/Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c b/Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c index f01255a7..f629f038 100644 --- a/Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c +++ b/Cryptlib/OpenSSL/crypto/dso/dso_dlfcn.c @@ -57,6 +57,15 @@ * */ +/* + * 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. + */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE /* make sure dladdr is declared */ +#endif + #include <stdio.h> #include "cryptlib.h" #include <openssl/dso.h> @@ -69,7 +78,18 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) #else # ifdef HAVE_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)) || \ + defined(__ANDROID__) +# undef HAVE_DLINFO +# endif # endif /* Part of the hack in "dlfcn_load" ... */ @@ -88,6 +108,8 @@ static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); 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", @@ -104,7 +126,9 @@ static DSO_METHOD dso_meth_dlfcn = { dlfcn_name_converter, dlfcn_merger, NULL, /* init */ - NULL /* finish */ + NULL, /* finish */ + dlfcn_pathbyaddr, + dlfcn_globallookup }; DSO_METHOD *DSO_METHOD_dlfcn(void) @@ -164,7 +188,7 @@ static int dlfcn_load(DSO *dso) 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; } @@ -187,15 +211,15 @@ static int dlfcn_unload(DSO *dso) 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() */ @@ -211,11 +235,11 @@ static void *dlfcn_bind_var(DSO *dso, const char *symname) 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); return (NULL); @@ -241,11 +265,11 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) 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); @@ -272,7 +296,7 @@ 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); @@ -290,7 +314,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1, return (NULL); } strcpy(merged, filespec2); - } else + } else { /* * This part isn't as trivial as it looks. It assumes that the * second file specification really is a directory, and makes no @@ -298,13 +322,12 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1, * concatenation of filespec2 followed by a slash followed by * filespec1. */ - { int spec2len, len; - spec2len = (filespec2 ? strlen(filespec2) : 0); - len = spec2len + (filespec1 ? strlen(filespec1) : 0); + spec2len = strlen(filespec2); + len = spec2len + strlen(filespec1); - if (filespec2 && filespec2[spec2len - 1] == '/') { + if (spec2len && filespec2[spec2len - 1] == '/') { spec2len--; len--; } @@ -357,4 +380,86 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename) 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(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 */ |
