提交 7ed87653 编写于 作者: A Andy Polyakov

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...
上级 b2d91a69
......@@ -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;
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;
}
#endif /* OPENSSL_SYS_WIN32 */
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 */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册