Reuben Thomas wrote:
> > The patch looks nearly fine. A few small nits, though:
>
> Thanks for the rapid review; I attach a revised patch.
Thanks. I am adding it, with
- fixed indentation in relocatable.c,
- moving the added block of _GL_* definitions up,
- systematic m4 quoting even of single words in m4 code,
- and a GNU-style ChangeLog entry.
Then I notice that
- m4/libdl.m4 is missing from modules/relocatable-lib-lgpl,
- Testing with
./configure --enable-relocatable CFLAGS="-DPIC -DINSTALLDIR=\\\"/tmp\\\"
-DENABLE_COSTLY_RELOCATABLE"
on AIX, I get a compilation error:
../../gllib/relocatable.c: In function 'find_shared_library_fullname':
../../gllib/relocatable.c:465:3: error: unknown type name 'Dl_info'; did you
mean 'fh_ino'?
Dl_info info;
^~~~~~~
fh_ino
../../gllib/relocatable.c:466:13: warning: implicit declaration of function
'dladdr' [-Wimplicit-function-declaration]
int ret = dladdr (find_shared_library_fullname, &info);
^~~~~~
../../gllib/relocatable.c:467:23: error: request for member 'dli_fname' in
something not a structure or union
if (ret != 0 && info.dli_fname != NULL)
^
../../gllib/relocatable.c:468:43: error: request for member 'dli_fname' in
something not a structure or union
shared_library_fullname = strdup (info.dli_fname);
^
gmake[3]: *** [Makefile:2276: relocatable.o] Error 1
This is because AIX has <dlfcn.h> but does not have dladdr().
The next question is: How costly is this dladdr() call? Would it therefore
make sense to enable ENABLE_COSTLY_RELOCATABLE by default on more platforms?
Bruno
>From a7d3b961679194c60c9e2a24d57505abf411ae60 Mon Sep 17 00:00:00 2001
From: Reuben Thomas <[email protected]>
Date: Mon, 8 Dec 2025 18:59:01 +0000
Subject: [PATCH 1/2] relocatable-lib: Find shared library filename via dladdr.
* lib/relocatable.c (_GL_USE_PROCFS, _GL_USE_WIN32, _GL_USE_DLADDR):
New macros.
(find_shared_library_fullname): Use dladdr if _GL_USE_DLADDR is defined.
(get_shared_library_fullname): Use _GL_USE_WIN32.
* m4/libdl.m4 (gl_LIBDL): Update comment.
* modules/relocatable-lib (Files): Add m4/libdl.m4.
(configure.ac): Invoke gl_LIBDL. Define _GL_DLADDR_IN_LIBC.
* modules/relocatable-lib-lgpl (configure.ac): Likewise.
---
ChangeLog | 12 ++++++++++++
lib/relocatable.c | 38 ++++++++++++++++++++++++++----------
m4/libdl.m4 | 2 +-
modules/relocatable-lib | 5 +++++
modules/relocatable-lib-lgpl | 4 ++++
5 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index ab93efe052..cf3ddd6df8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2025-12-09 Reuben Thomas <[email protected]>
+
+ relocatable-lib: Find shared library filename via dladdr.
+ * lib/relocatable.c (_GL_USE_PROCFS, _GL_USE_WIN32, _GL_USE_DLADDR):
+ New macros.
+ (find_shared_library_fullname): Use dladdr if _GL_USE_DLADDR is defined.
+ (get_shared_library_fullname): Use _GL_USE_WIN32.
+ * m4/libdl.m4 (gl_LIBDL): Update comment.
+ * modules/relocatable-lib (Files): Add m4/libdl.m4.
+ (configure.ac): Invoke gl_LIBDL. Define _GL_DLADDR_IN_LIBC.
+ * modules/relocatable-lib-lgpl (configure.ac): Likewise.
+
2025-12-07 Bruno Haible <[email protected]>
argp: Replace some 'continue;' statements with if/else.
diff --git a/lib/relocatable.c b/lib/relocatable.c
index 15b3bc442d..a3d741aff2 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -65,6 +65,21 @@
# include <libintl.h>
#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
+
#if defined _WIN32 && !defined __CYGWIN__
/* Don't assume that UNICODE is not defined. */
# undef GetModuleFileName
@@ -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;
+ int ret = dladdr (find_shared_library_fullname, &info);
+ if (ret != 0 && 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..d2f513861b 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,6 +20,10 @@ gl_RELOCATABLE_LIBRARY
if test $RELOCATABLE = yes; then
AC_LIBOBJ([relocatable])
fi
+gl_LIBDL
+if test -z "$LIBDL"; then
+ AC_DEFINE([_GL_DLADDR_IN_LIBC], [1], [Define to 1 if dladdr is in libc.])
+fi
Makefile.am:
diff --git a/modules/relocatable-lib-lgpl b/modules/relocatable-lib-lgpl
index b8ecb51ef8..4fe84cea85 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 -z "$LIBDL"; then
+ AC_DEFINE([_GL_DLADDR_IN_LIBC], [1], [Define to 1 if dladdr is in libc.])
+fi
Makefile.am:
DEFS += -DNO_XMALLOC
--
2.52.0
From 34951d0cb0fbfcc86fa8e37bc9ff5a2e03662f60 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Tue, 9 Dec 2025 14:58:00 +0100
Subject: [PATCH 2/2] relocatable-lib: Fix and simplify previous commit.
* m4/relocatable-lib.m4 (gl_RELOCATABLE_LIBRARY_BODY): Invoke gl_LIBDL.
Define HAVE_DLADDR_IN_LIBC.
* modules/relocatable-lib (configure.ac): Revert last change.
* modules/relocatable-lib-lgpl (Files): Add m4/libdl.m4.
(configure.ac): Revert last change.
* lib/relocatable.c (_GL_USE_PROCFS, _GL_USE_WIN32, _GL_USE_DLADDR):
Remove macros.
(ENABLE_COSTLY_RELOCATABLE): Update comments.
(find_shared_library_fullname): Use dladdr as first alternative. Test
HAVE_DLADDR_IN_LIBC instead of _GL_USE_PROCFS. Define as macro.
(get_shared_library_fullname): Update comments. Test
find_shared_library_fullname instead of _GL_USE_WIN32.
---
ChangeLog | 16 ++++++++++
lib/relocatable.c | 57 +++++++++++++++++-------------------
m4/libdl.m4 | 4 +--
m4/relocatable-lib.m4 | 10 ++++++-
modules/relocatable-lib | 6 +---
modules/relocatable-lib-lgpl | 5 +---
6 files changed, 56 insertions(+), 42 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index cf3ddd6df8..e745af71cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2025-12-09 Bruno Haible <[email protected]>
+
+ relocatable-lib: Fix and simplify previous commit.
+ * m4/relocatable-lib.m4 (gl_RELOCATABLE_LIBRARY_BODY): Invoke gl_LIBDL.
+ Define HAVE_DLADDR_IN_LIBC.
+ * modules/relocatable-lib (configure.ac): Revert last change.
+ * modules/relocatable-lib-lgpl (Files): Add m4/libdl.m4.
+ (configure.ac): Revert last change.
+ * lib/relocatable.c (_GL_USE_PROCFS, _GL_USE_WIN32, _GL_USE_DLADDR):
+ Remove macros.
+ (ENABLE_COSTLY_RELOCATABLE): Update comments.
+ (find_shared_library_fullname): Use dladdr as first alternative. Test
+ HAVE_DLADDR_IN_LIBC instead of _GL_USE_PROCFS. Define as macro.
+ (get_shared_library_fullname): Update comments. Test
+ find_shared_library_fullname instead of _GL_USE_WIN32.
+
2025-12-09 Reuben Thomas <[email protected]>
relocatable-lib: Find shared library filename via dladdr.
diff --git a/lib/relocatable.c b/lib/relocatable.c
index a3d741aff2..5eb7e8b716 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -55,6 +55,10 @@
# define strncmp strnicmp
#endif
+#if HAVE_DLADDR_IN_LIBC
+# include <dlfcn.h>
+#endif
+
#if DEPENDS_ON_LIBCHARSET
# include <libcharset.h>
#endif
@@ -65,21 +69,6 @@
# include <libintl.h>
#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
-
#if defined _WIN32 && !defined __CYGWIN__
/* Don't assume that UNICODE is not defined. */
# undef GetModuleFileName
@@ -116,9 +105,8 @@
/* Whether to enable the more costly support for relocatable libraries.
It allows libraries to be have been installed with a different original
- prefix than the program. But it is quite costly, especially on Cygwin
- platforms, see below. Therefore we enable it by default only on native
- Windows platforms. */
+ prefix than the program. But it is quite costly, see below. Therefore
+ we enable it by default only on native Windows platforms. */
#ifndef ENABLE_COSTLY_RELOCATABLE
# if defined _WIN32 && !defined __CYGWIN__
# define ENABLE_COSTLY_RELOCATABLE 1
@@ -333,9 +321,10 @@ static char *shared_library_fullname;
#if defined _WIN32 && !defined __CYGWIN__
/* Native Windows only.
- 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>). */
+ On Cygwin, it is better to use either dladdr() or 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>). */
/* Determine the full pathname of the shared library when it is loaded.
@@ -416,7 +405,17 @@ _DLL_InitTerm (unsigned long hModule, unsigned long ulFlag)
static void
find_shared_library_fullname ()
{
-#if _GL_USE_PROCFS
+#if HAVE_DLADDR_IN_LIBC
+ /* glibc >= 2.34, musl, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Cygwin, Minix */
+ /* We can use dladdr() without introducing extra link dependencies. */
+ Dl_info info;
+ /* It is OK to use a 'static' function ??? that does not appear in the
+ dynamic symbol table of any ELF object ??? as argument of dladdr() here,
+ because we don't access the fields info.dli_sname and info.dli_saddr. */
+ int ret = dladdr (find_shared_library_fullname, &info);
+ if (ret != 0 && info.dli_fname != NULL)
+ shared_library_fullname = strdup (info.dli_fname);
+#elif (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
/* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
function.
But it is costly: ca. 0.3 ms. */
@@ -461,24 +460,22 @@ find_shared_library_fullname ()
}
fclose (fp);
}
-#elif _GL_USE_DLADDR
- Dl_info info;
- int ret = dladdr (find_shared_library_fullname, &info);
- if (ret != 0 && info.dli_fname != NULL)
- shared_library_fullname = strdup (info.dli_fname);
#endif
}
+# define find_shared_library_fullname find_shared_library_fullname
+
#endif /* Native Windows / EMX / Unix */
/* Return the full pathname of the current shared library.
Return NULL if unknown.
- Guaranteed to work only on Linux, EMX, Cygwin, native Windows, and
- systems with dladdr in libc. */
+ Guaranteed to work only on
+ glibc >= 2.34, Linux, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Cygwin,
+ Minix, native Windows, EMX. */
static char *
get_shared_library_fullname ()
{
-#if !_GL_USE_WIN32
+#if defined find_shared_library_fullname
static bool tried_find_shared_library_fullname;
if (!tried_find_shared_library_fullname)
{
diff --git a/m4/libdl.m4 b/m4/libdl.m4
index 839b053af5..6c87f727bc 100644
--- a/m4/libdl.m4
+++ b/m4/libdl.m4
@@ -1,5 +1,5 @@
# libdl.m4
-# serial 2
+# serial 3
dnl Copyright (C) 2024-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -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, uClibc.
+ dnl - in a separate libdl on glibc < 2.34, uClibc, Android.
AC_CACHE_CHECK([for library needed for dlopen and dlsym],
[gl_cv_lib_dl],
[AC_LINK_IFELSE(
diff --git a/m4/relocatable-lib.m4 b/m4/relocatable-lib.m4
index 5efed5218d..222fb68494 100644
--- a/m4/relocatable-lib.m4
+++ b/m4/relocatable-lib.m4
@@ -1,5 +1,5 @@
# relocatable-lib.m4
-# serial 8
+# serial 9
dnl Copyright (C) 2003, 2005-2007, 2009-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -31,6 +31,14 @@ AC_DEFUN([gl_RELOCATABLE_LIBRARY_BODY]
[Define to 1 if the package shall run at any location in the file
system.])
fi
+ dnl Determine whether dladdr() exists in libc.
+ gl_LIBDL
+ if test -z "$LIBDL"; then
+ AC_CHECK_FUNC([dladdr],
+ [AC_DEFINE([HAVE_DLADDR_IN_LIBC], [1],
+ [Define to 1 if dladdr exists and is defined in libc.])
+ ])
+ fi
])
dnl Support for relocatable packages for which it is a nop.
diff --git a/modules/relocatable-lib b/modules/relocatable-lib
index d2f513861b..64be8dbf49 100644
--- a/modules/relocatable-lib
+++ b/modules/relocatable-lib
@@ -7,8 +7,8 @@ doc/relocatable.texi
lib/relocatable.h
lib/relocatable.c
lib/relocatable.valgrind
-m4/libdl.m4
m4/relocatable-lib.m4
+m4/libdl.m4
m4/build-to-host.m4
Depends-on:
@@ -20,10 +20,6 @@ gl_RELOCATABLE_LIBRARY
if test $RELOCATABLE = yes; then
AC_LIBOBJ([relocatable])
fi
-gl_LIBDL
-if test -z "$LIBDL"; then
- AC_DEFINE([_GL_DLADDR_IN_LIBC], [1], [Define to 1 if dladdr is in libc.])
-fi
Makefile.am:
diff --git a/modules/relocatable-lib-lgpl b/modules/relocatable-lib-lgpl
index 4fe84cea85..c0cdafade2 100644
--- a/modules/relocatable-lib-lgpl
+++ b/modules/relocatable-lib-lgpl
@@ -8,6 +8,7 @@ lib/relocatable.h
lib/relocatable.c
lib/relocatable.valgrind
m4/relocatable-lib.m4
+m4/libdl.m4
m4/build-to-host.m4
Depends-on:
@@ -18,10 +19,6 @@ gl_RELOCATABLE_LIBRARY
if test $RELOCATABLE = yes; then
AC_LIBOBJ([relocatable])
fi
-gl_LIBDL
-if test -z "$LIBDL"; then
- AC_DEFINE([_GL_DLADDR_IN_LIBC], [1], [Define to 1 if dladdr is in libc.])
-fi
Makefile.am:
DEFS += -DNO_XMALLOC
--
2.52.0