diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index 6cbb012fc..f23681308 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 159d4fe88..9959ff752 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/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 308bc8b0f..602313199 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -472,12 +472,13 @@ details. */ 305: [f]pathconf flag _PC_CASE_INSENSITIVE added. 306: Export getentropy, getrandom. 307: Export timingsafe_bcmp, timingsafe_memcmp. + 308: Export dladdr. Note that we forgot to bump the api for ualarm, strtoll, strtoull, sigaltstack, sethostname. */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 307 +#define CYGWIN_VERSION_API_MINOR 308 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible changes are made to the shared diff --git a/winsup/cygwin/include/dlfcn.h b/winsup/cygwin/include/dlfcn.h index 8522ec579..d9435d044 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 +#include + #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/cygwin/release/2.7.1 b/winsup/cygwin/release/2.7.1 index 227d7a2a8..43d9bd0a2 100644 --- a/winsup/cygwin/release/2.7.1 +++ b/winsup/cygwin/release/2.7.1 @@ -3,6 +3,8 @@ What's new: - New API: timingsafe_bcmp, timingsafe_memcmp +- New API: dladdr + What changed: ------------- diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index fac32b771..03d168d3e 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -1277,6 +1277,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). 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.basename is available in both POSIX and GNU flavors, depending on whether libgen.h is included or not. +dladdr always sets the Dl_info members dli_sname and +dli_saddr to NULL, indicating no symbol matching addr could be found. +