1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ 6 #define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ 7 8 #include "base/allocator/buildflags.h" 9 #include "base/base_export.h" 10 #include "base/functional/callback.h" 11 #include "base/memory/raw_ptr.h" 12 #include "base/memory/singleton.h" 13 #include "base/synchronization/lock.h" 14 #include "base/time/time.h" 15 #include "base/trace_event/memory_dump_provider.h" 16 #include "build/build_config.h" 17 #include "partition_alloc/buildflags.h" 18 19 #if PA_BUILDFLAG(USE_PARTITION_ALLOC) 20 #include "partition_alloc/partition_stats.h" // nogncheck 21 #endif 22 23 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ 24 BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) 25 #define MALLOC_MEMORY_TRACING_SUPPORTED 26 #endif 27 28 namespace base { 29 namespace trace_event { 30 31 class MemoryAllocatorDump; 32 33 // Dump provider which collects process-wide memory stats. 34 class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider { 35 public: 36 // Name of the allocated_objects dump. Use this to declare suballocator dumps 37 // from other dump providers. 38 static const char kAllocatedObjects[]; 39 40 static MallocDumpProvider* GetInstance(); 41 42 // The Extreme LUD is implemented in //components/gwp_asan, which //base 43 // cannot depend on. The following API allows an injection of stats-report 44 // function of the Extreme LUD. 45 struct ExtremeLUDStats { 46 #if PA_BUILDFLAG(USE_PARTITION_ALLOC) 47 // This default-constructs to be zero'ed. 48 partition_alloc::LightweightQuarantineStats lq_stats{0}; 49 #endif 50 size_t capacity_in_bytes = 0; 51 }; 52 struct ExtremeLUDStatsSet { 53 ExtremeLUDStats for_small_objects{}; 54 ExtremeLUDStats for_large_objects{}; 55 }; 56 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 57 using ExtremeLUDGetStatsCallback = RepeatingCallback<ExtremeLUDStatsSet()>; 58 static void SetExtremeLUDGetStatsCallback( 59 ExtremeLUDGetStatsCallback callback); 60 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 61 62 MallocDumpProvider(const MallocDumpProvider&) = delete; 63 MallocDumpProvider& operator=(const MallocDumpProvider&) = delete; 64 65 // MemoryDumpProvider implementation. 66 bool OnMemoryDump(const MemoryDumpArgs& args, 67 ProcessMemoryDump* pmd) override; 68 69 private: 70 struct CumulativeEludStats { 71 size_t quarantined_bytes = 0; 72 size_t quarantined_count = 0; 73 size_t miss_count = 0; 74 }; 75 76 friend struct DefaultSingletonTraits<MallocDumpProvider>; 77 78 MallocDumpProvider(); 79 ~MallocDumpProvider() override; 80 81 void ReportPerMinuteStats(uint64_t syscall_count, 82 size_t cumulative_brp_quarantined_bytes, 83 size_t cumulative_brp_quarantined_count, 84 const ExtremeLUDStats& elud_stats_for_small_objects, 85 const ExtremeLUDStats& elud_stats_for_large_objects, 86 MemoryAllocatorDump* malloc_dump, 87 MemoryAllocatorDump* partition_alloc_dump, 88 MemoryAllocatorDump* elud_dump_for_small_objects, 89 MemoryAllocatorDump* elud_dump_for_large_objects); 90 91 bool emit_metrics_on_memory_dump_ 92 GUARDED_BY(emit_metrics_on_memory_dump_lock_) = true; 93 base::Lock emit_metrics_on_memory_dump_lock_; 94 95 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 96 // Returns a reference to the injected stats-report function of the Extreme 97 // LUD. The returned callback is_null() if the Extreme LUD is not enabled. 98 static ExtremeLUDGetStatsCallback& GetExtremeLUDGetStatsCallback(); 99 // To be accurate, this requires the dump provider to be created very early, 100 // which is the case. The alternative would be to drop the first data point, 101 // which is not desirable as early process activity is highly relevant. 102 base::TimeTicks last_memory_dump_time_ = base::TimeTicks::Now(); 103 uint64_t last_syscall_count_ = 0; 104 size_t last_cumulative_brp_quarantined_bytes_ = 0; 105 size_t last_cumulative_brp_quarantined_count_ = 0; 106 CumulativeEludStats last_cumulative_elud_stats_for_small_objects_{0}; 107 CumulativeEludStats last_cumulative_elud_stats_for_large_objects_{0}; 108 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 109 }; 110 111 #if PA_BUILDFLAG(USE_PARTITION_ALLOC) 112 // This class is used to invert the dependency of PartitionAlloc on the 113 // PartitionAllocMemoryDumpProvider. This implements an interface that will 114 // be called with memory statistics for each bucket in the allocator. 115 class BASE_EXPORT MemoryDumpPartitionStatsDumper final 116 : public partition_alloc::PartitionStatsDumper { 117 public: 118 MemoryDumpPartitionStatsDumper(const char* root_name, 119 ProcessMemoryDump* memory_dump, 120 MemoryDumpLevelOfDetail level_of_detail); 121 122 static constexpr char kPartitionsDumpName[] = "partitions"; 123 124 // PartitionStatsDumper implementation. 125 void PartitionDumpTotals( 126 const char* partition_name, 127 const partition_alloc::PartitionMemoryStats*) override; 128 void PartitionsDumpBucketStats( 129 const char* partition_name, 130 const partition_alloc::PartitionBucketMemoryStats*) override; 131 132 size_t total_mmapped_bytes() const { return total_mmapped_bytes_; } 133 size_t total_resident_bytes() const { return total_resident_bytes_; } 134 size_t total_active_bytes() const { return total_active_bytes_; } 135 size_t total_active_count() const { return total_active_count_; } 136 uint64_t syscall_count() const { return syscall_count_; } 137 size_t cumulative_brp_quarantined_bytes() const { 138 return cumulative_brp_quarantined_bytes_; 139 } 140 size_t cumulative_brp_quarantined_count() const { 141 return cumulative_brp_quarantined_count_; 142 } 143 144 private: 145 const char* root_name_; 146 raw_ptr<base::trace_event::ProcessMemoryDump> memory_dump_; 147 uint64_t uid_ = 0; 148 size_t total_mmapped_bytes_ = 0; 149 size_t total_resident_bytes_ = 0; 150 size_t total_active_bytes_ = 0; 151 size_t total_active_count_ = 0; 152 uint64_t syscall_count_ = 0; 153 size_t cumulative_brp_quarantined_bytes_ = 0; 154 size_t cumulative_brp_quarantined_count_ = 0; 155 bool detailed_; 156 }; 157 158 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC) 159 160 } // namespace trace_event 161 } // namespace base 162 163 #endif // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ 164