From db492b3ca753c4ef688d0daf648294de0c89145e Mon Sep 17 00:00:00 2001
From: Elliott Hughes <enh@google.com>
Date: Thu, 3 Jan 2013 15:44:03 -0800
Subject: [PATCH] Fix debug malloc.

...which has been broken since the linker data structures went read-only.

Bug: 7941716
Change-Id: If28f6bac0fcb13e371e4d85b064544f561c8d692
---
 libc/bionic/malloc_debug_common.cpp | 18 ++++++++----------
 linker/linker.cpp                   | 12 ++++++------
 2 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 0594c0aa8..624a40e26 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -242,7 +242,7 @@ extern "C" void* memalign(size_t alignment, size_t bytes) {
     return __libc_malloc_dispatch->memalign(alignment, bytes);
 }
 
-/* We implement malloc debugging only in libc.so, so code bellow
+/* We implement malloc debugging only in libc.so, so code below
  * must be excluded if we compile this file for static libc.a
  */
 #ifndef LIBC_STATIC
@@ -280,13 +280,10 @@ extern char* __progname;
  */
 static void* libc_malloc_impl_handle = NULL;
 
-/* Make sure we have MALLOC_ALIGNMENT that matches the one that is
- * used in dlmalloc. Emulator's memchecker needs this value to properly
- * align its guarding zones.
- */
+// This must match the alignment used by dlmalloc.
 #ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT ((size_t)8U)
-#endif  /* MALLOC_ALIGNMENT */
+#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
+#endif
 
 /* This variable is set to the value of property libc.debug.malloc.backlog,
  * when the value of libc.debug.malloc = 10.  It determines the size of the
@@ -449,6 +446,7 @@ static void malloc_init_impl() {
             dlclose(libc_malloc_impl_handle);
             return;
         }
+
         if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) {
             dlclose(libc_malloc_impl_handle);
             return;
@@ -513,17 +511,17 @@ 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
 }
 
 extern "C" void malloc_debug_fini() {
-  /* We need to finalize malloc iff we implement here custom
+    /* 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/linker/linker.cpp b/linker/linker.cpp
index 6a2a958ec..09f479fbb 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1366,24 +1366,24 @@ void soinfo::CallArray(const char* array_name UNUSED, unsigned* array, int count
     TRACE("[ Looking at %s[%d] *%p == 0x%08x ]\n", array_name, n, array, *array);
     void (*func)() = (void (*)()) *array;
     array += step;
-    if (((int) func == 0) || ((int) func == -1)) {
-      continue;
-    }
-    TRACE("[ Calling func @ %p ]\n", func);
-    func();
+    CallFunction("function", func);
   }
 
   TRACE("[ Done calling %s for '%s' ]\n", array_name, name);
 }
 
 void soinfo::CallFunction(const char* function_name UNUSED, void (*function)()) {
-  if (function == NULL) {
+  if (function == NULL || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
     return;
   }
 
   TRACE("[ Calling %s @ %p for '%s' ]\n", function_name, function, name);
   function();
   TRACE("[ Done calling %s for '%s' ]\n", function_name, name);
+
+  // The function may have called dlopen(3) or dlclose(3), so we need to ensure our data structures
+  // are still writable. This happens with our debug malloc (see http://b/7941716).
+  set_soinfo_pool_protection(PROT_READ | PROT_WRITE);
 }
 
 void soinfo::CallPreInitConstructors() {