New function, DSO_pathbyaddr, to find pathname for loaded shared object
by an address within it. Tested on Linux, Solaris, IRIX, Tru64, Darwin, HP-UX, Win32, few BSD flavors...
This commit is contained in:
parent
b2d91a6913
commit
7ed876533a
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
#endif /* OPENSSL_SYS_WIN32 */
|
||||
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 *);
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user