Fix debug malloc.

Previously the dynamically-loaded part of the debug malloc implementation
wanted to access hidden symbols in libc itself.

Bug: 15426546
Change-Id: I6a366ef626854d1af1d705ca24842817b1c02a19
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index 2590ce7..0575595 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -51,10 +51,6 @@
 #include "malloc_debug_common.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
-/* libc.debug.malloc.backlog */
-extern unsigned int g_malloc_debug_backlog;
-extern int g_malloc_debug_level;
-
 #define MAX_BACKTRACE_DEPTH 16
 #define ALLOCATION_TAG      0x1ee7d00d
 #define BACKLOG_TAG         0xbabecafe
@@ -120,6 +116,12 @@
 static hdr_t* backlog_head;
 static pthread_mutex_t backlog_lock = PTHREAD_MUTEX_INITIALIZER;
 
+// This variable is set to the value of property libc.debug.malloc.backlog.
+// It determines the size of the backlog we use to detect multiple frees.
+static unsigned g_malloc_debug_backlog = 100;
+
+__LIBC_HIDDEN__ HashTable* g_hash_table;
+
 static inline void init_front_guard(hdr_t* hdr) {
     memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
 }
@@ -508,11 +510,6 @@
 }
 
 static void ReportMemoryLeaks() {
-  // We only track leaks at level 10.
-  if (g_malloc_debug_level != 10) {
-    return;
-  }
-
   // Use /proc/self/exe link to obtain the program name for logging
   // purposes. If it's not available, we set it to "<unknown>".
   char exe[PATH_MAX];
@@ -546,12 +543,23 @@
   }
 }
 
-extern "C" int malloc_debug_initialize() {
+extern "C" bool malloc_debug_initialize(HashTable* hash_table) {
+  g_hash_table = hash_table;
+
+  char debug_backlog[PROP_VALUE_MAX];
+  if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
+    g_malloc_debug_backlog = atoi(debug_backlog);
+    info_log("%s: setting backlog length to %d\n", getprogname(), g_malloc_debug_backlog);
+  }
+
   backtrace_startup();
-  return 0;
+  return true;
 }
 
-extern "C" void malloc_debug_finalize() {
-  ReportMemoryLeaks();
+extern "C" void malloc_debug_finalize(int malloc_debug_level) {
+  // We only track leaks at level 10.
+  if (malloc_debug_level == 10) {
+    ReportMemoryLeaks();
+  }
   backtrace_shutdown();
 }
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index db3f995..19524bb 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -48,13 +48,48 @@
 
 #include "private/ScopedPthreadMutexLocker.h"
 
-/*
- * In a VM process, this is set to 1 after fork()ing out of zygote.
- */
+// In a VM process, this is set to 1 after fork()ing out of zygote.
 int gMallocLeakZygoteChild = 0;
 
-__LIBC_HIDDEN__ pthread_mutex_t g_allocations_mutex = PTHREAD_MUTEX_INITIALIZER;
-__LIBC_HIDDEN__ HashTable g_hash_table;
+static HashTable g_hash_table;
+
+// Support for malloc debugging.
+// Table for dispatching malloc calls, initialized with default dispatchers.
+static const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) = {
+  Malloc(malloc), Malloc(free), Malloc(calloc), Malloc(realloc), Malloc(memalign), Malloc(malloc_usable_size),
+};
+
+// Selector of dispatch table to use for dispatching malloc calls.
+static const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
+
+// Handle to shared library where actual memory allocation is implemented.
+// This library is loaded and memory allocation calls are redirected there
+// when libc.debug.malloc environment variable contains value other than
+// zero:
+// 1  - For memory leak detections.
+// 5  - For filling allocated / freed memory with patterns defined by
+//      CHK_SENTINEL_VALUE, and CHK_FILL_FREE macros.
+// 10 - For adding pre-, and post- allocation stubs in order to detect
+//      buffer overruns.
+// Note that emulator's memory allocation instrumentation is not controlled by
+// libc.debug.malloc value, but rather by emulator, started with -memcheck
+// option. Note also, that if emulator has started with -memcheck option,
+// emulator's instrumented memory allocation will take over value saved in
+// libc.debug.malloc. In other words, if emulator has started with -memcheck
+// option, libc.debug.malloc value is ignored.
+// Actual functionality for debug levels 1-10 is implemented in
+// libc_malloc_debug_leak.so, while functionality for emulator's instrumented
+// allocations is implemented in libc_malloc_debug_qemu.so and can be run inside
+// the emulator only.
+#if !defined(LIBC_STATIC)
+static void* libc_malloc_impl_handle = NULL;
+#endif
+
+
+// The value of libc.debug.malloc.
+#if !defined(LIBC_STATIC)
+static int g_malloc_debug_level = 0;
+#endif
 
 // =============================================================================
 // output functions
