add time64 redirect for, and redirecting implementation of, dlsym
authorRich Felker <dalias@aerifal.cx>
Fri, 9 Aug 2019 19:26:23 +0000 (15:26 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 2 Nov 2019 22:30:56 +0000 (18:30 -0400)
if symbols are being redirected to provide the new time64 ABI, dlsym
must perform matching redirections; otherwise, it would poke a hole in
the magic and return pointers to functions that are not safe to call
from a caller using time64 types.

rather than duplicating a table of redirections, use the time64
symbols present in libc's symbol table to derive the decision for
whether a particular symbol needs to be redirected.

include/dlfcn.h
ldso/dynlink.c

index 78fb073..13ab71d 100644 (file)
@@ -35,6 +35,10 @@ int dladdr(const void *, Dl_info *);
 int dlinfo(void *, int, void *);
 #endif
 
+#if _REDIR_TIME64
+__REDIR(dlsym, __dlsym_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 7ac0bf7..7810356 100644 (file)
@@ -2237,6 +2237,33 @@ hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra
        return res;
 }
 
+hidden void *__dlsym_redir_time64(void *restrict p, const char *restrict s, void *restrict ra)
+{
+#if _REDIR_TIME64
+       const char *suffix, *suffix2 = "";
+       char redir[36];
+
+       /* Map the symbol name to a time64 version of itself according to the
+        * pattern used for naming the redirected time64 symbols. */
+       size_t l = strnlen(s, sizeof redir);
+       if (l<4 || l==sizeof redir) goto no_redir;
+       if (s[l-2]=='_' && s[l-1]=='r') {
+               l -= 2;
+               suffix2 = s+l;
+       }
+       if (l<4) goto no_redir;
+       if (!strcmp(s+l-4, "time")) suffix = "64";
+       else suffix = "_time64";
+
+       /* Use the presence of the remapped symbol name in libc to determine
+        * whether it's one that requires time64 redirection; replace if so. */
+       snprintf(redir, sizeof redir, "__%.*s%s%s", (int)l, s, suffix, suffix2);
+       if (find_sym(&ldso, redir, 1).sym) s = redir;
+no_redir:
+#endif
+       return __dlsym(p, s, ra);
+}
+
 int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
 {
        struct dso *current;