Răsfoiți Sursa

libsanitizer: link.h/dl-iterate-phdr: expose dl_phdr_info TLS fields

Since the 2006 glibc-sync (commit c0a3c2d9) the four extra members of
struct dl_phdr_info -- dlpi_adds, dlpi_subs, dlpi_tls_modid,
dlpi_tls_data -- have been carried inside an #if 0 block because
uClibc's dl_iterate_phdr() never populated them. Modern consumers
such as gcc/libsanitizer expect at least dlpi_tls_modid to be
present in order to do TLS bookkeeping; without it libsanitizer
fails to build with errors like "struct dl_phdr_info has no member
named 'dlpi_tls_modid'".

uClibc-ng already tracks the TLS module id per loaded object in
struct elf_resolve (l_tls_modid in dl-hash.h) when UCLIBC_HAS_TLS
is enabled, so we can supply a real value here. dlpi_tls_data is
left at NULL: libsanitizer's Linux non-glibc path keeps
g_use_dlpi_tls_data at 0 and falls back to __tls_get_addr(), which
uClibc-ng implements. dlpi_adds / dlpi_subs are not tracked and
stay at 0; they are not read by the Linux libsanitizer code path.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Ramin Moussavi 4 săptămâni în urmă
părinte
comite
a9be148ece
2 a modificat fișierele cu 19 adăugiri și 6 ștergeri
  1. 3 6
      include/link.h
  2. 16 0
      libc/misc/elf/dl-iterate-phdr.c

+ 3 - 6
include/link.h

@@ -197,11 +197,9 @@ struct dl_phdr_info
     const ElfW(Phdr) *dlpi_phdr;
     ElfW(Half) dlpi_phnum;
 
-#if 0
-    /* Note: Following members were introduced after the first
-       version of this structure was available.  Check the SIZE
-       argument passed to the dl_iterate_phdr callback to determine
-       whether or not each later member is available.  */
+    /* The members below were originally guarded by #if 0 because
+       uClibc-ng's dl_iterate_phdr did not populate them.  They are
+       now wired up to enable libsanitizer / TLS tracking.  */
 
     /* Incremented when a new object may have been added.  */
     unsigned long long int dlpi_adds;
@@ -216,7 +214,6 @@ struct dl_phdr_info
        PT_TLS segment, if it has one and it has been allocated
        in the calling thread, otherwise a null pointer.  */
     void *dlpi_tls_data;
-#endif
   };
 
 __BEGIN_DECLS

+ 16 - 0
libc/misc/elf/dl-iterate-phdr.c

@@ -31,6 +31,15 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void
 		info.dlpi_name = l->libname;
 		info.dlpi_phdr = l->ppnt;
 		info.dlpi_phnum = l->n_phent;
+		info.dlpi_adds = 0;
+		info.dlpi_subs = 0;
+#if defined(USE_TLS) && USE_TLS
+		info.dlpi_tls_modid = l->l_tls_modid;
+#else
+		info.dlpi_tls_modid = 0;
+#endif
+		/* libsanitizer falls back to __tls_get_addr() on non-glibc.  */
+		info.dlpi_tls_data = NULL;
 		ret = callback (&info, sizeof (struct dl_phdr_info), data);
 		if (ret)
 			break;
@@ -69,6 +78,13 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
       info.dlpi_name = "";
       info.dlpi_phdr = _dl_phdr;
       info.dlpi_phnum = _dl_phnum;
+      info.dlpi_adds = 0;
+      info.dlpi_subs = 0;
+      /* No easy access to TLS info on the static fallback path; report
+         0 / NULL.  libsanitizer will skip TLS tracking for this entry,
+         which is acceptable for a single statically linked program.  */
+      info.dlpi_tls_modid = 0;
+      info.dlpi_tls_data = NULL;
       ret = (*callback) (&info, sizeof (struct dl_phdr_info), data);
       if (ret)
         return ret;