@@ -123,7 +158,7 @@
     }
     *totalMemory = 0;
 
-    ScopedPthreadMutexLocker locker(&g_allocations_mutex);
+    ScopedPthreadMutexLocker locker(&g_hash_table.lock);
 
     if (g_hash_table.count == 0) {
         *info = NULL;
@@ -204,17 +239,6 @@
     return Malloc(posix_memalign)(memptr, alignment, size);
 }
 
-// Support for malloc debugging.
-// Table for dispatching malloc calls, initialized with default dispatchers.
-extern const MallocDebug __libc_malloc_default_dispatch;
-const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) =
-{
-    Malloc(malloc), Malloc(free), Malloc(calloc), Malloc(realloc), Malloc(memalign), Malloc(malloc_usable_size),
-};
-
-/* Selector of dispatch table to use for dispatching malloc calls. */
-const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
-
 extern "C" void* malloc(size_t bytes) {
     return __libc_malloc_dispatch->malloc(bytes);
 }
@@ -248,59 +272,19 @@
 #include <stdio.h>
 #include "private/libc_logging.h"
 
-/* Table for dispatching malloc calls, depending on environment. */
-static MallocDebug g_malloc_dispatch_table __attribute__((aligned(32))) = {
-    Malloc(malloc), Malloc(free), Malloc(calloc), Malloc(realloc), Malloc(memalign), Malloc(malloc_usable_size)
-};
-
-extern const char* __progname;
-
-/* Handle to shared library where actual memory allocation is implemented.
- * This library is loaded and memory allocation calls are redirected there
- * when libc.debug.malloc environment variable contains value other than
- * zero:
- * 1  - For memory leak detections.
- * 5  - For filling allocated / freed memory with patterns defined by
- *      CHK_SENTINEL_VALUE, and CHK_FILL_FREE macros.
- * 10 - For adding pre-, and post- allocation stubs in order to detect
- *      buffer overruns.
- * Note that emulator's memory allocation instrumentation is not controlled by
- * libc.debug.malloc value, but rather by emulator, started with -memcheck
- * option. Note also, that if emulator has started with -memcheck option,
- * emulator's instrumented memory allocation will take over value saved in
- * libc.debug.malloc. In other words, if emulator has started with -memcheck
- * option, libc.debug.malloc value is ignored.
- * Actual functionality for debug levels 1-10 is implemented in
- * libc_malloc_debug_leak.so, while functionality for emultor's instrumented
- * allocations is implemented in libc_malloc_debug_qemu.so and can be run inside
- * the emulator only.
- */
-static void* libc_malloc_impl_handle = NULL;
-
-/* 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
- * backlog we use to detect multiple frees.  If the property is not set, the
- * backlog length defaults to BACKLOG_DEFAULT_LEN.
- */
-__LIBC_HIDDEN__ unsigned int g_malloc_debug_backlog;
-#define BACKLOG_DEFAULT_LEN 100
-
-/* The value of libc.debug.malloc. */
-__LIBC_HIDDEN__ int g_malloc_debug_level;
-
 template<typename FunctionType>
 static void InitMallocFunction(void* malloc_impl_handler, FunctionType* func, const char* prefix, const char* suffix) {
     char symbol[128];
     snprintf(symbol, sizeof(symbol), "%s_%s", prefix, suffix);
     *func = reinterpret_cast<FunctionType>(dlsym(malloc_impl_handler, symbol));
     if (*func == NULL) {
-        error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
+        error_log("%s: dlsym(\"%s\") failed", getprogname(), symbol);
     }
 }
 
 static void InitMalloc(void* malloc_impl_handler, MallocDebug* table, const char* prefix) {
     __libc_format_log(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
-                      __progname, g_malloc_debug_level, prefix);
+                      getprogname(), g_malloc_debug_level, prefix);
 
     InitMallocFunction<MallocDebugMalloc>(malloc_impl_handler, &table->malloc, prefix, "malloc");
     InitMallocFunction<MallocDebugFree>(malloc_impl_handler, &table->free, prefix, "free");
