Export malloc_iterate and friends
Export malloc_iterate, malloc_enable, and malloc_disable to be used by
libmemunreachable.
Change-Id: I08a50349af82a95d096b6b4cbac37ababe4b9b06
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 56f1c10..b991b9a 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -40,6 +40,8 @@
// free_malloc_leak_info: Frees the data allocated by the call to
// get_malloc_leak_info.
+#include <pthread.h>
+
#include <private/bionic_config.h>
#include <private/bionic_globals.h>
#include <private/bionic_malloc_dispatch.h>
@@ -63,6 +65,9 @@
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Malloc(valloc),
#endif
+ Malloc(iterate),
+ Malloc(malloc_disable),
+ Malloc(malloc_enable),
};
// In a VM process, this is set to 1 after fork()ing out of zygote.
@@ -159,7 +164,6 @@
#if !defined(LIBC_STATIC)
#include <dlfcn.h>
-#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -215,6 +219,7 @@
}
g_debug_free_malloc_leak_info_func(info);
}
+
// =============================================================================
template<typename FunctionType>
@@ -262,6 +267,18 @@
prefix, "realloc")) {
return false;
}
+ if (!InitMallocFunction<MallocIterate>(malloc_impl_handler, &table->iterate,
+ prefix, "iterate")) {
+ return false;
+ }
+ if (!InitMallocFunction<MallocMallocDisable>(malloc_impl_handler, &table->malloc_disable,
+ prefix, "malloc_disable")) {
+ return false;
+ }
+ if (!InitMallocFunction<MallocMallocEnable>(malloc_impl_handler, &table->malloc_enable,
+ prefix, "malloc_enable")) {
+ return false;
+ }
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
if (!InitMallocFunction<MallocPvalloc>(malloc_impl_handler, &table->pvalloc,
prefix, "pvalloc")) {
@@ -385,3 +402,37 @@
malloc_init_impl(globals);
}
#endif // !LIBC_STATIC
+
+// =============================================================================
+// Exported for use by libmemunreachable.
+// =============================================================================
+
+// Calls callback for every allocation in the anonymous heap mapping
+// [base, base+size). Must be called between malloc_disable and malloc_enable.
+extern "C" int malloc_iterate(uintptr_t base, size_t size,
+ void (*callback)(uintptr_t base, size_t size, void* arg), void* arg) {
+ auto _iterate = __libc_globals->malloc_dispatch.iterate;
+ if (__predict_false(_iterate != nullptr)) {
+ return _iterate(base, size, callback, arg);
+ }
+ return Malloc(iterate)(base, size, callback, arg);
+}
+
+// Disable calls to malloc so malloc_iterate gets a consistent view of
+// allocated memory.
+extern "C" void malloc_disable() {
+ auto _malloc_disable = __libc_globals->malloc_dispatch.malloc_disable;
+ if (__predict_false(_malloc_disable != nullptr)) {
+ return _malloc_disable();
+ }
+ return Malloc(malloc_disable)();
+}
+
+// Re-enable calls to malloc after a previous call to malloc_disable.
+extern "C" void malloc_enable() {
+ auto _malloc_enable = __libc_globals->malloc_dispatch.malloc_enable;
+ if (__predict_false(_malloc_enable != nullptr)) {
+ return _malloc_enable();
+ }
+ return Malloc(malloc_enable)();
+}