diff dynload/dynload_unix.c @ 248:ab23f9f2934a

- BeOS impl for dlGetLibraryPath - more dynload doc clarifications
author Tassilo Philipp
date Fri, 05 May 2017 13:13:43 +0200
parents 06a354b2e120
children 5cfe4322c500
line wrap: on
line diff
--- 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
-