@@ -349,14 +333,14 @@
      * then exit.
      */
     if (__system_property_get("libc.debug.malloc.program", debug_program)) {
-        if (!strstr(__progname, debug_program)) {
+        if (!strstr(getprogname(), debug_program)) {
             return;
         }
     }
 
     // mksh is way too leaky. http://b/7291287.
     if (g_malloc_debug_level >= 10) {
-        if (strcmp(__progname, "sh") == 0 || strcmp(__progname, "/system/bin/sh") == 0) {
+        if (strcmp(getprogname(), "sh") == 0 || strcmp(getprogname(), "/system/bin/sh") == 0) {
             return;
         }
     }
@@ -365,35 +349,26 @@
     switch (g_malloc_debug_level) {
         case 1:
         case 5:
-        case 10: {
-            char debug_backlog[PROP_VALUE_MAX];
-            if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
-                g_malloc_debug_backlog = atoi(debug_backlog);
-                info_log("%s: setting backlog length to %d\n", __progname, g_malloc_debug_backlog);
-            }
-            if (g_malloc_debug_backlog == 0) {
-                g_malloc_debug_backlog = BACKLOG_DEFAULT_LEN;
-            }
+        case 10:
             so_name = "libc_malloc_debug_leak.so";
             break;
-        }
         case 20:
             // Quick check: debug level 20 can only be handled in emulator.
             if (!qemu_running) {
                 error_log("%s: Debug level %d can only be set in emulator\n",
-                          __progname, g_malloc_debug_level);
+                          getprogname(), g_malloc_debug_level);
                 return;
             }
             // Make sure that memory checking has been enabled in emulator.
             if (!memcheck_enabled) {
                 error_log("%s: Memory checking is not enabled in the emulator\n",
-                          __progname);
+                          getprogname());
                 return;
             }
             so_name = "libc_malloc_debug_qemu.so";
             break;
         default:
-            error_log("%s: Debug level %d is unknown\n", __progname, g_malloc_debug_level);
+            error_log("%s: Debug level %d is unknown\n", getprogname(), g_malloc_debug_level);
             return;
     }
 
@@ -401,7 +376,7 @@
     void* malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
     if (malloc_impl_handle == NULL) {
         error_log("%s: Missing module %s required for malloc debug level %d: %s",
-                  __progname, so_name, g_malloc_debug_level, dlerror());
+                  getprogname(), so_name, g_malloc_debug_level, dlerror());
         return;
     }
 
@@ -410,11 +385,11 @@
                                                                       "malloc_debug_initialize"));
     if (malloc_debug_initialize == NULL) {
         error_log("%s: Initialization routine is not found in %s\n",
-                  __progname, so_name);
+                  getprogname(), so_name);
         dlclose(malloc_impl_handle);
         return;
     }
-    if (malloc_debug_initialize() == -1) {
+    if (malloc_debug_initialize(&g_hash_table) == -1) {
         dlclose(malloc_impl_handle);
         return;
     }
@@ -427,7 +402,7 @@
                                                  "memcheck_initialize"));
         if (memcheck_initialize == NULL) {
             error_log("%s: memcheck_initialize routine is not found in %s\n",
-                      __progname, so_name);
+                      getprogname(), so_name);
             dlclose(malloc_impl_handle);
             return;
         }
@@ -438,44 +413,52 @@
         }
     }
 
-
     // Initialize malloc dispatch table with appropriate routines.
