Merge "malloc debug: fix LogFreeError error log"
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 1c3f53f..ce3e761 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -303,23 +303,25 @@
   return true;
 }
 
-static void InstallHooks(libc_globals* globals, const char* options, const char* prefix,
+static bool InstallHooks(libc_globals* globals, const char* options, const char* prefix,
                          const char* shared_lib) {
   void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &globals->malloc_dispatch_table);
   if (impl_handle == nullptr) {
-    return;
+    return false;
   }
 
   init_func_t init_func = reinterpret_cast<init_func_t>(gFunctions[FUNC_INITIALIZE]);
   if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
     error_log("%s: failed to enable malloc %s", getprogname(), prefix);
     ClearGlobalFunctions();
-    return;
+    return false;
   }
 
   if (!FinishInstallHooks(globals, options, prefix)) {
     dlclose(impl_handle);
+    return false;
   }
+  return true;
 }
 
 // Initializes memory allocation framework once per process.
@@ -329,16 +331,25 @@
 
   // Prefer malloc debug since it existed first and is a more complete
   // malloc interceptor than the hooks.
+  bool hook_installed = false;
   if (CheckLoadMallocDebug(&options)) {
-    InstallHooks(globals, options, kDebugPrefix, kDebugSharedLib);
+    hook_installed = InstallHooks(globals, options, kDebugPrefix, kDebugSharedLib);
   } else if (CheckLoadMallocHooks(&options)) {
-    InstallHooks(globals, options, kHooksPrefix, kHooksSharedLib);
-  } else if (HeapprofdShouldLoad()) {
-    HeapprofdInstallHooksAtInit(globals);
+    hook_installed = InstallHooks(globals, options, kHooksPrefix, kHooksSharedLib);
   }
 
-  // Install this last to avoid as many race conditions as possible.
-  HeapprofdInstallSignalHandler();
+  if (!hook_installed) {
+    if (HeapprofdShouldLoad()) {
+      HeapprofdInstallHooksAtInit(globals);
+    }
+
+    // Install this last to avoid as many race conditions as possible.
+    HeapprofdInstallSignalHandler();
+  } else {
+    // Install a signal handler that prints an error since we don't support
+    // heapprofd and any other hook to be installed at the same time.
+    HeapprofdInstallErrorSignalHandler();
+  }
 }
 
 // Initializes memory allocation framework.
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index fb7266a..c492bac 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -211,6 +211,16 @@
   sigaction(kHeapprofdSignal, &action, nullptr);
 }
 
+static void DisplayError(int) {
+  error_log("Cannot install heapprofd while malloc debug/malloc hooks are enabled.");
+}
+
+void HeapprofdInstallErrorSignalHandler() {
+  struct sigaction action = {};
+  action.sa_handler = DisplayError;
+  sigaction(kHeapprofdSignal, &action, nullptr);
+}
+
 static void CommonInstallHooks(libc_globals* globals) {
   void* impl_handle = atomic_load(&gHeapprofdHandle);
   bool reusing_handle = impl_handle != nullptr;
diff --git a/libc/bionic/malloc_heapprofd.h b/libc/bionic/malloc_heapprofd.h
index 91188b9..5a766fc 100644
--- a/libc/bionic/malloc_heapprofd.h
+++ b/libc/bionic/malloc_heapprofd.h
@@ -38,4 +38,6 @@
 
 void HeapprofdInstallSignalHandler();
 
+void HeapprofdInstallErrorSignalHandler();
+
 bool HeapprofdMallopt(int optcode, void* arg, size_t arg_size);
diff --git a/linker/Android.bp b/linker/Android.bp
index fed921d..06a942d 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -296,6 +296,10 @@
         },
     },
     system_shared_libs: [],
+
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
     target: {
         android: {
             static_libs: ["libdebuggerd_handler_fallback"],
@@ -364,6 +368,9 @@
     nocrt: true,
     system_shared_libs: [],
 
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
     sanitize: {
         never: true,
     },