Refactor Config from a struct to a class.

This should make it easier to add new options, and to add options that
are complex. For example, I want to modify the behavior of
record_allocs_file so that it also enables record_allocs to a default
state.

Test: All unit tests pass.
Test: Enable the backtrace option and restart.
Change-Id: Idf5cdeed06ade3bc2c8ae39d228734bf65209b4f
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index bb16faa..addb5d4 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -118,7 +118,7 @@
   error_log(LOG_DIVIDER);
   if (header->tag == DEBUG_FREE_TAG) {
     error_log("+++ ALLOCATION %p USED AFTER FREE (%s)", pointer, name);
-    if (g_debug->config().options & FREE_TRACK) {
+    if (g_debug->config().options() & FREE_TRACK) {
       g_debug->free_track->LogBacktrace(header);
     }
   } else {
@@ -147,32 +147,32 @@
   header->usable_size -= g_debug->pointer_offset() +
       reinterpret_cast<uintptr_t>(header) - reinterpret_cast<uintptr_t>(orig_pointer);
 
-  if (g_debug->config().options & FRONT_GUARD) {
+  if (g_debug->config().options() & FRONT_GUARD) {
     uint8_t* guard = g_debug->GetFrontGuard(header);
-    memset(guard, g_debug->config().front_guard_value, g_debug->config().front_guard_bytes);
+    memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
   }
 
-  if (g_debug->config().options & REAR_GUARD) {
+  if (g_debug->config().options() & REAR_GUARD) {
     uint8_t* guard = g_debug->GetRearGuard(header);
-    memset(guard, g_debug->config().rear_guard_value, g_debug->config().rear_guard_bytes);
+    memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
     // If the rear guard is enabled, set the usable size to the exact size
     // of the allocation.
     header->usable_size = header->real_size();
   }
 
   bool backtrace_found = false;
-  if (g_debug->config().options & BACKTRACE) {
+  if (g_debug->config().options() & BACKTRACE) {
     BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
     if (g_debug->backtrace->enabled()) {
       back_header->num_frames = backtrace_get(
-          &back_header->frames[0], g_debug->config().backtrace_frames);
+          &back_header->frames[0], g_debug->config().backtrace_frames());
       backtrace_found = back_header->num_frames > 0;
     } else {
       back_header->num_frames = 0;
     }
   }
 
-  if (g_debug->config().options & TRACK_ALLOCS) {
+  if (g_debug->config().options() & TRACK_ALLOCS) {
     g_debug->track->Add(header, backtrace_found);
   }
 
@@ -215,11 +215,11 @@
     return;
   }
 
-  if (g_debug->config().options & FREE_TRACK) {
+  if (g_debug->config().options() & FREE_TRACK) {
     g_debug->free_track->VerifyAll();
   }
 
-  if (g_debug->config().options & LEAK_TRACK) {
+  if (g_debug->config().options() & LEAK_TRACK) {
     g_debug->track->DisplayLeaks();
   }
 
@@ -250,7 +250,7 @@
   *total_memory = 0;
   *backtrace_size = 0;
 
-  if (!(g_debug->config().options & BACKTRACE)) {
+  if (!(g_debug->config().options() & BACKTRACE)) {
     error_log("get_malloc_leak_info: Allocations not being tracked, to enable "
               "set the option 'backtrace'.");
     return;
@@ -315,11 +315,11 @@
     pointer = g_dispatch->malloc(real_size);
   }
 
-  if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
+  if (pointer != nullptr && g_debug->config().options() & FILL_ON_ALLOC) {
     size_t bytes = internal_malloc_usable_size(pointer);
-    size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
+    size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
     bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
-    memset(pointer, g_debug->config().fill_alloc_value, bytes);
+    memset(pointer, g_debug->config().fill_alloc_value(), bytes);
   }
   return pointer;
 }
@@ -332,7 +332,7 @@
 
   void* pointer = internal_malloc(size);
 
-  if (g_debug->config().options & RECORD_ALLOCS) {
+  if (g_debug->config().options() & RECORD_ALLOCS) {
     g_debug->record->AddEntry(new MallocEntry(pointer, size));
   }
 
@@ -351,20 +351,20 @@
     }
     free_pointer = header->orig_pointer;
 
-    if (g_debug->config().options & FRONT_GUARD) {
+    if (g_debug->config().options() & FRONT_GUARD) {
       if (!g_debug->front_guard->Valid(header)) {
         g_debug->front_guard->LogFailure(header);
       }
     }
-    if (g_debug->config().options & REAR_GUARD) {
+    if (g_debug->config().options() & REAR_GUARD) {
       if (!g_debug->rear_guard->Valid(header)) {
         g_debug->rear_guard->LogFailure(header);
       }
     }
 
-    if (g_debug->config().options & TRACK_ALLOCS) {
+    if (g_debug->config().options() & TRACK_ALLOCS) {
       bool backtrace_found = false;
-      if (g_debug->config().options & BACKTRACE) {
+      if (g_debug->config().options() & BACKTRACE) {
         BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
         backtrace_found = back_header->num_frames > 0;
       }
@@ -377,13 +377,13 @@
     bytes = g_dispatch->malloc_usable_size(pointer);
   }
 
-  if (g_debug->config().options & FILL_ON_FREE) {
-    size_t fill_bytes = g_debug->config().fill_on_free_bytes;
+  if (g_debug->config().options() & FILL_ON_FREE) {
+    size_t fill_bytes = g_debug->config().fill_on_free_bytes();
     bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
-    memset(pointer, g_debug->config().fill_free_value, bytes);
+    memset(pointer, g_debug->config().fill_free_value(), bytes);
   }
 
-  if (g_debug->config().options & FREE_TRACK) {
+  if (g_debug->config().options() & FREE_TRACK) {
     // Do not add the allocation until we are done modifying the pointer
     // itself. This avoids a race if a lot of threads are all doing
     // frees at the same time and we wind up trying to really free this
@@ -401,7 +401,7 @@
   }
   ScopedDisableDebugCalls disable;
 
-  if (g_debug->config().options & RECORD_ALLOCS) {
+  if (g_debug->config().options() & RECORD_ALLOCS) {
     g_debug->record->AddEntry(new FreeEntry(pointer));
   }
 
@@ -466,14 +466,14 @@
     pointer = g_dispatch->memalign(alignment, real_size);
   }
 
-  if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
+  if (pointer != nullptr && g_debug->config().options() & FILL_ON_ALLOC) {
     size_t bytes = internal_malloc_usable_size(pointer);
-    size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
+    size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
     bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
-    memset(pointer, g_debug->config().fill_alloc_value, bytes);
+    memset(pointer, g_debug->config().fill_alloc_value(), bytes);
   }
 
-  if (g_debug->config().options & RECORD_ALLOCS) {
+  if (g_debug->config().options() & RECORD_ALLOCS) {
     g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
   }
 
@@ -488,14 +488,14 @@
 
   if (pointer == nullptr) {
     pointer = internal_malloc(bytes);
-    if (g_debug->config().options & RECORD_ALLOCS) {
+    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) {
+    if (g_debug->config().options() & RECORD_ALLOCS) {
       g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
     }
 
@@ -504,8 +504,8 @@
   }
 
   size_t real_size = bytes;
-  if (g_debug->config().options & EXPAND_ALLOC) {
-    real_size += g_debug->config().expand_alloc_bytes;
+  if (g_debug->config().options() & EXPAND_ALLOC) {
+    real_size += g_debug->config().expand_alloc_bytes();
     if (real_size < bytes) {
       // Overflow.
       errno = ENOMEM;
@@ -539,12 +539,12 @@
       if (*g_malloc_zygote_child) {
         header->set_zygote();
       }
-      if (g_debug->config().options & REAR_GUARD) {
+      if (g_debug->config().options() & REAR_GUARD) {
         // Don't bother allocating a smaller pointer in this case, simply
         // change the header usable_size and reset the rear guard.
         header->usable_size = header->real_size();
-        memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value,
-               g_debug->config().rear_guard_bytes);
+        memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
+               g_debug->config().rear_guard_bytes());
       }
       // Do not bother recording, this is essentially a nop.
       return pointer;
@@ -568,18 +568,18 @@
     }
   }
 
-  if (g_debug->config().options & FILL_ON_ALLOC) {
+  if (g_debug->config().options() & FILL_ON_ALLOC) {
     size_t bytes = internal_malloc_usable_size(new_pointer);
-    if (bytes > g_debug->config().fill_on_alloc_bytes) {
-      bytes = g_debug->config().fill_on_alloc_bytes;
+    if (bytes > g_debug->config().fill_on_alloc_bytes()) {
+      bytes = g_debug->config().fill_on_alloc_bytes();
     }
     if (bytes > prev_size) {
       memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
-             g_debug->config().fill_alloc_value, bytes - prev_size);
+             g_debug->config().fill_alloc_value(), bytes - prev_size);
     }
   }
 
-  if (g_debug->config().options & RECORD_ALLOCS) {
+  if (g_debug->config().options() & RECORD_ALLOCS) {
     g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
   }
 
@@ -629,7 +629,7 @@
   } else {
     pointer = g_dispatch->calloc(1, real_size);
   }
-  if (g_debug->config().options & RECORD_ALLOCS) {
+  if (g_debug->config().options() & RECORD_ALLOCS) {
     g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
   }
   return pointer;
@@ -668,7 +668,7 @@
         const void* pointer = reinterpret_cast<void*>(base);
         if (g_debug->need_header()) {
           const Header* header = reinterpret_cast<const Header*>(pointer);
-          if (g_debug->config().options & TRACK_ALLOCS) {
+          if (g_debug->config().options() & TRACK_ALLOCS) {
             if (g_debug->track->Contains(header)) {
               // Return just the body of the allocation if we're sure the header exists
               ctx->callback(reinterpret_cast<uintptr_t>(g_debug->GetPointer(header)),
@@ -704,7 +704,7 @@
 
   if (g_debug->need_header()) {
     Header* header;
-    if (g_debug->config().options & TRACK_ALLOCS) {
+    if (g_debug->config().options() & TRACK_ALLOCS) {
       header = g_debug->GetHeader(pointer);
       if (!g_debug->track->Contains(header)) {
         return 0;
@@ -715,7 +715,7 @@
     if (header->tag != DEBUG_TAG) {
       return 0;
     }
-    if (g_debug->config().options & BACKTRACE) {
+    if (g_debug->config().options() & BACKTRACE) {
       BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
       if (back_header->num_frames > 0) {
         if (frame_count > back_header->num_frames) {