+    static MallocDebug malloc_dispatch_table __attribute__((aligned(32))) = {
+        Malloc(malloc),
+        Malloc(free),
+        Malloc(calloc),
+        Malloc(realloc),
+        Malloc(memalign),
+        Malloc(malloc_usable_size)
+    };
+
     switch (g_malloc_debug_level) {
         case 1:
-            InitMalloc(malloc_impl_handle, &g_malloc_dispatch_table, "leak");
+            InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "leak");
             break;
         case 5:
-            InitMalloc(malloc_impl_handle, &g_malloc_dispatch_table, "fill");
+            InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "fill");
             break;
         case 10:
-            InitMalloc(malloc_impl_handle, &g_malloc_dispatch_table, "chk");
+            InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "chk");
             break;
         case 20:
-            InitMalloc(malloc_impl_handle, &g_malloc_dispatch_table, "qemu_instrumented");
+            InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "qemu_instrumented");
             break;
         default:
             break;
     }
 
     // Make sure dispatch table is initialized
-    if ((g_malloc_dispatch_table.malloc == NULL) ||
-        (g_malloc_dispatch_table.free == NULL) ||
-        (g_malloc_dispatch_table.calloc == NULL) ||
-        (g_malloc_dispatch_table.realloc == NULL) ||
-        (g_malloc_dispatch_table.memalign == NULL) ||
-        (g_malloc_dispatch_table.malloc_usable_size == NULL)) {
+    if ((malloc_dispatch_table.malloc == NULL) ||
+        (malloc_dispatch_table.free == NULL) ||
+        (malloc_dispatch_table.calloc == NULL) ||
+        (malloc_dispatch_table.realloc == NULL) ||
+        (malloc_dispatch_table.memalign == NULL) ||
+        (malloc_dispatch_table.malloc_usable_size == NULL)) {
         error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
-                  __progname, g_malloc_debug_level);
+                  getprogname(), g_malloc_debug_level);
         dlclose(malloc_impl_handle);
     } else {
-        __libc_malloc_dispatch = &g_malloc_dispatch_table;
+        __libc_malloc_dispatch = &malloc_dispatch_table;
         libc_malloc_impl_handle = malloc_impl_handle;
     }
 }
 
 static void malloc_fini_impl() {
     // Our BSD stdio implementation doesn't close the standard streams, it only flushes them.
-    // And it doesn't do that until its atexit handler (_cleanup) is run, and we run first!
+    // And it doesn't do that until its atexit handler is run, and we run first!
     // It's great that other unclosed FILE*s show up as malloc leaks, but we need to manually
     // clean up the standard streams ourselves.
     fclose(stdin);
@@ -487,14 +470,11 @@
             reinterpret_cast<MallocDebugFini>(dlsym(libc_malloc_impl_handle,
                                                     "malloc_debug_finalize"));
         if (malloc_debug_finalize != NULL) {
-            malloc_debug_finalize();
+            malloc_debug_finalize(g_malloc_debug_level);
         }
     }
 }
 
-static pthread_once_t  malloc_init_once_ctl = PTHREAD_ONCE_INIT;
-static pthread_once_t  malloc_fini_once_ctl = PTHREAD_ONCE_INIT;
-
 #endif  // !LIBC_STATIC
 
 /* Initializes memory allocation framework.
@@ -502,21 +482,19 @@
  * in libc_init_static.c and libc_init_dynamic.c files.
  */
 extern "C" __LIBC_HIDDEN__ 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)) {
-        error_log("Unable to initialize malloc_debug component.");
-    }
+  static pthread_once_t malloc_init_once_ctl = PTHREAD_ONCE_INIT;
+  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" __LIBC_HIDDEN__ 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)) {
-        error_log("Unable to finalize malloc_debug component.");
-    }
+  static pthread_once_t malloc_fini_once_ctl = PTHREAD_ONCE_INIT;
+  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 c1c3c89..21cb44c 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -33,6 +33,8 @@
 #ifndef MALLOC_DEBUG_COMMON_H
 #define MALLOC_DEBUG_COMMON_H
 
+#include <pthread.h>
+#include <stdint.h>
 #include <stdlib.h>
 
 #include "private/libc_logging.h"
