diff options
Diffstat (limited to 'crypto/dso')
-rw-r--r-- | crypto/dso/dso_dl.c | 34 | ||||
-rw-r--r-- | crypto/dso/dso_dlfcn.c | 34 | ||||
-rw-r--r-- | crypto/dso/dso_err.c | 2 | ||||
-rw-r--r-- | crypto/dso/dso_lib.c | 12 | ||||
-rw-r--r-- | crypto/dso/dso_locl.h | 2 | ||||
-rw-r--r-- | crypto/dso/dso_vms.c | 4 | ||||
-rw-r--r-- | crypto/dso/dso_win32.c | 1 |
7 files changed, 88 insertions, 1 deletions
diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index bc29fb23e0..d80bf562c7 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 624052b86a..a4b0cdd95b 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 a180580759..07588d5c39 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 bea8776d71..2dac20082c 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 19767871fa..fbfad0544a 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 2e0d84cb53..e3c157bf57 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 4ac6e7176d..4a4c34abb6 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 }; |