Merge "ARM: warn about atexit() calls from legacy shared libraries"
diff --git a/libc/Android.mk b/libc/Android.mk
index f20e671..837b5be 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -505,7 +505,8 @@
     -I$(LOCAL_PATH)/private \
     -DPOSIX_MISTAKE \
     -DLOG_ON_HEAP_ERROR \
-    -std=gnu99
+    -std=gnu99 \
+    -Wall -Wextra
 
 # these macro definitions are required to implement the
 # 'timezone' and 'daylight' global variables, as well as
@@ -805,7 +806,7 @@
 	$(libc_arch_static_src_files) \
 	$(libc_static_common_src_files) \
 	bionic/dlmalloc.c \
-	bionic/malloc_debug_common.c \
+	bionic/malloc_debug_common.cpp \
 	bionic/libc_init_static.c
 
 LOCAL_CFLAGS := $(libc_common_cflags) \
@@ -837,7 +838,7 @@
 	$(libc_arch_dynamic_src_files) \
 	$(libc_static_common_src_files) \
 	bionic/dlmalloc.c \
-	bionic/malloc_debug_common.c \
+	bionic/malloc_debug_common.cpp \
 	bionic/pthread_debug.c \
 	bionic/libc_init_dynamic.c
 
@@ -890,10 +891,10 @@
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 
 LOCAL_SRC_FILES := \
-	bionic/malloc_debug_leak.c \
-	bionic/malloc_debug_check.c \
-	bionic/malloc_debug_check_mapinfo.c \
-	bionic/malloc_debug_stacktrace.c
+	bionic/malloc_debug_leak.cpp \
+	bionic/malloc_debug_check.cpp \
+	bionic/malloc_debug_check_mapinfo.cpp \
+	bionic/malloc_debug_stacktrace.cpp
 
 LOCAL_MODULE:= libc_malloc_debug_leak
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -921,7 +922,7 @@
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 
 LOCAL_SRC_FILES := \
-	bionic/malloc_debug_qemu.c
+	bionic/malloc_debug_qemu.cpp
 
 LOCAL_MODULE:= libc_malloc_debug_qemu
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 6f12be8..26673e6 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -62,6 +62,7 @@
 int     getgroups:getgroups(int, gid_t *)      -1,-1,80
 pid_t   getpgid(pid_t)             132
 pid_t   getppid()                  64
+pid_t   getsid(pid_t)              147
 pid_t   setsid()                   66
 int     setgid:setgid32(gid_t)     214,214,-1
 int     setgid:setgid(gid_t)       -1,-1,46
diff --git a/libc/arch-arm/bionic/crtbegin.c b/libc/arch-arm/bionic/crtbegin.c
index 9dcd254..0e2d31e 100644
--- a/libc/arch-arm/bionic/crtbegin.c
+++ b/libc/arch-arm/bionic/crtbegin.c
@@ -31,7 +31,6 @@
     void (**preinit_array)(void);
     void (**init_array)(void);
     void (**fini_array)(void);
-    void (**ctors_array)(void);
 } structors_array_t;
 
 extern int main(int argc, char **argv, char **env);
@@ -52,10 +51,7 @@
 __attribute__ ((section (".fini_array")))
 void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
 
-__attribute__ ((section (".ctors")))
-void (*__CTOR_LIST__)(void) = (void (*)(void)) -1;
-
-__attribute__((visbility("hidden")))
+__attribute__((visibility("hidden")))
 void _start() {
   structors_array_t array;
   void *elfdata;
@@ -63,7 +59,6 @@
   array.preinit_array = &__PREINIT_ARRAY__;
   array.init_array =    &__INIT_ARRAY__;
   array.fini_array =    &__FINI_ARRAY__;
-  array.ctors_array =   &__CTOR_LIST__;
 
   elfdata = __builtin_frame_address(0) + sizeof(void *);
   __libc_init(elfdata, (void *) 0, &main, &array);
diff --git a/libc/arch-arm/bionic/crtbegin_so.c b/libc/arch-arm/bionic/crtbegin_so.c
index 36e4b9c..f382f63 100644
--- a/libc/arch-arm/bionic/crtbegin_so.c
+++ b/libc/arch-arm/bionic/crtbegin_so.c
@@ -29,7 +29,7 @@
 extern void __cxa_finalize(void *);
 extern void *__dso_handle;
 
-__attribute__((visbility("hidden")))
+__attribute__((visibility("hidden"),destructor))
 void __on_dlclose() {
   __cxa_finalize(&__dso_handle);
 }
diff --git a/libc/arch-arm/bionic/crtend.S b/libc/arch-arm/bionic/crtend.S
index 7196fc1..fffb0ab 100644
--- a/libc/arch-arm/bionic/crtend.S
+++ b/libc/arch-arm/bionic/crtend.S
@@ -35,9 +35,6 @@
 	.section .fini_array, "aw"
 	.long 0
 
-	.section .ctors, "aw"
-	.long 0
-
 #if defined(__linux__) && defined(__ELF__)
 	.section .note.GNU-stack,"",%progbits
 #endif
diff --git a/libc/arch-arm/bionic/crtend_so.S b/libc/arch-arm/bionic/crtend_so.S
index 0cb9947..bb6570e 100644
--- a/libc/arch-arm/bionic/crtend_so.S
+++ b/libc/arch-arm/bionic/crtend_so.S
@@ -26,16 +26,6 @@
  * SUCH DAMAGE.
  */
 
-/* This is the same than crtend.S except that a shared library
- * cannot have a .preinit_array
- */
-	
-	.section .init_array, "aw"
-	.long 0
-
-	.section .fini_array, "aw"
-	.long 0
-
 #if defined(__linux__) && defined(__ELF__)
 	.section .note.GNU-stack,"",%progbits
 #endif
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index b1c669d..565c2bd 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -18,6 +18,7 @@
 syscall_src += arch-arm/syscalls/getgroups.S
 syscall_src += arch-arm/syscalls/getpgid.S
 syscall_src += arch-arm/syscalls/getppid.S
+syscall_src += arch-arm/syscalls/getsid.S
 syscall_src += arch-arm/syscalls/setsid.S
 syscall_src += arch-arm/syscalls/setgid.S
 syscall_src += arch-arm/syscalls/__setreuid.S
diff --git a/libc/arch-arm/syscalls/getsid.S b/libc/arch-arm/syscalls/getsid.S
new file mode 100644
index 0000000..856d41a
--- /dev/null
+++ b/libc/arch-arm/syscalls/getsid.S
@@ -0,0 +1,14 @@
+/* autogenerated by gensyscalls.py */
+#include <machine/asm.h>
+#include <sys/linux-syscalls.h>
+
+ENTRY(getsid)
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_getsid
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+END(getsid)
diff --git a/libc/arch-mips/bionic/crtbegin.S b/libc/arch-mips/bionic/crtbegin.S
index d85d52c..40b689e 100644
--- a/libc/arch-mips/bionic/crtbegin.S
+++ b/libc/arch-mips/bionic/crtbegin.S
@@ -70,8 +70,6 @@
 1:	.long	__PREINIT_ARRAY__
 	.long	__INIT_ARRAY__
 	.long	__FINI_ARRAY__
-	.long	__CTOR_LIST__
-	.long	__DTOR_LIST__
 
 	.section .preinit_array, "aw"
 	.type __PREINIT_ARRAY__, @object
@@ -92,18 +90,6 @@
 	.long -1
 	.long __do_global_dtors_aux
 
-	.section .ctors, "aw"
-	.type __CTOR_LIST__, @object
-	.globl __CTOR_LIST__
-__CTOR_LIST__:
-	.long -1
-
-	.section .dtors, "aw"
-	.type __DTOR_LIST__, @object
-	.globl __DTOR_LIST__
-__DTOR_LIST__:
-	.long -1
-
 	.abicalls
 	.text
 	.align	2
diff --git a/libc/arch-mips/bionic/crtend.S b/libc/arch-mips/bionic/crtend.S
index 7a319be..6984d0e 100644
--- a/libc/arch-mips/bionic/crtend.S
+++ b/libc/arch-mips/bionic/crtend.S
@@ -35,13 +35,3 @@
 	.section .fini_array, "aw"
 	.long 0
 
-	.section .ctors, "aw"
-	.type __CTOR_END__, @object
-__CTOR_END__:
-	.long 0
-
-	.section .dtors, "aw"
-	.type __DTOR_END__, @object
-__DTOR_END__:
-	.long 0
-
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 6de0c8f..51fd32d 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -19,6 +19,7 @@
 syscall_src += arch-mips/syscalls/getgroups.S
 syscall_src += arch-mips/syscalls/getpgid.S
 syscall_src += arch-mips/syscalls/getppid.S
+syscall_src += arch-mips/syscalls/getsid.S
 syscall_src += arch-mips/syscalls/setsid.S
 syscall_src += arch-mips/syscalls/setgid.S
 syscall_src += arch-mips/syscalls/__setreuid.S
diff --git a/libc/arch-mips/syscalls/getsid.S b/libc/arch-mips/syscalls/getsid.S
new file mode 100644
index 0000000..2c089ac
--- /dev/null
+++ b/libc/arch-mips/syscalls/getsid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getsid
+    .align 4
+    .ent getsid
+
+getsid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getsid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getsid
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 2352221..623c193 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -19,6 +19,7 @@
 syscall_src += arch-x86/syscalls/getgroups.S
 syscall_src += arch-x86/syscalls/getpgid.S
 syscall_src += arch-x86/syscalls/getppid.S
+syscall_src += arch-x86/syscalls/getsid.S
 syscall_src += arch-x86/syscalls/setsid.S
 syscall_src += arch-x86/syscalls/setgid.S
 syscall_src += arch-x86/syscalls/__setreuid.S
diff --git a/libc/arch-x86/syscalls/getsid.S b/libc/arch-x86/syscalls/getsid.S
new file mode 100644
index 0000000..7046b9a
--- /dev/null
+++ b/libc/arch-x86/syscalls/getsid.S
@@ -0,0 +1,23 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type getsid, @function
+    .globl getsid
+    .align 4
+
+getsid:
+    pushl   %ebx
+    mov     8(%esp), %ebx
+    movl    $__NR_getsid, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ebx
+    ret
diff --git a/libc/bionic/dlmalloc.h b/libc/bionic/dlmalloc.h
index 913e98d..a00a583 100644
--- a/libc/bionic/dlmalloc.h
+++ b/libc/bionic/dlmalloc.h
@@ -20,11 +20,11 @@
 /* Configure dlmalloc. */
 #define HAVE_GETPAGESIZE 1
 #define MALLOC_INSPECT_ALL 1
-#define MORECORE_CONTIGUOUS 0
 #define MSPACES 0
 #define REALLOC_ZERO_BYTES_FREES 1
 #define USE_DL_PREFIX 1
 #define USE_LOCKS 1
+#define LOCK_AT_FORK 1
 #define USE_RECURSIVE_LOCK 0
 #define USE_SPIN_LOCKS 0
 
diff --git a/libc/bionic/getcwd.cpp b/libc/bionic/getcwd.cpp
index e06f52e..2ff22db 100644
--- a/libc/bionic/getcwd.cpp
+++ b/libc/bionic/getcwd.cpp
@@ -47,7 +47,7 @@
       // TODO: if we need to support paths longer than that, we'll have to walk the tree ourselves.
       size = getpagesize();
     }
-    buf = allocated_buf = reinterpret_cast<char*>(malloc(allocated_size));
+    buf = allocated_buf = static_cast<char*>(malloc(allocated_size));
     if (buf == NULL) {
       // malloc set errno.
       return NULL;
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 35050a1..c55594b 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -35,9 +35,6 @@
     void (**preinit_array)(void);
     void (**init_array)(void);
     void (**fini_array)(void);
-#ifndef __i386__
-    void (**ctors_array)(void);
-#endif
 } structors_array_t;
 
 extern void __libc_init_common(uintptr_t *elfdata);
diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c
index f97961d..97156e8 100644
--- a/libc/bionic/libc_init_static.c
+++ b/libc/bionic/libc_init_static.c
@@ -80,11 +80,6 @@
     /* pre-init array. */
     call_array(structors->preinit_array);
 
-#ifndef __i386__
-    /* .ctors section initializers, for non-arm-eabi ABIs */
-    call_array(structors->ctors_array);
-#endif
-
     // call static constructors
     call_array(structors->init_array);
 
diff --git a/libc/bionic/malloc_debug_check.c b/libc/bionic/malloc_debug_check.cpp
similarity index 74%
rename from libc/bionic/malloc_debug_check.c
rename to libc/bionic/malloc_debug_check.cpp
index 4ae21fe..9e6d92e 100644
--- a/libc/bionic/malloc_debug_check.c
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -67,33 +67,27 @@
 #define REAR_GUARD          0xbb
 #define REAR_GUARD_LEN      (1<<5)
 