@@ -43,8 +45,6 @@
 #define SIZE_FLAG_ZYGOTE_CHILD  (1<<31)
 #define SIZE_FLAG_MASK          (SIZE_FLAG_ZYGOTE_CHILD)
 
-#define MAX_SIZE_T           (~(size_t)0)
-
 // This must match the alignment used by the malloc implementation.
 #ifndef MALLOC_ALIGNMENT
 #define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
@@ -77,6 +77,7 @@
 };
 
 struct HashTable {
+    pthread_mutex_t lock;
     size_t count;
     HashEntry* slots[HASHTABLE_SIZE];
 };
@@ -97,20 +98,8 @@
   MallocDebugMallocUsableSize malloc_usable_size;
 };
 
-/* Malloc debugging initialization and finalization routines.
- *
- * These routines must be implemented in .so modules that implement malloc
- * debugging. The are is called once per process from malloc_init_impl and
- * malloc_fini_impl respectively.
- *
- * They are implemented in bionic/libc/bionic/malloc_debug_common.c when malloc
- * debugging gets initialized for the process.
- *
- * MallocDebugInit returns:
- *    0 on success, -1 on failure.
- */
-typedef int (*MallocDebugInit)();
-typedef void (*MallocDebugFini)();
+typedef bool (*MallocDebugInit)(HashTable*);
+typedef void (*MallocDebugFini)(int);
 
 // =============================================================================
 // log functions
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 035765f..aa7c072 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -58,10 +58,8 @@
 #error MALLOC_LEAK_CHECK is not defined.
 #endif  // !MALLOC_LEAK_CHECK
 
-// Global variables defined in malloc_debug_common.c
 extern int gMallocLeakZygoteChild;
-extern pthread_mutex_t g_allocations_mutex;
-extern HashTable g_hash_table;
+extern HashTable* g_hash_table;
 
 // =============================================================================
 // stack trace functions
@@ -137,7 +135,7 @@
         size |= SIZE_FLAG_ZYGOTE_CHILD;
     }
 
