merge from donut
diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c
index de4919d..d78d673 100644
--- a/libc/bionic/libc_init_common.c
+++ b/libc/bionic/libc_init_common.c
@@ -39,23 +39,6 @@
 #include <bionic_tls.h>
 #include <errno.h>
 
-extern void _init(void);
-extern void _fini(void);
-
-static void call_array(void(**list)())
-{
-    // First element is -1, list is null-terminated
-    while (*++list) {
-        (*list)();
-    }
-}
-
-static void __bionic_do_global_dtors(structors_array_t const * const p)
-{
-    call_array(p->fini_array);
-    //_fini();
-}
-
 extern unsigned __get_sp(void);
 extern pid_t    gettid(void);
 
@@ -69,23 +52,19 @@
 
 int __system_properties_init(void);
 
-void __libc_init_common(uintptr_t *elfdata,
-                       void (*onexit)(void),
-                       int (*slingshot)(int, char**, char**),
-                       structors_array_t const * const structors,
-                       void (*pre_ctor_hook)())
+void __libc_init_common(uintptr_t *elfdata)
 {
-    pthread_internal_t thread;
-    pthread_attr_t thread_attr;
-    void *tls_area[BIONIC_TLS_SLOTS];
-    int argc;
-    char **argv, **envp, **envend;
-    struct auxentry *auxentry;
-    unsigned int page_size = 0, page_shift = 0;
+    int     argc = *elfdata;
+    char**  argv = (char**)(elfdata + 1);
+    char**  envp = argv + argc + 1;
 
-    /* The main thread's stack has empirically shown to be 84k */
+    pthread_attr_t             thread_attr;
+    static pthread_internal_t  thread;
+    static void*               tls_area[BIONIC_TLS_SLOTS];
+
+    /* setup pthread runtime and maint thread descriptor */
     unsigned stacktop = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
-    unsigned stacksize = 128 * 1024; //84 * 1024;
+    unsigned stacksize = 128 * 1024;
     unsigned stackbottom = stacktop - stacksize;
 
     pthread_attr_init(&thread_attr);
@@ -93,30 +72,15 @@
     _init_thread(&thread, gettid(), &thread_attr, (void*)stackbottom);
     __init_tls(tls_area, &thread);
 
-    argc = (int) *elfdata++;
-    argv = (char**) elfdata;
-    envp = argv+(argc+1);
-    environ = envp;
-
-    __progname = argv[0] ? argv[0] : "<unknown>";
-
+    /* clear errno - requires TLS area */
     errno = 0;
 
+    /* set program name */
+    __progname = argv[0] ? argv[0] : "<unknown>";
+
+    /* setup environment pointer */
+    environ = envp;
+
+    /* setup system properties - requires environment */
     __system_properties_init();
-
-    if (pre_ctor_hook) pre_ctor_hook();
-
-    // XXX: we should execute the .fini_array upon exit
-
-    // pre-init array.
-    // XXX: I'm not sure what's the different with the init array.
-    call_array(structors->preinit_array);
-
-    // for compatibility with non-eabi binary, call the .ctors section
-    call_array(structors->ctors_array);
-
-    // call static constructors
-    call_array(structors->init_array);
-
-    exit(slingshot(argc, argv, envp));
 }
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index bbc82e4..8663c61 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -38,10 +38,6 @@
     void (**ctors_array)(void);
 } structors_array_t;
 
-extern __noreturn void __libc_init_common(uintptr_t *elfdata,
-                       void (*onexit)(void),
-                       int (*slingshot)(int, char**, char**),
-                       structors_array_t const * const structors,
-                       void (*pre_ctor_hook)());
+extern void __libc_init_common(uintptr_t *elfdata);
 
 #endif
