Merge "Disable close_range test for musl"
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index f84ba7b..9b67d85 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -92,11 +92,6 @@
 pthread_mutex_t g_heap_tagging_lock = PTHREAD_MUTEX_INITIALIZER;
 
 // Requires `g_heap_tagging_lock` to be held.
-HeapTaggingLevel GetHeapTaggingLevel() {
-  return heap_tagging_level;
-}
-
-// Requires `g_heap_tagging_lock` to be held.
 bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
   if (tag_level == heap_tagging_level) {
     return true;
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index 110b6ed..a3588b8 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -40,7 +40,6 @@
 // useful for RAII on this lock.
 extern pthread_mutex_t g_heap_tagging_lock;
 
-// These functions can be called in a multithreaded context, and thus should
+// This function can be called in a multithreaded context, and thus should
 // only be called when holding the `g_heap_tagging_lock`.
 bool SetHeapTaggingLevel(HeapTaggingLevel level);
-HeapTaggingLevel GetHeapTaggingLevel();
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index 9aad0b3..ed6b9c6 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -39,37 +39,20 @@
 
 #define MMAP2_SHIFT 12 // 2**12 == 4096
 
-static bool kernel_has_MADV_MERGEABLE = true;
-
 void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
   if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
     errno = EINVAL;
     return MAP_FAILED;
   }
 
-  // prevent allocations large enough for `end - start` to overflow
+  // Prevent allocations large enough for `end - start` to overflow.
   size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE);
   if (rounded < size || rounded > PTRDIFF_MAX) {
     errno = ENOMEM;
     return MAP_FAILED;
   }
 
-  bool is_private_anonymous =
-      (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
-  bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
-
-  void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
-
-  if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
-      is_private_anonymous && !is_stack_or_grows_down) {
-    ErrnoRestorer errno_restorer;
-    int rc = madvise(result, size, MADV_MERGEABLE);
-    if (rc == -1 && errno == EINVAL) {
-      kernel_has_MADV_MERGEABLE = false;
-    }
-  }
-
-  return result;
+  return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
 }
 
 void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 864dfb6..e7a157e 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -122,6 +122,7 @@
 cc_test {
     name: "malloc_debug_unit_tests",
     test_suites: ["device-tests"],
+    isolated: true,
 
     srcs: [
         "tests/backtrace_fake.cpp",
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 5fd511f..6a81277 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -83,6 +83,19 @@
     },
 
     {
+        "backtrace_size",
+        {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceSize},
+    },
+    {
+        "backtrace_min_size",
+        {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceMinSize},
+    },
+    {
+        "backtrace_max_size",
+        {BACKTRACE_SPECIFIC_SIZES, &Config::SetBacktraceMaxSize},
+    },
+
+    {
         "backtrace",
         {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktrace},
     },
@@ -297,6 +310,23 @@
   return true;
 }
 
+bool Config::SetBacktraceSize(const std::string& option, const std::string& value) {
+  if (!ParseValue(option, value, 1, SIZE_MAX, &backtrace_min_size_bytes_)) {
+    return false;
+  }
+  backtrace_max_size_bytes_ = backtrace_min_size_bytes_;
+
+  return true;
+}
+
+bool Config::SetBacktraceMinSize(const std::string& option, const std::string& value) {
+  return ParseValue(option, value, 1, SIZE_MAX, &backtrace_min_size_bytes_);
+}
+
+bool Config::SetBacktraceMaxSize(const std::string& option, const std::string& value) {
+  return ParseValue(option, value, 1, SIZE_MAX, &backtrace_max_size_bytes_);
+}
+
 bool Config::SetExpandAlloc(const std::string& option, const std::string& value) {
   return ParseValue(option, value, DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, &expand_alloc_bytes_);
 }
@@ -403,6 +433,8 @@
   backtrace_enabled_ = false;
   backtrace_dump_on_exit_ = false;
   backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
