# HG changeset patch # User Tassilo Philipp # Date 1493982823 -7200 # Node ID ab23f9f2934a76039fe894db27906ddd6fb4992a # Parent 446d2220bc49c56420a9fc312fa300abd2906af6 - BeOS impl for dlGetLibraryPath - more dynload doc clarifications diff -r 446d2220bc49 -r ab23f9f2934a doc/manual/manual_dynload_api.tex --- 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} diff -r 446d2220bc49 -r ab23f9f2934a dynload/dynload.3 --- 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 diff -r 446d2220bc49 -r ab23f9f2934a dynload/dynload_unix.c --- 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 + +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 @@ -172,5 +232,3 @@ #endif -#endif - diff -r 446d2220bc49 -r ab23f9f2934a test/dynload_plain/dynload_plain.c --- 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",