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 #ifndef BASE_DEBUG_ACTIVITY_ANALYZER_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_DEBUG_ACTIVITY_ANALYZER_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #include <map> 9*635a8641SAndroid Build Coastguard Worker #include <memory> 10*635a8641SAndroid Build Coastguard Worker #include <set> 11*635a8641SAndroid Build Coastguard Worker #include <string> 12*635a8641SAndroid Build Coastguard Worker #include <vector> 13*635a8641SAndroid Build Coastguard Worker 14*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h" 15*635a8641SAndroid Build Coastguard Worker #include "base/debug/activity_tracker.h" 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker namespace base { 18*635a8641SAndroid Build Coastguard Worker namespace debug { 19*635a8641SAndroid Build Coastguard Worker 20*635a8641SAndroid Build Coastguard Worker class GlobalActivityAnalyzer; 21*635a8641SAndroid Build Coastguard Worker 22*635a8641SAndroid Build Coastguard Worker // This class provides analysis of data captured from a ThreadActivityTracker. 23*635a8641SAndroid Build Coastguard Worker // When created, it takes a snapshot of the data held by the tracker and 24*635a8641SAndroid Build Coastguard Worker // makes that information available to other code. 25*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT ThreadActivityAnalyzer { 26*635a8641SAndroid Build Coastguard Worker public: 27*635a8641SAndroid Build Coastguard Worker struct BASE_EXPORT Snapshot : ThreadActivityTracker::Snapshot { 28*635a8641SAndroid Build Coastguard Worker Snapshot(); 29*635a8641SAndroid Build Coastguard Worker ~Snapshot(); 30*635a8641SAndroid Build Coastguard Worker 31*635a8641SAndroid Build Coastguard Worker // The user-data snapshot for an activity, matching the |activity_stack| 32*635a8641SAndroid Build Coastguard Worker // of ThreadActivityTracker::Snapshot, if any. 33*635a8641SAndroid Build Coastguard Worker std::vector<ActivityUserData::Snapshot> user_data_stack; 34*635a8641SAndroid Build Coastguard Worker }; 35*635a8641SAndroid Build Coastguard Worker 36*635a8641SAndroid Build Coastguard Worker // This class provides keys that uniquely identify a thread, even across 37*635a8641SAndroid Build Coastguard Worker // multiple processes. 38*635a8641SAndroid Build Coastguard Worker class ThreadKey { 39*635a8641SAndroid Build Coastguard Worker public: ThreadKey(int64_t pid,int64_t tid)40*635a8641SAndroid Build Coastguard Worker ThreadKey(int64_t pid, int64_t tid) : pid_(pid), tid_(tid) {} 41*635a8641SAndroid Build Coastguard Worker 42*635a8641SAndroid Build Coastguard Worker bool operator<(const ThreadKey& rhs) const { 43*635a8641SAndroid Build Coastguard Worker if (pid_ != rhs.pid_) 44*635a8641SAndroid Build Coastguard Worker return pid_ < rhs.pid_; 45*635a8641SAndroid Build Coastguard Worker return tid_ < rhs.tid_; 46*635a8641SAndroid Build Coastguard Worker } 47*635a8641SAndroid Build Coastguard Worker 48*635a8641SAndroid Build Coastguard Worker bool operator==(const ThreadKey& rhs) const { 49*635a8641SAndroid Build Coastguard Worker return (pid_ == rhs.pid_ && tid_ == rhs.tid_); 50*635a8641SAndroid Build Coastguard Worker } 51*635a8641SAndroid Build Coastguard Worker 52*635a8641SAndroid Build Coastguard Worker private: 53*635a8641SAndroid Build Coastguard Worker int64_t pid_; 54*635a8641SAndroid Build Coastguard Worker int64_t tid_; 55*635a8641SAndroid Build Coastguard Worker }; 56*635a8641SAndroid Build Coastguard Worker 57*635a8641SAndroid Build Coastguard Worker // Creates an analyzer for an existing activity |tracker|. A snapshot is taken 58*635a8641SAndroid Build Coastguard Worker // immediately and the tracker is not referenced again. 59*635a8641SAndroid Build Coastguard Worker explicit ThreadActivityAnalyzer(const ThreadActivityTracker& tracker); 60*635a8641SAndroid Build Coastguard Worker 61*635a8641SAndroid Build Coastguard Worker // Creates an analyzer for a block of memory currently or previously in-use 62*635a8641SAndroid Build Coastguard Worker // by an activity-tracker. A snapshot is taken immediately and the memory 63*635a8641SAndroid Build Coastguard Worker // is not referenced again. 64*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer(void* base, size_t size); 65*635a8641SAndroid Build Coastguard Worker 66*635a8641SAndroid Build Coastguard Worker // Creates an analyzer for a block of memory held within a persistent-memory 67*635a8641SAndroid Build Coastguard Worker // |allocator| at the given |reference|. A snapshot is taken immediately and 68*635a8641SAndroid Build Coastguard Worker // the memory is not referenced again. 69*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer(PersistentMemoryAllocator* allocator, 70*635a8641SAndroid Build Coastguard Worker PersistentMemoryAllocator::Reference reference); 71*635a8641SAndroid Build Coastguard Worker 72*635a8641SAndroid Build Coastguard Worker ~ThreadActivityAnalyzer(); 73*635a8641SAndroid Build Coastguard Worker 74*635a8641SAndroid Build Coastguard Worker // Adds information from the global analyzer. 75*635a8641SAndroid Build Coastguard Worker void AddGlobalInformation(GlobalActivityAnalyzer* global); 76*635a8641SAndroid Build Coastguard Worker 77*635a8641SAndroid Build Coastguard Worker // Returns true iff the contained data is valid. Results from all other 78*635a8641SAndroid Build Coastguard Worker // methods are undefined if this returns false. IsValid()79*635a8641SAndroid Build Coastguard Worker bool IsValid() { return activity_snapshot_valid_; } 80*635a8641SAndroid Build Coastguard Worker 81*635a8641SAndroid Build Coastguard Worker // Gets the process id and its creation stamp. 82*635a8641SAndroid Build Coastguard Worker int64_t GetProcessId(int64_t* out_stamp = nullptr) { 83*635a8641SAndroid Build Coastguard Worker if (out_stamp) 84*635a8641SAndroid Build Coastguard Worker *out_stamp = activity_snapshot_.create_stamp; 85*635a8641SAndroid Build Coastguard Worker return activity_snapshot_.process_id; 86*635a8641SAndroid Build Coastguard Worker } 87*635a8641SAndroid Build Coastguard Worker 88*635a8641SAndroid Build Coastguard Worker // Gets the name of the thread. GetThreadName()89*635a8641SAndroid Build Coastguard Worker const std::string& GetThreadName() { 90*635a8641SAndroid Build Coastguard Worker return activity_snapshot_.thread_name; 91*635a8641SAndroid Build Coastguard Worker } 92*635a8641SAndroid Build Coastguard Worker 93*635a8641SAndroid Build Coastguard Worker // Gets the TheadKey for this thread. GetThreadKey()94*635a8641SAndroid Build Coastguard Worker ThreadKey GetThreadKey() { 95*635a8641SAndroid Build Coastguard Worker return ThreadKey(activity_snapshot_.process_id, 96*635a8641SAndroid Build Coastguard Worker activity_snapshot_.thread_id); 97*635a8641SAndroid Build Coastguard Worker } 98*635a8641SAndroid Build Coastguard Worker activity_snapshot()99*635a8641SAndroid Build Coastguard Worker const Snapshot& activity_snapshot() { return activity_snapshot_; } 100*635a8641SAndroid Build Coastguard Worker 101*635a8641SAndroid Build Coastguard Worker private: 102*635a8641SAndroid Build Coastguard Worker friend class GlobalActivityAnalyzer; 103*635a8641SAndroid Build Coastguard Worker 104*635a8641SAndroid Build Coastguard Worker // The snapshot of the activity tracker taken at the moment of construction. 105*635a8641SAndroid Build Coastguard Worker Snapshot activity_snapshot_; 106*635a8641SAndroid Build Coastguard Worker 107*635a8641SAndroid Build Coastguard Worker // Flag indicating if the snapshot data is valid. 108*635a8641SAndroid Build Coastguard Worker bool activity_snapshot_valid_; 109*635a8641SAndroid Build Coastguard Worker 110*635a8641SAndroid Build Coastguard Worker // A reference into a persistent memory allocator, used by the global 111*635a8641SAndroid Build Coastguard Worker // analyzer to know where this tracker came from. 112*635a8641SAndroid Build Coastguard Worker PersistentMemoryAllocator::Reference allocator_reference_ = 0; 113*635a8641SAndroid Build Coastguard Worker 114*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ThreadActivityAnalyzer); 115*635a8641SAndroid Build Coastguard Worker }; 116*635a8641SAndroid Build Coastguard Worker 117*635a8641SAndroid Build Coastguard Worker 118*635a8641SAndroid Build Coastguard Worker // This class manages analyzers for all known processes and threads as stored 119*635a8641SAndroid Build Coastguard Worker // in a persistent memory allocator. It supports retrieval of them through 120*635a8641SAndroid Build Coastguard Worker // iteration and directly using a ThreadKey, which allows for cross-references 121*635a8641SAndroid Build Coastguard Worker // to be resolved. 122*635a8641SAndroid Build Coastguard Worker // Note that though atomic snapshots are used and everything has its snapshot 123*635a8641SAndroid Build Coastguard Worker // taken at the same time, the multi-snapshot itself is not atomic and thus may 124*635a8641SAndroid Build Coastguard Worker // show small inconsistencies between threads if attempted on a live system. 125*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT GlobalActivityAnalyzer { 126*635a8641SAndroid Build Coastguard Worker public: 127*635a8641SAndroid Build Coastguard Worker struct ProgramLocation { 128*635a8641SAndroid Build Coastguard Worker int module; 129*635a8641SAndroid Build Coastguard Worker uintptr_t offset; 130*635a8641SAndroid Build Coastguard Worker }; 131*635a8641SAndroid Build Coastguard Worker 132*635a8641SAndroid Build Coastguard Worker using ThreadKey = ThreadActivityAnalyzer::ThreadKey; 133*635a8641SAndroid Build Coastguard Worker 134*635a8641SAndroid Build Coastguard Worker // Creates a global analyzer from a persistent memory allocator. 135*635a8641SAndroid Build Coastguard Worker explicit GlobalActivityAnalyzer( 136*635a8641SAndroid Build Coastguard Worker std::unique_ptr<PersistentMemoryAllocator> allocator); 137*635a8641SAndroid Build Coastguard Worker 138*635a8641SAndroid Build Coastguard Worker ~GlobalActivityAnalyzer(); 139*635a8641SAndroid Build Coastguard Worker 140*635a8641SAndroid Build Coastguard Worker // Creates a global analyzer using a given persistent-memory |allocator|. 141*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<GlobalActivityAnalyzer> CreateWithAllocator( 142*635a8641SAndroid Build Coastguard Worker std::unique_ptr<PersistentMemoryAllocator> allocator); 143*635a8641SAndroid Build Coastguard Worker 144*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL) 145*635a8641SAndroid Build Coastguard Worker // Creates a global analyzer using the contents of a file given in 146*635a8641SAndroid Build Coastguard Worker // |file_path|. 147*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<GlobalActivityAnalyzer> CreateWithFile( 148*635a8641SAndroid Build Coastguard Worker const FilePath& file_path); 149*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_NACL) 150*635a8641SAndroid Build Coastguard Worker 151*635a8641SAndroid Build Coastguard Worker // Like above but accesses an allocator in a mapped shared-memory segment. 152*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<GlobalActivityAnalyzer> CreateWithSharedMemory( 153*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SharedMemory> shm); 154*635a8641SAndroid Build Coastguard Worker 155*635a8641SAndroid Build Coastguard Worker // Like above but takes a handle to an existing shared memory segment and 156*635a8641SAndroid Build Coastguard Worker // maps it before creating the tracker. 157*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<GlobalActivityAnalyzer> CreateWithSharedMemoryHandle( 158*635a8641SAndroid Build Coastguard Worker const SharedMemoryHandle& handle, 159*635a8641SAndroid Build Coastguard Worker size_t size); 160*635a8641SAndroid Build Coastguard Worker 161*635a8641SAndroid Build Coastguard Worker // Iterates over all known valid processes and returns their PIDs or zero 162*635a8641SAndroid Build Coastguard Worker // if there are no more. Calls to GetFirstProcess() will perform a global 163*635a8641SAndroid Build Coastguard Worker // snapshot in order to provide a relatively consistent state across the 164*635a8641SAndroid Build Coastguard Worker // future calls to GetNextProcess() and GetFirst/NextAnalyzer(). PIDs are 165*635a8641SAndroid Build Coastguard Worker // returned in the order they're found meaning that a first-launched 166*635a8641SAndroid Build Coastguard Worker // controlling process will be found first. Note, however, that space 167*635a8641SAndroid Build Coastguard Worker // freed by an exiting process may be re-used by a later process. 168*635a8641SAndroid Build Coastguard Worker int64_t GetFirstProcess(); 169*635a8641SAndroid Build Coastguard Worker int64_t GetNextProcess(); 170*635a8641SAndroid Build Coastguard Worker 171*635a8641SAndroid Build Coastguard Worker // Iterates over all known valid analyzers for the a given process or returns 172*635a8641SAndroid Build Coastguard Worker // null if there are no more. 173*635a8641SAndroid Build Coastguard Worker // 174*635a8641SAndroid Build Coastguard Worker // GetFirstProcess() must be called first in order to capture a global 175*635a8641SAndroid Build Coastguard Worker // snapshot! Ownership stays with the global analyzer object and all existing 176*635a8641SAndroid Build Coastguard Worker // analyzer pointers are invalidated when GetFirstProcess() is called. 177*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GetFirstAnalyzer(int64_t pid); 178*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GetNextAnalyzer(); 179*635a8641SAndroid Build Coastguard Worker 180*635a8641SAndroid Build Coastguard Worker // Gets the analyzer for a specific thread or null if there is none. 181*635a8641SAndroid Build Coastguard Worker // Ownership stays with the global analyzer object. 182*635a8641SAndroid Build Coastguard Worker ThreadActivityAnalyzer* GetAnalyzerForThread(const ThreadKey& key); 183*635a8641SAndroid Build Coastguard Worker 184*635a8641SAndroid Build Coastguard Worker // Extract user data based on a reference and its identifier. 185*635a8641SAndroid Build Coastguard Worker ActivityUserData::Snapshot GetUserDataSnapshot(int64_t pid, 186*635a8641SAndroid Build Coastguard Worker uint32_t ref, 187*635a8641SAndroid Build Coastguard Worker uint32_t id); 188*635a8641SAndroid Build Coastguard Worker 189*635a8641SAndroid Build Coastguard Worker // Extract the data for a specific process. An empty snapshot will be 190*635a8641SAndroid Build Coastguard Worker // returned if the process is not known. 191*635a8641SAndroid Build Coastguard Worker const ActivityUserData::Snapshot& GetProcessDataSnapshot(int64_t pid); 192*635a8641SAndroid Build Coastguard Worker 193*635a8641SAndroid Build Coastguard Worker // Gets all log messages stored within. 194*635a8641SAndroid Build Coastguard Worker std::vector<std::string> GetLogMessages(); 195*635a8641SAndroid Build Coastguard Worker 196*635a8641SAndroid Build Coastguard Worker // Gets modules corresponding to a pid. This pid must come from a call to 197*635a8641SAndroid Build Coastguard Worker // GetFirst/NextProcess. Only modules that were first registered prior to 198*635a8641SAndroid Build Coastguard Worker // GetFirstProcess's snapshot are returned. 199*635a8641SAndroid Build Coastguard Worker std::vector<GlobalActivityTracker::ModuleInfo> GetModules(int64_t pid); 200*635a8641SAndroid Build Coastguard Worker 201*635a8641SAndroid Build Coastguard Worker // Gets the corresponding "program location" for a given "program counter". 202*635a8641SAndroid Build Coastguard Worker // This will return {0,0} if no mapping could be found. 203*635a8641SAndroid Build Coastguard Worker ProgramLocation GetProgramLocationFromAddress(uint64_t address); 204*635a8641SAndroid Build Coastguard Worker 205*635a8641SAndroid Build Coastguard Worker // Returns whether the data is complete. Data can be incomplete if the 206*635a8641SAndroid Build Coastguard Worker // recording size quota is hit. 207*635a8641SAndroid Build Coastguard Worker bool IsDataComplete() const; 208*635a8641SAndroid Build Coastguard Worker 209*635a8641SAndroid Build Coastguard Worker private: 210*635a8641SAndroid Build Coastguard Worker using AnalyzerMap = 211*635a8641SAndroid Build Coastguard Worker std::map<ThreadKey, std::unique_ptr<ThreadActivityAnalyzer>>; 212*635a8641SAndroid Build Coastguard Worker 213*635a8641SAndroid Build Coastguard Worker struct UserDataSnapshot { 214*635a8641SAndroid Build Coastguard Worker // Complex class needs out-of-line ctor/dtor. 215*635a8641SAndroid Build Coastguard Worker UserDataSnapshot(); 216*635a8641SAndroid Build Coastguard Worker UserDataSnapshot(const UserDataSnapshot& rhs); 217*635a8641SAndroid Build Coastguard Worker UserDataSnapshot(UserDataSnapshot&& rhs); 218*635a8641SAndroid Build Coastguard Worker ~UserDataSnapshot(); 219*635a8641SAndroid Build Coastguard Worker 220*635a8641SAndroid Build Coastguard Worker int64_t process_id; 221*635a8641SAndroid Build Coastguard Worker int64_t create_stamp; 222*635a8641SAndroid Build Coastguard Worker ActivityUserData::Snapshot data; 223*635a8641SAndroid Build Coastguard Worker }; 224*635a8641SAndroid Build Coastguard Worker 225*635a8641SAndroid Build Coastguard Worker // Finds, creates, and indexes analyzers for all known processes and threads. 226*635a8641SAndroid Build Coastguard Worker void PrepareAllAnalyzers(); 227*635a8641SAndroid Build Coastguard Worker 228*635a8641SAndroid Build Coastguard Worker // The persistent memory allocator holding all tracking data. 229*635a8641SAndroid Build Coastguard Worker std::unique_ptr<PersistentMemoryAllocator> allocator_; 230*635a8641SAndroid Build Coastguard Worker 231*635a8641SAndroid Build Coastguard Worker // The time stamp when analysis began. This is used to prevent looking into 232*635a8641SAndroid Build Coastguard Worker // process IDs that get reused when analyzing a live system. 233*635a8641SAndroid Build Coastguard Worker int64_t analysis_stamp_; 234*635a8641SAndroid Build Coastguard Worker 235*635a8641SAndroid Build Coastguard Worker // The iterator for finding tracking information in the allocator. 236*635a8641SAndroid Build Coastguard Worker PersistentMemoryAllocator::Iterator allocator_iterator_; 237*635a8641SAndroid Build Coastguard Worker 238*635a8641SAndroid Build Coastguard Worker // A set of all interesting memory references found within the allocator. 239*635a8641SAndroid Build Coastguard Worker std::set<PersistentMemoryAllocator::Reference> memory_references_; 240*635a8641SAndroid Build Coastguard Worker 241*635a8641SAndroid Build Coastguard Worker // A set of all process-data memory references found within the allocator. 242*635a8641SAndroid Build Coastguard Worker std::map<int64_t, UserDataSnapshot> process_data_; 243*635a8641SAndroid Build Coastguard Worker 244*635a8641SAndroid Build Coastguard Worker // A set of all process IDs collected during PrepareAllAnalyzers. These are 245*635a8641SAndroid Build Coastguard Worker // popped and returned one-by-one with calls to GetFirst/NextProcess(). 246*635a8641SAndroid Build Coastguard Worker std::vector<int64_t> process_ids_; 247*635a8641SAndroid Build Coastguard Worker 248*635a8641SAndroid Build Coastguard Worker // A map, keyed by ThreadKey, of all valid activity analyzers. 249*635a8641SAndroid Build Coastguard Worker AnalyzerMap analyzers_; 250*635a8641SAndroid Build Coastguard Worker 251*635a8641SAndroid Build Coastguard Worker // The iterator within the analyzers_ map for returning analyzers through 252*635a8641SAndroid Build Coastguard Worker // first/next iteration. 253*635a8641SAndroid Build Coastguard Worker AnalyzerMap::iterator analyzers_iterator_; 254*635a8641SAndroid Build Coastguard Worker int64_t analyzers_iterator_pid_; 255*635a8641SAndroid Build Coastguard Worker 256*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(GlobalActivityAnalyzer); 257*635a8641SAndroid Build Coastguard Worker }; 258*635a8641SAndroid Build Coastguard Worker 259*635a8641SAndroid Build Coastguard Worker } // namespace debug 260*635a8641SAndroid Build Coastguard Worker } // namespace base 261*635a8641SAndroid Build Coastguard Worker 262*635a8641SAndroid Build Coastguard Worker #endif // BASE_DEBUG_ACTIVITY_ANALYZER_H_ 263