I just ran into the problem that this function does nothing on macOS.
Indeed, it only works on Linux with glibc or uClibc, and Cygwin. (There's
equivalent but separate code for native Windows, of course.)

A little investigation suggests that macOS and other platforms could use
dladdr to get this information. This seems rather obvious, so is there any
reason this has not already been implemented? dladdr is not standardized,
of course, but it does seem to be implemented on FreeBSD, NetBSD and
OpenBSD. The only reason not to use it that I can think of is that it
requires -ldl, but that seems a fairly small price to pay on platforms that
don't have another solution.

I tried it on macOS, and it worked as expected.

I attach a proof of concept patch for current git master.

Things I can think of that would need to be improved: check that the
returned path isn't NULL, add the same support to the relocatable-lib
module (I've just patched relocatable-lib-lgpl). But since it's so obvious,
I thought I'd check first that there isn't a fatal flaw!

-- 
https://rrt.sc3d.org
From e03c16c8827d83d1a77ad19f121b9ee3ab0dd860 Mon Sep 17 00:00:00 2001
From: Reuben Thomas <r...@sc3d.org>
Date: Thu, 1 May 2025 20:45:19 +0100
Subject: [PATCH] relocatable-lib-lgpl: use dladdr to get path to shared
 library

Where neither the Windows nor Linux solution is available, use
dladdr to get the path of a shared library.
---
 lib/relocatable.c            | 10 ++++++++++
 modules/relocatable-lib-lgpl |  3 +++
 2 files changed, 13 insertions(+)

diff --git a/lib/relocatable.c b/lib/relocatable.c
index 15b3bc442d..f83fb0ff17 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -71,6 +71,12 @@
 # define GetModuleFileName GetModuleFileNameA
 #endif
 
+#if !(defined _WIN32 && !defined __CYGWIN__) && !(defined __EMX__) && \
+  !((defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__)
+/* We are on Unix and need dlopen.  */
+#include <dlfcn.h>
+#endif
+
 /* Faked cheap 'bool'.  */
 #undef bool
 #undef false
@@ -449,6 +455,10 @@ find_shared_library_fullname ()
         }
       fclose (fp);
     }
+#else
+  Dl_info info;
+  dladdr (find_shared_library_fullname, &info);
+  shared_library_fullname = strdup (info.dli_fname);
 #endif
 }
 
diff --git a/modules/relocatable-lib-lgpl b/modules/relocatable-lib-lgpl
index b8ecb51ef8..da905347cd 100644
--- a/modules/relocatable-lib-lgpl
+++ b/modules/relocatable-lib-lgpl
@@ -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
 
@@ -18,9 +19,11 @@ gl_RELOCATABLE_LIBRARY
 if test $RELOCATABLE = yes; then
   AC_LIBOBJ([relocatable])
 fi
+gl_LIBDL
 
 Makefile.am:
 DEFS += -DNO_XMALLOC
+lib_LDFLAGS += $(LIBDL)
 
 Include:
 "relocatable.h"
-- 
2.49.0

Reply via email to