+  backtrace_min_size_bytes_ = 0;
+  backtrace_max_size_bytes_ = SIZE_MAX;
   check_unreachable_signal_ = SIGRTMAX - 16;
 
   // Process each option name we can find.
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index 5e3ff71..ef1d2a9 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -47,6 +47,7 @@
 constexpr uint64_t ABORT_ON_ERROR = 0x800;
 constexpr uint64_t VERBOSE = 0x1000;
 constexpr uint64_t CHECK_UNREACHABLE_ON_SIGNAL = 0x2000;
+constexpr uint64_t BACKTRACE_SPECIFIC_SIZES = 0x4000;
 
 // In order to guarantee posix compliance, set the minimum alignment
 // to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
@@ -90,6 +91,9 @@
   uint8_t fill_alloc_value() const { return fill_alloc_value_; }
   uint8_t fill_free_value() const { return fill_free_value_; }
 
+  size_t backtrace_min_size_bytes() const { return backtrace_min_size_bytes_; }
+  size_t backtrace_max_size_bytes() const { return backtrace_max_size_bytes_; }
+
   int record_allocs_signal() const { return record_allocs_signal_; }
   size_t record_allocs_num_entries() const { return record_allocs_num_entries_; }
   const std::string& record_allocs_file() const { return record_allocs_file_; }
@@ -121,6 +125,10 @@
   bool SetBacktraceDumpOnExit(const std::string& option, const std::string& value);
   bool SetBacktraceDumpPrefix(const std::string& option, const std::string& value);
 
+  bool SetBacktraceSize(const std::string& option, const std::string& value);
+  bool SetBacktraceMinSize(const std::string& option, const std::string& value);
+  bool SetBacktraceMaxSize(const std::string& option, const std::string& value);
+
   bool SetExpandAlloc(const std::string& option, const std::string& value);
 
   bool SetFreeTrack(const std::string& option, const std::string& value);
@@ -145,6 +153,8 @@
   size_t backtrace_frames_ = 0;
   bool backtrace_dump_on_exit_ = false;
   std::string backtrace_dump_prefix_;
+  size_t backtrace_min_size_bytes_ = 0;
+  size_t backtrace_max_size_bytes_ = 0;
 
   size_t fill_on_alloc_bytes_ = 0;
   size_t fill_on_free_bytes_ = 0;
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index d062086..5ab2232 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -136,7 +136,22 @@
   return true;
 }
 