diff --git a/libc/bionic/libc_init_dynamic.c b/libc/bionic/libc_init_dynamic.c
index 8cf24b4..b479b27 100644
--- a/libc/bionic/libc_init_dynamic.c
+++ b/libc/bionic/libc_init_dynamic.c
@@ -26,41 +26,81 @@
  * SUCH DAMAGE.
  */
 /*
- * libc_init_static.c
+ * libc_init_dynamic.c
  *
- * This function takes the raw data block set up by the ELF loader
- * in the kernel and parses it.  It is invoked by crt0.S which makes
- * any necessary adjustments and passes calls this function using
- * the standard C calling convention.
+ * This source files provides two important functions for dynamic
+ * executables:
  *
- * The arguments are:
- *  uintptr_t *elfdata	 -- The ELF loader data block; usually from the stack.
- *                          Basically a pointer to argc.
- *  void (*onexit)(void) -- Function to install into onexit
+ * - a C runtime initializer (__libc_preinit), which is called by
+ *   the dynamic linker when libc.so is loaded. This happens before
+ *   any other initializer (e.g. static C++ constructors in other
+ *   shared libraries the program depends on).
+ *
+ * - a program launch function (__libc_init), which is called after
+ *   all dynamic linking has been performed. Technically, it is called
+ *   from arch-$ARCH/bionic/crtbegin_dynamic.S which is itself called
+ *   by the dynamic linker after all libraries have been loaded and
+ *   initialized.
  */
 
-/*
- * Several Linux ABIs don't pass the onexit pointer, and the ones that
- * do never use it.  Therefore, unless USE_ONEXIT is defined, we just
- * ignore the onexit pointer.
- */
-/* #define USE_ONEXIT */
-
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <elf.h>
-#include "pthread_internal.h"
 #include "atexit.h"
 #include "libc_init_common.h"
+#include <bionic_tls.h>
 
 extern void malloc_debug_init();
 
+/* We flag the __libc_preinit function as a constructor to ensure
+ * that its address is listed in libc.so's .init_array section.
+ * This ensures that the function is called by the dynamic linker
+ * as soon as the shared library is loaded.
+ */
+void __attribute__((constructor)) __libc_prenit(void);
+
+void __libc_prenit(void)
+{
+    /* Read the ELF data pointer form a special slot of the
+     * TLS area, then call __libc_init_common with it.
+     *
+     * Note that:
+     * - we clear the slot so no other initializer sees its value.
+     * - __libc_init_common() will change the TLS area so the old one
+     *   won't be accessible anyway.
+     */
+    void**      tls_area = (void**)__get_tls();
+    unsigned*   elfdata   = tls_area[TLS_SLOT_BIONIC_PREINIT];
+
+    tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL;
+
+    __libc_init_common(elfdata);
+
+#ifdef MALLOC_LEAK_CHECK
+    /* setup malloc leak checker, requires system properties */
+    extern void malloc_debug_init(void);
+    malloc_debug_init();
+#endif
+
+}
+
 __noreturn void __libc_init(uintptr_t *elfdata,
                        void (*onexit)(void),
                        int (*slingshot)(int, char**, char**),
                        structors_array_t const * const structors)
 {
-    __libc_init_common(elfdata, onexit, slingshot, structors, malloc_debug_init);
+    /* When we reach this point, all initializers have been already
+     * run by the dynamic linker, so ignore 'structors'.
+     */
+    int     argc = (int)*elfdata;
+    char**  argv = (char**)(elfdata + 1);
+    char**  envp = argv + argc + 1;
+
+    /* Several Linux ABIs don't pass the onexit pointer, and the ones that
+     * do never use it.  Therefore, we ignore it.
+     */
+
+    exit(slingshot(argc, argv, envp));
 }
diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c
index ec463f7..e6264bb 100644
--- a/libc/bionic/libc_init_static.c
+++ b/libc/bionic/libc_init_static.c
@@ -28,24 +28,15 @@
 /*
  * libc_init_static.c
  *
- * This function takes the raw data block set up by the ELF loader
- * in the kernel and parses it.  It is invoked by crt0.S which makes
- * any necessary adjustments and passes calls this function using
- * the standard C calling convention.
+ * The program startup function __libc_init() defined here is
+ * used for static executables only (i.e. those that don't depend
+ * on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
+ * which is directly invoked by the kernel when the program is launched.
  *
- * The arguments are:
- *  uintptr_t *elfdata	 -- The ELF loader data block; usually from the stack.
- *                          Basically a pointer to argc.
- *  void (*onexit)(void) -- Function to install into onexit
+ * The 'structors' parameter contains pointers to various initializer
+ * arrays that must be run before the program's 'main' routine is launched.
  */
 
-/*
- * Several Linux ABIs don't pass the onexit pointer, and the ones that
- * do never use it.  Therefore, unless USE_ONEXIT is defined, we just
- * ignore the onexit pointer.
- */
-/* #define USE_ONEXIT */
-
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,19 +49,47 @@
 #include <bionic_tls.h>
 #include <errno.h>
 
+static void call_array(void(**list)())
+{
+    // First element is -1, list is null-terminated
+    while (*++list) {
+        (*list)();
+    }
+}
+
 __noreturn void __libc_init(uintptr_t *elfdata,
                        void (*onexit)(void),
                        int (*slingshot)(int, char**, char**),
                        structors_array_t const * const structors)
 {
-/* 
- * To enable malloc checks for statically linked programs, add
- * "WITH_MALLOC_CHECK_LIBC_A := true" in device/buildspec.mk
- */
+    int  argc;
+    char **argv, **envp;
+
+    /* Initialize the C runtime environment */
+    __libc_init_common(elfdata);
+
 #ifdef MALLOC_LEAK_CHECK
-    extern void malloc_debug_init();
-    __libc_init_common(elfdata, onexit, slingshot, structors, malloc_debug_init);
-#else
-    __libc_init_common(elfdata, onexit, slingshot, structors, NULL);
+    /* setup malloc leak checker, requires system properties */
+    extern void malloc_debug_init(void);
+    malloc_debug_init();
 #endif
+
+    /* Several Linux ABIs don't pass the onexit pointer, and the ones that
+     * do never use it.  Therefore, we ignore it.
+     */
+
+    /* pre-init array. */
+    call_array(structors->preinit_array);
+
+    /* .ctors section initializers, for non-arm-eabi ABIs */
+    call_array(structors->ctors_array);
+
+    // call static constructors
+    call_array(structors->init_array);
+
+    argc = (int) *elfdata;
+    argv = (char**)(elfdata + 1);
+    envp = argv + argc + 1;
+
+    exit(slingshot(argc, argv, envp));
 }
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 7c3608b..211b527 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -126,10 +126,10 @@
 }
 
 
