[tracing] Sanitize process memory dump names for background mode
For background mode:
1. ProcessMemoryDump knows the level of detail.
2. It checks for dump name to be present in whitelist. If not then
returns a dummy mad. The strings are stripped of numbers (ids) and
checked against a whitelist of dump names.
3. Disable creating new dumps just to mark suballocations.
4. Disable creation of global allocator dumps.
5. Disable string attributes in allocator dumps.
Also creates a new whitelist file to handle whitelisting logic.
BUG=613198
TBR=shess@chromium.org, jochen@chromium.org
Review-Url: https://codereview.chromium.org/2006943003
Cr-Commit-Position: refs/heads/master@{#397918}
CrOS-Libchrome-Original-Commit: 448e5edbdae14ce8b983726b9d89d248f3d52d23
diff --git a/base/trace_event/java_heap_dump_provider_android_unittest.cc b/base/trace_event/java_heap_dump_provider_android_unittest.cc
index 6b31bd6..44e4387 100644
--- a/base/trace_event/java_heap_dump_provider_android_unittest.cc
+++ b/base/trace_event/java_heap_dump_provider_android_unittest.cc
@@ -12,8 +12,9 @@
TEST(JavaHeapDumpProviderTest, JavaHeapDump) {
auto jhdp = JavaHeapDumpProvider::GetInstance();
- std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr));
MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<ProcessMemoryDump> pmd(
+ new ProcessMemoryDump(nullptr, dump_args));
jhdp->OnMemoryDump(dump_args, pmd.get());
}
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc
index f9b5799..7583763 100644
--- a/base/trace_event/memory_allocator_dump.cc
+++ b/base/trace_event/memory_allocator_dump.cc
@@ -80,6 +80,13 @@
void MemoryAllocatorDump::AddString(const char* name,
const char* units,
const std::string& value) {
+ // String attributes are disabled in background mode.
+ if (process_memory_dump_->dump_args().level_of_detail ==
+ MemoryDumpLevelOfDetail::BACKGROUND) {
+ NOTREACHED();
+ return;
+ }
+
attributes_->BeginDictionary(name);
attributes_->SetString("type", kTypeString);
attributes_->SetString("units", units);
diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc
index 359f081..1bf9715 100644
--- a/base/trace_event/memory_allocator_dump_unittest.cc
+++ b/base/trace_event/memory_allocator_dump_unittest.cc
@@ -129,8 +129,8 @@
TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
FakeMemoryAllocatorDumpProvider fmadp;
- ProcessMemoryDump pmd(new MemoryDumpSessionState);
MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
+ ProcessMemoryDump pmd(new MemoryDumpSessionState, dump_args);
fmadp.OnMemoryDump(dump_args, &pmd);
@@ -176,7 +176,8 @@
#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
FakeMemoryAllocatorDumpProvider fmadp;
- ProcessMemoryDump pmd(new MemoryDumpSessionState);
+ MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
+ ProcessMemoryDump pmd(new MemoryDumpSessionState, dump_args);
pmd.CreateAllocatorDump("foo_allocator");
pmd.CreateAllocatorDump("bar_allocator/heap");
ASSERT_DEATH(pmd.CreateAllocatorDump("foo_allocator"), "");
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index a2628d9..4e2cc60 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -16,7 +16,6 @@
#include "base/memory/ptr_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/timer/timer.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
@@ -24,6 +23,7 @@
#include "base/trace_event/malloc_dump_provider.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/memory_dump_session_state.h"
+#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
@@ -49,15 +49,6 @@
StaticAtomicSequenceNumber g_next_guid;
MemoryDumpManager* g_instance_for_testing = nullptr;
-// The names of dump providers whitelisted for background tracing. Dump
-// providers can be added here only if the background mode dump has very
-// less performance and memory overhead.
-const char* const kDumpProviderWhitelist[] = {
- // TODO(ssid): Fill this list with dump provider names which support
- // background mode, crbug.com/613198.
- nullptr, // End of list marker.
-};
-
// Callback wrapper to hook upon the completion of RequestGlobalDump() and
// inject trace markers.
void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback,
@@ -100,16 +91,6 @@
GetterFunctPtr const getter_function;
};
-// Checks if the name is in the given |list|. Last element of the list should be
-// an empty string.
-bool IsNameInList(const char* name, const char* const* list) {
- for (size_t i = 0; list[i] != nullptr; ++i) {
- if (strcmp(name, list[i]) == 0)
- return true;
- }
- return false;
-}
-
} // namespace
// static
@@ -150,7 +131,6 @@
: delegate_(nullptr),
is_coordinator_(false),
memory_tracing_enabled_(0),
- dump_provider_whitelist_(kDumpProviderWhitelist),
tracing_process_id_(kInvalidTracingProcessId),
dumper_registrations_ignored_for_testing_(false),
heap_profiling_enabled_(false) {
@@ -274,8 +254,7 @@
if (dumper_registrations_ignored_for_testing_)
return;
- bool whitelisted_for_background_mode =
- IsNameInList(name, dump_provider_whitelist_);
+ bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name);
scoped_refptr<MemoryDumpProviderInfo> mdpinfo =
new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options,
whitelisted_for_background_mode);
@@ -561,9 +540,10 @@
// process), non-zero when the coordinator process creates dumps on behalf
// of child processes (see crbug.com/461788).
ProcessId target_pid = mdpinfo->options.target_pid;
- ProcessMemoryDump* pmd =
- pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(target_pid);
MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail};
+ ProcessMemoryDump* pmd =
+ pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(target_pid,
+ args);
bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd);
mdpinfo->consecutive_failures =
dump_successful ? 0 : mdpinfo->consecutive_failures + 1;
@@ -770,11 +750,12 @@
}
ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState::
- GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) {
+ GetOrCreateMemoryDumpContainerForProcess(ProcessId pid,
+ const MemoryDumpArgs& dump_args) {
auto iter = process_dumps.find(pid);
if (iter == process_dumps.end()) {
std::unique_ptr<ProcessMemoryDump> new_pmd(
- new ProcessMemoryDump(session_state));
+ new ProcessMemoryDump(session_state, dump_args));
iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first;
}
return iter->second.get();
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 2b1bb01..fd2226a 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -141,11 +141,6 @@
dumper_registrations_ignored_for_testing_ = ignored;
}
- // Resets the dump provider whitelist to the list given.
- void set_dump_provider_whitelist_for_testing(const char* const* list) {
- dump_provider_whitelist_ = list;
- }
-
private:
friend std::default_delete<MemoryDumpManager>; // For the testing instance.
friend struct DefaultSingletonTraits<MemoryDumpManager>;
@@ -230,7 +225,9 @@
~ProcessMemoryDumpAsyncState();
// Gets or creates the memory dump container for the given target process.
- ProcessMemoryDump* GetOrCreateMemoryDumpContainerForProcess(ProcessId pid);
+ ProcessMemoryDump* GetOrCreateMemoryDumpContainerForProcess(
+ ProcessId pid,
+ const MemoryDumpArgs& dump_args);
// A map of ProcessId -> ProcessMemoryDump, one for each target process
// being dumped from the current process. Typically each process dumps only
@@ -365,9 +362,6 @@
// affinity.
std::unique_ptr<Thread> dump_thread_;
- // List of names of the dump providers whitelisted for background mode.
- const char* const* dump_provider_whitelist_;
-
// The unique id of the child process. This is created only for tracing and is
// expected to be valid only when tracing is enabled.
uint64_t tracing_process_id_;
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 6fa6624..2b49228 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -23,6 +23,7 @@
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_config_memory_test_util.h"
@@ -1112,7 +1113,7 @@
TEST_F(MemoryDumpManagerTest, TestWhitelistingMDP) {
InitializeMemoryDumpManager(false /* is_coordinator */);
- mdm_->set_dump_provider_whitelist_for_testing(kTestMDPWhitelist);
+ SetDumpProviderWhitelistForTesting(kTestMDPWhitelist);
std::unique_ptr<MockMemoryDumpProvider> mdp1(new MockMemoryDumpProvider);
RegisterDumpProvider(mdp1.get());
std::unique_ptr<MockMemoryDumpProvider> mdp2(new MockMemoryDumpProvider);
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
index 79ab793..c899ea9 100644
--- a/base/trace_event/memory_dump_provider.h
+++ b/base/trace_event/memory_dump_provider.h
@@ -15,12 +15,6 @@
class ProcessMemoryDump;
-// Args passed to OnMemoryDump(). This is to avoid rewriting all the subclasses
-// in the codebase when extending the MemoryDumpProvider API.
-struct MemoryDumpArgs {
- MemoryDumpLevelOfDetail level_of_detail;
-};
-
// The contract interface that memory dump providers must implement.
class BASE_EXPORT MemoryDumpProvider {
public:
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h
index f78e31c..74ec5dc 100644
--- a/base/trace_event/memory_dump_request_args.h
+++ b/base/trace_event/memory_dump_request_args.h
@@ -60,6 +60,13 @@
MemoryDumpLevelOfDetail level_of_detail;
};
+// Args for ProcessMemoryDump and passed to OnMemoryDump calls for memory dump
+// providers. Dump providers are expected to read the args for creating dumps.
+struct MemoryDumpArgs {
+ // Specifies how detailed the dumps should be.
+ MemoryDumpLevelOfDetail level_of_detail;
+};
+
using MemoryDumpCallback = Callback<void(uint64_t dump_guid, bool success)>;
BASE_EXPORT const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type);
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
new file mode 100644
index 0000000..03dc108
--- /dev/null
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -0,0 +1,88 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_infra_background_whitelist.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include <string>
+
+namespace base {
+namespace trace_event {
+namespace {
+
+// The names of dump providers whitelisted for background tracing. Dump
+// providers can be added here only if the background mode dump has very
+// less performance and memory overhead.
+const char* const kDumpProviderWhitelist[] = {
+ // TODO(ssid): Fill this list with dump provider names which support
+ // background mode, crbug.com/613198.
+ nullptr // End of list marker.
+};
+
+// A list of string names that are allowed for the memory allocator dumps in
+// background mode.
+const char* const kAllocatorDumpNameWhitelist[] = {
+ // TODO(ssid): Fill this list with dump names, crbug.com/613198.
+ nullptr // End of list marker.
+};
+
+const char* const* g_dump_provider_whitelist = kDumpProviderWhitelist;
+const char* const* g_allocator_dump_name_whitelist =
+ kAllocatorDumpNameWhitelist;
+
+} // namespace
+
+bool IsMemoryDumpProviderWhitelisted(const char* mdp_name) {
+ for (size_t i = 0; g_dump_provider_whitelist[i] != nullptr; ++i) {
+ if (strcmp(mdp_name, g_dump_provider_whitelist[i]) == 0)
+ return true;
+ }
+ return false;
+}
+
+bool IsMemoryAllocatorDumpNameWhitelisted(const std::string& name) {
+ // Remove special characters, numbers (including hexadecimal which are marked
+ // by '0x') from the given string.
+ const size_t length = name.size();
+ std::string stripped_str;
+ stripped_str.reserve(length);
+ bool parsing_hex = false;
+ for (size_t i = 0; i < length; ++i) {
+ if (parsing_hex) {
+ if (isxdigit(name[i])) {
+ continue;
+ } else {
+ parsing_hex = false;
+ }
+ }
+ if (i + 1 < length && name[i] == '0' && name[i + 1] == 'x') {
+ parsing_hex = true;
+ ++i;
+ } else if (isalpha(name[i]) ||
+ (name[i] == '/' && stripped_str.back() != '/')) {
+ // Do not add successive '/'(s) in |stripped_str|.
+ stripped_str.push_back(name[i]);
+ }
+ }
+
+ for (size_t i = 0; g_allocator_dump_name_whitelist[i] != nullptr; ++i) {
+ if (stripped_str == g_allocator_dump_name_whitelist[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void SetDumpProviderWhitelistForTesting(const char* const* list) {
+ g_dump_provider_whitelist = list;
+}
+
+void SetAllocatorDumpNameWhitelistForTesting(const char* const* list) {
+ g_allocator_dump_name_whitelist = list;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/memory_infra_background_whitelist.h b/base/trace_event/memory_infra_background_whitelist.h
new file mode 100644
index 0000000..b8d704a
--- /dev/null
+++ b/base/trace_event/memory_infra_background_whitelist.h
@@ -0,0 +1,33 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
+#define BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
+
+// This file contains the whitelists for background mode to limit the tracing
+// overhead and remove sensitive information from traces.
+
+#include <string>
+
+#include "base/base_export.h"
+
+namespace base {
+namespace trace_event {
+
+// Checks if the given |mdp_name| is in the whitelist.
+bool BASE_EXPORT IsMemoryDumpProviderWhitelisted(const char* mdp_name);
+
+// Checks if the given |name| matches any of the whitelisted patterns.
+bool BASE_EXPORT IsMemoryAllocatorDumpNameWhitelisted(const std::string& name);
+
+// The whitelist is replaced with the given list for tests. The last element of
+// the list must be nullptr.
+void BASE_EXPORT SetDumpProviderWhitelistForTesting(const char* const* list);
+void BASE_EXPORT
+SetAllocatorDumpNameWhitelistForTesting(const char* const* list);
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
index ada6aa4..8269892 100644
--- a/base/trace_event/process_memory_dump.cc
+++ b/base/trace_event/process_memory_dump.cc
@@ -12,6 +12,7 @@
#include "base/process/process_metrics.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/heap_profiler_heap_dump_writer.h"
+#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/process_memory_totals.h"
#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"
@@ -48,6 +49,9 @@
} // namespace
+// static
+bool ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = false;
+
#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
// static
size_t ProcessMemoryDump::GetSystemPageSize() {
@@ -148,10 +152,12 @@
#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED)
ProcessMemoryDump::ProcessMemoryDump(
- scoped_refptr<MemoryDumpSessionState> session_state)
+ scoped_refptr<MemoryDumpSessionState> session_state,
+ const MemoryDumpArgs& dump_args)
: has_process_totals_(false),
has_process_mmaps_(false),
- session_state_(std::move(session_state)) {}
+ session_state_(std::move(session_state)),
+ dump_args_(dump_args) {}
ProcessMemoryDump::~ProcessMemoryDump() {}
@@ -170,6 +176,13 @@
MemoryAllocatorDump* ProcessMemoryDump::AddAllocatorDumpInternal(
std::unique_ptr<MemoryAllocatorDump> mad) {
+ // In background mode return the black hole dump, if invalid dump name is
+ // given.
+ if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND &&
+ !IsMemoryAllocatorDumpNameWhitelisted(mad->absolute_name())) {
+ return GetBlackHoleMad();
+ }
+
auto insertion_result = allocator_dumps_.insert(
std::make_pair(mad->absolute_name(), std::move(mad)));
MemoryAllocatorDump* inserted_mad = insertion_result.first->second.get();
@@ -181,7 +194,11 @@
MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump(
const std::string& absolute_name) const {
auto it = allocator_dumps_.find(absolute_name);
- return it == allocator_dumps_.end() ? nullptr : it->second.get();
+ if (it != allocator_dumps_.end())
+ return it->second.get();
+ if (black_hole_mad_)
+ return black_hole_mad_.get();
+ return nullptr;
}
MemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump(
@@ -192,6 +209,10 @@
MemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump(
const MemoryAllocatorDumpGuid& guid) {
+ // Global dumps are disabled in background mode.
+ if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND)
+ return GetBlackHoleMad();
+
// A shared allocator dump can be shared within a process and the guid could
// have been created already.
MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
@@ -206,6 +227,10 @@
MemoryAllocatorDump* ProcessMemoryDump::CreateWeakSharedGlobalAllocatorDump(
const MemoryAllocatorDumpGuid& guid) {
+ // Global dumps are disabled in background mode.
+ if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND)
+ return GetBlackHoleMad();
+
MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
if (mad)
return mad;
@@ -328,10 +353,21 @@
void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source,
const std::string& target_node_name) {
+ // Do not create new dumps for suballocations in background mode.
+ if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND)
+ return;
+
std::string child_mad_name = target_node_name + "/__" + source.ToString();
MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name);
AddOwnershipEdge(source, target_child_mad->guid());
}
+MemoryAllocatorDump* ProcessMemoryDump::GetBlackHoleMad() {
+ DCHECK(is_black_hole_non_fatal_for_testing_);
+ if (!black_hole_mad_)
+ black_hole_mad_.reset(new MemoryAllocatorDump("discarded", this));
+ return black_hole_mad_.get();
+}
+
} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h
index c18e10c..d020c7d 100644
--- a/base/trace_event/process_memory_dump.h
+++ b/base/trace_event/process_memory_dump.h
@@ -16,6 +16,7 @@
#include "base/memory/scoped_vector.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_allocator_dump_guid.h"
+#include "base/trace_event/memory_dump_request_args.h"
#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_maps.h"
#include "base/trace_event/process_memory_totals.h"
@@ -67,7 +68,8 @@
static size_t CountResidentBytes(void* start_address, size_t mapped_size);
#endif
- ProcessMemoryDump(scoped_refptr<MemoryDumpSessionState> session_state);
+ ProcessMemoryDump(scoped_refptr<MemoryDumpSessionState> session_state,
+ const MemoryDumpArgs& dump_args);
~ProcessMemoryDump();
// Creates a new MemoryAllocatorDump with the given name and returns the
@@ -175,10 +177,16 @@
const HeapDumpsMap& heap_dumps() const { return heap_dumps_; }
+ const MemoryDumpArgs& dump_args() const { return dump_args_; }
+
private:
+ FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, BackgroundModeTest);
+
MemoryAllocatorDump* AddAllocatorDumpInternal(
std::unique_ptr<MemoryAllocatorDump> mad);
+ MemoryAllocatorDump* GetBlackHoleMad();
+
ProcessMemoryTotals process_totals_;
bool has_process_totals_;
@@ -194,6 +202,18 @@
// Keeps track of relationships between MemoryAllocatorDump(s).
std::vector<MemoryAllocatorDumpEdge> allocator_dumps_edges_;
+ // Level of detail of the current dump.
+ const MemoryDumpArgs dump_args_;
+
+ // This allocator dump is returned when an invalid dump is created in
+ // background mode. The attributes of the dump are ignored and not added to
+ // the trace.
+ std::unique_ptr<MemoryAllocatorDump> black_hole_mad_;
+
+ // When set to true, the DCHECK(s) for invalid dump creations on the
+ // background mode are disabled for testing.
+ static bool is_black_hole_non_fatal_for_testing_;
+
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
};
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc
index 938c184..e31aeaa 100644
--- a/base/trace_event/process_memory_dump_unittest.cc
+++ b/base/trace_event/process_memory_dump_unittest.cc
@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "base/process/process_metrics.h"
#include "base/trace_event/memory_allocator_dump_guid.h"
+#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/trace_event_argument.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,14 +18,20 @@
namespace trace_event {
namespace {
+
+const MemoryDumpArgs kDetailedDumpArgs = {MemoryDumpLevelOfDetail::DETAILED};
+const char* const kTestDumpNameWhitelist[] = {"Whitelisted/TestName", nullptr};
+
TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) {
auto it = pmd.heap_dumps().find(name);
return it == pmd.heap_dumps().end() ? nullptr : it->second.get();
}
+
} // namespace
TEST(ProcessMemoryDumpTest, Clear) {
- std::unique_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr));
+ std::unique_ptr<ProcessMemoryDump> pmd1(
+ new ProcessMemoryDump(nullptr, kDetailedDumpArgs));
pmd1->CreateAllocatorDump("mad1");
pmd1->CreateAllocatorDump("mad2");
ASSERT_FALSE(pmd1->allocator_dumps().empty());
@@ -92,7 +99,7 @@
session_state->SetTypeNameDeduplicator(
WrapUnique(new TypeNameDeduplicator));
std::unique_ptr<ProcessMemoryDump> pmd1(
- new ProcessMemoryDump(session_state.get()));
+ new ProcessMemoryDump(session_state.get(), kDetailedDumpArgs));
auto mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1");
auto mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2");
pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid());
@@ -100,7 +107,7 @@
pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump2");
std::unique_ptr<ProcessMemoryDump> pmd2(
- new ProcessMemoryDump(session_state.get()));
+ new ProcessMemoryDump(session_state.get(), kDetailedDumpArgs));
auto mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1");
auto mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2");
pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid());
@@ -156,7 +163,8 @@
}
TEST(ProcessMemoryDumpTest, Suballocations) {
- std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr));
+ std::unique_ptr<ProcessMemoryDump> pmd(
+ new ProcessMemoryDump(nullptr, kDetailedDumpArgs));
const std::string allocator_dump_name = "fakealloc/allocated_objects";
pmd->CreateAllocatorDump(allocator_dump_name);
@@ -200,7 +208,8 @@
}
TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) {
- std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr));
+ std::unique_ptr<ProcessMemoryDump> pmd(
+ new ProcessMemoryDump(nullptr, kDetailedDumpArgs));
MemoryAllocatorDumpGuid shared_mad_guid(1);
auto shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid);
ASSERT_EQ(shared_mad_guid, shared_mad1->guid());
@@ -223,6 +232,53 @@
ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags());
}
+TEST(ProcessMemoryDumpTest, BackgroundModeTest) {
+ MemoryDumpArgs background_args = {MemoryDumpLevelOfDetail::BACKGROUND};
+ std::unique_ptr<ProcessMemoryDump> pmd(
+ new ProcessMemoryDump(nullptr, background_args));
+ ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = true;
+ SetAllocatorDumpNameWhitelistForTesting(kTestDumpNameWhitelist);
+ MemoryAllocatorDump* black_hole_mad = pmd->GetBlackHoleMad();
+
+ // Invalid dump names.
+ EXPECT_EQ(black_hole_mad,
+ pmd->CreateAllocatorDump("NotWhitelisted/TestName"));
+ EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("TestName"));
+ EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("Whitelisted/Test"));
+ EXPECT_EQ(black_hole_mad,
+ pmd->CreateAllocatorDump("Not/Whitelisted/TestName"));
+ EXPECT_EQ(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted/TestName/Google"));
+ EXPECT_EQ(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted/TestName/0x1a2Google"));
+ EXPECT_EQ(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted/TestName/__12/Google"));
+
+ // Global dumps.
+ MemoryAllocatorDumpGuid guid(1);
+ EXPECT_EQ(black_hole_mad, pmd->CreateSharedGlobalAllocatorDump(guid));
+ EXPECT_EQ(black_hole_mad, pmd->CreateWeakSharedGlobalAllocatorDump(guid));
+ EXPECT_EQ(black_hole_mad, pmd->GetSharedGlobalAllocatorDump(guid));
+
+ // Suballocations.
+ pmd->AddSuballocation(guid, "malloc/allocated_objects");
+ EXPECT_EQ(0u, pmd->allocator_dumps_edges_.size());
+ EXPECT_EQ(0u, pmd->allocator_dumps_.size());
+
+ // Valid dump names.
+ EXPECT_NE(black_hole_mad, pmd->CreateAllocatorDump("Whitelisted/TestName"));
+ EXPECT_NE(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted/TestName0xA1b2"));
+ EXPECT_NE(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted/TestName_123"));
+ EXPECT_NE(black_hole_mad,
+ pmd->CreateAllocatorDump("Whitelisted_12/0xaB/TestName"));
+
+ // GetAllocatorDump is consistent.
+ EXPECT_EQ(black_hole_mad, pmd->GetAllocatorDump("NotWhitelisted/TestName"));
+ EXPECT_NE(black_hole_mad, pmd->GetAllocatorDump("Whitelisted/TestName"));
+}
+
#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
TEST(ProcessMemoryDumpTest, CountResidentBytes) {
const size_t page_size = ProcessMemoryDump::GetSystemPageSize();
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi
index 4335ea1..f915780 100644
--- a/base/trace_event/trace_event.gypi
+++ b/base/trace_event/trace_event.gypi
@@ -35,6 +35,8 @@
'trace_event/memory_dump_request_args.h',
'trace_event/memory_dump_session_state.cc',
'trace_event/memory_dump_session_state.h',
+ 'trace_event/memory_infra_background_whitelist.cc',
+ 'trace_event/memory_infra_background_whitelist.h',
'trace_event/process_memory_dump.cc',
'trace_event/process_memory_dump.h',
'trace_event/process_memory_maps.cc',