changeset 248:ab23f9f2934a

- BeOS impl for dlGetLibraryPath - more dynload doc clarifications
author Tassilo Philipp
date Fri, 05 May 2017 13:13:43 +0200
parents 446d2220bc49
children 91db39538e78
files doc/manual/manual_dynload_api.tex dynload/dynload.3 dynload/dynload_unix.c test/dynload_plain/dynload_plain.c
diffstat 4 files changed, 75 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/doc/manual/manual_dynload_api.tex	Thu May 04 23:53:05 2017 +0200
+++ b/doc/manual/manual_dynload_api.tex	Fri May 05 13:13:43 2017 +0200
@@ -59,7 +59,8 @@
 \lstinline{bufSize} (in bytes), to hold the output string. The return value is the size
 of the buffer (in bytes) needed to hold the null-terminated string, or 0 if it can't be
 looked up. If \lstinline{bufSize} >= return value > 1, a null-terminted string with the
-path to the library should be in \lstinline{sOut}.
+path to the library should be in \lstinline{sOut}.  If it returns 0, the library name wasn't
+able to be found. Please note that this might happen in some rare cases, so make sure to always check.
 
 \subsection{Symbol iteration}
 
--- a/dynload/dynload.3	Thu May 04 23:53:05 2017 +0200
+++ b/dynload/dynload.3	Fri May 05 13:13:43 2017 +0200
@@ -78,6 +78,7 @@
 .Ar bufSize
 >= return value > 1, a null-terminted string with the path to the library should be in
 .Ar sOut .
+If it returns 0, the library name wasn't able to be found. Please note that this might happen in some rare cases, so make sure to always check.
 .Pp
 The dlSyms* functions can be used to iterate over symbols. Since they can be used on libraries that are not linked, they are made
 for symbol name lookups, not to get symbols' addresses. For that refer to
@@ -97,9 +98,15 @@
 must point to a loaded symbol.
 .Sh BUGS
 .Fn dlGetLibraryPath
-and
+is not thread-safe on Darwin (macOS, iOS, ...) and OpenBSD.
 .Fn dlSymsInit
-are not thread-safe on Darwin (macOS, iOS, ...).
+is not thread-safe on Darwin.
+.Fn dlGetLibraryPath
+will not work on Haiku when the library in question doesn't have the (default)
+.Fn _init
+and
+.Fn _fini
+symbols exported (rare, but possible).
 .Sh SEE ALSO
 .Xr dyncall 3 ,
 .Xr dyncallback 3
--- a/dynload/dynload_unix.c	Thu May 04 23:53:05 2017 +0200
+++ b/dynload/dynload_unix.c	Fri May 05 13:13:43 2017 +0200
@@ -114,9 +114,7 @@
   return l+1; /* strlen + '\0' */
 }
 
-#else /* non-Darwin --> */
-
-#if defined(OS_OpenBSD) /* doesn't have dlinfo() but dl_iterate_phdr() --> */
+#elif defined(OS_OpenBSD) /* doesn't have dlinfo() but dl_iterate_phdr() --> */
 
 /* @@@ dl_iterate_phdr() only exists on OpenBSD >= 3.7 */
 
@@ -154,6 +152,68 @@
   return dl_iterate_phdr(iter_phdr_cb, &d);
 }
 
+#elif defined(OS_BeOS) /* neither dlinfo(), nor dl_iterate_phdr(), but ltdl stuff*/
+
+#if 0
+#include <ltdl.h>
+
+typedef struct { // @@@share
+  DLLib* pLib;
+  char*  sOut;
+  int    bufSize;
+} iter_phdr_data;
+
+static int handle_map_cb(lt_dlhandle h, void* data)
+{
+  int l = -1;
+  iter_phdr_data* d = (iter_phdr_data*)data;
+  /* same idea as with dl_iterate_phdr, see above */
+  const lt_dlinfo* dli = lt_dlgetinfo(h);
+  if(dli) {
+    void* lib = dlopen(dli->filename, RTLD_LIGHTEST);
+    if(lib) {
+      dlclose(lib);
+      if(lib == (void*)d->pLib) {
+        l = strlen(dli->filename);
+        if(l < d->bufSize) /* l+'\0' <= bufSize */
+          strcpy(d->sOut, dli->filename);
+      }
+    }
+  }
+  return l+1; /* strlen + '\0'; is 0 if lib not found, which continues iter */
+}
+
+int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize)
+{
+  iter_phdr_data d = { pLib, sOut, bufSize };
+  lt_dlinterface_id ii = lt_dlinterface_register("not_sure_here...", NULL);
+  int l = lt_dlhandle_map(ii, handle_map_cb, &d);
+  lt_dlinterface_free(ii);
+  return l;
+}
+#endif
+
+/* we have lt_dlgetinfo on BeOS, which requires iterating over ltdl stuff, */
+/* but was unable to get that to work (would also have introduced a link   */
+/* dependency on libltdl); so do a hacky dladdr() based attempt, instead,  */
+/* which might not always work, but probably is ok for nearly all libs     */
+
+int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize)
+{
+  /* BeOS uses ELF, cross fingers that .so is standard and look for _fini */
+  int l = -1;
+  void* s = dlsym((void*)pLib, "_fini");
+  if(s) {
+    Dl_info i;
+    if(dladdr(s, &i) != 0) {
+      l = strlen(i.dli_fname);
+      if(l < bufSize) /* l+'\0' <= bufSize */
+        strcpy(sOut, i.dli_fname);
+    }
+  }
+  return l+1; /* strlen + '\0' */
+}
+
 #else /* use dlinfo() --> */
 
 #include <link.h>
@@ -172,5 +232,3 @@
 
 #endif
 
-#endif
-
--- a/test/dynload_plain/dynload_plain.c	Thu May 04 23:53:05 2017 +0200
+++ b/test/dynload_plain/dynload_plain.c	Fri May 05 13:13:43 2017 +0200
@@ -59,6 +59,7 @@
     "/usr/lib/libc.so.39.3", /* hack: for OpenBSD used in dyncall test env */
     "/usr/lib/system/libsystem_c.dylib",
     "/usr/lib/libc.dylib",
+    "/boot/system/lib/libroot.so", /* Haiku */
     "\\ReactOS\\system32\\msvcrt.dll",
     "C:\\ReactOS\\system32\\msvcrt.dll",
     "\\Windows\\system32\\msvcrt.dll",