-static int __android_log_vprint(int prio, const char *tag, const char *fmt,
-				va_list ap)
+int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
+                              va_list ap)
 {
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
 
@@ -139,7 +139,7 @@
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
 {
     va_list ap;
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
diff --git a/libc/bionic/malloc_leak.c b/libc/bionic/malloc_leak.c
index a0aa2ae..305f954 100644
--- a/libc/bionic/malloc_leak.c
+++ b/libc/bionic/malloc_leak.c
@@ -91,7 +91,14 @@
 static HashTable gHashTable;
 
 // =============================================================================
-// output fucntions
+// log functions
+// =============================================================================
+
+#define debug_log(format, ...)  \
+    __libc_android_log_print(ANDROID_LOG_DEBUG, "malloc_leak", (format), ##__VA_ARGS__ )
+
+// =============================================================================
+// output functions
 // =============================================================================
 
 static int hash_entry_compare(const void* arg1, const void* arg2)
@@ -257,12 +264,6 @@
     uint32_t guard;
 };
 
-// =============================================================================
-// log funtions
-// =============================================================================
-
-#define debug_log(format, ...)  \
-    __libc_android_log_print(ANDROID_LOG_DEBUG, "malloc_leak", (format), ##__VA_ARGS__ )
 
 // =============================================================================
 // Hash Table functions
@@ -515,8 +516,8 @@
 
     tmp[0] = 0; // Need to initialize tmp[0] for the first strcat
     for (i=0 ; i<c; i++) {
-        sprintf(buf, "%2d: %08x\n", i, addrs[i]);
-        strcat(tmp, buf);
+        snprintf(buf, sizeof buf, "%2d: %08x\n", i, addrs[i]);
+        strlcat(tmp, buf, sizeof tmp);
     }
     __libc_android_log_print(ANDROID_LOG_ERROR, "libc", "call stack:\n%s", tmp);
 }
@@ -526,69 +527,90 @@
     return 1;
 }
 
+static void assert_log_message(const char* format, ...)
+{
+    va_list  args;
+
+    pthread_mutex_lock(&gAllocationsMutex);
+        gMallocDispatch = &gMallocEngineTable[INDEX_NORMAL];
+        va_start(args, format);
+        __libc_android_log_vprint(ANDROID_LOG_ERROR, "libc",
+                                format, args);
+        va_end(args);
+        dump_stack_trace();
+        if (gTrapOnError) {
+            __builtin_trap();
+        }
+        gMallocDispatch = &gMallocEngineTable[INDEX_MALLOC_CHECK];
+    pthread_mutex_unlock(&gAllocationsMutex);
+}
+
 static void assert_valid_malloc_pointer(void* mem)
 {
     if (mem && !is_valid_malloc_pointer(mem)) {
-        pthread_mutex_lock(&gAllocationsMutex);
-        gMallocDispatch = &gMallocEngineTable[INDEX_NORMAL];
-            __libc_android_log_print(ANDROID_LOG_ERROR, "libc",
-                    "*** MALLOC CHECK: buffer %p, is not a valid "
-                    "malloc pointer (are you mixing up new/delete "
-                    "and malloc/free?)", mem);
-            dump_stack_trace();
-                if (gTrapOnError) {
-                    __builtin_trap();
-                }
-        gMallocDispatch = &gMallocEngineTable[INDEX_MALLOC_CHECK];
-        pthread_mutex_unlock(&gAllocationsMutex);
+        assert_log_message(
+            "*** MALLOC CHECK: buffer %p, is not a valid "
+            "malloc pointer (are you mixing up new/delete "
+            "and malloc/free?)", mem);
     }
 }
 
-static void chk_out_of_bounds_check__locked(void* buffer, size_t size)
+/* Check that a given address corresponds to a guarded block,
+ * and returns its original allocation size in '*allocated'.
+ * 'func' is the capitalized name of the caller function.
+ * Returns 0 on success, or -1 on failure.
+ * NOTE: Does not return if gTrapOnError is set.
+ */
+static int chk_mem_check(void*       mem,
+                         size_t*     allocated,
+                         const char* func)
 {
-    int i;
-    char* buf = (char*)buffer - CHK_SENTINEL_HEAD_SIZE;
+    char*  buffer;
+    size_t offset, bytes;
+    int    i;
+    char*  buf;
+
+    /* first check the bytes in the sentinel header */
+    buf = (char*)mem - CHK_SENTINEL_HEAD_SIZE;
     for (i=0 ; i<CHK_SENTINEL_HEAD_SIZE ; i++) {
         if (buf[i] != CHK_SENTINEL_VALUE) {
-            gMallocDispatch = &gMallocEngineTable[INDEX_NORMAL];
-            __libc_android_log_print(ANDROID_LOG_ERROR, "libc",
-                    "*** MALLOC CHECK: buffer %p, size=%lu, "
-                    "corrupted %d bytes before allocation",
-                    buffer, size, CHK_SENTINEL_HEAD_SIZE-i);
-            dump_stack_trace();
-            if (gTrapOnError) {
-                __builtin_trap();
-            }
-            gMallocDispatch = &gMallocEngineTable[INDEX_MALLOC_CHECK];
+            assert_log_message( 
+                "*** %s CHECK: buffer %p "
+                "corrupted %d bytes before allocation",
+                func, mem, CHK_SENTINEL_HEAD_SIZE-i);
+            return -1;
         }
     }
-    buf = (char*)buffer + size;
+
+    /* then the ones in the sentinel trailer */
+    buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE;
+    offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
+    bytes  = *(size_t *)(buffer + offset);
+
+    buf = (char*)mem + bytes;
     for (i=CHK_SENTINEL_TAIL_SIZE-1 ; i>=0 ; i--) {
         if (buf[i] != CHK_SENTINEL_VALUE) {
-            gMallocDispatch = &gMallocEngineTable[INDEX_NORMAL];
-            __libc_android_log_print(ANDROID_LOG_ERROR, "libc",
-                    "*** MALLOC CHECK: buffer %p, size=%lu, "
-                    "corrupted %d bytes after allocation",
-                    buffer, size, i+1);
-            dump_stack_trace();
-            if (gTrapOnError) {
-                __builtin_trap();
-            }
-            gMallocDispatch = &gMallocEngineTable[INDEX_MALLOC_CHECK];
+            assert_log_message( 
+                "*** %s CHECK: buffer %p, size=%lu, "
+                "corrupted %d bytes after allocation",
+                func, buffer, bytes, i+1);
+            return -1;
         }
     }
+
+    *allocated = bytes;
+    return 0;
 }
 
+
 void* chk_malloc(size_t bytes)
 {
     char* buffer = (char*)dlmalloc(bytes + CHK_OVERHEAD_SIZE);
     if (buffer) {
-        pthread_mutex_lock(&gAllocationsMutex);
-            memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE);
-            size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
-            *(size_t *)(buffer + offset) = bytes;
-            buffer += CHK_SENTINEL_HEAD_SIZE;
-        pthread_mutex_unlock(&gAllocationsMutex);
+        memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE);
+        size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
+        *(size_t *)(buffer + offset) = bytes;
+        buffer += CHK_SENTINEL_HEAD_SIZE;
     }
     return buffer;
 }
