diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index bc29fb23e03955b12a12a2e5f09318f06d02395d..d80bf562c7f225223ba1a4d5b08c626c08f0dfd7 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -22,6 +22,7 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname); 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 void *dl_globallookup(const char *name); static DSO_METHOD dso_meth_dl = { @@ -34,6 +35,7 @@ static DSO_METHOD dso_meth_dl = { dl_merger, NULL, /* init */ NULL, /* finish */ + dl_pathbyaddr, dl_globallookup }; @@ -235,6 +237,38 @@ 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) { + union { + int (*f) (void *, char *, int); + void *p; + } t = { + dl_pathbyaddr + }; + addr = t.p; + } + + 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; +} + static void *dl_globallookup(const char *name) { void *ret; diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index 624052b86a310d8e254fcca3db33cd5cc6bf37cb..a4b0cdd95b5d78c16fd9c224f6ea5ceac392c343 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -44,6 +44,7 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); 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 = { @@ -56,6 +57,7 @@ static DSO_METHOD dso_meth_dlfcn = { dlfcn_merger, NULL, /* init */ NULL, /* finish */ + dlfcn_pathbyaddr, dlfcn_globallookup }; @@ -306,6 +308,38 @@ static int dladdr(void *address, Dl_info *dl) } # 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); diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c index a1805807597db75859c55caf0de4647f347f4b40..07588d5c3993305ab7c986ed910654697dd51c30 100644 --- a/crypto/dso/dso_err.c +++ b/crypto/dso/dso_err.c @@ -38,6 +38,7 @@ static ERR_STRING_DATA DSO_str_functs[] = { {ERR_FUNC(DSO_F_DSO_LOAD), "DSO_load"}, {ERR_FUNC(DSO_F_DSO_MERGE), "DSO_merge"}, {ERR_FUNC(DSO_F_DSO_NEW_METHOD), "DSO_new_method"}, + {ERR_FUNC(DSO_F_DSO_PATHBYADDR), "DSO_pathbyaddr"}, {ERR_FUNC(DSO_F_DSO_SET_FILENAME), "DSO_set_filename"}, {ERR_FUNC(DSO_F_DSO_UP_REF), "DSO_up_ref"}, {ERR_FUNC(DSO_F_VMS_BIND_SYM), "vms_bind_sym"}, @@ -50,6 +51,7 @@ static ERR_STRING_DATA DSO_str_functs[] = { {ERR_FUNC(DSO_F_WIN32_LOAD), "win32_load"}, {ERR_FUNC(DSO_F_WIN32_MERGER), "win32_merger"}, {ERR_FUNC(DSO_F_WIN32_NAME_CONVERTER), "win32_name_converter"}, + {ERR_FUNC(DSO_F_WIN32_PATHBYADDR), "win32_pathbyaddr"}, {ERR_FUNC(DSO_F_WIN32_SPLITTER), "win32_splitter"}, {ERR_FUNC(DSO_F_WIN32_UNLOAD), "win32_unload"}, {0, NULL} diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index bea8776d71b83bc2afd8b559ea1a464ddf9c2fbb..2dac20082ceecdddacc8fd89567166917156014e 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -304,6 +304,18 @@ char *DSO_convert_filename(DSO *dso, const char *filename) return (result); } +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_DSO_PATHBYADDR, DSO_R_UNSUPPORTED); + return -1; + } + return (*meth->pathbyaddr) (addr, path, sz); +} + void *DSO_global_lookup(const char *name) { DSO_METHOD *meth = default_DSO_meth; diff --git a/crypto/dso/dso_locl.h b/crypto/dso/dso_locl.h index 19767871fa6f1430cdc2fb1bb339d3996577a1af..fbfad0544a73d1e63c1f1b352388d3d95f2cce69 100644 --- a/crypto/dso/dso_locl.h +++ b/crypto/dso/dso_locl.h @@ -99,6 +99,8 @@ 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); /* Perform global symbol lookup, i.e. among *all* modules */ void *(*globallookup) (const char *symname); }; diff --git a/crypto/dso/dso_vms.c b/crypto/dso/dso_vms.c index 2e0d84cb538aa055633346d4776e2de2834c425c..e3c157bf57926b332e6b9ba5489163b6fe216b08 100644 --- a/crypto/dso/dso_vms.c +++ b/crypto/dso/dso_vms.c @@ -50,7 +50,9 @@ static DSO_METHOD dso_meth_vms = { vms_name_converter, vms_merger, NULL, /* init */ - NULL /* finish */ + NULL, /* finish */ + NULL, /* pathbyaddr */ + NULL /* globallookup */ }; /* diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index 4ac6e7176d726952079e54f5d7db30ce52167f3a..4a4c34abb65817eeb30524153669cbbbf473b99a 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -77,6 +77,7 @@ static DSO_METHOD dso_meth_win32 = { win32_merger, NULL, /* init */ NULL, /* finish */ + NULL, /* pathbyaddr */ win32_globallookup }; diff --git a/include/internal/dso.h b/include/internal/dso.h index 79d98f4785390c48c1391a44235f773cfbaf09ed..6f50f005a997867aec972105e71dfbcb4ca5440d 100644 --- a/include/internal/dso.h +++ b/include/internal/dso.h @@ -130,6 +130,17 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname); */ DSO_METHOD *DSO_METHOD_openssl(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 accommodate 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); + /* * This function should be used with caution! It looks up symbols in *all* * loaded modules and if module gets unloaded by somebody else attempt to @@ -171,6 +182,7 @@ int ERR_load_DSO_strings(void); # define DSO_F_DSO_LOAD 112 # define DSO_F_DSO_MERGE 132 # define DSO_F_DSO_NEW_METHOD 113 +# define DSO_F_DSO_PATHBYADDR 105 # define DSO_F_DSO_SET_FILENAME 129 # define DSO_F_DSO_UP_REF 114 # define DSO_F_VMS_BIND_SYM 115 @@ -183,6 +195,7 @@ int ERR_load_DSO_strings(void); # define DSO_F_WIN32_LOAD 120 # define DSO_F_WIN32_MERGER 134 # define DSO_F_WIN32_NAME_CONVERTER 125 +# define DSO_F_WIN32_PATHBYADDR 109 # define DSO_F_WIN32_SPLITTER 136 # define DSO_F_WIN32_UNLOAD 121 diff --git a/util/libcrypto.num b/util/libcrypto.num index e04580c4859d9fa1f4c9dd69ca92a474dadc119b..3645c1ad1c74936584a3749df2c92c92117d14d2 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4216,3 +4216,4 @@ BIO_meth_get_read_ex 4166 1_1_1 EXIST::FUNCTION: BIO_write_ex 4167 1_1_1 EXIST::FUNCTION: BIO_meth_get_write_ex 4168 1_1_1 EXIST::FUNCTION: BIO_meth_set_write_ex 4169 1_1_1 EXIST::FUNCTION: +DSO_pathbyaddr 4170 1_1_0c EXIST::FUNCTION: