Commit 7ed87653 authored by Andy Polyakov's avatar Andy Polyakov
Browse files

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...
parent b2d91a69
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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
+26 −1
Original line number Diff line number Diff line
@@ -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 −1
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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}
	};

+12 −0
Original line number Diff line number Diff line
@@ -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);
	}
Loading