@@ -174,7 +174,19 @@ static char *get_origin() {
174174}
175175#endif
176176
177- #if defined(__linux__ )
177+ /*
178+ * Glibc, Musl, FreeBSD and Soloris support RTLD_DI_LINKMAP.
179+ * Musl hate the vendor detect macro and refuse to support __musl__.
180+ * They think we should test feature instead of detect vendor, it's normally right,
181+ * but for dlinfo(3), it's almost impossible because dlinfo has no errno or similar thing,
182+ * there is dlerror(3), right? No! dlerror(3) can only return a implementation-defined error string
183+ * (In C term, it should be called unspecified behavior because libc implementation needn't have
184+ * documentation for it) instead of an integer which we can compare it with specific value
185+ * programmatically. So we can't test this feature is available, we can only assume there is only
186+ * Glibc and Musl on Linux, forget Nolibc and other libc implementations on Linux.
187+ */
188+ #if defined(RTLD_DI_LINKMAP ) || defined(__GLIBC__ ) || defined(__linux__ ) || defined(__FreeBSD__ ) \
189+ || (defined(__sun ) && defined(__SVR4 ))
178190static const char * get_runpath () {
179191 void * handle = dlopen (NULL , RTLD_NOW );
180192 if (handle == NULL ) {
@@ -194,18 +206,18 @@ static const char *get_runpath() {
194206 } else if (dyn -> d_tag == DT_RUNPATH ) {
195207 runpath = dyn ;
196208 } else if (dyn -> d_tag == DT_STRTAB ) {
197- strtab = (const char * )dyn -> d_un .d_val ;
209+ strtab = (const char * )dyn -> d_un .d_ptr ;
198210 }
199211 }
200- if (runpath ) {
212+ if (runpath != NULL && strtab != NULL ) {
201213 return strtab + runpath -> d_un .d_val ;
202214 } else {
203215 return NULL ;
204216 }
205217}
206218
207219#else
208- // FIXME: I still didn't find the way to determine RUNPATH on non-Linux .
220+ // FIXME: I still didn't find the way to determine RUNPATH on non-Glibc/Musl/Soloris .
209221// So use $ORIGIN as a temporary solution
210222static char * get_runpath () { return get_origin (); }
211223#endif
@@ -224,7 +236,7 @@ static char *get_driver_path() {
224236 char * LPAC_DRIVER_HOME = get_first_runpath (get_runpath ());
225237 if (LPAC_DRIVER_HOME == NULL )
226238 return NULL ;
227- if (!strcmp (LPAC_DRIVER_HOME , "$ORIGIN" )) {
239+ if (!strcmp (LPAC_DRIVER_HOME , "$ORIGIN" ) || ! strcmp ( LPAC_DRIVER_HOME , "@loader_path" ) ) {
228240 free (LPAC_DRIVER_HOME );
229241 LPAC_DRIVER_HOME = get_origin ();
230242 if (LPAC_DRIVER_HOME == NULL )
@@ -324,7 +336,7 @@ static const struct euicc_driver *find_driver_by_name(const enum euicc_driver_ty
324336 _cleanup_free_ char * LPAC_DRIVER_HOME = get_driver_path ();
325337 if (LPAC_DRIVER_HOME == NULL )
326338 return false;
327- if (!strcmp (LPAC_DRIVER_HOME , "$ORIGIN" )) {
339+ if (!strcmp (LPAC_DRIVER_HOME , "$ORIGIN" ) || ! strcmp ( LPAC_DRIVER_HOME , "@loader_path" ) ) {
328340 free (LPAC_DRIVER_HOME );
329341 LPAC_DRIVER_HOME = get_origin ();
330342 if (LPAC_DRIVER_HOME == NULL )
0 commit comments