@@ -597,14 +619,14 @@
 {
     assert_valid_malloc_pointer(mem);
     if (mem) {
-        pthread_mutex_lock(&gAllocationsMutex);
-            char* buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE;
-            size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
-            size_t bytes = *(size_t *)(buffer + offset);
-            chk_out_of_bounds_check__locked(mem, bytes);
-        pthread_mutex_unlock(&gAllocationsMutex);
-        memset(buffer, CHK_FILL_FREE, bytes);
-        dlfree(buffer);
+        size_t  size;
+        char*   buffer;
+
+        if (chk_mem_check(mem, &size, "FREE") == 0) {
+            buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE;
+            memset(buffer, CHK_FILL_FREE, size + CHK_OVERHEAD_SIZE);
+            dlfree(buffer);
+        }
     }
 }
 
@@ -628,19 +650,20 @@
 
 void* chk_realloc(void* mem, size_t bytes)
 {
+    char*   buffer;
+    int     ret;
+    size_t  old_bytes = 0;
+
     assert_valid_malloc_pointer(mem);
+
+    if (mem != NULL && chk_mem_check(mem, &old_bytes, "REALLOC") < 0)
+        return NULL;
+
     char* new_buffer = chk_malloc(bytes);
     if (mem == NULL) {
         return new_buffer;
     }
 
-    pthread_mutex_lock(&gAllocationsMutex);
-        char* buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE;
-        size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
-        size_t old_bytes = *(size_t *)(buffer + offset);
-        chk_out_of_bounds_check__locked(mem, old_bytes);
-    pthread_mutex_unlock(&gAllocationsMutex);
-
     if (new_buffer) {
         size_t size = (bytes < old_bytes)?(bytes):(old_bytes);
         memcpy(new_buffer, mem, size);
diff --git a/libc/kernel/common/linux/uinput.h b/libc/kernel/common/linux/uinput.h
new file mode 100644
index 0000000..b7a6add
--- /dev/null
+++ b/libc/kernel/common/linux/uinput.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __UINPUT_H_
+#define __UINPUT_H_
+
+#include <linux/input.h>
+
+#define UINPUT_VERSION 3
+
+struct uinput_ff_upload {
+ int request_id;
+ int retval;
+ struct ff_effect effect;
+ struct ff_effect old;
+};
+
+struct uinput_ff_erase {
+ int request_id;
+ int retval;
+ int effect_id;
+};
+
+#define UINPUT_IOCTL_BASE 'U'
+#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
+#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
+
+#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int)
+#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int)
+#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int)
+#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int)
+#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int)
+#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int)
+#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int)
+#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
+#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
+#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
+
+#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
+#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
+#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
+#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+
+#define EV_UINPUT 0x0101
+#define UI_FF_UPLOAD 1
+#define UI_FF_ERASE 2
+
+#define UINPUT_MAX_NAME_SIZE 80
+struct uinput_user_dev {
+ char name[UINPUT_MAX_NAME_SIZE];
+ struct input_id id;
+ int ff_effects_max;
+ int absmax[ABS_MAX + 1];
+ int absmin[ABS_MAX + 1];
+ int absfuzz[ABS_MAX + 1];
+ int absflat[ABS_MAX + 1];
+};
+#endif
+
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 @@
 #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/libc/private/logd.h b/libc/private/logd.h
index 671cb48..43fa742 100644
--- a/libc/private/logd.h
+++ b/libc/private/logd.h
@@ -28,6 +28,8 @@
 #ifndef _ANDROID_BIONIC_LOGD_H
 #define _ANDROID_BIONIC_LOGD_H
 
+#include <stdarg.h>
+
 enum  {
     ANDROID_LOG_UNKNOWN = 0,
     ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
@@ -43,5 +45,6 @@
 };
 
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...);
+int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
 
 #endif /* _ANDROID_BIONIC_LOGD_H */
diff --git a/libstdc++/include/cerrno b/libstdc++/include/cerrno
new file mode 100644
index 0000000..e53ca25
--- /dev/null
+++ b/libstdc++/include/cerrno
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef BIONIC_LIBSTDCPP_INCLUDE_CERRNO__
+#define BIONIC_LIBSTDCPP_INCLUDE_CERRNO__
+
+/*
+ * Standard C++ Library wrapper around the C errno.h header file.
+ */
+#include <errno.h>
+
+// errno is a macro, so we can't define std::errno
+
+#endif  // BIONIC_LIBSTDCPP_INCLUDE_CERRNO__
diff --git a/libstdc++/include/cfloat b/libstdc++/include/cfloat
new file mode 100644
index 0000000..21c01d9
--- /dev/null
+++ b/libstdc++/include/cfloat
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__
+#define BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__
+
+/*
+ * Standard C++ Library wrapper around the C float.h header file.
+ */
+#include <sys/limits.h>
+#include <float.h>
+
+#endif  // BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__
diff --git a/libstdc++/include/cstdlib b/libstdc++/include/cstdlib
index 9e8a7ce..5e6a0b3 100644
--- a/libstdc++/include/cstdlib
+++ b/libstdc++/include/cstdlib
@@ -85,6 +85,11 @@
 using ::random;
 using ::srandom;
 
+using ::malloc;
+using ::free;
+using ::calloc;
+using ::realloc;
+
 using ::unlockpt;
 using ::ptsname;
 using ::ptsname_r;
diff --git a/libstdc++/include/cwchar_is_not_supported b/libstdc++/include/cwchar
similarity index 100%
rename from libstdc++/include/cwchar_is_not_supported
rename to libstdc++/include/cwchar
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 @@
     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 @@
     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();