xref: /aosp_15_r20/external/libchrome/base/debug/activity_analyzer.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/debug/activity_analyzer.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <algorithm>
8*635a8641SAndroid Build Coastguard Worker #include <utility>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include "base/files/file.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/files/file_path.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/files/memory_mapped_file.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/stl_util.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker namespace base {
21*635a8641SAndroid Build Coastguard Worker namespace debug {
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker namespace {
24*635a8641SAndroid Build Coastguard Worker // An empty snapshot that can be returned when there otherwise is none.
25*635a8641SAndroid Build Coastguard Worker LazyInstance<ActivityUserData::Snapshot>::Leaky g_empty_user_data_snapshot;
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker // DO NOT CHANGE VALUES. This is logged persistently in a histogram.
28*635a8641SAndroid Build Coastguard Worker enum AnalyzerCreationError {
29*635a8641SAndroid Build Coastguard Worker   kInvalidMemoryMappedFile,
30*635a8641SAndroid Build Coastguard Worker   kPmaBadFile,
31*635a8641SAndroid Build Coastguard Worker   kPmaUninitialized,
32*635a8641SAndroid Build Coastguard Worker   kPmaDeleted,
33*635a8641SAndroid Build Coastguard Worker   kPmaCorrupt,
34*635a8641SAndroid Build Coastguard Worker   kAnalyzerCreationErrorMax  // Keep this last.
35*635a8641SAndroid Build Coastguard Worker };
36*635a8641SAndroid Build Coastguard Worker 
LogAnalyzerCreationError(AnalyzerCreationError error)37*635a8641SAndroid Build Coastguard Worker void LogAnalyzerCreationError(AnalyzerCreationError error) {
38*635a8641SAndroid Build Coastguard Worker   UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.AnalyzerCreationError",
39*635a8641SAndroid Build Coastguard Worker                             error, kAnalyzerCreationErrorMax);
40*635a8641SAndroid Build Coastguard Worker }
41*635a8641SAndroid Build Coastguard Worker 
42*635a8641SAndroid Build Coastguard Worker }  // namespace
43*635a8641SAndroid Build Coastguard Worker 
44*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::Snapshot::Snapshot() = default;
45*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::Snapshot::~Snapshot() = default;
46*635a8641SAndroid Build Coastguard Worker 
ThreadActivityAnalyzer(const ThreadActivityTracker & tracker)47*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::ThreadActivityAnalyzer(
48*635a8641SAndroid Build Coastguard Worker     const ThreadActivityTracker& tracker)
49*635a8641SAndroid Build Coastguard Worker     : activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {}
50*635a8641SAndroid Build Coastguard Worker 
ThreadActivityAnalyzer(void * base,size_t size)51*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size)
52*635a8641SAndroid Build Coastguard Worker     : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {}
53*635a8641SAndroid Build Coastguard Worker 
ThreadActivityAnalyzer(PersistentMemoryAllocator * allocator,PersistentMemoryAllocator::Reference reference)54*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::ThreadActivityAnalyzer(
55*635a8641SAndroid Build Coastguard Worker     PersistentMemoryAllocator* allocator,
56*635a8641SAndroid Build Coastguard Worker     PersistentMemoryAllocator::Reference reference)
57*635a8641SAndroid Build Coastguard Worker     : ThreadActivityAnalyzer(allocator->GetAsArray<char>(
58*635a8641SAndroid Build Coastguard Worker                                  reference,
59*635a8641SAndroid Build Coastguard Worker                                  GlobalActivityTracker::kTypeIdActivityTracker,
60*635a8641SAndroid Build Coastguard Worker                                  PersistentMemoryAllocator::kSizeAny),
61*635a8641SAndroid Build Coastguard Worker                              allocator->GetAllocSize(reference)) {}
62*635a8641SAndroid Build Coastguard Worker 
63*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer::~ThreadActivityAnalyzer() = default;
64*635a8641SAndroid Build Coastguard Worker 
AddGlobalInformation(GlobalActivityAnalyzer * global)65*635a8641SAndroid Build Coastguard Worker void ThreadActivityAnalyzer::AddGlobalInformation(
66*635a8641SAndroid Build Coastguard Worker     GlobalActivityAnalyzer* global) {
67*635a8641SAndroid Build Coastguard Worker   if (!IsValid())
68*635a8641SAndroid Build Coastguard Worker     return;
69*635a8641SAndroid Build Coastguard Worker 
70*635a8641SAndroid Build Coastguard Worker   // User-data is held at the global scope even though it's referenced at the
71*635a8641SAndroid Build Coastguard Worker   // thread scope.
72*635a8641SAndroid Build Coastguard Worker   activity_snapshot_.user_data_stack.clear();
73*635a8641SAndroid Build Coastguard Worker   for (auto& activity : activity_snapshot_.activity_stack) {
74*635a8641SAndroid Build Coastguard Worker     // The global GetUserDataSnapshot will return an empty snapshot if the ref
75*635a8641SAndroid Build Coastguard Worker     // or id is not valid.
76*635a8641SAndroid Build Coastguard Worker     activity_snapshot_.user_data_stack.push_back(global->GetUserDataSnapshot(
77*635a8641SAndroid Build Coastguard Worker         activity_snapshot_.process_id, activity.user_data_ref,
78*635a8641SAndroid Build Coastguard Worker         activity.user_data_id));
79*635a8641SAndroid Build Coastguard Worker   }
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker 
GlobalActivityAnalyzer(std::unique_ptr<PersistentMemoryAllocator> allocator)82*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::GlobalActivityAnalyzer(
83*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<PersistentMemoryAllocator> allocator)
84*635a8641SAndroid Build Coastguard Worker     : allocator_(std::move(allocator)),
85*635a8641SAndroid Build Coastguard Worker       analysis_stamp_(0LL),
86*635a8641SAndroid Build Coastguard Worker       allocator_iterator_(allocator_.get()) {
87*635a8641SAndroid Build Coastguard Worker   DCHECK(allocator_);
88*635a8641SAndroid Build Coastguard Worker }
89*635a8641SAndroid Build Coastguard Worker 
90*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::~GlobalActivityAnalyzer() = default;
91*635a8641SAndroid Build Coastguard Worker 
92*635a8641SAndroid Build Coastguard Worker // static
93*635a8641SAndroid Build Coastguard Worker std::unique_ptr<GlobalActivityAnalyzer>
CreateWithAllocator(std::unique_ptr<PersistentMemoryAllocator> allocator)94*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::CreateWithAllocator(
95*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<PersistentMemoryAllocator> allocator) {
96*635a8641SAndroid Build Coastguard Worker   if (allocator->GetMemoryState() ==
97*635a8641SAndroid Build Coastguard Worker       PersistentMemoryAllocator::MEMORY_UNINITIALIZED) {
98*635a8641SAndroid Build Coastguard Worker     LogAnalyzerCreationError(kPmaUninitialized);
99*635a8641SAndroid Build Coastguard Worker     return nullptr;
100*635a8641SAndroid Build Coastguard Worker   }
101*635a8641SAndroid Build Coastguard Worker   if (allocator->GetMemoryState() ==
102*635a8641SAndroid Build Coastguard Worker       PersistentMemoryAllocator::MEMORY_DELETED) {
103*635a8641SAndroid Build Coastguard Worker     LogAnalyzerCreationError(kPmaDeleted);
104*635a8641SAndroid Build Coastguard Worker     return nullptr;
105*635a8641SAndroid Build Coastguard Worker   }
106*635a8641SAndroid Build Coastguard Worker   if (allocator->IsCorrupt()) {
107*635a8641SAndroid Build Coastguard Worker     LogAnalyzerCreationError(kPmaCorrupt);
108*635a8641SAndroid Build Coastguard Worker     return nullptr;
109*635a8641SAndroid Build Coastguard Worker   }
110*635a8641SAndroid Build Coastguard Worker 
111*635a8641SAndroid Build Coastguard Worker   return WrapUnique(new GlobalActivityAnalyzer(std::move(allocator)));
112*635a8641SAndroid Build Coastguard Worker }
113*635a8641SAndroid Build Coastguard Worker 
114*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL)
115*635a8641SAndroid Build Coastguard Worker // static
CreateWithFile(const FilePath & file_path)116*635a8641SAndroid Build Coastguard Worker std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile(
117*635a8641SAndroid Build Coastguard Worker     const FilePath& file_path) {
118*635a8641SAndroid Build Coastguard Worker   // Map the file read-write so it can guarantee consistency between
119*635a8641SAndroid Build Coastguard Worker   // the analyzer and any trackers that my still be active.
120*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
121*635a8641SAndroid Build Coastguard Worker   mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE);
122*635a8641SAndroid Build Coastguard Worker   if (!mmfile->IsValid()) {
123*635a8641SAndroid Build Coastguard Worker     LogAnalyzerCreationError(kInvalidMemoryMappedFile);
124*635a8641SAndroid Build Coastguard Worker     return nullptr;
125*635a8641SAndroid Build Coastguard Worker   }
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker   if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) {
128*635a8641SAndroid Build Coastguard Worker     LogAnalyzerCreationError(kPmaBadFile);
129*635a8641SAndroid Build Coastguard Worker     return nullptr;
130*635a8641SAndroid Build Coastguard Worker   }
131*635a8641SAndroid Build Coastguard Worker 
132*635a8641SAndroid Build Coastguard Worker   return CreateWithAllocator(std::make_unique<FilePersistentMemoryAllocator>(
133*635a8641SAndroid Build Coastguard Worker       std::move(mmfile), 0, 0, StringPiece(), /*readonly=*/true));
134*635a8641SAndroid Build Coastguard Worker }
135*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL)
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker // static
138*635a8641SAndroid Build Coastguard Worker std::unique_ptr<GlobalActivityAnalyzer>
CreateWithSharedMemory(std::unique_ptr<SharedMemory> shm)139*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::CreateWithSharedMemory(
140*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<SharedMemory> shm) {
141*635a8641SAndroid Build Coastguard Worker   if (shm->mapped_size() == 0 ||
142*635a8641SAndroid Build Coastguard Worker       !SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(*shm)) {
143*635a8641SAndroid Build Coastguard Worker     return nullptr;
144*635a8641SAndroid Build Coastguard Worker   }
145*635a8641SAndroid Build Coastguard Worker   return CreateWithAllocator(std::make_unique<SharedPersistentMemoryAllocator>(
146*635a8641SAndroid Build Coastguard Worker       std::move(shm), 0, StringPiece(), /*readonly=*/true));
147*635a8641SAndroid Build Coastguard Worker }
148*635a8641SAndroid Build Coastguard Worker 
149*635a8641SAndroid Build Coastguard Worker // static
150*635a8641SAndroid Build Coastguard Worker std::unique_ptr<GlobalActivityAnalyzer>
CreateWithSharedMemoryHandle(const SharedMemoryHandle & handle,size_t size)151*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::CreateWithSharedMemoryHandle(
152*635a8641SAndroid Build Coastguard Worker     const SharedMemoryHandle& handle,
153*635a8641SAndroid Build Coastguard Worker     size_t size) {
154*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(
155*635a8641SAndroid Build Coastguard Worker       new SharedMemory(handle, /*readonly=*/true));
156*635a8641SAndroid Build Coastguard Worker   if (!shm->Map(size))
157*635a8641SAndroid Build Coastguard Worker     return nullptr;
158*635a8641SAndroid Build Coastguard Worker   return CreateWithSharedMemory(std::move(shm));
159*635a8641SAndroid Build Coastguard Worker }
160*635a8641SAndroid Build Coastguard Worker 
GetFirstProcess()161*635a8641SAndroid Build Coastguard Worker int64_t GlobalActivityAnalyzer::GetFirstProcess() {
162*635a8641SAndroid Build Coastguard Worker   PrepareAllAnalyzers();
163*635a8641SAndroid Build Coastguard Worker   return GetNextProcess();
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker 
GetNextProcess()166*635a8641SAndroid Build Coastguard Worker int64_t GlobalActivityAnalyzer::GetNextProcess() {
167*635a8641SAndroid Build Coastguard Worker   if (process_ids_.empty())
168*635a8641SAndroid Build Coastguard Worker     return 0;
169*635a8641SAndroid Build Coastguard Worker   int64_t pid = process_ids_.back();
170*635a8641SAndroid Build Coastguard Worker   process_ids_.pop_back();
171*635a8641SAndroid Build Coastguard Worker   return pid;
172*635a8641SAndroid Build Coastguard Worker }
173*635a8641SAndroid Build Coastguard Worker 
GetFirstAnalyzer(int64_t pid)174*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetFirstAnalyzer(int64_t pid) {
175*635a8641SAndroid Build Coastguard Worker   analyzers_iterator_ = analyzers_.begin();
176*635a8641SAndroid Build Coastguard Worker   analyzers_iterator_pid_ = pid;
177*635a8641SAndroid Build Coastguard Worker   if (analyzers_iterator_ == analyzers_.end())
178*635a8641SAndroid Build Coastguard Worker     return nullptr;
179*635a8641SAndroid Build Coastguard Worker   int64_t create_stamp;
180*635a8641SAndroid Build Coastguard Worker   if (analyzers_iterator_->second->GetProcessId(&create_stamp) == pid &&
181*635a8641SAndroid Build Coastguard Worker       create_stamp <= analysis_stamp_) {
182*635a8641SAndroid Build Coastguard Worker     return analyzers_iterator_->second.get();
183*635a8641SAndroid Build Coastguard Worker   }
184*635a8641SAndroid Build Coastguard Worker   return GetNextAnalyzer();
185*635a8641SAndroid Build Coastguard Worker }
186*635a8641SAndroid Build Coastguard Worker 
GetNextAnalyzer()187*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetNextAnalyzer() {
188*635a8641SAndroid Build Coastguard Worker   DCHECK(analyzers_iterator_ != analyzers_.end());
189*635a8641SAndroid Build Coastguard Worker   int64_t create_stamp;
190*635a8641SAndroid Build Coastguard Worker   do {
191*635a8641SAndroid Build Coastguard Worker     ++analyzers_iterator_;
192*635a8641SAndroid Build Coastguard Worker     if (analyzers_iterator_ == analyzers_.end())
193*635a8641SAndroid Build Coastguard Worker       return nullptr;
194*635a8641SAndroid Build Coastguard Worker   } while (analyzers_iterator_->second->GetProcessId(&create_stamp) !=
195*635a8641SAndroid Build Coastguard Worker                analyzers_iterator_pid_ ||
196*635a8641SAndroid Build Coastguard Worker            create_stamp > analysis_stamp_);
197*635a8641SAndroid Build Coastguard Worker   return analyzers_iterator_->second.get();
198*635a8641SAndroid Build Coastguard Worker }
199*635a8641SAndroid Build Coastguard Worker 
GetAnalyzerForThread(const ThreadKey & key)200*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread(
201*635a8641SAndroid Build Coastguard Worker     const ThreadKey& key) {
202*635a8641SAndroid Build Coastguard Worker   auto found = analyzers_.find(key);
203*635a8641SAndroid Build Coastguard Worker   if (found == analyzers_.end())
204*635a8641SAndroid Build Coastguard Worker     return nullptr;
205*635a8641SAndroid Build Coastguard Worker   return found->second.get();
206*635a8641SAndroid Build Coastguard Worker }
207*635a8641SAndroid Build Coastguard Worker 
GetUserDataSnapshot(int64_t pid,uint32_t ref,uint32_t id)208*635a8641SAndroid Build Coastguard Worker ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot(
209*635a8641SAndroid Build Coastguard Worker     int64_t pid,
210*635a8641SAndroid Build Coastguard Worker     uint32_t ref,
211*635a8641SAndroid Build Coastguard Worker     uint32_t id) {
212*635a8641SAndroid Build Coastguard Worker   ActivityUserData::Snapshot snapshot;
213*635a8641SAndroid Build Coastguard Worker 
214*635a8641SAndroid Build Coastguard Worker   void* memory = allocator_->GetAsArray<char>(
215*635a8641SAndroid Build Coastguard Worker       ref, GlobalActivityTracker::kTypeIdUserDataRecord,
216*635a8641SAndroid Build Coastguard Worker       PersistentMemoryAllocator::kSizeAny);
217*635a8641SAndroid Build Coastguard Worker   if (memory) {
218*635a8641SAndroid Build Coastguard Worker     size_t size = allocator_->GetAllocSize(ref);
219*635a8641SAndroid Build Coastguard Worker     const ActivityUserData user_data(memory, size);
220*635a8641SAndroid Build Coastguard Worker     user_data.CreateSnapshot(&snapshot);
221*635a8641SAndroid Build Coastguard Worker     int64_t process_id;
222*635a8641SAndroid Build Coastguard Worker     int64_t create_stamp;
223*635a8641SAndroid Build Coastguard Worker     if (!ActivityUserData::GetOwningProcessId(memory, &process_id,
224*635a8641SAndroid Build Coastguard Worker                                               &create_stamp) ||
225*635a8641SAndroid Build Coastguard Worker         process_id != pid || user_data.id() != id) {
226*635a8641SAndroid Build Coastguard Worker       // This allocation has been overwritten since it was created. Return an
227*635a8641SAndroid Build Coastguard Worker       // empty snapshot because whatever was captured is incorrect.
228*635a8641SAndroid Build Coastguard Worker       snapshot.clear();
229*635a8641SAndroid Build Coastguard Worker     }
230*635a8641SAndroid Build Coastguard Worker   }
231*635a8641SAndroid Build Coastguard Worker 
232*635a8641SAndroid Build Coastguard Worker   return snapshot;
233*635a8641SAndroid Build Coastguard Worker }
234*635a8641SAndroid Build Coastguard Worker 
235*635a8641SAndroid Build Coastguard Worker const ActivityUserData::Snapshot&
GetProcessDataSnapshot(int64_t pid)236*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::GetProcessDataSnapshot(int64_t pid) {
237*635a8641SAndroid Build Coastguard Worker   auto iter = process_data_.find(pid);
238*635a8641SAndroid Build Coastguard Worker   if (iter == process_data_.end())
239*635a8641SAndroid Build Coastguard Worker     return g_empty_user_data_snapshot.Get();
240*635a8641SAndroid Build Coastguard Worker   if (iter->second.create_stamp > analysis_stamp_)
241*635a8641SAndroid Build Coastguard Worker     return g_empty_user_data_snapshot.Get();
242*635a8641SAndroid Build Coastguard Worker   DCHECK_EQ(pid, iter->second.process_id);
243*635a8641SAndroid Build Coastguard Worker   return iter->second.data;
244*635a8641SAndroid Build Coastguard Worker }
245*635a8641SAndroid Build Coastguard Worker 
GetLogMessages()246*635a8641SAndroid Build Coastguard Worker std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() {
247*635a8641SAndroid Build Coastguard Worker   std::vector<std::string> messages;
248*635a8641SAndroid Build Coastguard Worker   PersistentMemoryAllocator::Reference ref;
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker   PersistentMemoryAllocator::Iterator iter(allocator_.get());
251*635a8641SAndroid Build Coastguard Worker   while ((ref = iter.GetNextOfType(
252*635a8641SAndroid Build Coastguard Worker               GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) {
253*635a8641SAndroid Build Coastguard Worker     const char* message = allocator_->GetAsArray<char>(
254*635a8641SAndroid Build Coastguard Worker         ref, GlobalActivityTracker::kTypeIdGlobalLogMessage,
255*635a8641SAndroid Build Coastguard Worker         PersistentMemoryAllocator::kSizeAny);
256*635a8641SAndroid Build Coastguard Worker     if (message)
257*635a8641SAndroid Build Coastguard Worker       messages.push_back(message);
258*635a8641SAndroid Build Coastguard Worker   }
259*635a8641SAndroid Build Coastguard Worker 
260*635a8641SAndroid Build Coastguard Worker   return messages;
261*635a8641SAndroid Build Coastguard Worker }
262*635a8641SAndroid Build Coastguard Worker 
263*635a8641SAndroid Build Coastguard Worker std::vector<GlobalActivityTracker::ModuleInfo>
GetModules(int64_t pid)264*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::GetModules(int64_t pid) {
265*635a8641SAndroid Build Coastguard Worker   std::vector<GlobalActivityTracker::ModuleInfo> modules;
266*635a8641SAndroid Build Coastguard Worker 
267*635a8641SAndroid Build Coastguard Worker   PersistentMemoryAllocator::Iterator iter(allocator_.get());
268*635a8641SAndroid Build Coastguard Worker   const GlobalActivityTracker::ModuleInfoRecord* record;
269*635a8641SAndroid Build Coastguard Worker   while (
270*635a8641SAndroid Build Coastguard Worker       (record =
271*635a8641SAndroid Build Coastguard Worker            iter.GetNextOfObject<GlobalActivityTracker::ModuleInfoRecord>()) !=
272*635a8641SAndroid Build Coastguard Worker       nullptr) {
273*635a8641SAndroid Build Coastguard Worker     int64_t process_id;
274*635a8641SAndroid Build Coastguard Worker     int64_t create_stamp;
275*635a8641SAndroid Build Coastguard Worker     if (!OwningProcess::GetOwningProcessId(&record->owner, &process_id,
276*635a8641SAndroid Build Coastguard Worker                                            &create_stamp) ||
277*635a8641SAndroid Build Coastguard Worker         pid != process_id || create_stamp > analysis_stamp_) {
278*635a8641SAndroid Build Coastguard Worker       continue;
279*635a8641SAndroid Build Coastguard Worker     }
280*635a8641SAndroid Build Coastguard Worker     GlobalActivityTracker::ModuleInfo info;
281*635a8641SAndroid Build Coastguard Worker     if (record->DecodeTo(&info, allocator_->GetAllocSize(
282*635a8641SAndroid Build Coastguard Worker                                     allocator_->GetAsReference(record)))) {
283*635a8641SAndroid Build Coastguard Worker       modules.push_back(std::move(info));
284*635a8641SAndroid Build Coastguard Worker     }
285*635a8641SAndroid Build Coastguard Worker   }
286*635a8641SAndroid Build Coastguard Worker 
287*635a8641SAndroid Build Coastguard Worker   return modules;
288*635a8641SAndroid Build Coastguard Worker }
289*635a8641SAndroid Build Coastguard Worker 
290*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::ProgramLocation
GetProgramLocationFromAddress(uint64_t address)291*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) {
292*635a8641SAndroid Build Coastguard Worker   // TODO(bcwhite): Implement this.
293*635a8641SAndroid Build Coastguard Worker   return { 0, 0 };
294*635a8641SAndroid Build Coastguard Worker }
295*635a8641SAndroid Build Coastguard Worker 
IsDataComplete() const296*635a8641SAndroid Build Coastguard Worker bool GlobalActivityAnalyzer::IsDataComplete() const {
297*635a8641SAndroid Build Coastguard Worker   DCHECK(allocator_);
298*635a8641SAndroid Build Coastguard Worker   return !allocator_->IsFull();
299*635a8641SAndroid Build Coastguard Worker }
300*635a8641SAndroid Build Coastguard Worker 
301*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot() = default;
302*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
303*635a8641SAndroid Build Coastguard Worker     const UserDataSnapshot& rhs) = default;
304*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
305*635a8641SAndroid Build Coastguard Worker     UserDataSnapshot&& rhs) = default;
306*635a8641SAndroid Build Coastguard Worker GlobalActivityAnalyzer::UserDataSnapshot::~UserDataSnapshot() = default;
307*635a8641SAndroid Build Coastguard Worker 
PrepareAllAnalyzers()308*635a8641SAndroid Build Coastguard Worker void GlobalActivityAnalyzer::PrepareAllAnalyzers() {
309*635a8641SAndroid Build Coastguard Worker   // Record the time when analysis started.
310*635a8641SAndroid Build Coastguard Worker   analysis_stamp_ = base::Time::Now().ToInternalValue();
311*635a8641SAndroid Build Coastguard Worker 
312*635a8641SAndroid Build Coastguard Worker   // Fetch all the records. This will retrieve only ones created since the
313*635a8641SAndroid Build Coastguard Worker   // last run since the PMA iterator will continue from where it left off.
314*635a8641SAndroid Build Coastguard Worker   uint32_t type;
315*635a8641SAndroid Build Coastguard Worker   PersistentMemoryAllocator::Reference ref;
316*635a8641SAndroid Build Coastguard Worker   while ((ref = allocator_iterator_.GetNext(&type)) != 0) {
317*635a8641SAndroid Build Coastguard Worker     switch (type) {
318*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdActivityTracker:
319*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdActivityTrackerFree:
320*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdProcessDataRecord:
321*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdProcessDataRecordFree:
322*635a8641SAndroid Build Coastguard Worker       case PersistentMemoryAllocator::kTypeIdTransitioning:
323*635a8641SAndroid Build Coastguard Worker         // Active, free, or transitioning: add it to the list of references
324*635a8641SAndroid Build Coastguard Worker         // for later analysis.
325*635a8641SAndroid Build Coastguard Worker         memory_references_.insert(ref);
326*635a8641SAndroid Build Coastguard Worker         break;
327*635a8641SAndroid Build Coastguard Worker     }
328*635a8641SAndroid Build Coastguard Worker   }
329*635a8641SAndroid Build Coastguard Worker 
330*635a8641SAndroid Build Coastguard Worker   // Clear out any old information.
331*635a8641SAndroid Build Coastguard Worker   analyzers_.clear();
332*635a8641SAndroid Build Coastguard Worker   process_data_.clear();
333*635a8641SAndroid Build Coastguard Worker   process_ids_.clear();
334*635a8641SAndroid Build Coastguard Worker   std::set<int64_t> seen_pids;
335*635a8641SAndroid Build Coastguard Worker 
336*635a8641SAndroid Build Coastguard Worker   // Go through all the known references and create objects for them with
337*635a8641SAndroid Build Coastguard Worker   // snapshots of the current state.
338*635a8641SAndroid Build Coastguard Worker   for (PersistentMemoryAllocator::Reference memory_ref : memory_references_) {
339*635a8641SAndroid Build Coastguard Worker     // Get the actual data segment for the tracker. Any type will do since it
340*635a8641SAndroid Build Coastguard Worker     // is checked below.
341*635a8641SAndroid Build Coastguard Worker     void* const base = allocator_->GetAsArray<char>(
342*635a8641SAndroid Build Coastguard Worker         memory_ref, PersistentMemoryAllocator::kTypeIdAny,
343*635a8641SAndroid Build Coastguard Worker         PersistentMemoryAllocator::kSizeAny);
344*635a8641SAndroid Build Coastguard Worker     const size_t size = allocator_->GetAllocSize(memory_ref);
345*635a8641SAndroid Build Coastguard Worker     if (!base)
346*635a8641SAndroid Build Coastguard Worker       continue;
347*635a8641SAndroid Build Coastguard Worker 
348*635a8641SAndroid Build Coastguard Worker     switch (allocator_->GetType(memory_ref)) {
349*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdActivityTracker: {
350*635a8641SAndroid Build Coastguard Worker         // Create the analyzer on the data. This will capture a snapshot of the
351*635a8641SAndroid Build Coastguard Worker         // tracker state. This can fail if the tracker is somehow corrupted or
352*635a8641SAndroid Build Coastguard Worker         // is in the process of shutting down.
353*635a8641SAndroid Build Coastguard Worker         std::unique_ptr<ThreadActivityAnalyzer> analyzer(
354*635a8641SAndroid Build Coastguard Worker             new ThreadActivityAnalyzer(base, size));
355*635a8641SAndroid Build Coastguard Worker         if (!analyzer->IsValid())
356*635a8641SAndroid Build Coastguard Worker           continue;
357*635a8641SAndroid Build Coastguard Worker         analyzer->AddGlobalInformation(this);
358*635a8641SAndroid Build Coastguard Worker 
359*635a8641SAndroid Build Coastguard Worker         // Track PIDs.
360*635a8641SAndroid Build Coastguard Worker         int64_t pid = analyzer->GetProcessId();
361*635a8641SAndroid Build Coastguard Worker         if (seen_pids.find(pid) == seen_pids.end()) {
362*635a8641SAndroid Build Coastguard Worker           process_ids_.push_back(pid);
363*635a8641SAndroid Build Coastguard Worker           seen_pids.insert(pid);
364*635a8641SAndroid Build Coastguard Worker         }
365*635a8641SAndroid Build Coastguard Worker 
366*635a8641SAndroid Build Coastguard Worker         // Add this analyzer to the map of known ones, indexed by a unique
367*635a8641SAndroid Build Coastguard Worker         // thread
368*635a8641SAndroid Build Coastguard Worker         // identifier.
369*635a8641SAndroid Build Coastguard Worker         DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey()));
370*635a8641SAndroid Build Coastguard Worker         analyzer->allocator_reference_ = ref;
371*635a8641SAndroid Build Coastguard Worker         analyzers_[analyzer->GetThreadKey()] = std::move(analyzer);
372*635a8641SAndroid Build Coastguard Worker       } break;
373*635a8641SAndroid Build Coastguard Worker 
374*635a8641SAndroid Build Coastguard Worker       case GlobalActivityTracker::kTypeIdProcessDataRecord: {
375*635a8641SAndroid Build Coastguard Worker         // Get the PID associated with this data record.
376*635a8641SAndroid Build Coastguard Worker         int64_t process_id;
377*635a8641SAndroid Build Coastguard Worker         int64_t create_stamp;
378*635a8641SAndroid Build Coastguard Worker         ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
379*635a8641SAndroid Build Coastguard Worker         DCHECK(!base::ContainsKey(process_data_, process_id));
380*635a8641SAndroid Build Coastguard Worker 
381*635a8641SAndroid Build Coastguard Worker         // Create a snapshot of the data. This can fail if the data is somehow
382*635a8641SAndroid Build Coastguard Worker         // corrupted or the process shutdown and the memory being released.
383*635a8641SAndroid Build Coastguard Worker         UserDataSnapshot& snapshot = process_data_[process_id];
384*635a8641SAndroid Build Coastguard Worker         snapshot.process_id = process_id;
385*635a8641SAndroid Build Coastguard Worker         snapshot.create_stamp = create_stamp;
386*635a8641SAndroid Build Coastguard Worker         const ActivityUserData process_data(base, size);
387*635a8641SAndroid Build Coastguard Worker         if (!process_data.CreateSnapshot(&snapshot.data))
388*635a8641SAndroid Build Coastguard Worker           break;
389*635a8641SAndroid Build Coastguard Worker 
390*635a8641SAndroid Build Coastguard Worker         // Check that nothing changed. If it did, forget what was recorded.
391*635a8641SAndroid Build Coastguard Worker         ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
392*635a8641SAndroid Build Coastguard Worker         if (process_id != snapshot.process_id ||
393*635a8641SAndroid Build Coastguard Worker             create_stamp != snapshot.create_stamp) {
394*635a8641SAndroid Build Coastguard Worker           process_data_.erase(process_id);
395*635a8641SAndroid Build Coastguard Worker           break;
396*635a8641SAndroid Build Coastguard Worker         }
397*635a8641SAndroid Build Coastguard Worker 
398*635a8641SAndroid Build Coastguard Worker         // Track PIDs.
399*635a8641SAndroid Build Coastguard Worker         if (seen_pids.find(process_id) == seen_pids.end()) {
400*635a8641SAndroid Build Coastguard Worker           process_ids_.push_back(process_id);
401*635a8641SAndroid Build Coastguard Worker           seen_pids.insert(process_id);
402*635a8641SAndroid Build Coastguard Worker         }
403*635a8641SAndroid Build Coastguard Worker       } break;
404*635a8641SAndroid Build Coastguard Worker     }
405*635a8641SAndroid Build Coastguard Worker   }
406*635a8641SAndroid Build Coastguard Worker 
407*635a8641SAndroid Build Coastguard Worker   // Reverse the list of PIDs so that they get popped in the order found.
408*635a8641SAndroid Build Coastguard Worker   std::reverse(process_ids_.begin(), process_ids_.end());
409*635a8641SAndroid Build Coastguard Worker }
410*635a8641SAndroid Build Coastguard Worker 
411*635a8641SAndroid Build Coastguard Worker }  // namespace debug
412*635a8641SAndroid Build Coastguard Worker }  // namespace base
413