On Sun, 30 Nov 2025 at 20:28, Bruno Haible <[email protected]> wrote:

> Hi Reuben,
>
> > My patch is incomplete: it unconditionally uses libdl.m4, meaning libdl
> > will always be linked on systems that have it. I appreciate this is what
> > we're trying to avoid! I'm unclear what the best way to fix this is.
> Should
> > I move the test for which code to use (i.e. Windows, libdl or /proc) to
> > configure.ac, and introduce an automake conditional to guard the
> addition
> > of libdl to the LIBS variable?
>
> I think you are on the right track. What I would do:
>   - Keep the invocation of gl_LIBDL, but don't use the value of $(LIBDL)
>     in lib_LDFLAGS.
>   - Define _GL_USE_DLADDR only if $(LIBDL) is empty.
>   - Use the value $(LIBDL) to decide this, in the configure.ac section of
> the
>     module. I don't know whether that will require an Automake conditional.


Updated patch attached. It seemed too simple: all I do is, as you say,
define _GL_USE_DLADDR only if $(LIBDL) is empty, and then use dladdr only
if _GL_USE_DLADDR is set, and we haven't defined either _GL_USE_PROCFS or
_GL_USE_WIN32.

-- 
Web: rrt.sc3d.org
From 8fc778805199b40777ab267bce0bfab9fdaccafe Mon Sep 17 00:00:00 2001
From: Reuben Thomas <[email protected]>
Date: Mon, 8 Dec 2025 18:59:01 +0000
Subject: [PATCH] relocatable-lib{,-lgpl}: allow using dladdr to get path to
 shared library

This is portable (in POSIX:2024 [1]), so use it on all systems where dladdr
is in libc.

[1] https://pubs.opengroup.org/onlinepubs/9799919799/functions/dladdr.html
---
 lib/relocatable.c            | 38 ++++++++++++++++++++++++++----------
 m4/libdl.m4                  |  2 +-
 modules/relocatable-lib      |  7 +++++--
 modules/relocatable-lib-lgpl |  4 ++++
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/lib/relocatable.c b/lib/relocatable.c
index 15b3bc442d..b060df91d4 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -71,6 +71,21 @@
 # define GetModuleFileName GetModuleFileNameA
 #endif
 
+/* We have special code for two types of system: non-Cygwin Windows, and
+   Linux where dladdr is in a separate library (uClibc and glibc < 2.34).
+   Need glibc >= 2, for getline().
+
+   Otherwise, use dladdr.
+*/
+#if defined __linux__ && (defined __UCLIBC__ || ((__GLIBC__ >= 2) && (__GLIBC_MINOR__ < 34)))
+#define _GL_USE_PROCFS 1
+#elif (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__
+#define _GL_USE_WIN32 1
+#elif _GL_DLADDR_IN_LIBC
+#define _GL_USE_DLADDR 1
+#include <dlfcn.h>
+#endif
+
 /* Faked cheap 'bool'.  */
 #undef bool
 #undef false
@@ -318,10 +333,9 @@ static char *shared_library_fullname;
 
 #if defined _WIN32 && !defined __CYGWIN__
 /* Native Windows only.
-   On Cygwin, it is better to use the Cygwin provided /proc interface, than
-   to use native Windows API and cygwin_conv_to_posix_path, because it
-   supports longer file names
-   (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
+   On Cygwin, it is better to use dladdr, than to use native Windows
+   API and cygwin_conv_to_posix_path, because it supports longer file
+   names (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
 
 /* Determine the full pathname of the shared library when it is loaded.
 
@@ -402,12 +416,10 @@ _DLL_InitTerm (unsigned long hModule, unsigned long ulFlag)
 static void
 find_shared_library_fullname ()
 {
-#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
+#if _GL_USE_PROCFS
   /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
      function.
-     Cygwin >= 1.5 has /proc/self/maps and the getline() function too.
-     But it is costly: ca. 0.3 ms on Linux, 3 ms on Cygwin 1.5, and 5 ms on
-     Cygwin 1.7.  */
+     But it is costly: ca. 0.3 ms.  */
   FILE *fp;
 
   /* Open the current process' maps file.  It describes one VMA per line.  */
@@ -449,6 +461,11 @@ find_shared_library_fullname ()
         }
       fclose (fp);
     }
+#elif _GL_USE_DLADDR
+  Dl_info info;
+  dladdr (find_shared_library_fullname, &info);
+  if (info.dli_fname != NULL)
+      shared_library_fullname = strdup (info.dli_fname);
 #endif
 }
 
@@ -456,11 +473,12 @@ find_shared_library_fullname ()
 
 /* Return the full pathname of the current shared library.
    Return NULL if unknown.
-   Guaranteed to work only on Linux, EMX, Cygwin, and native Windows.  */
+   Guaranteed to work only on Linux, EMX, Cygwin, native Windows, and
+   systems with dladdr in libc.  */
 static char *
 get_shared_library_fullname ()
 {
-#if !(defined _WIN32 && !defined __CYGWIN__) && !defined __EMX__
+#if !_GL_USE_WIN32
   static bool tried_find_shared_library_fullname;
   if (!tried_find_shared_library_fullname)
     {
diff --git a/m4/libdl.m4 b/m4/libdl.m4
index 4b4357b7f8..839b053af5 100644
--- a/m4/libdl.m4
+++ b/m4/libdl.m4
@@ -15,7 +15,7 @@ AC_DEFUN([gl_LIBDL],
   dnl dlopen, dlsym are
   dnl - in libc on glibc >= 2.34, musl libc, macOS, FreeBSD, NetBSD, OpenBSD,
   dnl   AIX, Solaris, Cygwin, Haiku,
-  dnl - in a separate libdl on glibc < 2.34, Android.
+  dnl - in a separate libdl on glibc < 2.34, Android, uClibc.
   AC_CACHE_CHECK([for library needed for dlopen and dlsym],
     [gl_cv_lib_dl],
     [AC_LINK_IFELSE(
diff --git a/modules/relocatable-lib b/modules/relocatable-lib
index 0d59464fe6..583df4bccc 100644
--- a/modules/relocatable-lib
+++ b/modules/relocatable-lib
@@ -7,6 +7,7 @@ doc/relocatable.texi
 lib/relocatable.h
 lib/relocatable.c
 lib/relocatable.valgrind
+m4/libdl.m4
 m4/relocatable-lib.m4
 m4/build-to-host.m4
 
@@ -19,8 +20,10 @@ gl_RELOCATABLE_LIBRARY
 if test $RELOCATABLE = yes; then
   AC_LIBOBJ([relocatable])
 fi
-
-Makefile.am:
+gl_LIBDL
+if test "$LIBDL" = ""; then
+   AC_DEFINE([_GL_DLADDR_IN_LIBC], 1, [Define to 1 if dladdr is in libc.])
+fi
 
 Include:
 "relocatable.h"
diff --git a/modules/relocatable-lib-lgpl b/modules/relocatable-lib-lgpl
index b8ecb51ef8..99dac18f50 100644
--- a/modules/relocatable-lib-lgpl
+++ b/modules/relocatable-lib-lgpl
@@ -18,6 +18,10 @@ gl_RELOCATABLE_LIBRARY
 if test $RELOCATABLE = yes; then
   AC_LIBOBJ([relocatable])
 fi
+gl_LIBDL
+if test "$LIBDL" = ""; then
+   AC_DEFINE([_GL_DLADDR_IN_LIBC], 1, [Define to 1 if dladdr is in libc.])
+fi
 
 Makefile.am:
 DEFS += -DNO_XMALLOC
-- 
2.43.0

Reply via email to