Refactor the malloc_info code.
malloc_info needs to be per native allocator, but the code treated it
like a global function that doesn't depend on the native memory allocator.
Update malloc debug to dump the actual pointers that it has been tracking.
Test: bionic-unit-tests pass.
Test: malloc debug tests pass.
Test: malloc hook tests pass.
Change-Id: I3b0d4d748489dd84c16d16933479dc8b8d79013e
Merged-In: I3b0d4d748489dd84c16d16933479dc8b8d79013e
(cherry picked from commit a3656a98b10d2a4a6194a5d9705ad9c2cc5877b0)
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index 3fd36e4..b9a4e99 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -34,6 +34,7 @@
struct mallinfo je_mallinfo();
void je_malloc_disable();
void je_malloc_enable();
+int je_malloc_info(int options, FILE* fp);
int je_mallopt(int, int);
void* je_memalign_round_up_boundary(size_t, size_t);
void* je_pvalloc(size_t);
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index c513246..bc3a9dc 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -19,8 +19,9 @@
#include <sys/param.h>
#include <unistd.h>
+#include <private/MallocXmlElem.h>
+
#include "jemalloc.h"
-#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
size_t pagesize = getpagesize();
@@ -116,3 +117,49 @@
}
return 0;
}
+
+__BEGIN_DECLS
+
+size_t __mallinfo_narenas();
+size_t __mallinfo_nbins();
+struct mallinfo __mallinfo_arena_info(size_t);
+struct mallinfo __mallinfo_bin_info(size_t, size_t);
+
+__END_DECLS
+
+int je_malloc_info(int options, FILE* fp) {
+ if (options != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ MallocXmlElem root(fp, "malloc", "version=\"jemalloc-1\"");
+
+ // Dump all of the large allocations in the arenas.
+ for (size_t i = 0; i < __mallinfo_narenas(); i++) {
+ struct mallinfo mi = __mallinfo_arena_info(i);
+ if (mi.hblkhd != 0) {
+ MallocXmlElem arena_elem(fp, "heap", "nr=\"%d\"", i);
+ {
+ MallocXmlElem(fp, "allocated-large").Contents("%zu", mi.ordblks);
+ MallocXmlElem(fp, "allocated-huge").Contents("%zu", mi.uordblks);
+ MallocXmlElem(fp, "allocated-bins").Contents("%zu", mi.fsmblks);
+
+ size_t total = 0;
+ for (size_t j = 0; j < __mallinfo_nbins(); j++) {
+ struct mallinfo mi = __mallinfo_bin_info(i, j);
+ if (mi.ordblks != 0) {
+ MallocXmlElem bin_elem(fp, "bin", "nr=\"%d\"", j);
+ MallocXmlElem(fp, "allocated").Contents("%zu", mi.ordblks);
+ MallocXmlElem(fp, "nmalloc").Contents("%zu", mi.uordblks);
+ MallocXmlElem(fp, "ndalloc").Contents("%zu", mi.fordblks);
+ total += mi.ordblks;
+ }
+ }
+ MallocXmlElem(fp, "bins-total").Contents("%zu", total);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index bb8ec59..edd697d 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -42,6 +42,7 @@
// write_malloc_leak_info: Writes the leak info data to a file.
#include <stdint.h>
+#include <stdio.h>
#include <private/bionic_config.h>
@@ -93,6 +94,14 @@
return Malloc(mallinfo)();
}
+extern "C" int malloc_info(int options, FILE* fp) {
+ auto dispatch_table = GetDispatchTable();
+ if (__predict_false(dispatch_table != nullptr)) {
+ return dispatch_table->malloc_info(options, fp);
+ }
+ return Malloc(malloc_info)(options, fp);
+}
+
extern "C" int mallopt(int param, int value) {
auto dispatch_table = GetDispatchTable();
if (__predict_false(dispatch_table != nullptr)) {
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index ce3e761..9656718 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -85,6 +85,7 @@
Malloc(malloc_enable),
Malloc(mallopt),
Malloc(aligned_alloc),
+ Malloc(malloc_info),
};
static constexpr char kHooksSharedLib[] = "libc_malloc_hooks.so";
@@ -146,6 +147,10 @@
if (!InitMallocFunction<MallocMalloc>(impl_handler, &table->malloc, prefix, "malloc")) {
return false;
}
+ if (!InitMallocFunction<MallocMallocInfo>(impl_handler, &table->malloc_info, prefix,
+ "malloc_info")) {
+ return false;
+ }
if (!InitMallocFunction<MallocMallocUsableSize>(impl_handler, &table->malloc_usable_size, prefix,
"malloc_usable_size")) {
return false;
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index 5129cd7..9cab67a 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -108,6 +108,7 @@
Malloc(malloc_enable),
Malloc(mallopt),
Malloc(aligned_alloc),
+ Malloc(malloc_info),
};
static void MaybeInstallInitHeapprofdHook(int) {
diff --git a/libc/bionic/malloc_info.cpp b/libc/bionic/malloc_info.cpp
deleted file mode 100644
index 9c8a4bf..0000000
--- a/libc/bionic/malloc_info.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * 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.
- */
-
-#include "malloc_info.h"
-
-#include <errno.h>
-#include "private/bionic_macros.h"
-
-class __LIBC_HIDDEN__ Elem {
-public:
- // name must be valid throughout lifetime of the object.
- explicit Elem(FILE* fp, const char* name,
- const char* attr_fmt = nullptr, ...) {
- this->fp = fp;
- this->name = name;
-
- fprintf(fp, "<%s", name);
- if (attr_fmt != nullptr) {
- va_list args;
- va_start(args, attr_fmt);
- fputc(' ', fp);
- vfprintf(fp, attr_fmt, args);
- va_end(args);
- }
- fputc('>', fp);
- }
-
- ~Elem() noexcept {
- fprintf(fp, "</%s>", name);
- }
-
- void contents(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vfprintf(fp, fmt, args);
- va_end(args);
- }
-
-private:
- FILE* fp;
- const char* name;
-
- BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(Elem);
-};
-
-int malloc_info(int options, FILE* fp) {
- if (options != 0) {
- errno = EINVAL;
- return -1;
- }
-
- Elem root(fp, "malloc", "version=\"jemalloc-1\"");
-
- // Dump all of the large allocations in the arenas.
- for (size_t i = 0; i < __mallinfo_narenas(); i++) {
- struct mallinfo mi = __mallinfo_arena_info(i);
- if (mi.hblkhd != 0) {
- Elem arena_elem(fp, "heap", "nr=\"%d\"", i);
- {
- Elem(fp, "allocated-large").contents("%zu", mi.ordblks);
- Elem(fp, "allocated-huge").contents("%zu", mi.uordblks);
- Elem(fp, "allocated-bins").contents("%zu", mi.fsmblks);
-
- size_t total = 0;
- for (size_t j = 0; j < __mallinfo_nbins(); j++) {
- struct mallinfo mi = __mallinfo_bin_info(i, j);
- if (mi.ordblks != 0) {
- Elem bin_elem(fp, "bin", "nr=\"%d\"", j);
- Elem(fp, "allocated").contents("%zu", mi.ordblks);
- Elem(fp, "nmalloc").contents("%zu", mi.uordblks);
- Elem(fp, "ndalloc").contents("%zu", mi.fordblks);
- total += mi.ordblks;
- }
- }
- Elem(fp, "bins-total").contents("%zu", total);
- }
- }
- }
-
- return 0;
-}
diff --git a/libc/bionic/malloc_info.h b/libc/bionic/malloc_info.h
deleted file mode 100644
index 257fec1..0000000
--- a/libc/bionic/malloc_info.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * 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.
- */
-
-#pragma once
-
-#include <malloc.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-__LIBC_HIDDEN__ size_t __mallinfo_narenas();
-__LIBC_HIDDEN__ size_t __mallinfo_nbins();
-__LIBC_HIDDEN__ struct mallinfo __mallinfo_arena_info(size_t);
-__LIBC_HIDDEN__ struct mallinfo __mallinfo_bin_info(size_t, size_t);
-
-__END_DECLS