-static void print_backtrace(const intptr_t *bt, unsigned int depth);
-
-static void log_message(const char* format, ...)
-{
-    extern pthread_mutex_t gAllocationsMutex;
+static void log_message(const char* format, ...) {
     extern const MallocDebug __libc_malloc_default_dispatch;
     extern const MallocDebug* __libc_malloc_dispatch;
+    extern pthread_mutex_t gAllocationsMutex;
 
-    va_list  args;
-
-    pthread_mutex_lock(&gAllocationsMutex);
+    va_list args;
     {
+        ScopedPthreadMutexLocker locker(&gAllocationsMutex);
         const MallocDebug* current_dispatch = __libc_malloc_dispatch;
         __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
         va_start(args, format);
-        __libc_android_log_vprint(ANDROID_LOG_ERROR, "libc",
-                                format, args);
+        __libc_android_log_vprint(ANDROID_LOG_ERROR, "libc", format, args);
         va_end(args);
         __libc_malloc_dispatch = current_dispatch;
     }
-    pthread_mutex_unlock(&gAllocationsMutex);
 }
 
-struct hdr {
+struct hdr_t {
     uint32_t tag;
-    struct hdr *prev;
-    struct hdr *next;
+    hdr_t* prev;
+    hdr_t* next;
     intptr_t bt[MAX_BACKTRACE_DEPTH];
     int bt_depth;
     intptr_t freed_bt[MAX_BACKTRACE_DEPTH];
@@ -102,43 +96,35 @@
     char front_guard[FRONT_GUARD_LEN];
 } __attribute__((packed));
 
-struct ftr {
+struct ftr_t {
     char rear_guard[REAR_GUARD_LEN];
 } __attribute__((packed));
 
-static inline struct ftr * to_ftr(struct hdr *hdr)
-{
-    return (struct ftr *)(((char *)(hdr + 1)) + hdr->size);
+static inline ftr_t* to_ftr(hdr_t* hdr) {
+    return reinterpret_cast<ftr_t*>(reinterpret_cast<char*>(hdr + 1) + hdr->size);
 }
 
-static inline void *user(struct hdr *hdr)
-{
+static inline void* user(hdr_t* hdr) {
     return hdr + 1;
 }
 
-static inline struct hdr *meta(void *user)
-{
-    return ((struct hdr *)user) - 1;
+static inline hdr_t* meta(void* user) {
+    return reinterpret_cast<hdr_t*>(user) - 1;
 }
 
-/* Call this on exit() to get leaked memory */
-void free_leaked_memory(void);
-
 static unsigned num;
-static struct hdr *tail;
-static struct hdr *head;
+static hdr_t *tail;
+static hdr_t *head;
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 
 static unsigned backlog_num;
-static struct hdr *backlog_tail;
-static struct hdr *backlog_head;
+static hdr_t *backlog_tail;
+static hdr_t *backlog_head;
 static pthread_mutex_t backlog_lock = PTHREAD_MUTEX_INITIALIZER;
 
-extern __LIBC_HIDDEN__
-int get_backtrace(intptr_t* addrs, size_t max_entries);
+extern __LIBC_HIDDEN__ int get_backtrace(intptr_t* addrs, size_t max_entries);
 
-static void print_backtrace(const intptr_t *bt, unsigned int depth)
-{
+static void print_backtrace(const intptr_t *bt, unsigned int depth) {
     const mapinfo *mi;
     unsigned int cnt;
     unsigned int rel_pc;
@@ -158,39 +144,35 @@
     }
 }
 
-static inline void init_front_guard(struct hdr *hdr)
-{
+static inline void init_front_guard(hdr_t *hdr) {
     memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
 }
 
-static inline bool is_front_guard_valid(struct hdr *hdr)
-{
-    unsigned i;
-    for (i = 0; i < FRONT_GUARD_LEN; i++)
-        if (hdr->front_guard[i] != FRONT_GUARD)
+static inline bool is_front_guard_valid(hdr_t *hdr) {
+    for (size_t i = 0; i < FRONT_GUARD_LEN; i++) {
+        if (hdr->front_guard[i] != FRONT_GUARD) {
             return 0;
+        }
+    }
     return 1;
 }
 
-static inline void init_rear_guard(struct hdr *hdr)
-{
-    struct ftr *ftr = to_ftr(hdr);
+static inline void init_rear_guard(hdr_t *hdr) {
+    ftr_t* ftr = to_ftr(hdr);
     memset(ftr->rear_guard, REAR_GUARD, REAR_GUARD_LEN);
 }
 
-static inline bool is_rear_guard_valid(struct hdr *hdr)
-{
+static inline bool is_rear_guard_valid(hdr_t *hdr) {
     unsigned i;
     int valid = 1;
     int first_mismatch = -1;
-    struct ftr *ftr = to_ftr(hdr);
+    ftr_t* ftr = to_ftr(hdr);
     for (i = 0; i < REAR_GUARD_LEN; i++) {
         if (ftr->rear_guard[i] != REAR_GUARD) {
             if (first_mismatch < 0)
                 first_mismatch = i;
             valid = 0;
-        }
-        else if (first_mismatch >= 0) {
+        } else if (first_mismatch >= 0) {
             log_message("+++ REAR GUARD MISMATCH [%d, %d)\n", first_mismatch, i);
             first_mismatch = -1;
         }
@@ -201,8 +183,7 @@
     return valid;
 }
 
-static inline void add_locked(struct hdr *hdr, struct hdr **tail, struct hdr **head)
-{
+static inline void add_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
     hdr->prev = NULL;
     hdr->next = *head;
     if (*head)
@@ -212,50 +193,46 @@
     *head = hdr;
 }
 
-static inline int del_locked(struct hdr *hdr, struct hdr **tail, struct hdr **head)
-{
-    if (hdr->prev)
+static inline int del_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
+    if (hdr->prev) {
         hdr->prev->next = hdr->next;
-    else
+    } else {
         *head = hdr->next;
-    if (hdr->next)
+    }
+    if (hdr->next) {
         hdr->next->prev = hdr->prev;
-    else
+    } else {
         *tail = hdr->prev;
+    }
     return 0;
 }
 
-static inline void add(struct hdr *hdr, size_t size)
-{
-    pthread_mutex_lock(&lock);
+static inline void add(hdr_t *hdr, size_t size) {
+    ScopedPthreadMutexLocker locker(&lock);
     hdr->tag = ALLOCATION_TAG;
     hdr->size = size;
     init_front_guard(hdr);
     init_rear_guard(hdr);
     num++;
     add_locked(hdr, &tail, &head);
-    pthread_mutex_unlock(&lock);
 }
 
-static inline int del(struct hdr *hdr)
-{
-    if (hdr->tag != ALLOCATION_TAG)
+static inline int del(hdr_t *hdr) {
+    if (hdr->tag != ALLOCATION_TAG) {
         return -1;
+    }
 
-    pthread_mutex_lock(&lock);
+    ScopedPthreadMutexLocker locker(&lock);
     del_locked(hdr, &tail, &head);
     num--;
-    pthread_mutex_unlock(&lock);
     return 0;
 }
 
-static inline void poison(struct hdr *hdr)
-{
+static inline void poison(hdr_t *hdr) {
     memset(user(hdr), FREE_POISON, hdr->size);
 }
 
-static int was_used_after_free(struct hdr *hdr)
-{
+static int was_used_after_free(hdr_t *hdr) {
     unsigned i;
     const char *data = (const char *)user(hdr);
     for (i = 0; i < hdr->size; i++)
@@ -265,8 +242,7 @@
 }
 
 /* returns 1 if valid, *safe == 1 if safe to dump stack */
-static inline int check_guards(struct hdr *hdr, int *safe)
-{
+static inline int check_guards(hdr_t *hdr, int *safe) {
     *safe = 1;
     if (!is_front_guard_valid(hdr)) {
         if (hdr->front_guard[0] == FRONT_GUARD) {
@@ -291,17 +267,15 @@
 }
 
 /* returns 1 if valid, *safe == 1 if safe to dump stack */
-static inline int check_allocation_locked(struct hdr *hdr, int *safe)
-{
+static inline int check_allocation_locked(hdr_t *hdr, int *safe) {
     int valid = 1;
     *safe = 1;
 
     if (hdr->tag != ALLOCATION_TAG && hdr->tag != BACKLOG_TAG) {
         log_message("+++ ALLOCATION %p HAS INVALID TAG %08x (NOT DUMPING STACKTRACE)\n",
                    user(hdr), hdr->tag);
-	/* Allocation header is probably corrupt, do not dequeue or dump stack
-         * trace.
-         */
+        // Allocation header is probably corrupt, do not dequeue or dump stack
+        // trace.
         *safe = 0;
         return 0;
     }
@@ -310,11 +284,11 @@
         log_message("+++ ALLOCATION %p SIZE %d WAS USED AFTER BEING FREED\n",
                    user(hdr), hdr->size);
         valid = 0;
-	/* check the guards to see if it's safe to dump a stack trace */
-        (void)check_guards(hdr, safe);
-    }
-    else
+        /* check the guards to see if it's safe to dump a stack trace */
+        check_guards(hdr, safe);
+    } else {
         valid = check_guards(hdr, safe);
+    }
 
     if (!valid && *safe) {
         log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
@@ -330,12 +304,10 @@
     return valid;
 }
 
-static inline int del_and_check_locked(struct hdr *hdr,
-                                   struct hdr **tail, struct hdr **head, unsigned *cnt,
-                                   int *safe)
-{
-    int valid;
-    valid = check_allocation_locked(hdr, safe);
+static inline int del_and_check_locked(hdr_t *hdr,
+                                       hdr_t **tail, hdr_t **head, unsigned *cnt,
+                                       int *safe) {
+    int valid = check_allocation_locked(hdr, safe);
     if (safe) {
         (*cnt)--;
         del_locked(hdr, tail, head);
@@ -343,56 +315,42 @@
     return valid;
 }
 
-static inline void del_from_backlog_locked(struct hdr *hdr)
-{
-        int safe;
-        (void)del_and_check_locked(hdr,
-                              &backlog_tail, &backlog_head, &backlog_num,
-                              &safe);
-        hdr->tag = 0; /* clear the tag */
+static inline void del_from_backlog_locked(hdr_t *hdr) {
+    int safe;
+    del_and_check_locked(hdr,
+                         &backlog_tail, &backlog_head, &backlog_num,
+                         &safe);
+    hdr->tag = 0; /* clear the tag */
 }
 
-static inline void del_from_backlog(struct hdr *hdr)
-{
-    pthread_mutex_lock(&backlog_lock);
+static inline void del_from_backlog(hdr_t *hdr) {
+    ScopedPthreadMutexLocker locker(&backlog_lock);
     del_from_backlog_locked(hdr);
-    pthread_mutex_unlock(&backlog_lock);
 }
 
-static inline int del_leak(struct hdr *hdr, int *safe)
-{
-    int valid;
-    pthread_mutex_lock(&lock);
-    valid = del_and_check_locked(hdr,
-                            &tail, &head, &num,
-                            safe);
-    pthread_mutex_unlock(&lock);
-    return valid;
+static inline int del_leak(hdr_t *hdr, int *safe) {
+    ScopedPthreadMutexLocker locker(&lock);
+    return del_and_check_locked(hdr, &tail, &head, &num, safe);
 }
 
-static inline void add_to_backlog(struct hdr *hdr)
-{
-    pthread_mutex_lock(&backlog_lock);
+static inline void add_to_backlog(hdr_t *hdr) {
+    ScopedPthreadMutexLocker locker(&backlog_lock);
     hdr->tag = BACKLOG_TAG;
     backlog_num++;
     add_locked(hdr, &backlog_tail, &backlog_head);
     poison(hdr);
     /* If we've exceeded the maximum backlog, clear it up */
     while (backlog_num > malloc_double_free_backlog) {
-        struct hdr *gone = backlog_tail;
+        hdr_t *gone = backlog_tail;
         del_from_backlog_locked(gone);
         dlfree(gone);
     }
-    pthread_mutex_unlock(&backlog_lock);
 }
 
-void* chk_malloc(size_t size)
-{
-    struct hdr *hdr;
-
+extern "C" void* chk_malloc(size_t size) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
 
-    hdr = dlmalloc(sizeof(struct hdr) + size + sizeof(struct ftr));
+    hdr_t* hdr = static_cast<hdr_t*>(dlmalloc(sizeof(hdr_t) + size + sizeof(ftr_t)));
     if (hdr) {
         hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, size);
@@ -401,23 +359,19 @@
     return NULL;
 }
 
-void* chk_memalign(size_t alignment, size_t bytes)
-{
+extern "C" void* chk_memalign(size_t, size_t bytes) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
     // XXX: it's better to use malloc, than being wrong
     return chk_malloc(bytes);
 }
 
-void chk_free(void *ptr)
-{
-    struct hdr *hdr;
-
+extern "C" void chk_free(void *ptr) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
 
     if (!ptr) /* ignore free(NULL) */
         return;
 
-    hdr = meta(ptr);
+    hdr_t* hdr = meta(ptr);
 
     if (del(hdr) < 0) {
         intptr_t bt[MAX_BACKTRACE_DEPTH];
@@ -436,26 +390,21 @@
             log_message("+++ ALLOCATION %p SIZE %d NOW BEING FREED HERE:\n",
                        user(hdr), hdr->size);
             print_backtrace(bt, depth);
-        }
-        else {
+        } else {
             log_message("+++ ALLOCATION %p IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
                        user(hdr));
             print_backtrace(bt, depth);
             /* Leak here so that we do not crash */
             //dlfree(user(hdr));
         }
-    }
-    else {
+    } else {
         hdr->freed_bt_depth = get_backtrace(hdr->freed_bt,
                                       MAX_BACKTRACE_DEPTH);
         add_to_backlog(hdr);
     }
 }
 
-void *chk_realloc(void *ptr, size_t size)
-{
-    struct hdr *hdr;
-
+extern "C" void *chk_realloc(void *ptr, size_t size) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
 
     if (!size) {
@@ -463,10 +412,11 @@
         return NULL;
     }
 
-    if (!ptr)
+    if (!ptr) {
         return chk_malloc(size);
+    }
 
-    hdr = meta(ptr);
+    hdr_t* hdr = meta(ptr);
 
     if (del(hdr) < 0) {
         intptr_t bt[MAX_BACKTRACE_DEPTH];
@@ -491,8 +441,7 @@
              * can default to this behavior.
              */
             del_from_backlog(hdr);
-        }
-        else {
+        } else {
             log_message("+++ REALLOCATION %p SIZE %d IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
                        user(hdr), size);
             print_backtrace(bt, depth);
@@ -502,7 +451,7 @@
         }
     }
 
-    hdr = dlrealloc(hdr, sizeof(struct hdr) + size + sizeof(struct ftr));
+    hdr = static_cast<hdr_t*>(dlrealloc(hdr, sizeof(hdr_t) + size + sizeof(ftr_t)));
     if (hdr) {
         hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, size);
@@ -512,12 +461,10 @@
     return NULL;
 }
 
-void *chk_calloc(int nmemb, size_t size)
-{
+extern "C" void *chk_calloc(int nmemb, size_t size) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
-    struct hdr *hdr;
     size_t total_size = nmemb * size;
-    hdr = dlcalloc(1, sizeof(struct hdr) + total_size + sizeof(struct ftr));
+    hdr_t* hdr = static_cast<hdr_t*>(dlcalloc(1, sizeof(hdr_t) + total_size + sizeof(ftr_t)));
     if (hdr) {
         hdr->bt_depth = get_backtrace(
                             hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -527,13 +474,12 @@
     return NULL;
 }
 
-static void heaptracker_free_leaked_memory(void)
-{
-    struct hdr *del; int cnt;
-
-    if (num)
+static void heaptracker_free_leaked_memory() {
+    if (num) {
         log_message("+++ THERE ARE %d LEAKED ALLOCATIONS\n", num);
+    }
 
+    hdr_t *del = NULL;
     while (head) {
         int safe;
         del = head;
@@ -550,7 +496,7 @@
 
 //  log_message("+++ DELETING %d BACKLOGGED ALLOCATIONS\n", backlog_num);
     while (backlog_head) {
-	del = backlog_tail;
+        del = backlog_tail;
         del_from_backlog(del);
         dlfree(del);
     }
@@ -559,16 +505,14 @@
 /* Initializes malloc debugging framework.
  * See comments on MallocDebugInit in malloc_debug_common.h
  */
-int malloc_debug_initialize(void)
-{
+extern "C" int malloc_debug_initialize() {
     if (!malloc_double_free_backlog)
         malloc_double_free_backlog = BACKLOG_DEFAULT_LEN;
     milist = init_mapinfo(getpid());
     return 0;
 }
 
-void malloc_debug_finalize(void)
-{
+extern "C" void malloc_debug_finalize() {
     heaptracker_free_leaked_memory();
     deinit_mapinfo(milist);
 }
diff --git a/libc/bionic/malloc_debug_check_mapinfo.c b/libc/bionic/malloc_debug_check_mapinfo.cpp
similarity index 78%
rename from libc/bionic/malloc_debug_check_mapinfo.c
rename to libc/bionic/malloc_debug_check_mapinfo.cpp
index 044fc65..8cc2c99 100644
--- a/libc/bionic/malloc_debug_check_mapinfo.c
+++ b/libc/bionic/malloc_debug_check_mapinfo.cpp
@@ -37,19 +37,17 @@
 // 012345678901234567890123456789012345678901234567890123456789
 // 0         1         2         3         4         5
 
-static mapinfo *parse_maps_line(char *line)
-{
-    mapinfo *mi;
+static mapinfo* parse_maps_line(char* line) {
     int len = strlen(line);
 
-    if(len < 1) return 0;
+    if (len < 1) return 0;
     line[--len] = 0;
 
-    if(len < 50) return 0;
-    if(line[20] != 'x') return 0;
+    if (len < 50) return 0;
+    if (line[20] != 'x') return 0;
 
-    mi = dlmalloc(sizeof(mapinfo) + (len - 47));
-    if(mi == 0) return 0;
+    mapinfo* mi = static_cast<mapinfo*>(dlmalloc(sizeof(mapinfo) + (len - 47)));
+    if (mi == 0) return 0;
 
     mi->start = strtoul(line, 0, 16);
     mi->end = strtoul(line + 9, 0, 16);
@@ -63,16 +61,15 @@
 }
 
 __LIBC_HIDDEN__
-mapinfo *init_mapinfo(int pid)
-{
+mapinfo *init_mapinfo(int pid) {
     struct mapinfo *milist = NULL;
-    char data[1024];
-    sprintf(data, "/proc/%d/maps", pid);
+    char data[1024]; // Used to read lines as well as to construct the filename.
+    snprintf(data, sizeof(data), "/proc/%d/maps", pid);
     FILE *fp = fopen(data, "r");
-    if(fp) {
-        while(fgets(data, sizeof(data), fp)) {
+    if (fp) {
+        while (fgets(data, sizeof(data), fp)) {
             mapinfo *mi = parse_maps_line(data);
-            if(mi) {
+            if (mi) {
                 mi->next = milist;
                 milist = mi;
             }
@@ -84,22 +81,20 @@
 }
 
 __LIBC_HIDDEN__
-void deinit_mapinfo(mapinfo *mi)
-{
-   mapinfo *del;
-   while(mi) {
-       del = mi;
-       mi = mi->next;
-       dlfree(del);
-   }
+void deinit_mapinfo(mapinfo *mi) {
+    mapinfo *del;
+    while (mi) {
+        del = mi;
+        mi = mi->next;
+        dlfree(del);
+    }
 }
 
 /* Map a pc address to the name of the containing ELF file */
 __LIBC_HIDDEN__
-const char *map_to_name(mapinfo *mi, unsigned pc, const char* def)
-{
-    while(mi) {
-        if((pc >= mi->start) && (pc < mi->end)){
+const char *map_to_name(mapinfo *mi, unsigned pc, const char* def) {
+    while (mi) {
+        if ((pc >= mi->start) && (pc < mi->end)) {
             return mi->name;
         }
         mi = mi->next;
@@ -109,11 +104,10 @@
 
 /* Find the containing map info for the pc */
 __LIBC_HIDDEN__
-const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc)
-{
+const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) {
     *rel_pc = pc;
-    while(mi) {
-        if((pc >= mi->start) && (pc < mi->end)){
+    while (mi) {
+        if ((pc >= mi->start) && (pc < mi->end)) {
             // Only calculate the relative offset for shared libraries
             if (strstr(mi->name, ".so")) {
                 *rel_pc -= mi->start;
diff --git a/libc/bionic/malloc_debug_check_mapinfo.h b/libc/bionic/malloc_debug_check_mapinfo.h
index 8a01cd3..e19f71e 100644
--- a/libc/bionic/malloc_debug_check_mapinfo.h
+++ b/libc/bionic/malloc_debug_check_mapinfo.h
@@ -31,16 +31,16 @@
 
 #include <sys/cdefs.h>
 
-typedef struct mapinfo {
-    struct mapinfo *next;
-    unsigned start;
-    unsigned end;
-    char name[];
-} mapinfo;
+struct mapinfo {
+  struct mapinfo* next;
+  unsigned start;
+  unsigned end;
+  char name[];
+};
 
 __LIBC_HIDDEN__ mapinfo *init_mapinfo(int pid);
 __LIBC_HIDDEN__ void deinit_mapinfo(mapinfo *mi);
 __LIBC_HIDDEN__ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def);
 __LIBC_HIDDEN__ const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc);
 
-#endif/*MALLOC_DEBUG_CHECK_MAPINFO_H*/
+#endif /*MALLOC_DEBUG_CHECK_MAPINFO_H*/
diff --git a/libc/bionic/malloc_debug_common.c b/libc/bionic/malloc_debug_common.cpp
similarity index 74%
rename from libc/bionic/malloc_debug_common.c
rename to libc/bionic/malloc_debug_common.cpp
index 2f4e55b..3a12cd4 100644
--- a/libc/bionic/malloc_debug_common.c
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -58,12 +58,11 @@
 // output functions
 // =============================================================================
 
-static int hash_entry_compare(const void* arg1, const void* arg2)
-{
+static int hash_entry_compare(const void* arg1, const void* arg2) {
     int result;
 
-    HashEntry* e1 = *(HashEntry**)arg1;
-    HashEntry* e2 = *(HashEntry**)arg2;
+    const HashEntry* e1 = *static_cast<HashEntry* const*>(arg1);
+    const HashEntry* e2 = *static_cast<HashEntry* const*>(arg2);
 
     // if one or both arg pointers are null, deal gracefully
     if (e1 == NULL) {
@@ -111,9 +110,8 @@
  *   not include heap overhead
  * "*backtraceSize" is set to the maximum number of entries in the back trace
  */
-void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
-        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize)
-{
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize) {
     // don't do anything if we have invalid arguments
     if (info == NULL || overallSize == NULL || infoSize == NULL ||
             totalMemory == NULL || backtraceSize == NULL) {
@@ -121,22 +119,21 @@
     }
     *totalMemory = 0;
 
-    pthread_mutex_lock(&gAllocationsMutex);
+    ScopedPthreadMutexLocker locker(&gAllocationsMutex);
 
     if (gHashTable.count == 0) {
         *info = NULL;
         *overallSize = 0;
         *infoSize = 0;
         *backtraceSize = 0;
-        goto done;
+        return;
     }
 
-    void** list = (void**)dlmalloc(sizeof(void*) * gHashTable.count);
+    HashEntry** list = static_cast<HashEntry**>(dlmalloc(sizeof(void*) * gHashTable.count));
 
     // get the entries into an array to be sorted
     int index = 0;
-    int i;
-    for (i = 0 ; i < HASHTABLE_SIZE ; i++) {
+    for (size_t i = 0 ; i < HASHTABLE_SIZE ; ++i) {
         HashEntry* entry = gHashTable.slots[i];
         while (entry != NULL) {
             list[index] = entry;
@@ -152,19 +149,20 @@
     *overallSize = *infoSize * gHashTable.count;
     *backtraceSize = BACKTRACE_SIZE;
 
-    // now get A byte array big enough for this
-    *info = (uint8_t*)dlmalloc(*overallSize);
+    // now get a byte array big enough for this
+    *info = static_cast<uint8_t*>(dlmalloc(*overallSize));
 
     if (*info == NULL) {
         *overallSize = 0;
-        goto out_nomem_info;
+        dlfree(list);
+        return;
     }
 
-    qsort((void*)list, gHashTable.count, sizeof(void*), hash_entry_compare);
+    qsort(list, gHashTable.count, sizeof(void*), hash_entry_compare);
 
     uint8_t* head = *info;
     const int count = gHashTable.count;
-    for (i = 0 ; i < count ; i++) {
+    for (int i = 0 ; i < count ; ++i) {
         HashEntry* entry = list[i];
         size_t entrySize = (sizeof(size_t) * 2) + (sizeof(intptr_t) * entry->numEntries);
         if (entrySize < *infoSize) {
@@ -178,40 +176,30 @@
         head += *infoSize;
     }
 
-out_nomem_info:
     dlfree(list);
-
-done:
-    pthread_mutex_unlock(&gAllocationsMutex);
 }
 
-void free_malloc_leak_info(uint8_t* info)
-{
+extern "C" void free_malloc_leak_info(uint8_t* info) {
     dlfree(info);
 }
 
-struct mallinfo mallinfo()
-{
+extern "C" struct mallinfo mallinfo() {
     return dlmallinfo();
 }
 
-size_t malloc_usable_size(void* mem)
-{
+extern "C" size_t malloc_usable_size(void* mem) {
     return dlmalloc_usable_size(mem);
 }
 
-void* valloc(size_t bytes)
-{
+extern "C" void* valloc(size_t bytes) {
     return dlvalloc(bytes);
 }
 
-void* pvalloc(size_t bytes)
-{
+extern "C" void* pvalloc(size_t bytes) {
     return dlpvalloc(bytes);
 }
 
-int posix_memalign(void** memptr, size_t alignment, size_t size)
-{
+extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
     return dlposix_memalign(memptr, alignment, size);
 }
 
@@ -223,27 +211,31 @@
 #ifdef USE_DL_PREFIX
 
 /* Table for dispatching malloc calls, initialized with default dispatchers. */
-const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) =
-{
+extern const MallocDebug __libc_malloc_default_dispatch;
+const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) = {
     dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
 };
 
 /* Selector of dispatch table to use for dispatching malloc calls. */
 const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
 
-void* malloc(size_t bytes) {
+extern "C" void* malloc(size_t bytes) {
     return __libc_malloc_dispatch->malloc(bytes);
 }
-void free(void* mem) {
+
+extern "C" void free(void* mem) {
     __libc_malloc_dispatch->free(mem);
 }
-void* calloc(size_t n_elements, size_t elem_size) {
+
+extern "C" void* calloc(size_t n_elements, size_t elem_size) {
     return __libc_malloc_dispatch->calloc(n_elements, elem_size);
 }
-void* realloc(void* oldMem, size_t bytes) {
+
+extern "C" void* realloc(void* oldMem, size_t bytes) {
     return __libc_malloc_dispatch->realloc(oldMem, bytes);
 }
-void* memalign(size_t alignment, size_t bytes) {
+
+extern "C" void* memalign(size_t alignment, size_t bytes) {
     return __libc_malloc_dispatch->memalign(alignment, bytes);
 }
 
@@ -253,6 +245,7 @@
 #ifndef LIBC_STATIC
 #include <sys/system_properties.h>
 #include <dlfcn.h>
+#include <stdio.h>
 #include "logd.h"
 
 /* Table for dispatching malloc calls, depending on environment. */
@@ -260,7 +253,7 @@
     dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
 };
 
-extern char*  __progname;
+extern char* __progname;
 
 /* Handle to shared library where actual memory allocation is implemented.
  * This library is loaded and memory allocation calls are redirected there
@@ -296,13 +289,49 @@
  * when the value of libc.debug.malloc = 10.  It determines the size of the
  * backlog we use to detect multiple frees.  If the property is not set, the
  * backlog length defaults to an internal constant defined in
- * malloc_debug_check.c
+ * malloc_debug_check.cpp.
  */
 unsigned int malloc_double_free_backlog;
 
+static void InitMalloc(MallocDebug* table, int debug_level, const char* prefix) {
+  __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
+                           __progname, debug_level, prefix);
+
+  char symbol[128];
+
+  snprintf(symbol, sizeof(symbol), "%s_malloc", prefix);
+  table->malloc = reinterpret_cast<MallocDebugMalloc>(dlsym(libc_malloc_impl_handle, symbol));
+  if (table->malloc == NULL) {
+      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+  }
+
+  snprintf(symbol, sizeof(symbol), "%s_free", prefix);
+  table->free = reinterpret_cast<MallocDebugFree>(dlsym(libc_malloc_impl_handle, symbol));
+  if (table->free == NULL) {
+      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+  }
+
+  snprintf(symbol, sizeof(symbol), "%s_calloc", prefix);
+  table->calloc = reinterpret_cast<MallocDebugCalloc>(dlsym(libc_malloc_impl_handle, symbol));
+  if (table->calloc == NULL) {
+      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+  }
+
+  snprintf(symbol, sizeof(symbol), "%s_realloc", prefix);
+  table->realloc = reinterpret_cast<MallocDebugRealloc>(dlsym(libc_malloc_impl_handle, symbol));
+  if (table->realloc == NULL) {
+      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+  }
+
+  snprintf(symbol, sizeof(symbol), "%s_memalign", prefix);
+  table->memalign = reinterpret_cast<MallocDebugMemalign>(dlsym(libc_malloc_impl_handle, symbol));
+  if (table->memalign == NULL) {
+      error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+  }
+}
+
 /* Initializes memory allocation framework once per process. */
-static void malloc_init_impl(void)
-{
+static void malloc_init_impl() {
     const char* so_name = NULL;
     MallocDebugInit malloc_debug_initialize = NULL;
     unsigned int qemu_running = 0;
@@ -328,13 +357,13 @@
 
     /* If debug level has not been set by memcheck option in the emulator,
      * lets grab it from libc.debug.malloc system property. */
-    if (!debug_level && __system_property_get("libc.debug.malloc", env)) {
+    if (debug_level == 0 && __system_property_get("libc.debug.malloc", env)) {
         debug_level = atoi(env);
     }
 
     /* Debug level 0 means that we should use dlxxx allocation
      * routines (default). */
-    if (!debug_level) {
+    if (debug_level == 0) {
         return;
     }
 
@@ -386,14 +415,14 @@
     // Load .so that implements the required malloc debugging functionality.
     libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
     if (libc_malloc_impl_handle == NULL) {
-        error_log("%s: Missing module %s required for malloc debug level %d\n",
-                 __progname, so_name, debug_level);
+        error_log("%s: Missing module %s required for malloc debug level %d: %s",
+                  __progname, so_name, debug_level, dlerror());
         return;
     }
 
     // Initialize malloc debugging in the loaded module.
-    malloc_debug_initialize =
-            dlsym(libc_malloc_impl_handle, "malloc_debug_initialize");
+    malloc_debug_initialize = reinterpret_cast<MallocDebugInit>(dlsym(libc_malloc_impl_handle,
+                                                                      "malloc_debug_initialize"));
     if (malloc_debug_initialize == NULL) {
         error_log("%s: Initialization routine is not found in %s\n",
                   __progname, so_name);
@@ -407,8 +436,10 @@
 
     if (debug_level == 20) {
         // For memory checker we need to do extra initialization.
-        int (*memcheck_initialize)(int, const char*) =
-                dlsym(libc_malloc_impl_handle, "memcheck_initialize");
+        typedef int (*MemCheckInit)(int, const char*);
+        MemCheckInit memcheck_initialize =
+            reinterpret_cast<MemCheckInit>(dlsym(libc_malloc_impl_handle,
+                                                 "memcheck_initialize"));
         if (memcheck_initialize == NULL) {
             error_log("%s: memcheck_initialize routine is not found in %s\n",
                       __progname, so_name);
@@ -424,63 +455,16 @@
     // Initialize malloc dispatch table with appropriate routines.
     switch (debug_level) {
         case 1:
-            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
-                    "%s using MALLOC_DEBUG = %d (leak checker)\n",
-                    __progname, debug_level);
-            gMallocUse.malloc =
-                dlsym(libc_malloc_impl_handle, "leak_malloc");
-            gMallocUse.free =
-                dlsym(libc_malloc_impl_handle, "leak_free");
-            gMallocUse.calloc =
-                dlsym(libc_malloc_impl_handle, "leak_calloc");
-            gMallocUse.realloc =
-                dlsym(libc_malloc_impl_handle, "leak_realloc");
-            gMallocUse.memalign =
-                dlsym(libc_malloc_impl_handle, "leak_memalign");
+            InitMalloc(&gMallocUse, debug_level, "leak");
             break;
         case 5:
-            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
-                    "%s using MALLOC_DEBUG = %d (fill)\n",
-                    __progname, debug_level);
-            gMallocUse.malloc =
-                dlsym(libc_malloc_impl_handle, "fill_malloc");
-            gMallocUse.free =
-                dlsym(libc_malloc_impl_handle, "fill_free");
-            gMallocUse.calloc = dlcalloc;
-            gMallocUse.realloc =
-                dlsym(libc_malloc_impl_handle, "fill_realloc");
-            gMallocUse.memalign =
-                dlsym(libc_malloc_impl_handle, "fill_memalign");
+            InitMalloc(&gMallocUse, debug_level, "fill");
             break;
         case 10:
-            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
-                    "%s using MALLOC_DEBUG = %d (sentinels, fill)\n",
-                    __progname, debug_level);
-            gMallocUse.malloc =
-                dlsym(libc_malloc_impl_handle, "chk_malloc");
-            gMallocUse.free =
-                dlsym(libc_malloc_impl_handle, "chk_free");
-            gMallocUse.calloc =
-                dlsym(libc_malloc_impl_handle, "chk_calloc");
-            gMallocUse.realloc =
-                dlsym(libc_malloc_impl_handle, "chk_realloc");
-            gMallocUse.memalign =
-                dlsym(libc_malloc_impl_handle, "chk_memalign");
+            InitMalloc(&gMallocUse, debug_level, "chk");
             break;
         case 20:
-            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
-                "%s[%u] using MALLOC_DEBUG = %d (instrumented for emulator)\n",
-                __progname, getpid(), debug_level);
-            gMallocUse.malloc =
-                dlsym(libc_malloc_impl_handle, "qemu_instrumented_malloc");
-            gMallocUse.free =
-                dlsym(libc_malloc_impl_handle, "qemu_instrumented_free");
-            gMallocUse.calloc =
-                dlsym(libc_malloc_impl_handle, "qemu_instrumented_calloc");
-            gMallocUse.realloc =
-                dlsym(libc_malloc_impl_handle, "qemu_instrumented_realloc");
-            gMallocUse.memalign =
-                dlsym(libc_malloc_impl_handle, "qemu_instrumented_memalign");
+            InitMalloc(&gMallocUse, debug_level, "qemu_instrumented");
             break;
         default:
             break;
@@ -492,12 +476,8 @@
         (gMallocUse.calloc == NULL) ||
         (gMallocUse.realloc == NULL) ||
         (gMallocUse.memalign == NULL)) {
-        error_log("%s: Cannot initialize malloc dispatch table for debug level"
-                  " %d: %p, %p, %p, %p, %p\n",
-                  __progname, debug_level,
-                  gMallocUse.malloc, gMallocUse.free,
-                  gMallocUse.calloc, gMallocUse.realloc,
-                  gMallocUse.memalign);
+        error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
+                  __progname, debug_level);
         dlclose(libc_malloc_impl_handle);
         libc_malloc_impl_handle = NULL;
     } else {
@@ -505,14 +485,14 @@
     }
 }
 
-static void malloc_fini_impl(void)
-{
+static void malloc_fini_impl() {
     if (libc_malloc_impl_handle) {
-        MallocDebugFini malloc_debug_finalize = NULL;
-        malloc_debug_finalize =
-                dlsym(libc_malloc_impl_handle, "malloc_debug_finalize");
-        if (malloc_debug_finalize)
+        MallocDebugFini malloc_debug_finalize =
+            reinterpret_cast<MallocDebugFini>(dlsym(libc_malloc_impl_handle,
+                                                    "malloc_debug_finalize"));
+        if (malloc_debug_finalize) {
             malloc_debug_finalize();
+        }
     }
 }
 
@@ -526,23 +506,21 @@
  * This routine is called from __libc_init routines implemented
  * in libc_init_static.c and libc_init_dynamic.c files.
  */
-void malloc_debug_init(void)
-{
+extern "C" void malloc_debug_init() {
     /* We need to initialize malloc iff we implement here custom
      * malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
 #if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
-    if (pthread_once(&malloc_init_once_ctl, malloc_init_impl)) {
+  if (pthread_once(&malloc_init_once_ctl, malloc_init_impl)) {
         error_log("Unable to initialize malloc_debug component.");
     }
 #endif  // USE_DL_PREFIX && !LIBC_STATIC
 }
 
-void malloc_debug_fini(void)
-{
-    /* We need to finalize malloc iff we implement here custom
+extern "C" void malloc_debug_fini() {
+  /* We need to finalize malloc iff we implement here custom
      * malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
 #if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
-    if (pthread_once(&malloc_fini_once_ctl, malloc_fini_impl)) {
+  if (pthread_once(&malloc_fini_once_ctl, malloc_fini_impl)) {
         error_log("Unable to finalize malloc_debug component.");
     }
 #endif  // USE_DL_PREFIX && !LIBC_STATIC
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index c78846b..45b4e36 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -33,10 +33,6 @@
 #ifndef MALLOC_DEBUG_COMMON_H
 #define MALLOC_DEBUG_COMMON_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define HASHTABLE_SIZE      1543
 #define BACKTRACE_SIZE      32
 /* flag definitions, currently sharing storage with "size" */
@@ -49,7 +45,6 @@
 // Structures
 // =============================================================================
 
-typedef struct HashEntry HashEntry;
 struct HashEntry {
     size_t slot;
     HashEntry* prev;
@@ -61,25 +56,23 @@
     intptr_t backtrace[0];
 };
 
-typedef struct HashTable HashTable;
 struct HashTable {
     size_t count;
     HashEntry* slots[HASHTABLE_SIZE];
 };
 
 /* Entry in malloc dispatch table. */
-typedef struct MallocDebug MallocDebug;
+typedef void* (*MallocDebugMalloc)(size_t);
+typedef void (*MallocDebugFree)(void*);
+typedef void* (*MallocDebugCalloc)(size_t, size_t);
+typedef void* (*MallocDebugRealloc)(void*, size_t);
+typedef void* (*MallocDebugMemalign)(size_t, size_t);
 struct MallocDebug {
-    /* Address of the actual malloc routine. */
-    void* (*malloc)(size_t bytes);
-    /* Address of the actual free routine. */
-    void  (*free)(void* mem);
-    /* Address of the actual calloc routine. */
-    void* (*calloc)(size_t n_elements, size_t elem_size);
-    /* Address of the actual realloc routine. */
-    void* (*realloc)(void* oldMem, size_t bytes);
-    /* Address of the actual memalign routine. */
-    void* (*memalign)(size_t alignment, size_t bytes);
+  MallocDebugMalloc malloc;
+  MallocDebugFree free;
+  MallocDebugCalloc calloc;
+  MallocDebugRealloc realloc;
+  MallocDebugMemalign memalign;
 };
 
 /* Malloc debugging initialization and finalization routines.
@@ -94,8 +87,8 @@
  * MallocDebugInit returns:
  *    0 on success, -1 on failure.
  */
-typedef int (*MallocDebugInit)(void);
-typedef void (*MallocDebugFini)(void);
+typedef int (*MallocDebugInit)();
+typedef void (*MallocDebugFini)();
 
 // =============================================================================
 // log functions
@@ -108,8 +101,18 @@
 #define info_log(format, ...)  \
     __libc_android_log_print(ANDROID_LOG_INFO, "malloc_leak_check", (format), ##__VA_ARGS__ )
 
-#ifdef __cplusplus
-};  /* end of extern "C" */
-#endif
+class ScopedPthreadMutexLocker {
+ public:
+  explicit ScopedPthreadMutexLocker(pthread_mutex_t* mu) : mu_(mu) {
+    pthread_mutex_lock(mu_);
+  }
+
+  ~ScopedPthreadMutexLocker() {
+    pthread_mutex_unlock(mu_);
+  }
+
+ private:
+  pthread_mutex_t* mu_;
+};
 
 #endif  // MALLOC_DEBUG_COMMON_H
diff --git a/libc/bionic/malloc_debug_leak.c b/libc/bionic/malloc_debug_leak.cpp
similarity index 78%
rename from libc/bionic/malloc_debug_leak.c
rename to libc/bionic/malloc_debug_leak.cpp
index 4bcf8e5..c13b520 100644
--- a/libc/bionic/malloc_debug_leak.c
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -75,18 +75,21 @@
 // =============================================================================
 // Structures
 // =============================================================================
-typedef struct AllocationEntry AllocationEntry;
+
 struct AllocationEntry {
     HashEntry* entry;
     uint32_t guard;
 };
 
+static AllocationEntry* to_header(void* mem) {
+  return reinterpret_cast<AllocationEntry*>(mem) - 1;
+}
 
 // =============================================================================
 // Hash Table functions
 // =============================================================================
-static uint32_t get_hash(intptr_t* backtrace, size_t numEntries)
-{
+
+static uint32_t get_hash(intptr_t* backtrace, size_t numEntries) {
     if (backtrace == NULL) return 0;
 
     int hash = 0;
@@ -99,8 +102,7 @@
 }
 
 static HashEntry* find_entry(HashTable* table, int slot,
-        intptr_t* backtrace, size_t numEntries, size_t size)
-{
+        intptr_t* backtrace, size_t numEntries, size_t size) {
     HashEntry* entry = table->slots[slot];
     while (entry != NULL) {
         //debug_log("backtrace: %p, entry: %p entry->backtrace: %p\n",
@@ -120,8 +122,7 @@
     return NULL;
 }
 
-static HashEntry* record_backtrace(intptr_t* backtrace, size_t numEntries, size_t size)
-{
+static HashEntry* record_backtrace(intptr_t* backtrace, size_t numEntries, size_t size) {
     size_t hash = get_hash(backtrace, numEntries);
     size_t slot = hash % HASHTABLE_SIZE;
 
@@ -130,8 +131,9 @@
         abort();
     }
 
-    if (gMallocLeakZygoteChild)
+    if (gMallocLeakZygoteChild) {
         size |= SIZE_FLAG_ZYGOTE_CHILD;
+    }
 
     HashEntry* entry = find_entry(&gHashTable, slot, backtrace, numEntries, size);
 
@@ -139,9 +141,10 @@
         entry->allocations++;
     } else {
         // create a new entry
-        entry = (HashEntry*)dlmalloc(sizeof(HashEntry) + numEntries*sizeof(intptr_t));
-        if (!entry)
+        entry = static_cast<HashEntry*>(dlmalloc(sizeof(HashEntry) + numEntries*sizeof(intptr_t)));
+        if (!entry) {
             return NULL;
+        }
         entry->allocations = 1;
         entry->slot = slot;
         entry->prev = NULL;
@@ -164,8 +167,7 @@
     return entry;
 }
 
-static int is_valid_entry(HashEntry* entry)
-{
+static int is_valid_entry(HashEntry* entry) {
     if (entry != NULL) {
         int i;
         for (i = 0 ; i < HASHTABLE_SIZE ; i++) {
@@ -184,8 +186,7 @@
     return 0;
 }
 
-static void remove_entry(HashEntry* entry)
-{
+static void remove_entry(HashEntry* entry) {
     HashEntry* prev = entry->prev;
     HashEntry* next = entry->next;
 
@@ -206,10 +207,13 @@
 // =============================================================================
 
 #define CHK_FILL_FREE           0xef
-#define CHK_SENTINEL_VALUE      (char)0xeb
+#define CHK_SENTINEL_VALUE      0xeb
 
-void* fill_malloc(size_t bytes)
-{
+extern "C" void* fill_calloc(size_t n_elements, size_t elem_size) {
+    return dlcalloc(n_elements, elem_size);
+}
+
+extern "C" void* fill_malloc(size_t bytes) {
     void* buffer = dlmalloc(bytes);
     if (buffer) {
         memset(buffer, CHK_SENTINEL_VALUE, bytes);
@@ -217,15 +221,13 @@
     return buffer;
 }
 
-void  fill_free(void* mem)
-{
+extern "C" void fill_free(void* mem) {
     size_t bytes = dlmalloc_usable_size(mem);
     memset(mem, CHK_FILL_FREE, bytes);
     dlfree(mem);
 }
 
-void* fill_realloc(void* mem, size_t bytes)
-{
+extern "C" void* fill_realloc(void* mem, size_t bytes) {
     void* buffer = fill_malloc(bytes);
     if (mem == NULL) {
         return buffer;
@@ -239,8 +241,7 @@
     return buffer;
 }
 
-void* fill_memalign(size_t alignment, size_t bytes)
-{
+extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
     void* buffer = dlmemalign(alignment, bytes);
     if (buffer) {
         memset(buffer, CHK_SENTINEL_VALUE, bytes);
@@ -252,13 +253,11 @@
 // malloc leak functions
 // =============================================================================
 
-#define MEMALIGN_GUARD  ((void*)0xA1A41520)
+static void* MEMALIGN_GUARD = reinterpret_cast<void*>(0xA1A41520);
 
-extern __LIBC_HIDDEN__
-int get_backtrace(intptr_t* addrs, size_t max_entries);
+extern __LIBC_HIDDEN__ int get_backtrace(intptr_t* addrs, size_t max_entries);
 
-void* leak_malloc(size_t bytes)
-{
+extern "C" void* leak_malloc(size_t bytes) {
     // allocate enough space infront of the allocation to store the pointer for
     // the alloc structure. This will making free'ing the structer really fast!
 
@@ -272,38 +271,35 @@
 
     void* base = dlmalloc(size);
     if (base != NULL) {
-        pthread_mutex_lock(&gAllocationsMutex);
+        ScopedPthreadMutexLocker locker(&gAllocationsMutex);
 
-            intptr_t backtrace[BACKTRACE_SIZE];
-            size_t numEntries = get_backtrace(backtrace, BACKTRACE_SIZE);
+        intptr_t backtrace[BACKTRACE_SIZE];
+        size_t numEntries = get_backtrace(backtrace, BACKTRACE_SIZE);
 
-            AllocationEntry* header = (AllocationEntry*)base;
-            header->entry = record_backtrace(backtrace, numEntries, bytes);
-            header->guard = GUARD;
+        AllocationEntry* header = reinterpret_cast<AllocationEntry*>(base);
+        header->entry = record_backtrace(backtrace, numEntries, bytes);
+        header->guard = GUARD;
 
-            // now increment base to point to after our header.
-            // this should just work since our header is 8 bytes.
-            base = (AllocationEntry*)base + 1;
-
-        pthread_mutex_unlock(&gAllocationsMutex);
+        // now increment base to point to after our header.
+        // this should just work since our header is 8 bytes.
+        base = reinterpret_cast<AllocationEntry*>(base) + 1;
     }
 
     return base;
 }
 
-void leak_free(void* mem)
-{
+extern "C" void leak_free(void* mem) {
     if (mem != NULL) {
-        pthread_mutex_lock(&gAllocationsMutex);
+        ScopedPthreadMutexLocker locker(&gAllocationsMutex);
 
         // check the guard to make sure it is valid
-        AllocationEntry* header = (AllocationEntry*)mem - 1;
+        AllocationEntry* header = to_header(mem);
 
         if (header->guard != GUARD) {
             // could be a memaligned block
-            if (((void**)mem)[-1] == MEMALIGN_GUARD) {
-                mem = ((void**)mem)[-2];
-                header = (AllocationEntry*)mem - 1;
+            if (reinterpret_cast<void**>(mem)[-1] == MEMALIGN_GUARD) {
+                mem = reinterpret_cast<void**>(mem)[-2];
+                header = to_header(mem);
             }
         }
 
@@ -322,36 +318,29 @@
             debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
                     header->guard, header->entry);
         }
-
-        pthread_mutex_unlock(&gAllocationsMutex);
     }
 }
 
-void* leak_calloc(size_t n_elements, size_t elem_size)
-{
-    size_t  size;
-    void*   ptr;
-
+extern "C" void* leak_calloc(size_t n_elements, size_t elem_size) {
     /* Fail on overflow - just to be safe even though this code runs only
      * within the debugging C library, not the production one */
     if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
         return NULL;
     }
-    size = n_elements * elem_size;
-    ptr  = leak_malloc(size);
+    size_t size = n_elements * elem_size;
+    void* ptr  = leak_malloc(size);
     if (ptr != NULL) {
         memset(ptr, 0, size);
     }
     return ptr;
 }
 
-void* leak_realloc(void* oldMem, size_t bytes)
-{
+extern "C" void* leak_realloc(void* oldMem, size_t bytes) {
     if (oldMem == NULL) {
         return leak_malloc(bytes);
     }
     void* newMem = NULL;
-    AllocationEntry* header = (AllocationEntry*)oldMem - 1;
+    AllocationEntry* header = to_header(oldMem);
     if (header && header->guard == GUARD) {
         size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK;
         newMem = leak_malloc(bytes);
@@ -366,15 +355,16 @@
     return newMem;
 }
 
-void* leak_memalign(size_t alignment, size_t bytes)
-{
+extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
     // we can just use malloc
-    if (alignment <= MALLOC_ALIGNMENT)
+    if (alignment <= MALLOC_ALIGNMENT) {
         return leak_malloc(bytes);
+    }
 
     // need to make sure it's a power of two
-    if (alignment & (alignment-1))
+    if (alignment & (alignment-1)) {
         alignment = 1L << (31 - __builtin_clz(alignment));
+    }
 
     // here, aligment is at least MALLOC_ALIGNMENT<<1 bytes
     // we will align by at least MALLOC_ALIGNMENT bytes
@@ -386,18 +376,19 @@
 
     void* base = leak_malloc(size);
     if (base != NULL) {
-        intptr_t ptr = (intptr_t)base;
-        if ((ptr % alignment) == 0)
+        intptr_t ptr = reinterpret_cast<intptr_t>(base);
+        if ((ptr % alignment) == 0) {
             return base;
+        }
 
         // align the pointer
         ptr += ((-ptr) % alignment);
 
         // there is always enough space for the base pointer and the guard
-        ((void**)ptr)[-1] = MEMALIGN_GUARD;
-        ((void**)ptr)[-2] = base;
+        reinterpret_cast<void**>(ptr)[-1] = MEMALIGN_GUARD;
+        reinterpret_cast<void**>(ptr)[-2] = base;
 
-        return (void*)ptr;
+        return reinterpret_cast<void*>(ptr);
     }
     return base;
 }
diff --git a/libc/bionic/malloc_debug_qemu.c b/libc/bionic/malloc_debug_qemu.cpp
similarity index 94%
rename from libc/bionic/malloc_debug_qemu.c
rename to libc/bionic/malloc_debug_qemu.cpp
index bcbf1e6..e586b1b 100644
--- a/libc/bionic/malloc_debug_qemu.c
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -79,7 +79,7 @@
  * sources (file memcheck/memcheck_common.h). So, every time a change is made to
  * any of these two declaration, another one must be also updated accordingly.
  */
-typedef struct MallocDesc {
+struct MallocDesc {
     /* Pointer to the memory block actually allocated from the heap. Note that
      * this is not the pointer that is returned to the malloc's caller. Pointer
      * returned to the caller is calculated by adding value stored in this field
@@ -115,7 +115,7 @@
 
     /* Number of access violations detected on this allocation. */
     uint32_t    av_count;
-} MallocDesc;
+};
 
 /* Describes memory block info queried from emulator. This structure is passed
  * along with TRACE_DEV_REG_QUERY_MALLOC event. When handling free and realloc
@@ -130,7 +130,7 @@
  * memcheck/memecheck_common.h). So, every time a change is made to any of these
  * two declaration, another one must be also updated accordingly.
  */
-typedef struct MallocDescQuery {
+struct MallocDescQuery {
     /* Pointer, for which information is queried. Note that this pointer doesn't
      * have to be exact pointer returned to malloc's caller, but can point
      * anywhere inside an allocated block, including guarding areas. Emulator
@@ -160,7 +160,7 @@
      * response to the query.
      */
     MallocDesc*  desc;
-} MallocDescQuery;
+};
 
 /* Describes memory block that is being freed back to the heap. This structure
  * is passed along with TRACE_DEV_REG_FREE_PTR event. The entire structure is
@@ -170,7 +170,7 @@
  * memcheck/memecheck_common.h). So, every time a change is made to any of these
  * two declaration, another one must be also updated accordingly.
  */
-typedef struct MallocFree {
+struct MallocFree {
     /* Pointer to be freed. */
     void*       ptr;
 
@@ -183,7 +183,7 @@
 
     /* Process ID in context of which memory is being freed. */
     uint32_t    free_pid;
-} MallocFree;
+};
 
 // =============================================================================
 // Communication events
@@ -267,7 +267,7 @@
 #define TR(...)                                         \
     do {                                                \
         char tr_str[4096];                              \
-        snprintf(tr_str, sizeof(tr_str), __VA_ARGS__ ); \
+        snprintf(tr_str, sizeof(tr_str), __VA_ARGS__);  \
         tr_str[sizeof(tr_str) - 1] = '\0';              \
         notify_qemu_string(&tr_str[0]);                 \
     } while (0)
@@ -290,27 +290,27 @@
 #define qemu_debug_log(format, ...)                                         \
     do {                                                                    \
         __libc_android_log_print(ANDROID_LOG_DEBUG, "memcheck",             \
-                                 (format), ##__VA_ARGS__ );                 \
+                                 (format), ##__VA_ARGS__);                  \
         if (tracing_flags & DEBUG_TRACING_ENABLED) {                        \
-            qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__ );          \
+            qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__);           \
         }                                                                   \
     } while (0)
 
 #define qemu_error_log(format, ...)                                         \
     do {                                                                    \
         __libc_android_log_print(ANDROID_LOG_ERROR, "memcheck",             \
-                                 (format), ##__VA_ARGS__ );                 \
+                                 (format), ##__VA_ARGS__);                  \
         if (tracing_flags & ERROR_TRACING_ENABLED) {                        \
-            qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__ );          \
+            qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__);           \
         }                                                                   \
     } while (0)
 
 #define qemu_info_log(format, ...)                                          \
     do {                                                                    \
         __libc_android_log_print(ANDROID_LOG_INFO, "memcheck",              \
-                                 (format), ##__VA_ARGS__ );                 \
+                                 (format), ##__VA_ARGS__);                  \
         if (tracing_flags & INFO_TRACING_ENABLED) {                         \
-            qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__ );           \
+            qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__);            \
         }                                                                   \
     } while (0)
 
@@ -368,10 +368,8 @@
  * Return:
  *  Pointer to the allocated memory returned to the malloc caller.
  */
-static inline void*
-mallocdesc_user_ptr(const MallocDesc* desc)
-{
-    return (char*)desc->ptr + desc->prefix_size;
+static inline void* mallocdesc_user_ptr(const MallocDesc* desc) {
+    return static_cast<char*>(desc->ptr) + desc->prefix_size;
 }
 
 /* Gets size of memory block actually allocated from the heap for the given
@@ -381,9 +379,7 @@
  * Return:
  *  Size of memory block actually allocated from the heap.
  */
-static inline uint32_t
-mallocdesc_alloc_size(const MallocDesc* desc)
-{
+static inline uint32_t mallocdesc_alloc_size(const MallocDesc* desc) {
     return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
 }
 
@@ -393,10 +389,8 @@
  * Return:
  *  Pointer to the end of (one byte past) the allocated block.
  */
-static inline void*
-mallocdesc_alloc_end(const MallocDesc* desc)
-{
-    return (char*)desc->ptr + mallocdesc_alloc_size(desc);
+static inline void* mallocdesc_alloc_end(const MallocDesc* desc) {
+    return static_cast<char*>(desc->ptr) + mallocdesc_alloc_size(desc);
 }
 
 /* Fires up an event in the emulator.
@@ -404,9 +398,7 @@
  *  code - Event code (one of the TRACE_DEV_XXX).
  *  val  - Event's value parameter.
  */
-static inline void
-notify_qemu(uint32_t code, uint32_t val)
-{
+static inline void notify_qemu(uint32_t code, uint32_t val) {
     if (NULL != qtrace) {
         *(volatile uint32_t*)((uint32_t)qtrace + ((code - 1024) << 2)) = val;
     }
@@ -417,9 +409,7 @@
  * Param:
  *  str - Zero-terminated string to print.
  */
-static void
-notify_qemu_string(const char* str)
-{
+static void notify_qemu_string(const char* str) {
     if (str != NULL) {
         notify_qemu(TRACE_DEV_REG_PRINT_USER_STR, (uint32_t)str);
     }
@@ -429,9 +419,7 @@
  * Param:
  *  pid - ID of the process that initialized libc.
  */
-static void
-notify_qemu_libc_initialized(uint32_t pid)
-{
+static void notify_qemu_libc_initialized(uint32_t pid) {
     notify_qemu(TRACE_DEV_REG_LIBC_INIT, pid);
 }
 
@@ -444,9 +432,7 @@
  *  the desc parameter passed to this routine has been zeroed out by the
  *  emulator.
  */
-static inline int
-notify_qemu_malloc(volatile MallocDesc* desc)
-{
+static inline int notify_qemu_malloc(volatile MallocDesc* desc) {
     desc->libc_pid = malloc_pid;
     desc->allocator_pid = getpid();
     desc->av_count = 0;
@@ -463,9 +449,7 @@
  * Return:
  *  Zero on success, or -1 on failure.
  */
-static inline int
-notify_qemu_free(void* ptr_to_free)
-{
+static inline int notify_qemu_free(void* ptr_to_free) {
     volatile MallocFree free_desc;
 
     free_desc.ptr = ptr_to_free;
@@ -489,9 +473,7 @@
  * Return:
  *  Zero on success, or -1 on failure.
  */
-static inline int
-query_qemu_malloc_info(void* ptr, MallocDesc* desc, uint32_t routine)
-{
+static inline int query_qemu_malloc_info(void* ptr, MallocDesc* desc, uint32_t routine) {
     volatile MallocDescQuery query;
 
     query.ptr = ptr;
@@ -511,9 +493,7 @@
  *  prio - Message priority (debug, info, or error)
  *  fmt + rest - Message format and parameters.
  */
-static void
-qemu_log(int prio, const char* fmt, ...)
-{
+static void qemu_log(int prio, const char* fmt, ...) {
     va_list ap;
     char buf[4096];
     const char* prefix;
@@ -555,9 +535,7 @@
  *  str_buf_size - Size of string's buffer.
  *  desc - Descriptor to dump.
  */
-static void
-dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc)
-{
+static void dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc) {
     if (str_buf_size) {
         snprintf(str, str_buf_size,
             "MDesc: %p: %X <-> %X [%u + %u + %u] by pid=%03u in libc_pid=%03u",
@@ -573,9 +551,7 @@
 /* Causes an access violation on allocation descriptor, and verifies that
  * violation has been detected by memory checker in the emulator.
  */
-static void
-test_access_violation(const MallocDesc* desc)
-{
+static void test_access_violation(const MallocDesc* desc) {
     MallocDesc desc_chk;
     char ch;
     volatile char* prefix = (volatile char*)desc->ptr;
@@ -617,9 +593,7 @@
  * Return:
  *  0 on success, or -1 on failure.
 */
-int
-malloc_debug_initialize(void)
-{
+int malloc_debug_initialize() {
     /* We will be using emulator's magic page to report memory allocation
      * activities. In essence, what magic page does, it translates writes to
      * the memory mapped spaces into writes to an I/O port that emulator
@@ -657,9 +631,7 @@
  * Return:
  *  0 on success, or -1 on failure.
 */
-int
-memcheck_initialize(int alignment, const char* memcheck_param)
-{
+int memcheck_initialize(int alignment, const char* memcheck_param) {
     malloc_alignment = alignment;
 
     /* Parse -memcheck parameter for the guest tracing flags. */
@@ -705,9 +677,7 @@
  * bytes (plus prefix, and suffix guards), and report allocation to the
  * emulator.
  */
-void*
-qemu_instrumented_malloc(size_t bytes)
-{
+void* qemu_instrumented_malloc(size_t bytes) {
     MallocDesc desc;
 
     /* Initialize block descriptor and allocate memory. Note that dlmalloc
@@ -742,9 +712,7 @@
  * Primary responsibility of this routine is to free requested memory, and
  * report free block to the emulator.
  */
-void
-qemu_instrumented_free(void* mem)
-{
+void qemu_instrumented_free(void* mem) {
     MallocDesc desc;
 
     if (mem == NULL) {
@@ -787,14 +755,7 @@
 /* This routine serves as entry point for 'calloc'.
  * This routine behaves similarly to qemu_instrumented_malloc.
  */
-void*
-qemu_instrumented_calloc(size_t n_elements, size_t elem_size)
-{
-    MallocDesc desc;
-    void* ret;
-    size_t total_size;
-    size_t total_elements;
-
+void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
     if (n_elements == 0 || elem_size == 0) {
         // Just let go zero bytes allocation.
         qemu_info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
@@ -808,6 +769,8 @@
         return NULL;
     }
 
+    MallocDesc desc;
+
     /* Calculating prefix size. The trick here is to make sure that
      * first element (returned to the caller) is properly aligned. */
     if (DEFAULT_PREFIX_SIZE >= elem_size) {
@@ -827,8 +790,8 @@
         desc.suffix_size = DEFAULT_SUFFIX_SIZE;
     }
     desc.requested_bytes = n_elements * elem_size;
-    total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
-    total_elements = total_size / elem_size;
+    size_t total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
+    size_t total_elements = total_size / elem_size;
     total_size %= elem_size;
     if (total_size != 0) {
         // Add extra to the suffix area.
@@ -864,9 +827,7 @@
  * allocation, but overall it doesn't seem to matter, as caller of realloc
  * should not expect that pointer returned after shrinking will remain the same.
  */
-void*
-qemu_instrumented_realloc(void* mem, size_t bytes)
-{
+void* qemu_instrumented_realloc(void* mem, size_t bytes) {
     MallocDesc new_desc;
     MallocDesc cur_desc;
     size_t to_copy;
@@ -936,7 +897,7 @@
     }
 
     // Register new block with emulator.
-    if(notify_qemu_malloc(&new_desc)) {
+    if (notify_qemu_malloc(&new_desc)) {
         log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) notify_malloc failed -> ",
                   malloc_pid, getpid(), mem, bytes);
         log_mdesc(error, &cur_desc, "                                                                <- ");
@@ -970,9 +931,7 @@
 /* This routine serves as entry point for 'memalign'.
  * This routine behaves similarly to qemu_instrumented_malloc.
  */
-void*
-qemu_instrumented_memalign(size_t alignment, size_t bytes)
-{
+void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
     MallocDesc desc;
 
     if (bytes == 0) {
diff --git a/libc/bionic/malloc_debug_stacktrace.c b/libc/bionic/malloc_debug_stacktrace.cpp
similarity index 86%
rename from libc/bionic/malloc_debug_stacktrace.c
rename to libc/bionic/malloc_debug_stacktrace.cpp
index c71b1c5..32b8ac0 100644
--- a/libc/bionic/malloc_debug_stacktrace.c
+++ b/libc/bionic/malloc_debug_stacktrace.cpp
@@ -32,11 +32,10 @@
 // stack trace functions
 // =============================================================================
 
-typedef struct
-{
+struct stack_crawl_state_t {
     size_t count;
     intptr_t* addrs;
-} stack_crawl_state_t;
+};
 
 
 /* depends how the system includes define this */
@@ -46,9 +45,8 @@
 typedef _Unwind_Context __unwind_context;
 #endif
 
-static _Unwind_Reason_Code trace_function(__unwind_context *context, void *arg)
-{
-    stack_crawl_state_t* state = (stack_crawl_state_t*)arg;
+static _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) {
+    stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg);
     if (state->count) {
         intptr_t ip = (intptr_t)_Unwind_GetIP(context);
         if (ip) {
@@ -65,12 +63,10 @@
     return _URC_END_OF_STACK;
 }
 
-__LIBC_HIDDEN__
-int get_backtrace(intptr_t* addrs, size_t max_entries)
-{
+__LIBC_HIDDEN__ int get_backtrace(intptr_t* addrs, size_t max_entries) {
     stack_crawl_state_t state;
     state.count = max_entries;
-    state.addrs = (intptr_t*)addrs;
-    _Unwind_Backtrace(trace_function, (void*)&state);
+    state.addrs = addrs;
+    _Unwind_Backtrace(trace_function, &state);
     return max_entries - state.count;
 }
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 652e522..a539b34 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -115,7 +115,7 @@
 }
 
 static stubs_state_t* stubs_state_alloc() {
-  stubs_state_t*  s = reinterpret_cast<stubs_state_t*>(calloc(1, sizeof(*s)));
+  stubs_state_t*  s = static_cast<stubs_state_t*>(calloc(1, sizeof(*s)));
   if (s != NULL) {
     s->group_.gr_mem = s->group_members_;
   }
@@ -123,7 +123,7 @@
 }
 
 static void stubs_state_free(void* ptr) {
-  stubs_state_t* state = reinterpret_cast<stubs_state_t*>(ptr);
+  stubs_state_t* state = static_cast<stubs_state_t*>(ptr);
   free(state);
 }
 
@@ -133,8 +133,7 @@
 
 static stubs_state_t* __stubs_state() {
   pthread_once(&stubs_once, __stubs_key_init);
-  stubs_state_t* s =
-      reinterpret_cast<stubs_state_t*>(pthread_getspecific(stubs_key));
+  stubs_state_t* s = static_cast<stubs_state_t*>(pthread_getspecific(stubs_key));
   if (s == NULL) {
     s = stubs_state_alloc();
     if (s == NULL) {
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 77c92be..7ab7205 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -51,14 +51,6 @@
 
 #if defined(__BIONIC_FORTIFY_INLINE)
 
-# if !defined(__clang__)
-/*
- * Clang doesn't have support for __builtin_va_arg_pack()
- * and __builtin_va_arg_pack_len()
- *
- * http://clang.llvm.org/docs/UsersManual.html#c_unimpl_gcc
- */
-
 extern void __creat_error()
     __attribute__((__error__ ("called with O_CREAT, but missing mode")));
 extern void __too_many_args_error()
@@ -109,7 +101,6 @@
     return __openat_real(dirfd, pathname, flags, __builtin_va_arg_pack());
 }
 
-#endif /* !defined(__clang__) */
 #endif /* defined(__BIONIC_FORTIFY_INLINE) */
 
 __END_DECLS
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 453cf0b..8b95663 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -500,13 +500,6 @@
         __builtin_object_size(dest, 0), format, ap);
 }
 
-
-# if !defined(__clang__)
-/*
- * Clang doesn't have support for __builtin_va_arg_pack()
- * http://clang.llvm.org/docs/UsersManual.html#c_unimpl_gcc
- */
-
 __BIONIC_FORTIFY_INLINE
 __attribute__((__format__ (printf, 3, 4)))
 __attribute__((__nonnull__ (3)))
@@ -525,8 +518,6 @@
         __builtin_object_size(dest, 0), format, __builtin_va_arg_pack());
 }
 
-# endif /* !defined(__clang__) */
-
 extern char *__fgets_real(char *, int, FILE *)
     __asm__(__USER_LABEL_PREFIX__ "fgets");
 extern void __fgets_too_big_error()
diff --git a/libc/include/string.h b/libc/include/string.h
index d1dc4c4..06e2284 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -147,7 +147,6 @@
     return __builtin___memset_chk(s, c, n, __builtin_object_size (s, 0));
 }
 
-#if !defined(__clang__)
 extern size_t __strlcpy_real(char *, const char *, size_t)
     __asm__(__USER_LABEL_PREFIX__ "strlcpy");
 extern void __strlcpy_error()
@@ -224,8 +223,6 @@
 
     return __strlen_chk(s, bos);
 }
-#endif  /* !defined(__clang__) */
-
 
 #endif /* defined(__BIONIC_FORTIFY_INLINE) */
 
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 987a5e3..ca81cb6 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -501,7 +501,7 @@
 #define  __BIONIC__   1
 #include <android/api-level.h>
 
-#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 && !defined(__clang__)
 #define __BIONIC_FORTIFY_INLINE \
     extern inline \
     __attribute__ ((always_inline)) \
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 48564cd..0568293 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -83,6 +83,7 @@
 #define __NR_msync                        (__NR_SYSCALL_BASE + 144)
 #define __NR_readv                        (__NR_SYSCALL_BASE + 145)
 #define __NR_writev                       (__NR_SYSCALL_BASE + 146)
+#define __NR_getsid                       (__NR_SYSCALL_BASE + 147)
 #define __NR_perf_event_open              (__NR_SYSCALL_BASE + 364)
 
 #ifdef __arm__
diff --git a/libc/include/termios.h b/libc/include/termios.h
index ad19089..0d44355 100644
--- a/libc/include/termios.h
+++ b/libc/include/termios.h
@@ -66,6 +66,11 @@
     return ioctl(fd, TCFLSH, (void *)(intptr_t)__queue);
 }
 
+static __inline__ int tcdrain(int fd)
+{
+    return ioctl(fd, TCSBRK, (void *)(intptr_t)1);
+}
+
 static __inline__ pid_t tcgetsid(int fd)
 {
     pid_t _pid;
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index d8263fe..a6a6dbf 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -60,6 +60,7 @@
 extern pid_t  getppid(void);
 extern pid_t  getpgrp(void);
 extern int    setpgrp(void);
+extern pid_t  getsid(pid_t);
 extern pid_t  setsid(void);
 
 extern int execv(const char *, char * const *);
@@ -192,7 +193,6 @@
 extern int   tcsetpgrp(int fd, pid_t _pid);
 
 #if 0 /* MISSING FROM BIONIC */
-extern pid_t  getsid(pid_t);
 extern int execvpe(const char *, char * const *, char * const *);
 extern int execlpe(const char *, const char *, ...);
 extern int getfsuid(uid_t);
diff --git a/libc/upstream-dlmalloc/README.txt b/libc/upstream-dlmalloc/README.txt
index bd5f3c6..485704b 100644
--- a/libc/upstream-dlmalloc/README.txt
+++ b/libc/upstream-dlmalloc/README.txt
@@ -3,7 +3,7 @@
 upstream and then pull down the new version of the file.
 
 This code is imported from: ftp://g.oswego.edu/pub/misc/
-It is currently version 2.8.5.
+It is currently version 2.8.6.
 
 Currently there are very minor modifications that are signified with:
 BEGIN android-changed: change description
diff --git a/libc/upstream-dlmalloc/malloc.c b/libc/upstream-dlmalloc/malloc.c
index 6b54937..d951841 100644
--- a/libc/upstream-dlmalloc/malloc.c
+++ b/libc/upstream-dlmalloc/malloc.c
@@ -4,8 +4,7 @@
   http://creativecommons.org/publicdomain/zero/1.0/ Send questions,
   comments, complaints, performance data, etc to dl@cs.oswego.edu
 
-* Version 2.8.5 Sun May 22 10:26:02 2011  Doug Lea  (dl at gee)
-
+* Version 2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
    Note: There may be an updated version of this malloc obtainable at
            ftp://gee.cs.oswego.edu/pub/misc/malloc.c
          Check before installing!
@@ -19,7 +18,7 @@
   compile-time and dynamic tuning options.
 
   For convenience, an include file for code using this malloc is at:
-     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.5.h
+     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h
   You don't really need this .h file unless you call functions not
   defined in your system include files.  The .h file contains only the
   excerpts from this file needed for using this malloc on ANSI C/C++
@@ -41,7 +40,7 @@
        than pointers, you can use a previous release of this malloc
        (e.g. 2.7.2) supporting these.)
 
-  Alignment:                                     8 bytes (default)
+  Alignment:                                     8 bytes (minimum)
        This suffices for nearly all current machines and C compilers.
        However, you can define MALLOC_ALIGNMENT to be wider than this
        if necessary (up to 128bytes), at the expense of using more space.
@@ -242,11 +241,11 @@
 DLMALLOC_EXPORT       default: extern
   Defines how public APIs are declared. If you want to export via a
   Windows DLL, you might define this as
-    #define DLMALLOC_EXPORT extern  __declspace(dllexport)
+    #define DLMALLOC_EXPORT extern  __declspec(dllexport)
   If you want a POSIX ELF shared object, you might use
     #define DLMALLOC_EXPORT extern __attribute__((visibility("default")))
 
-MALLOC_ALIGNMENT         default: (size_t)8
+MALLOC_ALIGNMENT         default: (size_t)(2 * sizeof(void *))
   Controls the minimum alignment for malloc'ed chunks.  It must be a
   power of two and at least 8, even on machines for which smaller
   alignments would suffice. It may be defined as larger than this
@@ -279,6 +278,12 @@
   uses plain mutexes. This is not required for malloc proper, but may
   be needed for layered allocators such as nedmalloc.
 
+LOCK_AT_FORK            default: not defined
+  If defined nonzero, performs pthread_atfork upon initialization
+  to initialize child lock while holding parent lock. The implementation
+  assumes that pthread locks (not custom locks) are being used. In other
+  cases, you may need to customize the implementation.
+
 FOOTERS                  default: 0
   If true, provide extra checking and dispatching by placing
   information in the footers of allocated chunks. This adds
@@ -518,7 +523,7 @@
 
 /* Version identifier to allow people to support multiple versions */
 #ifndef DLMALLOC_VERSION
-#define DLMALLOC_VERSION 20805
+#define DLMALLOC_VERSION 20806
 #endif /* DLMALLOC_VERSION */
 
 #ifndef DLMALLOC_EXPORT
@@ -610,7 +615,7 @@
 #endif  /* ONLY_MSPACES */
 #endif  /* MSPACES */
 #ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT ((size_t)8U)
+#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
 #endif  /* MALLOC_ALIGNMENT */
 #ifndef FOOTERS
 #define FOOTERS 0
@@ -1238,8 +1243,6 @@
 */
 DLMALLOC_EXPORT void  dlmalloc_stats(void);
 
-#endif /* ONLY_MSPACES */
-
 /*
   malloc_usable_size(void* p);
 
@@ -1254,7 +1257,11 @@
   p = malloc(n);
   assert(malloc_usable_size(p) >= 256);
 */
-size_t dlmalloc_usable_size(void*);
+/* BEGIN android-changed: added const */
+size_t dlmalloc_usable_size(const void*);
+/* END android-change */
+
+#endif /* ONLY_MSPACES */
 
 #if MSPACES
 
@@ -1387,9 +1394,7 @@
 /*
   malloc_usable_size(void* p) behaves the same as malloc_usable_size;
 */
-// BEGIN android-changed: added const
 DLMALLOC_EXPORT size_t mspace_usable_size(const void* mem);
-// END android-changed
 
 /*
   mspace_malloc_stats behaves as malloc_stats, but reports
@@ -1516,11 +1521,16 @@
 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
 #define interlockedexchange __sync_lock_test_and_set
 #endif /* Win32 */
+#else /* USE_LOCKS */
 #endif /* USE_LOCKS */
 
+#ifndef LOCK_AT_FORK
+#define LOCK_AT_FORK 0
+#endif
+
 /* Declarations for bit scanning on win32 */
 #if defined(_MSC_VER) && _MSC_VER>=1300
-#ifndef BitScanForward	/* Try to avoid pulling in WinNT.h */
+#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -1845,8 +1855,8 @@
 #define CLEAR_LOCK(sl)   x86_clear_lock(sl)
 
 #else /* Win32 MSC */
-#define CAS_LOCK(sl)     interlockedexchange(sl, 1)
-#define CLEAR_LOCK(sl)   interlockedexchange (sl, 0)
+#define CAS_LOCK(sl)     interlockedexchange(sl, (LONG)1)
+#define CLEAR_LOCK(sl)   interlockedexchange (sl, (LONG)0)
 
 #endif /* ... gcc spins locks ... */
 
@@ -1970,7 +1980,7 @@
 #define NEED_GLOBAL_LOCK_INIT
 
 static MLOCK_T malloc_global_mutex;
-static volatile long malloc_global_mutex_status;
+static volatile LONG malloc_global_mutex_status;
 
 /* Use spin loop to initialize global lock */
 static void init_malloc_global_mutex() {
@@ -1980,9 +1990,9 @@
       return;
     /* transition to < 0 while initializing, then to > 0) */
     if (stat == 0 &&
-        interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) {
+        interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) {
       InitializeCriticalSection(&malloc_global_mutex);
-      interlockedexchange(&malloc_global_mutex_status,1);
+      interlockedexchange(&malloc_global_mutex_status, (LONG)1);
       return;
     }
     SleepEx(0, FALSE);
@@ -2001,7 +2011,7 @@
 /* Cope with old-style linux recursive lock initialization by adding */
 /* skipped internal declaration from pthread.h */
 extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
-					   int __kind));
+                                              int __kind));
 #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
 #define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
 #endif /* USE_RECURSIVE_LOCKS ... */
@@ -2817,7 +2827,9 @@
 #define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
 
 /* addressing by index. See above about smallbin repositioning */
-#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
+/* BEGIN android-changed: strict aliasing change: char* cast to void* */
+#define smallbin_at(M, i)   ((sbinptr)((void*)&((M)->smallbins[(i)<<1])))
+/* END android-changed */
 #define treebin_at(M,i)     (&((M)->treebins[i]))
 
 /* assign tree index for size S to variable I. Use x86 asm if possible  */
@@ -3079,8 +3091,17 @@
 
 /* ---------------------------- setting mparams -------------------------- */
 
+#if LOCK_AT_FORK
+static void pre_fork(void)         { ACQUIRE_LOCK(&(gm)->mutex); }
+static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); }
+static void post_fork_child(void)  { INITIAL_LOCK(&(gm)->mutex); }
+#endif /* LOCK_AT_FORK */
+
 /* Initialize mparams */
 static int init_mparams(void) {
+  /* BEGIN android-added: move pthread_atfork outside of lock */
+  int first_run = 0;
+  /* END android-added */
 #ifdef NEED_GLOBAL_LOCK_INIT
   if (malloc_global_mutex_status <= 0)
     init_malloc_global_mutex();
@@ -3091,6 +3112,9 @@
     size_t magic;
     size_t psize;
     size_t gsize;
+    /* BEGIN android-added: move pthread_atfork outside of lock */
+    first_run = 1;
+    /* END android-added */
 
 #ifndef WIN32
     psize = malloc_getpagesize;
@@ -3120,7 +3144,6 @@
         ((gsize            & (gsize-SIZE_T_ONE))            != 0) ||
         ((psize            & (psize-SIZE_T_ONE))            != 0))
       ABORT;
-
     mparams.granularity = gsize;
     mparams.page_size = psize;
     mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
@@ -3136,6 +3159,11 @@
     gm->mflags = mparams.default_mflags;
     (void)INITIAL_LOCK(&gm->mutex);
 #endif
+    /* BEGIN android-removed: move pthread_atfork outside of lock */
+#if 0 && LOCK_AT_FORK
+    pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
+#endif
+    /* END android-removed */
 
     {
 #if USE_DEV_RANDOM
@@ -3150,11 +3178,11 @@
       else
 #endif /* USE_DEV_RANDOM */
 #ifdef WIN32
-        magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
+      magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
 #elif defined(LACKS_TIME_H)
       magic = (size_t)&magic ^ (size_t)0x55555555U;
 #else
-        magic = (size_t)(time(0) ^ (size_t)0x55555555U);
+      magic = (size_t)(time(0) ^ (size_t)0x55555555U);
 #endif
       magic |= (size_t)8U;    /* ensure nonzero */
       magic &= ~(size_t)7U;   /* improve chances of fault for bad values */
@@ -3164,6 +3192,13 @@
   }
 
   RELEASE_MALLOC_GLOBAL_LOCK();
+  /* BEGIN android-added: move pthread_atfork outside of lock */
+#if LOCK_AT_FORK
+  if (first_run != 0) {
+    pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
+  }
+#endif
+  /* END android-added */
   return 1;
 }
 
@@ -3836,9 +3871,7 @@
 /* Realloc using mmap */
 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
   size_t oldsize = chunksize(oldp);
-  // BEGIN android-changed: avoid self assignment
   (void)flags; /* placate people compiling -Wunused */
-  // END android-changed
   if (is_small(nb)) /* Can't shrink mmap regions below small size */
     return 0;
   /* Keep old chunk if big enough but not too big */
@@ -4031,12 +4064,20 @@
   }
 
   asize = granularity_align(nb + SYS_ALLOC_PADDING);
-  if (asize <= nb)
+  if (asize <= nb) {
+    /* BEGIN android-added: set errno */
+    MALLOC_FAILURE_ACTION;
+    /* END android-added */
     return 0; /* wraparound */
+  }
   if (m->footprint_limit != 0) {
     size_t fp = m->footprint + asize;
-    if (fp <= m->footprint || fp > m->footprint_limit)
+    if (fp <= m->footprint || fp > m->footprint_limit) {
+      /* BEGIN android-added: set errno */
+      MALLOC_FAILURE_ACTION;
+      /* END android-added */
       return 0;
+    }
   }
 
   /*
@@ -4063,6 +4104,7 @@
 
   if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
     char* br = CMFAIL;
+    size_t ssize = asize; /* sbrk call size */
     msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
     ACQUIRE_MALLOC_GLOBAL_LOCK();
 
@@ -4072,39 +4114,39 @@
         size_t fp;
         /* Adjust to end on a page boundary */
         if (!is_page_aligned(base))
-          asize += (page_align((size_t)base) - (size_t)base);
-        fp = m->footprint + asize; /* recheck limits */
-        if (asize > nb && asize < HALF_MAX_SIZE_T &&
+          ssize += (page_align((size_t)base) - (size_t)base);
+        fp = m->footprint + ssize; /* recheck limits */
+        if (ssize > nb && ssize < HALF_MAX_SIZE_T &&
             (m->footprint_limit == 0 ||
              (fp > m->footprint && fp <= m->footprint_limit)) &&
-            (br = (char*)(CALL_MORECORE(asize))) == base) {
+            (br = (char*)(CALL_MORECORE(ssize))) == base) {
           tbase = base;
-          tsize = asize;
+          tsize = ssize;
         }
       }
     }
     else {
       /* Subtract out existing available top space from MORECORE request. */
-      asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
+      ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
       /* Use mem here only if it did continuously extend old space */
-      if (asize < HALF_MAX_SIZE_T &&
-          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
+      if (ssize < HALF_MAX_SIZE_T &&
+          (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) {
         tbase = br;
-        tsize = asize;
+        tsize = ssize;
       }
     }
 
     if (tbase == CMFAIL) {    /* Cope with partial failure */
       if (br != CMFAIL) {    /* Try to use/extend the space we did get */
-        if (asize < HALF_MAX_SIZE_T &&
-            asize < nb + SYS_ALLOC_PADDING) {
-          size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize);
+        if (ssize < HALF_MAX_SIZE_T &&
+            ssize < nb + SYS_ALLOC_PADDING) {
+          size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize);
           if (esize < HALF_MAX_SIZE_T) {
             char* end = (char*)CALL_MORECORE(esize);
             if (end != CMFAIL)
-              asize += esize;
+              ssize += esize;
             else {            /* Can't use; try to release */
-              (void) CALL_MORECORE(-asize);
+              (void) CALL_MORECORE(-ssize);
               br = CMFAIL;
             }
           }
@@ -4112,7 +4154,7 @@
       }
       if (br != CMFAIL) {    /* Use the space we did get */
         tbase = br;
-        tsize = asize;
+        tsize = ssize;
       }
       else
         disable_contiguous(m); /* Don't try contiguous path in the future */
@@ -4267,10 +4309,8 @@
     sp = next;
   }
   /* Reset check counter */
-  // BEGIN android-changed: signed/unsigned mismatches
   m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)?
-      (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
-  // END android-changed
+                       (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
   return released;
 }
 
@@ -4293,9 +4333,7 @@
               sp->size >= extra &&
               !has_segment_link(m, sp)) { /* can't shrink if pinned */
             size_t newsize = sp->size - extra;
-            // BEGIN android-changed
             (void)newsize; /* placate people compiling -Wunused-variable */
-            // END android-changed
             /* Prefer mremap, fall back to munmap */
             if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
                 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
@@ -4866,9 +4904,7 @@
     }
   }
   else {
-    // BEGIN android-changed: s/oldmem/chunk2mem(p)/
     USAGE_ERROR_ACTION(m, chunk2mem(p));
-    // END android-changed
   }
   return newp;
 }
@@ -5147,14 +5183,10 @@
         else {
           used = 0;
           if (is_small(sz)) {     /* offset by possible bookkeeping */
-            // BEGIN android-changed: added struct
             start = (void*)((char*)q + sizeof(struct malloc_chunk));
-            // END android-changed
           }
           else {
-            // BEGIN android-changed: added struct
             start = (void*)((char*)q + sizeof(struct malloc_tree_chunk));
-            // END android-changed
           }
         }
         if (start < (void*)next)  /* skip if all space is bookkeeping */
@@ -5264,7 +5296,7 @@
     size_t r = alignment % sizeof(void*);
     if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0)
       return EINVAL;
-    else if (bytes >= MAX_REQUEST - alignment) {
+    else if (bytes <= MAX_REQUEST - alignment) {
       if (alignment <  MIN_CHUNK_SIZE)
         alignment = MIN_CHUNK_SIZE;
       mem = internal_memalign(gm, alignment, bytes);
@@ -5371,7 +5403,9 @@
   return change_mparam(param_number, value);
 }
 
-size_t dlmalloc_usable_size(void* mem) {
+/* BEGIN android-changed: added const */
+size_t dlmalloc_usable_size(const void* mem) {
+/* END android-change */
   if (mem != 0) {
     mchunkptr p = mem2chunk(mem);
     if (is_inuse(p))
@@ -5446,12 +5480,14 @@
   int ret = 0;
   mstate ms = (mstate)msp;
   if (!PREACTION(ms)) {
-    if (!use_mmap(ms))
+    if (!use_mmap(ms)) {
       ret = 1;
-    if (!enable)
+    }
+    if (!enable) {
       enable_mmap(ms);
-    else
+    } else {
       disable_mmap(ms);
+    }
     POSTACTION(ms);
   }
   return ret;
@@ -5465,11 +5501,9 @@
     (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */
     while (sp != 0) {
       char* base = sp->base;
-      // BEGIN android-changed
-      (void)base; /* placate people compiling -Wunused-variable */
-      // END android-changed
       size_t size = sp->size;
       flag_t flag = sp->sflags;
+      (void)base; /* placate people compiling -Wunused-variable */
       sp = sp->next;
       if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
           CALL_MUNMAP(base, size) == 0)
@@ -5606,7 +5640,7 @@
     mchunkptr p  = mem2chunk(mem);
 #if FOOTERS
     mstate fm = get_mstate_for(p);
-    msp = msp; /* placate people compiling -Wunused */
+    (void)msp; /* placate people compiling -Wunused */
 #else /* FOOTERS */
     mstate fm = (mstate)msp;
 #endif /* FOOTERS */
@@ -5780,7 +5814,7 @@
       mstate m = (mstate)msp;
 #else /* FOOTERS */
       mstate m = get_mstate_for(oldp);
-      msp = msp; /* placate people compiling -Wunused */
+      (void)msp; /* placate people compiling -Wunused */
       if (!ok_magic(m)) {
         USAGE_ERROR_ACTION(m, oldmem);
         return 0;
@@ -5947,9 +5981,7 @@
 }
 #endif /* NO_MALLINFO */
 
-// BEGIN android-changed: added const
 size_t mspace_usable_size(const void* mem) {
-// END android-changed
   if (mem != 0) {
     mchunkptr p = mem2chunk(mem);
     if (is_inuse(p))
@@ -6059,6 +6091,12 @@
 
 /* -----------------------------------------------------------------------
 History:
+    v2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
+      * fix bad comparison in dlposix_memalign
+      * don't reuse adjusted asize in sys_alloc
+      * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion
+      * reduce compiler warnings -- thanks to all who reported/suggested these
+
     v2.8.5 Sun May 22 10:26:02 2011  Doug Lea  (dl at gee)
       * Always perform unlink checks unless INSECURE
       * Add posix_memalign.
@@ -6269,4 +6307,3 @@
          structure of old version,  but most details differ.)
 
 */
-
diff --git a/libc/upstream-dlmalloc/malloc.h b/libc/upstream-dlmalloc/malloc.h
index 7ede698..e52c9e5 100644
--- a/libc/upstream-dlmalloc/malloc.h
+++ b/libc/upstream-dlmalloc/malloc.h
@@ -518,7 +518,7 @@
   p = malloc(n);
   assert(malloc_usable_size(p) >= 256);
 */
-size_t dlmalloc_usable_size(void*);
+size_t dlmalloc_usable_size(const void*);
 
 #if MSPACES
 
@@ -601,9 +601,7 @@
 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
                                    size_t sizes[], void* chunks[]);
 size_t mspace_bulk_free(mspace msp, void**, size_t n_elements);
-// BEGIN android-changed: added const
 size_t mspace_usable_size(const void* mem);
-// END android-changed
 void mspace_malloc_stats(mspace msp);
 int mspace_trim(mspace msp, size_t pad);
 size_t mspace_footprint(mspace msp);
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 09d9dd8..46d1335 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -162,12 +162,12 @@
 static char tmp_err_buf[768];
 static char __linker_dl_err_buf[768];
 #define BASENAME(s) (strrchr(s, '/') != NULL ? strrchr(s, '/') + 1 : s)
-#define DL_ERR(fmt, x...)                                                     \
-    do {                                                                      \
-        format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf),       \
-            "(%s:%d, pid %d) %s: " fmt,                                       \
-            BASENAME(__FILE__), __LINE__, pid, __func__, ##x);                \
-        ERROR(fmt "\n", ##x);                                                 \
+#define DL_ERR(fmt, x...) \
+    do { \
+        format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \
+                      "%s(%s:%d): " fmt, \
+                      __FUNCTION__, BASENAME(__FILE__), __LINE__, ##x); \
+        ERROR(fmt "\n", ##x); \
     } while(0)
 
 const char *linker_get_error(void)
@@ -434,26 +434,28 @@
 
 static Elf32_Sym *
 soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset,
-                 soinfo *needed[])
+                 soinfo *needed[], bool ignore_local)
 {
     unsigned elf_hash = elfhash(name);
-    Elf32_Sym *s;
+    Elf32_Sym *s = NULL;
     soinfo *lsi = si;
     int i;
 
-    /* Look for symbols in the local scope (the object who is
-     * searching). This happens with C++ templates on i386 for some
-     * reason.
-     *
-     * Notes on weak symbols:
-     * The ELF specs are ambiguous about treatment of weak definitions in
-     * dynamic linking.  Some systems return the first definition found
-     * and some the first non-weak definition.   This is system dependent.
-     * Here we return the first definition found for simplicity.  */
+    if (!ignore_local) {
+        /* Look for symbols in the local scope (the object who is
+         * searching). This happens with C++ templates on i386 for some
+         * reason.
+         *
+         * Notes on weak symbols:
+         * The ELF specs are ambiguous about treatment of weak definitions in
+         * dynamic linking.  Some systems return the first definition found
+         * and some the first non-weak definition.   This is system dependent.
+         * Here we return the first definition found for simplicity.  */
 
-    s = soinfo_elf_lookup(si, elf_hash, name);
-    if(s != NULL)
-        goto done;
+        s = soinfo_elf_lookup(si, elf_hash, name);
+        if(s != NULL)
+            goto done;
+    }
 
     /* Next, look for it in the preloads list */
     for(i = 0; preloads[i] != NULL; i++) {
@@ -684,6 +686,7 @@
     if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
     if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
     if (hdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
+    if (hdr->e_type != ET_DYN) return -1;
 
     /* TODO: Should we verify anything else in the header? */
 #ifdef ANDROID_ARM_LINKER
@@ -959,13 +962,17 @@
         }
         if(sym != 0) {
             sym_name = (char *)(strtab + symtab[sym].st_name);
-            s = soinfo_do_lookup(si, sym_name, &offset, needed);
+            bool ignore_local = false;
+#if defined(ANDROID_ARM_LINKER)
+            ignore_local = (type == R_ARM_COPY);
+#endif
+            s = soinfo_do_lookup(si, sym_name, &offset, needed, ignore_local);
             if(s == NULL) {
                 /* We only allow an undefined symbol if this is a weak
                    reference..   */
                 s = &symtab[sym];
                 if (ELF32_ST_BIND(s->st_info) != STB_WEAK) {
-                    DL_ERR("cannot locate \"%s\"...", sym_name);
+                    DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, si->name);
                     return -1;
                 }
 
@@ -1139,10 +1146,29 @@
 
 #ifdef ANDROID_ARM_LINKER
         case R_ARM_COPY:
+            if ((si->flags & FLAG_EXE) == 0) {
+                /*
+                 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+                 *
+                 * Section 4.7.1.10 "Dynamic relocations"
+                 * R_ARM_COPY may only appear in executable objects where e_type is
+                 * set to ET_EXEC.
+                 *
+                 * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+                 * We should explicitly disallow ET_DYN executables from having
+                 * R_ARM_COPY relocations.
+                 */
+                DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
+                return -1;
+            }
             count_relocation(kRelocCopy);
             MARK(rel->r_offset);
             TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid,
                        reloc, s->st_size, sym_addr, sym_name);
+            if (reloc == sym_addr) {
+                DL_ERR("Internal linker error detected. reloc == symaddr");
+                return -1;
+            }
             memcpy((void*)reloc, (void*)sym_addr, s->st_size);
             break;
 #endif /* ANDROID_ARM_LINKER */
@@ -1201,7 +1227,7 @@
 
         /* This is an undefined reference... try to locate it */
         sym_name = si->strtab + sym->st_name;
-        s = soinfo_do_lookup(si, sym_name, &base, needed);
+        s = soinfo_do_lookup(si, sym_name, &base, needed, false);
         if (s == NULL) {
             /* We only allow an undefined symbol if this is a weak
                reference..   */
@@ -1804,7 +1830,7 @@
         exit(-1);
     }
 
-        /* bootstrap the link map, the main exe always needs to be first */
+    /* bootstrap the link map, the main exe always needs to be first */
     si->flags |= FLAG_EXE;
     link_map* map = &(si->linkmap);
 
@@ -1839,7 +1865,7 @@
                                    &linker_soinfo.dynamic, NULL);
     insert_soinfo_into_debug_map(&linker_soinfo);
 
-        /* extract information passed from the kernel */
+    /* extract information passed from the kernel */
     while(vecs[0] != 0){
         switch(vecs[0]){
         case AT_PHDR:
diff --git a/tests/Android.mk b/tests/Android.mk
index d50d4d7..ba1112e 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -12,7 +12,9 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-# Copyright The Android Open Source Project
+#
+
+ifneq ($(BUILD_TINY_ANDROID), true)
 
 LOCAL_PATH := $(call my-dir)
 
@@ -35,3 +37,5 @@
 LOCAL_MODULE := bionic-unit-tests-glibc
 LOCAL_SRC_FILES := $(test_src_files)
 include $(BUILD_HOST_NATIVE_TEST)
+
+endif # !BUILD_TINY_ANDROID