-size_t PointerData::AddBacktrace(size_t num_frames) {
+static inline bool ShouldBacktraceAllocSize(size_t size_bytes) {
+  static bool only_backtrace_specific_sizes =
+      g_debug->config().options() & BACKTRACE_SPECIFIC_SIZES;
+  if (!only_backtrace_specific_sizes) {
+    return true;
+  }
+  static size_t min_size_bytes = g_debug->config().backtrace_min_size_bytes();
+  static size_t max_size_bytes = g_debug->config().backtrace_max_size_bytes();
+  return size_bytes >= min_size_bytes && size_bytes <= max_size_bytes;
+}
+
+size_t PointerData::AddBacktrace(size_t num_frames, size_t size_bytes) {
+  if (!ShouldBacktraceAllocSize(size_bytes)) {
+    return kBacktraceEmptyIndex;
+  }
+
   std::vector<uintptr_t> frames;
   std::vector<unwindstack::FrameData> frames_info;
   if (g_debug->config().options() & BACKTRACE_FULL) {
@@ -198,7 +213,7 @@
 void PointerData::Add(const void* ptr, size_t pointer_size) {
   size_t hash_index = 0;
   if (backtrace_enabled_) {
-    hash_index = AddBacktrace(g_debug->config().backtrace_frames());
+    hash_index = AddBacktrace(g_debug->config().backtrace_frames(), pointer_size);
   }
 
   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
@@ -336,11 +351,11 @@
   }
 }
 
-void* PointerData::AddFreed(const void* ptr) {
+void* PointerData::AddFreed(const void* ptr, size_t size_bytes) {
   size_t hash_index = 0;
   size_t num_frames = g_debug->config().free_track_backtrace_num_frames();
   if (num_frames) {
-    hash_index = AddBacktrace(num_frames);
+    hash_index = AddBacktrace(num_frames, size_bytes);
   }
 
   void* last = nullptr;
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 97eec0a..3194bab 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -137,13 +137,13 @@
 
   static void IteratePointers(std::function<void(uintptr_t pointer)> fn);
 
-  static size_t AddBacktrace(size_t num_frames);
+  static size_t AddBacktrace(size_t num_frames, size_t size_bytes);
   static void RemoveBacktrace(size_t hash_index);
 
   static void Add(const void* pointer, size_t size);
   static void Remove(const void* pointer);
 
-  static void* AddFreed(const void* pointer);
+  static void* AddFreed(const void* pointer, size_t size_bytes);
   static void LogFreeError(const FreePointerInfoType& info, size_t usable_size);
   static void LogFreeBacktrace(const void* ptr);
   static void VerifyFreedPointer(const FreePointerInfoType& info);
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 6b046db..3667624 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -160,6 +160,41 @@
 on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
 when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
 
+### backtrace\_min\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of a size greater than or equal to
+**ALLOCATION\_SIZE\_BYTES** will be backtraced. When used in combination
+with the backtrace\_max\_size option, then allocations greater than or
+equal to backtrace\_min\_size and less than or equal to
+backtrace\_max\_size will be backtraced. The backtrace\_size option
+overrides this option, and should not be used at the same time.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
+### backtrace\_max\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of a size less than or equal to
+**ALLOCATION\_SIZE\_BYTES** will be backtraced. When used in combination
+with the backtrace\_min\_size option, then allocations greater than or
+equal to backtrace\_min\_size and less than or equal to
+backtrace\_max\_size will be backtraced. The backtrace\_size option
+overrides this option, and should not be used at the same time.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
+### backtrace\_size=ALLOCATION\_SIZE\_BYTES
+As of U, setting this in combination with the backtrace option means
+that only allocations of size **ALLOCATION\_SIZE\_BYTES** will be backtraced.
+This option overrides the backtrace\_min\_size and the backtrace\_max\_size.
+
+This option can also be used in combination with other tools such
+as [libmemunreachable](https://android.googlesource.com/platform/system/memory/libmemunreachable/+/master/README.md)
+to only get backtraces for sizes of allocations listed as being leaked.
+
 ### backtrace\_full
 As of Q, any time that a backtrace is gathered, a different algorithm is used
 that is extra thorough and can unwind through Java frames. This will run
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 35cda83..617858a 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -522,8 +522,8 @@
 
   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);
+    fill_bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
+    memset(pointer, g_debug->config().fill_free_value(), fill_bytes);
   }
 
   if (g_debug->TrackPointers()) {
@@ -536,7 +536,7 @@
     // frees at the same time and we wind up trying to really free this
     // pointer from another thread, while still trying to free it in
     // this function.
-    pointer = PointerData::AddFreed(pointer);
+    pointer = PointerData::AddFreed(pointer, bytes);
     if (pointer != nullptr) {
       if (g_debug->HeaderEnabled()) {
         pointer = g_debug->GetHeader(pointer)->orig_pointer;
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index d08ba98..0a0eaef 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -779,3 +779,69 @@
       "which does not take a value\n");
   ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
 }
+
+TEST_F(MallocDebugConfigTest, size) {
+  ASSERT_TRUE(InitConfig("backtrace_size=37")) << getFakeLogPrint();
+  ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+  ASSERT_EQ(37U, config->backtrace_min_size_bytes());
+  ASSERT_EQ(37U, config->backtrace_max_size_bytes());
+
+  ASSERT_FALSE(InitConfig("backtrace_size")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_size=0")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_size=-1")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_size'\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_size', value "
+                      "must be >= 1: 0\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_size', value "
+                      "cannot be negative: -1\n" +
+                      usage_string);
+  ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, min_size) {
+  ASSERT_TRUE(InitConfig("backtrace_min_size=9")) << getFakeLogPrint();
+  ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+  ASSERT_EQ(9U, config->backtrace_min_size_bytes());
+  ASSERT_EQ(SIZE_MAX, config->backtrace_max_size_bytes());
+
+  ASSERT_FALSE(InitConfig("backtrace_min_size")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_min_size=0")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_min_size=-1")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size'\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size', "
+                      "value must be >= 1: 0\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_min_size', "
+                      "value cannot be negative: -1\n" +
+                      usage_string);
+  ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, max_size) {
+  ASSERT_TRUE(InitConfig("backtrace_max_size=13")) << getFakeLogPrint();
+  ASSERT_EQ(BACKTRACE_SPECIFIC_SIZES, config->options());
+  ASSERT_EQ(0U, config->backtrace_min_size_bytes());
+  ASSERT_EQ(13U, config->backtrace_max_size_bytes());
+
+  ASSERT_FALSE(InitConfig("backtrace_max_size")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_max_size=0")) << getFakeLogPrint();
+  ASSERT_FALSE(InitConfig("backtrace_max_size=-1")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg("6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size'\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size', "
+                      "value must be >= 1: 0\n" +
+                      usage_string +
+                      "6 malloc_debug malloc_testing: bad value for option 'backtrace_max_size', "
+                      "value cannot be negative: -1\n" +
+                      usage_string);
+  ASSERT_STREQ(log_msg.c_str(), getFakeLogPrint().c_str());
+}
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index ff743ac..961ddd3 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -83,6 +83,14 @@
 
 __END_DECLS
 
+// Change the slow threshold since some tests take more than 2 seconds.
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+  static const char* initial_args[] = {"--slow_threshold_ms=5000"};
+  *args = initial_args;
+  *num_args = 1;
+  return true;
+}
+
 constexpr char DIVIDER[] =
     "6 malloc_debug *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n";
 
@@ -90,7 +98,7 @@
   return __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
 }
 
-static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs.txt";
+static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs";
 
 static constexpr const char BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
 
@@ -100,8 +108,10 @@
     initialized = false;
     resetLogs();
     backtrace_fake_clear_all();
-    // Delete the record data file if it exists.
-    unlink(RECORD_ALLOCS_FILE);
+    if (!record_filename.empty()) {
+      // Delete the record data file if it exists.
+      unlink(record_filename.c_str());
+    }
   }
 
   void TearDown() override {
@@ -116,6 +126,13 @@
     initialized = true;
   }
 
+  void InitRecordAllocs(const char* options) {
+    record_filename = android::base::StringPrintf("%s.%d.txt", RECORD_ALLOCS_FILE, getpid());
+    std::string init(options);
+    init += android::base::StringPrintf(" record_allocs_file=%s", record_filename.c_str());
+    Init(init.c_str());
+  }
+
   void BacktraceDumpOnSignal(bool trigger_with_alloc);
 
   static size_t GetInfoEntrySize(size_t max_frames) {
@@ -126,6 +143,8 @@
 
   bool zygote_child;
 
+  std::string record_filename;
+
   static MallocDispatch dispatch;
 };
 
@@ -2148,7 +2167,7 @@
 }
 #endif
 
