[PATCH] Implement dladdr() (partially)

Jon Turney jon.turney@dronecode.org.uk
Wed Mar 8 14:25:00 GMT 2017


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 <jon.turney@dronecode.org.uk>
---

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



More information about the Cygwin-patches mailing list