summaryrefslogtreecommitdiffstats
path: root/linker
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-07-17 17:55:01 +0200
committerDavid 'Digit' Turner <digit@google.com>2009-07-17 17:55:01 +0200
commitef0bd1857041ffde069cf52138aaf22c1af7130e (patch)
treec61b6ca4b286821ff473533183eba42e7da234a3 /linker
parent348065586a2e6154d6cff36afa6e00af6bbc5918 (diff)
downloadbionic-ef0bd1857041ffde069cf52138aaf22c1af7130e.tar.gz
bionic-ef0bd1857041ffde069cf52138aaf22c1af7130e.tar.bz2
bionic-ef0bd1857041ffde069cf52138aaf22c1af7130e.zip
Pass the elfdata pointer in a slot of the temporary TLS area.
This is needed to properly initialize the C runtime when libc.so is loaded by the dynamic linker. Move the temporary TLS setup before the first system call, just in case something really horrible happens, we won't crash when trying to write an error code in 'errno' Remove the broken TLS_SLOT_THREAD_ID setup. First, this slot should normally receive the address of a pthread_internal_t, not a kernel thread identifier. Second, it is never used by the linker anyway. Also remove an obsolete comment.
Diffstat (limited to 'linker')
-rw-r--r--linker/linker.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/linker/linker.c b/linker/linker.c
index 77f995ea8..e23549853 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();