Add the record alloc option.

This option adds the ability to record all of the allocation requests
and dump them to a file when a signal is sent to the process.

Included in this change, redo the option processing to add a new
string option.

Bug: 27747898

Change-Id: Ida043362e38b5eb1d459c99db9c2581015dab366
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 5da5b88..d2bcf99 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -328,7 +328,13 @@
   }
   ScopedDisableDebugCalls disable;
 
-  return internal_malloc(size);
+  void* pointer = internal_malloc(size);
+
+  if (g_debug->config().options & RECORD_ALLOCS) {
+    g_debug->record->AddEntry(new MallocEntry(pointer, size));
+  }
+
+  return pointer;
 }
 
 static void internal_free(void* pointer) {
@@ -393,6 +399,10 @@
   }
   ScopedDisableDebugCalls disable;
 
+  if (g_debug->config().options & RECORD_ALLOCS) {
+    g_debug->record->AddEntry(new FreeEntry(pointer));
+  }
+
   internal_free(pointer);
 }
 
@@ -461,6 +471,10 @@
     memset(pointer, g_debug->config().fill_alloc_value, bytes);
   }
 
+  if (g_debug->config().options & RECORD_ALLOCS) {
+    g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
+  }
+
   return pointer;
 }
 
@@ -471,10 +485,18 @@
   ScopedDisableDebugCalls disable;
 
   if (pointer == nullptr) {
-    return internal_malloc(bytes);
+    pointer = internal_malloc(bytes);
+    if (g_debug->config().options & RECORD_ALLOCS) {
+      g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
+    }
+    return pointer;
   }
 
   if (bytes == 0) {
+    if (g_debug->config().options & RECORD_ALLOCS) {
+      g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
+    }
+
     internal_free(pointer);
     return nullptr;
   }
@@ -555,6 +577,10 @@
     }
   }
 
+  if (g_debug->config().options & RECORD_ALLOCS) {
+    g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
+  }
+
   return new_pointer;
 }
 
@@ -582,6 +608,7 @@
     return nullptr;
   }
 
+  void* pointer;
   if (g_debug->need_header()) {
     // The above check will guarantee the multiply will not overflow.
     if (size > Header::max_size()) {
@@ -596,10 +623,14 @@
       return nullptr;
     }
     memset(header, 0, g_dispatch->malloc_usable_size(header));
-    return InitHeader(header, header, size);
+    pointer = InitHeader(header, header, size);
   } else {
-    return g_dispatch->calloc(1, real_size);
+    pointer = g_dispatch->calloc(1, real_size);
   }
+  if (g_debug->config().options & RECORD_ALLOCS) {
+    g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
+  }
+  return pointer;
 }
 
 struct mallinfo debug_mallinfo() {