-    HashEntry* entry = find_entry(&g_hash_table, slot, backtrace, numEntries, size);
+    HashEntry* entry = find_entry(g_hash_table, slot, backtrace, numEntries, size);
 
     if (entry != NULL) {
         entry->allocations++;
@@ -150,58 +148,54 @@
         entry->allocations = 1;
         entry->slot = slot;
         entry->prev = NULL;
-        entry->next = g_hash_table.slots[slot];
+        entry->next = g_hash_table->slots[slot];
         entry->numEntries = numEntries;
         entry->size = size;
 
         memcpy(entry->backtrace, backtrace, numEntries * sizeof(uintptr_t));
 
-        g_hash_table.slots[slot] = entry;
+        g_hash_table->slots[slot] = entry;
 
         if (entry->next != NULL) {
             entry->next->prev = entry;
         }
 
         // we just added an entry, increase the size of the hashtable
-        g_hash_table.count++;
+        g_hash_table->count++;
     }
 
     return entry;
 }
 
 static int is_valid_entry(HashEntry* entry) {
-    if (entry != NULL) {
-        int i;
-        for (i = 0 ; i < HASHTABLE_SIZE ; i++) {
-            HashEntry* e1 = g_hash_table.slots[i];
-
-            while (e1 != NULL) {
-                if (e1 == entry) {
-                    return 1;
-                }
-
-                e1 = e1->next;
-            }
+  if (entry != NULL) {
+    for (size_t i = 0; i < HASHTABLE_SIZE; ++i) {
+      HashEntry* e1 = g_hash_table->slots[i];
+      while (e1 != NULL) {
+        if (e1 == entry) {
+          return 1;
         }
+        e1 = e1->next;
+      }
     }
-
-    return 0;
+  }
+  return 0;
 }
 
 static void remove_entry(HashEntry* entry) {
-    HashEntry* prev = entry->prev;
-    HashEntry* next = entry->next;
+  HashEntry* prev = entry->prev;
+  HashEntry* next = entry->next;
 
-    if (prev != NULL) entry->prev->next = next;
-    if (next != NULL) entry->next->prev = prev;
+  if (prev != NULL) entry->prev->next = next;
+  if (next != NULL) entry->next->prev = prev;
 
-    if (prev == NULL) {
-        // we are the head of the list. set the head to be next
-        g_hash_table.slots[entry->slot] = entry->next;
-    }
+  if (prev == NULL) {
+    // we are the head of the list. set the head to be next
+    g_hash_table->slots[entry->slot] = entry->next;
+  }
 
-    // we just removed and entry, decrease the size of the hashtable
-    g_hash_table.count--;
+  // we just removed and entry, decrease the size of the hashtable
+  g_hash_table->count--;
 }
 
 // =============================================================================
@@ -276,7 +270,7 @@
 
     void* base = Malloc(malloc)(size);
     if (base != NULL) {
-        ScopedPthreadMutexLocker locker(&g_allocations_mutex);
+        ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 
         uintptr_t backtrace[BACKTRACE_SIZE];
         size_t numEntries = get_backtrace(backtrace, BACKTRACE_SIZE);
@@ -294,43 +288,45 @@
 }
 
 extern "C" void leak_free(void* mem) {
-    if (mem != NULL) {
-        ScopedPthreadMutexLocker locker(&g_allocations_mutex);
+  if (mem == NULL) {
+    return;
+  }
 
-        // check the guard to make sure it is valid
-        AllocationEntry* header = to_header(mem);
+  ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 
-        if (header->guard != GUARD) {
-            // could be a memaligned block
-            if (header->guard == MEMALIGN_GUARD) {
-                // For memaligned blocks, header->entry points to the memory
-                // allocated through leak_malloc.
-                header = to_header(header->entry);
-            }
-        }
+  // check the guard to make sure it is valid
+  AllocationEntry* header = to_header(mem);
 
-        if (header->guard == GUARD || is_valid_entry(header->entry)) {
-            // decrement the allocations
-            HashEntry* entry = header->entry;
-            entry->allocations--;
-            if (entry->allocations <= 0) {
-                remove_entry(entry);
-                Malloc(free)(entry);
-            }
-
-            // now free the memory!
-            Malloc(free)(header);
-        } else {
-            debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
-                    header->guard, header->entry);
-        }
+  if (header->guard != GUARD) {
+    // could be a memaligned block
+    if (header->guard == MEMALIGN_GUARD) {
+      // For memaligned blocks, header->entry points to the memory
+      // allocated through leak_malloc.
+      header = to_header(header->entry);
     }
+  }
+
+  if (header->guard == GUARD || is_valid_entry(header->entry)) {
+    // decrement the allocations
+    HashEntry* entry = header->entry;
+    entry->allocations--;
+    if (entry->allocations <= 0) {
+      remove_entry(entry);
+      Malloc(free)(entry);
+    }
+
+    // now free the memory!
+    Malloc(free)(header);
+  } else {
+    debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
+              header->guard, header->entry);
+  }
 }
 
 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) {
+    // 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 && SIZE_MAX / n_elements < elem_size) {
         return NULL;
     }
     size_t size = n_elements * elem_size;
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index ac60c3b..2dda767 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -589,7 +589,7 @@
  * Return:
  *  0 on success, or -1 on failure.
 */
-extern "C" int malloc_debug_initialize() {
+extern "C" bool malloc_debug_initialize(HashTable*) {
     /* 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
@@ -598,7 +598,7 @@
     int fd = open("/dev/qemu_trace", O_RDWR);
     if (fd < 0) {
         error_log("Unable to open /dev/qemu_trace");
-        return -1;
+        return false;
     } else {
         qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
         close(fd);
@@ -606,14 +606,13 @@
         if (qtrace == MAP_FAILED) {
             qtrace = NULL;
             error_log("Unable to mmap /dev/qemu_trace");
-            return -1;
+            return false;
         }
     }
 
     /* Cache pid of the process this library has been initialized for. */
     malloc_pid = getpid();
-
-    return 0;
+    return true;
 }
 
 /* Completes malloc debugging instrumentation for the emulator.
@@ -759,9 +758,9 @@
         return qemu_instrumented_malloc(0);
     }
 
-    /* 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) {
+    // 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 && SIZE_MAX / n_elements < elem_size) {
         return NULL;
     }