-void VerifyRecordAllocs() {
+void VerifyRecordAllocs(const std::string& record_filename) {
   std::string expected;
 
   void* pointer = debug_malloc(10);
@@ -2217,8 +2236,7 @@
 
   // Read all of the contents.
   std::string actual;
-  ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
-  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+  ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -2229,19 +2247,19 @@
 }
 
 TEST_F(MallocDebugTest, record_allocs_no_header) {
-  Init("record_allocs");
+  InitRecordAllocs("record_allocs");
 
-  VerifyRecordAllocs();
+  VerifyRecordAllocs(record_filename);
 }
 
 TEST_F(MallocDebugTest, record_allocs_with_header) {
-  Init("record_allocs front_guard");
+  InitRecordAllocs("record_allocs front_guard");
 
-  VerifyRecordAllocs();
+  VerifyRecordAllocs(record_filename);
 }
 
 TEST_F(MallocDebugTest, record_allocs_max) {
-  Init("record_allocs=5");
+  InitRecordAllocs("record_allocs=5");
 
   std::string expected;
 
@@ -2272,8 +2290,7 @@
 
   // Read all of the contents.
   std::string actual;
-  ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
-  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+  ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -2284,7 +2301,7 @@
 }
 
 TEST_F(MallocDebugTest, record_allocs_thread_done) {
-  Init("record_allocs=5");
+  InitRecordAllocs("record_allocs=5");
 
   static pid_t tid = 0;
   static void* pointer = nullptr;
@@ -2311,8 +2328,7 @@
 
   // Read all of the contents.
   std::string actual;
-  ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
-  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+  ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -2323,13 +2339,13 @@
 }
 
 TEST_F(MallocDebugTest, record_allocs_file_name_fail) {
-  Init("record_allocs=5");
+  InitRecordAllocs("record_allocs=5");
 
   // Delete the special.txt file and create a symbolic link there to
   // make sure the create file will fail.
-  unlink(RECORD_ALLOCS_FILE);
+  unlink(record_filename.c_str());
 
-  ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", RECORD_ALLOCS_FILE));
+  ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
 
   std::string expected;
 
@@ -2350,10 +2366,10 @@
 
   // Read all of the contents.
   std::string actual;
-  ASSERT_FALSE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+  ASSERT_FALSE(android::base::ReadFileToString(record_filename, &actual));
 
   // Unlink the file so the next dump passes.
-  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+  ASSERT_EQ(0, unlink(record_filename.c_str()));
 
   // Dump all of the data accumulated so far.
   ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
@@ -2363,14 +2379,13 @@
   debug_free(pointer);
   expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
 
-  ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
-  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
+  ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   std::string expected_log = android::base::StringPrintf(
       "6 malloc_debug Cannot create record alloc file %s: Too many symbolic links encountered\n",
-      RECORD_ALLOCS_FILE);
+      record_filename.c_str());
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
@@ -2739,3 +2754,178 @@
       "6 malloc_debug Unreachable check failed, run setenforce 0 and try again.\n",
       getFakeLogPrint().c_str());
 }
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_size) {
+  Init("leak_track backtrace backtrace_size=120");
+
+  backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+  void* pointer1 = debug_malloc(119);
+  ASSERT_TRUE(pointer1 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+  void* pointer2 = debug_malloc(120);
+  ASSERT_TRUE(pointer2 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+  void* pointer3 = debug_malloc(121);
+  ASSERT_TRUE(pointer3 != nullptr);
+
+  debug_finalize();
+  initialized = false;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 121 at %p (leak 1 of 3)\n", pointer3);
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 120 at %p (leak 2 of 3)\n", pointer2);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0x1000\n";
+  expected_log += "6 malloc_debug   #01 pc 0x2000\n";
+  expected_log += "6 malloc_debug   #02 pc 0x3000\n";
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 119 at %p (leak 3 of 3)\n", pointer1);
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_min_size) {
+  Init("leak_track backtrace backtrace_min_size=1000");
+
+  backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+  void* pointer1 = debug_malloc(500);
+  ASSERT_TRUE(pointer1 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+  void* pointer2 = debug_malloc(1000);
+  ASSERT_TRUE(pointer2 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+  void* pointer3 = debug_malloc(1001);
+  ASSERT_TRUE(pointer3 != nullptr);
+
+  debug_finalize();
+  initialized = false;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 1 of 3)\n",
+      pointer3);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0xa000\n";
+  expected_log += "6 malloc_debug   #01 pc 0xb000\n";
+  expected_log += "6 malloc_debug   #02 pc 0xc000\n";
+  expected_log += "6 malloc_debug   #03 pc 0xd000\n";
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 2 of 3)\n",
+      pointer2);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0x1000\n";
+  expected_log += "6 malloc_debug   #01 pc 0x2000\n";
+  expected_log += "6 malloc_debug   #02 pc 0x3000\n";
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 500 at %p (leak 3 of 3)\n", pointer1);
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_max_size) {
+  Init("leak_track backtrace backtrace_max_size=1000");
+
+  backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+  void* pointer1 = debug_malloc(1000);
+  ASSERT_TRUE(pointer1 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+  void* pointer2 = debug_malloc(1001);
+  ASSERT_TRUE(pointer2 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+  void* pointer3 = debug_malloc(5000);
+  ASSERT_TRUE(pointer3 != nullptr);
+
+  debug_finalize();
+  initialized = false;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 5000 at %p (leak 1 of 3)\n",
+      pointer3);
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 2 of 3)\n",
+      pointer2);
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 3 of 3)\n",
+      pointer1);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0x1000\n";
+  expected_log += "6 malloc_debug   #01 pc 0x2000\n";
+  expected_log += "6 malloc_debug   #02 pc 0x3000\n";
+
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_only_some_sizes_with_backtrace_min_max_size) {
+  Init("leak_track backtrace backtrace_min_size=50 backtrace_max_size=1000");
+
+  backtrace_fake_add(std::vector<uintptr_t>{0x1000, 0x2000, 0x3000});
+
+  void* pointer1 = debug_malloc(49);
+  ASSERT_TRUE(pointer1 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xa000, 0xb000, 0xc000, 0xd000});
+
+  void* pointer2 = debug_malloc(50);
+  ASSERT_TRUE(pointer2 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0xfe000, 0xde000, 0xce000, 0xbe000, 0xae000});
+
+  void* pointer3 = debug_malloc(1000);
+  ASSERT_TRUE(pointer3 != nullptr);
+
+  backtrace_fake_add(std::vector<uintptr_t>{0x1a000, 0x1b000, 0x1c000, 0x1d000, 0x1e000});
+
+  void* pointer4 = debug_malloc(1001);
+  ASSERT_TRUE(pointer4 != nullptr);
+
+  debug_finalize();
+  initialized = false;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1001 at %p (leak 1 of 4)\n",
+      pointer4);
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 1000 at %p (leak 2 of 4)\n",
+      pointer3);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0xa000\n";
+  expected_log += "6 malloc_debug   #01 pc 0xb000\n";
+  expected_log += "6 malloc_debug   #02 pc 0xc000\n";
+  expected_log += "6 malloc_debug   #03 pc 0xd000\n";
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 50 at %p (leak 3 of 4)\n", pointer2);
+  expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
+  expected_log += "6 malloc_debug   #00 pc 0x1000\n";
+  expected_log += "6 malloc_debug   #01 pc 0x2000\n";
+  expected_log += "6 malloc_debug   #02 pc 0x3000\n";
+
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ malloc_testing leaked block of size 49 at %p (leak 4 of 4)\n", pointer1);
+
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
diff --git a/linker/linker_transparent_hugepage_support.cpp b/linker/linker_transparent_hugepage_support.cpp
index 65ba4cd..0631577 100644
--- a/linker/linker_transparent_hugepage_support.cpp
+++ b/linker/linker_transparent_hugepage_support.cpp
@@ -39,6 +39,6 @@
       return false;
     }
     return enabled.find("[never]") == std::string::npos;
-  };
+  }();
   return transparent_hugepages_supported;
 }