diff options
-rw-r--r-- | libc/private/bionic_tls.h | 7 | ||||
-rw-r--r-- | linker/linker.c | 21 |
2 files changed, 21 insertions, 7 deletions
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h index da34344..82c8cd9 100644 --- a/libc/private/bionic_tls.h +++ b/libc/private/bionic_tls.h @@ -60,6 +60,13 @@ __BEGIN_DECLS #define TLS_SLOT_OPENGL_API 3 #define TLS_SLOT_OPENGL 4 +/* this slot is only used to pass information from the dynamic linker to + * libc.so when the C library is loaded in to memory. The C runtime init + * function will then clear it. Since its use is extremely temporary, + * we reuse an existing location. + */ +#define TLS_SLOT_BIONIC_PREINIT (TLS_SLOT_ERRNO+1) + /* small technical note: it is not possible to call pthread_setspecific * on keys that are <= TLS_SLOT_MAX_WELL_KNOWN, which is why it is set to * TLS_SLOT_ERRNO. diff --git a/linker/linker.c b/linker/linker.c index 77f995e..e235498 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -76,11 +76,6 @@ * headers provide versions that are negative... * - allocate space for soinfo structs dynamically instead of * having a hard limit (64) - * - * features to add someday: - * - * - dlopen() and friends - * */ @@ -1744,6 +1739,11 @@ unsigned __linker_init(unsigned **elfdata) struct link_map * map; char *ldpath_env = NULL; + /* Setup a temporary TLS area that is used to get a working + * errno for system calls. + */ + __set_tls(__tls_area); + pid = getpid(); #if TIMING @@ -1751,8 +1751,15 @@ unsigned __linker_init(unsigned **elfdata) gettimeofday(&t0, 0); #endif - __set_tls(__tls_area); - ((unsigned *)__get_tls())[TLS_SLOT_THREAD_ID] = gettid(); + /* NOTE: we store the elfdata pointer on a special location + * of the temporary TLS area in order to pass it to + * the C Library's runtime initializer. + * + * The initializer must clear the slot and reset the TLS + * to point to a different location to ensure that no other + * shared library constructor can access it. + */ + __tls_area[TLS_SLOT_BIONIC_PREINIT] = elfdata; debugger_init(); |