comparison dynload/dynload_unix.c @ 356:2f64957d6a46

- fix to dynload to build with musl libc (latter has dlinfo but not RTLD_SELF, so fallback to dl_iterate_phdr if on ELF targets)
author Tassilo Philipp
date Tue, 25 Feb 2020 16:07:45 +0100
parents 85c80b0c021c
children 1d03a3a4220d
comparison
equal deleted inserted replaced
355:5ac53b2d5f1e 356:2f64957d6a46
38 38
39 #include <string.h> 39 #include <string.h>
40 40
41 #if defined(__GLIBC__) 41 #if defined(__GLIBC__)
42 /* @@@ version check glibc more precisely... dl_iterate_phdr(): glibc ver >= 2.2.4*/ 42 /* @@@ version check glibc more precisely... dl_iterate_phdr(): glibc ver >= 2.2.4*/
43 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 3) 43 # if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 3)
44 # define DL_USE_GLIBC_ITER_PHDR 44 # define DL_USE_GLIBC_ITER_PHDR
45 #endif 45 # endif
46 /* to access dl_iterate_phdr(), and related w/ glibc */ 46 /* to access dl_iterate_phdr(), and related w/ glibc */
47 # define _GNU_SOURCE 47 # define _GNU_SOURCE
48 # define __USE_GNU 48 # define __USE_GNU
49 #endif 49 #endif
50
50 #include <dlfcn.h> 51 #include <dlfcn.h>
51 52
52 53
53 DLLib* dlLoadLibrary(const char* libPath) 54 DLLib* dlLoadLibrary(const char* libPath)
54 { 55 {
95 /* code for dlGetLibraryPath() is platform specific */ 96 /* code for dlGetLibraryPath() is platform specific */
96 97
97 /* if dlinfo() exists use it (except on glibc, where it exists since version 98 /* if dlinfo() exists use it (except on glibc, where it exists since version
98 * 2.3.3, but its implementation is dangerous, as no checks are done whether 99 * 2.3.3, but its implementation is dangerous, as no checks are done whether
99 * the handle is valid, thus rendering the returned values useless) check for 100 * the handle is valid, thus rendering the returned values useless) check for
100 * RTLD_DI_LINKMAP which is a #define for dlinfo() on most supported targets, 101 * RTLD_DI_LINKMAP and RTLD_SELF, which are #defines used by dlinfo() on most
101 * or specifically check the OS (e.g. dlinfo() is originally from Solaris) */ 102 * supported targets, or specifically check the OS (e.g. dlinfo() is originally
102 #if (defined(RTLD_DI_LINKMAP) || defined(OS_SunOS)) && !defined(DL_USE_GLIBC_ITER_PHDR) 103 * from Solaris) */
104 #if ((defined(RTLD_DI_LINKMAP) && defined(RTLD_SELF)) || defined(OS_SunOS)) && !defined(DL_USE_GLIBC_ITER_PHDR)
103 105
104 #include <link.h> 106 #include <link.h>
105 107
106 int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize) 108 int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize)
107 { 109 {
155 157
156 return l+1; /* strlen + '\0' */ 158 return l+1; /* strlen + '\0' */
157 } 159 }
158 160
159 161
160 /* OpenBSD >= 3.7 has dl_iterate_phdr(), as well as glibc >= 2.2.4, however 162 /* - OpenBSD >= 3.7 has dl_iterate_phdr(), as well as glibc >= 2.2.4
161 * skip and use on dladdr()-based guessing if if explicitly requested, e.g. by 163 - also some libc impls (like musl) provide dlinfo(), but not RTLD_SELF (see above), however they might come
162 * ./configure */ 164 with dl_iterate_phdr (which comes from ELF program header iteration), so base it on that
163 #elif !defined(DL_DLADDR_TO_LIBPATH) && (defined(OS_OpenBSD) || defined(DL_USE_GLIBC_ITER_PHDR)) 165 - skip and use dladdr()-based guessing (see below) if explicitly requested, e.g. by ./configure */
166 #elif !defined(DL_DLADDR_TO_LIBPATH) && (defined(OS_OpenBSD) || defined(DL_USE_GLIBC_ITER_PHDR) || (!defined(RTLD_SELF) && defined(__ELF__)))
164 167
165 #include <sys/types.h> 168 #include <sys/types.h>
166 #include <link.h> 169 #include <link.h>
167 170
168 typedef struct { 171 typedef struct {
180 /* get loaded object's handle if not requesting info about process itself */ 183 /* get loaded object's handle if not requesting info about process itself */
181 if(d->pLib != NULL) { 184 if(d->pLib != NULL) {
182 /* unable to relate info->dlpi_addr directly to our dlopen handle, let's 185 /* unable to relate info->dlpi_addr directly to our dlopen handle, let's
183 * do what we do on macOS above, re-dlopen the already loaded lib (just 186 * do what we do on macOS above, re-dlopen the already loaded lib (just
184 * increases ref count) and compare handles */ 187 * increases ref count) and compare handles */
185 /* @@@ might be b/c it's the reloc addr... see below */ 188 /* @@@ might be b/c it's the reloc addr... see below */
186 lib = dlopen(info->dlpi_name, RTLD_LIGHTEST); 189 lib = dlopen(info->dlpi_name, RTLD_LIGHTEST);
187 if(lib) 190 if(lib)
188 dlclose(lib); 191 dlclose(lib);
189 } 192 }
190 193