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_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;
+}