aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto/dso/dso.h15
-rw-r--r--crypto/dso/dso_dl.c27
-rw-r--r--crypto/dso/dso_dlfcn.c69
-rw-r--r--crypto/dso/dso_err.c1
-rw-r--r--crypto/dso/dso_lib.c12
-rw-r--r--crypto/dso/dso_win32.c125
6 files changed, 244 insertions, 5 deletions
diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h
index 3de99f5..c9d7366 100644
--- a/crypto/dso/dso.h
+++ b/crypto/dso/dso.h
@@ -170,6 +170,9 @@ typedef struct dso_meth_st
/* [De]Initialisation handlers. */
int (*init)(DSO *dso);
int (*finish)(DSO *dso);
+
+ /* Return pathname of the module containing location */
+ int (*pathbyaddr)(void *addr,char *path,int sz);
} DSO_METHOD;
/**********************************************************************/
@@ -296,6 +299,17 @@ DSO_METHOD *DSO_METHOD_win32(void);
/* If VMS is defined, use shared images. If not, return NULL. */
DSO_METHOD *DSO_METHOD_vms(void);
+/* This function writes null-terminated pathname of DSO module
+ * containing 'addr' into 'sz' large caller-provided 'path' and
+ * returns the number of characters [including trailing zero]
+ * written to it. If 'sz' is 0 or negative, 'path' is ignored and
+ * required amount of charachers [including trailing zero] to
+ * accomodate pathname is returned. If 'addr' is NULL, then
+ * pathname of cryptolib itself is returned. Negative or zero
+ * return value denotes error.
+ */
+int DSO_pathbyaddr(void *addr,char *path,int sz);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -342,6 +356,7 @@ void ERR_load_DSO_strings(void);
#define DSO_F_WIN32_NAME_CONVERTER 125
#define DSO_F_WIN32_SPLITTER 136
#define DSO_F_WIN32_UNLOAD 121
+#define DSO_F_PATHBYADDR 137
/* Reason codes. */
#define DSO_R_CTRL_FAILED 100
diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c
index fd1c758..2de01b0 100644
--- a/crypto/dso/dso_dl.c
+++ b/crypto/dso/dso_dl.c
@@ -85,6 +85,7 @@ static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg);
#endif
static char *dl_name_converter(DSO *dso, const char *filename);
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2);
+static int dl_pathbyaddr(void *addr,char *path,int sz);
static DSO_METHOD dso_meth_dl = {
"OpenSSL 'dl' shared library method",
@@ -101,7 +102,8 @@ static DSO_METHOD dso_meth_dl = {
dl_name_converter,
dl_merger,
NULL, /* init */
- NULL /* finish */
+ NULL, /* finish */
+ dl_pathbyaddr
};
DSO_METHOD *DSO_METHOD_dl(void)
@@ -349,4 +351,27 @@ static char *dl_name_converter(DSO *dso, const char *filename)
return(translated);
}
+static int dl_pathbyaddr(void *addr,char *path,int sz)
+ {
+ struct shl_descriptor inf;
+ int i,len;
+
+ if (addr == NULL) addr = dl_pathbyaddr;
+
+ for (i=-1;shl_get_r(i,&inf)==0;i++)
+ {
+ if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) ||
+ ((size_t)addr >= inf.dstart && (size_t)addr < inf.dend))
+ {
+ len = (int)strlen(inf.filename);
+ if (sz <= 0) return len+1;
+ if (len >= sz) len=sz-1;
+ memcpy(path,inf.filename,len);
+ path[len++] = 0;
+ return len;
+ }
+ }
+
+ return -1;
+ }
#endif /* DSO_DL */
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index 1fd1010..67a0f32 100644
--- a/crypto/dso/dso_dlfcn.c
+++ b/crypto/dso/dso_dlfcn.c
@@ -68,6 +68,12 @@ DSO_METHOD *DSO_METHOD_dlfcn(void)
#else
#ifdef HAVE_DLFCN_H
+
+#ifdef __linux
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE /* make sure dladdr is declared */
+# endif
+#endif
#include <dlfcn.h>
#endif
@@ -87,6 +93,7 @@ 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 DSO_METHOD dso_meth_dlfcn = {
"OpenSSL 'dlfcn' shared library method",
@@ -103,7 +110,8 @@ static DSO_METHOD dso_meth_dlfcn = {
dlfcn_name_converter,
dlfcn_merger,
NULL, /* init */
- NULL /* finish */
+ NULL, /* finish */
+ dlfcn_pathbyaddr
};
DSO_METHOD *DSO_METHOD_dlfcn(void)
@@ -366,4 +374,63 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename)
return(translated);
}
+#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
+ 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.
+#endif
+#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
+
+static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
+ {
+ Dl_info dli;
+ int len;
+
+ if (addr == NULL) addr = dlfcn_pathbyaddr;
+
+ 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());
+ return -1;
+ }
#endif /* DSO_DLFCN */
diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c
index aa91170..a88db0d 100644
--- a/crypto/dso/dso_err.c
+++ b/crypto/dso/dso_err.c
@@ -107,6 +107,7 @@ static ERR_STRING_DATA DSO_str_functs[]=
{ERR_FUNC(DSO_F_WIN32_NAME_CONVERTER), "WIN32_NAME_CONVERTER"},
{ERR_FUNC(DSO_F_WIN32_SPLITTER), "WIN32_SPLITTER"},
{ERR_FUNC(DSO_F_WIN32_UNLOAD), "WIN32_UNLOAD"},
+{ERR_FUNC(DSO_F_PATHBYADDR), "DSO_pathbyaddr"},
{0,NULL}
};
diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c
index 49bdd71..0869a64 100644
--- a/crypto/dso/dso_lib.c
+++ b/crypto/dso/dso_lib.c
@@ -464,3 +464,15 @@ const char *DSO_get_loaded_filename(DSO *dso)
}
return(dso->loaded_filename);
}
+
+int DSO_pathbyaddr(void *addr,char *path,int sz)
+ {
+ DSO_METHOD *meth = default_DSO_meth;
+ if (meth == NULL) meth = DSO_METHOD_openssl();
+ if (meth->pathbyaddr == NULL)
+ {
+ DSOerr(DSO_F_PATHBYADDR,DSO_R_UNSUPPORTED);
+ return(NULL);
+ }
+ return (*meth->pathbyaddr)(addr,path,sz);
+ }
diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c
index e6eaa99..96ccd4b 100644
--- a/crypto/dso/dso_win32.c
+++ b/crypto/dso/dso_win32.c
@@ -85,6 +85,7 @@ static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg);
static char *win32_name_converter(DSO *dso, const char *filename);
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2);
+static int win32_pathbyaddr(void *addr,char *path,int sz);
static const char *openssl_strnchr(const char *string, int c, size_t len);
@@ -103,7 +104,8 @@ static DSO_METHOD dso_meth_win32 = {
win32_name_converter,
win32_merger,
NULL, /* init */
- NULL /* finish */
+ NULL, /* finish */
+ win32_pathbyaddr
};
DSO_METHOD *DSO_METHOD_win32(void)
@@ -127,7 +129,7 @@ static int win32_load(DSO *dso)
DSOerr(DSO_F_WIN32_LOAD,DSO_R_NO_FILENAME);
goto err;
}
- h = LoadLibrary(filename);
+ h = LoadLibraryA(filename);
if(h == NULL)
{
DSOerr(DSO_F_WIN32_LOAD,DSO_R_LOAD_FAILED);
@@ -593,5 +595,122 @@ static const char *openssl_strnchr(const char *string, int c, size_t len)
return NULL;
}
+#include <tlhelp32.h>
+#ifdef _WIN32_WCE
+# if _WIN32_WCE < 300
+static FARPROC GetProcAddressA(HMODULE hModule,LPCSTR lpProcName)
+ {
+ WCHAR lpProcNameW[64];
+ int i;
+
+ for (i=0;lpProcName[i] && i<64;i++)
+ lpProcNameW[i] = (WCHAR)lpProcName[i];
+ if (i==64) return NULL;
+ lpProcNameW[i] = 0;
+
+ return GetProcAddressW(hModule,lpProcNameW);
+ }
+# endif
+# undef GetProcAddress
+# define GetProcAddress GetProcAddressA
+# define DLLNAME "TOOLHELP.DLL"
+#else
+# ifdef MODULEENTRY32
+# undef MODULEENTRY32 /* unmask the ASCII version! */
+# endif
+# define DLLNAME "KERNEL32.DLL"
+#endif
+
+typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
+typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
+typedef BOOL (WINAPI *MODULE32)(HANDLE, MODULEENTRY32 *);
-#endif /* OPENSSL_SYS_WIN32 */
+static int win32_pathbyaddr(void *addr,char *path,int sz)
+ {
+ HMODULE dll;
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32;
+ CREATETOOLHELP32SNAPSHOT create_snap;
+ CLOSETOOLHELP32SNAPSHOT close_snap;
+ MODULE32 module_first, module_next;
+ int len;
+
+ if (addr == NULL) addr = win32_pathbyaddr;
+
+ dll = LoadLibrary(TEXT(DLLNAME));
+ if (dll == NULL)
+ {
+ DSOerr(DSO_F_PATHBYADDR,DSO_R_UNSUPPORTED);
+ return -1;
+ }
+
+ create_snap = (CREATETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll,"CreateToolhelp32Snapshot");
+ if (create_snap == NULL)
+ {
+ DSOerr(DSO_F_PATHBYADDR,DSO_R_UNSUPPORTED);
+ return -1;
+ }
+ /* We take the rest for granted... */
+#ifdef _WIN32_WCE
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll,"CloseToolhelp32Snapshot");
+#else
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle;
+#endif
+ module_first = (MODULE32)GetProcAddress(dll,"Module32First");
+ module_next = (MODULE32)GetProcAddress(dll,"Module32Next");
+
+ hModuleSnap = (*create_snap)(TH32CS_SNAPMODULE,0);
+ if( hModuleSnap == INVALID_HANDLE_VALUE )
+ {
+ FreeLibrary(dll);
+ DSOerr(DSO_F_PATHBYADDR,DSO_R_UNSUPPORTED);
+ return -1;
+ }
+
+ me32.dwSize = sizeof(me32);
+
+ if(!(*module_first)(hModuleSnap,&me32))
+ {
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+ DSOerr(DSO_F_PATHBYADDR,DSO_R_FAILURE);
+ return -1;
+ }
+
+ do {
+ if ((BYTE *)addr >= me32.modBaseAddr &&
+ (BYTE *)addr < me32.modBaseAddr+me32.modBaseSize)
+ {
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+#ifdef _WIN32_WCE
+# if _WIN32_WCE >= 101
+ return WideCharToMultiByte(CP_ACP,0,me32.szExePath,-1,
+ path,sz,NULL,NULL);
+# else
+ len = (int)wcslen(me32.szExePath);
+ if (sz <= 0) return len+1;
+ if (len >= sz) len=sz-1;
+ for(i=0;i<len;i++)
+ path[i] = (char)me32.szExePath[i];
+ path[len++] = 0;
+ return len;
+# endif
+#else
+ len = (int)strlen(me32.szExePath);
+ if (sz <= 0) return len+1;
+ if (len >= sz) len=sz-1;
+ memcpy(path,me32.szExePath,len);
+ path[len++] = 0;
+ return len;
+#endif
+ }
+ } while((*module_next)(hModuleSnap, &me32));
+
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+ return 0;
+ }
+#endif /* DSO_WIN32 */