Note that this always returns with dli_sname and dli_saddr set to NULL, indicating no symbol matching addr could be found.
Signed-off-by: Jon Turney <[email protected]> --- Notes: Mesa 17.1 will want to use dladdr() in order to use the mtime of a loadable module to control the validity of a cache, and this implementation suffices for that purpose (not that this caching is implemented for llvmpipe at the moment) winsup/cygwin/common.din | 1 + winsup/cygwin/dlfcn.cc | 34 ++++++++++++++++++++++++++++++++++ winsup/cygwin/include/dlfcn.h | 18 ++++++++++++++++++ winsup/doc/posix.xml | 4 ++++ 4 files changed, 57 insertions(+) diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index 6cbb012..f236813 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -364,6 +364,7 @@ difftime NOSIGFE dirfd SIGFE dirname NOSIGFE div NOSIGFE +dladdr SIGFE dlclose SIGFE dlerror NOSIGFE dlfork NOSIGFE diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index 159d4fe..87c1ab1 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -386,3 +386,37 @@ dlerror () } return res; } + +extern "C" int +dladdr (const void *addr, Dl_info *info) +{ + HMODULE hModule; + BOOL ret = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCSTR) addr, + &hModule); + if (!ret) + return 0; + + /* Module handle happens to be equal to it's base load address. */ + info->dli_fbase = hModule; + + /* Get the module filename. This pathname may be in short-, long- or //?/ + format, depending on how it was specified when loaded, but We assume this + is always an absolute pathname. */ + WCHAR fname[MAX_PATH]; + DWORD length = GetModuleFileNameW (hModule, fname, MAX_PATH); + if ((length == 0) || (length == MAX_PATH)) + return 0; + + /* Convert to a cygwin pathname */ + ssize_t conv = cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, fname, + info->dli_fname, MAX_PATH); + if (conv) + return 0; + + /* Always indicate no symbol matching addr could be found. */ + info->dli_sname = NULL; + info->dli_saddr = NULL; + + return 1; +} diff --git a/winsup/cygwin/include/dlfcn.h b/winsup/cygwin/include/dlfcn.h index 8522ec5..d9435d0 100644 --- a/winsup/cygwin/include/dlfcn.h +++ b/winsup/cygwin/include/dlfcn.h @@ -9,6 +9,9 @@ details. */ #ifndef _DLFCN_H #define _DLFCN_H +#include <sys/cdefs.h> +#include <limits.h> + #ifdef __cplusplus extern "C" { #endif @@ -42,6 +45,21 @@ extern void dlfork (int); #define RTLD_DEEPBIND 32 /* Place lookup scope so that this lib is */ /* preferred over global scope. */ + +#if __GNU_VISIBLE +typedef struct Dl_info Dl_info; + +struct Dl_info +{ + char dli_fname[PATH_MAX]; /* Filename of defining object */ + void *dli_fbase; /* Load address of that object */ + const char *dli_sname; /* Name of nearest lower symbol */ + void *dli_saddr; /* Exact value of nearest symbol */ +}; + +extern int dladdr (const void *addr, Dl_info *info); +#endif + #ifdef __cplusplus } #endif diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index fac32b7..03d168d 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -1277,6 +1277,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para> clog10 clog10f clog10l + dladdr (see chapter "Implementation Notes") dremf dup3 envz_add @@ -1665,6 +1666,9 @@ depending on whether _BSD_SOURCE or _GNU_SOURCE is defined when compiling.</para <para><function>basename</function> is available in both POSIX and GNU flavors, depending on whether libgen.h is included or not.</para> +<para><function>dladdr</function> always sets the Dl_info members dli_sname and +dli_saddr to NULL, indicating no symbol matching addr could be found.</para> + </sect1> </chapter> -- 2.8.3
