bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 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_DEBUG_ACTIVITY_ANALYZER_H_ |
| 6 | #define BASE_DEBUG_ACTIVITY_ANALYZER_H_ |
| 7 | |
| 8 | #include <map> |
| 9 | #include <memory> |
| 10 | #include <set> |
manzagop | 54b190f | 2016-11-10 00:44:25 +0900 | [diff] [blame] | 11 | #include <string> |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 12 | |
| 13 | #include "base/base_export.h" |
| 14 | #include "base/debug/activity_tracker.h" |
| 15 | |
| 16 | namespace base { |
| 17 | namespace debug { |
| 18 | |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 19 | class GlobalActivityAnalyzer; |
| 20 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 21 | // This class provides analysis of data captured from a ThreadActivityTracker. |
| 22 | // When created, it takes a snapshot of the data held by the tracker and |
| 23 | // makes that information available to other code. |
| 24 | class BASE_EXPORT ThreadActivityAnalyzer { |
| 25 | public: |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 26 | struct BASE_EXPORT Snapshot : ThreadActivityTracker::Snapshot { |
| 27 | Snapshot(); |
| 28 | ~Snapshot(); |
| 29 | |
| 30 | // The user-data snapshot for an activity, matching the |activity_stack| |
| 31 | // of ThreadActivityTracker::Snapshot, if any. |
| 32 | std::vector<ActivityUserData::Snapshot> user_data_stack; |
| 33 | }; |
| 34 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 35 | // This class provides keys that uniquely identify a thread, even across |
| 36 | // multiple processes. |
| 37 | class ThreadKey { |
| 38 | public: |
| 39 | ThreadKey(int64_t pid, int64_t tid) : pid_(pid), tid_(tid) {} |
| 40 | |
| 41 | bool operator<(const ThreadKey& rhs) const { |
| 42 | if (pid_ != rhs.pid_) |
| 43 | return pid_ < rhs.pid_; |
| 44 | return tid_ < rhs.tid_; |
| 45 | } |
| 46 | |
| 47 | bool operator==(const ThreadKey& rhs) const { |
| 48 | return (pid_ == rhs.pid_ && tid_ == rhs.tid_); |
| 49 | } |
| 50 | |
| 51 | private: |
| 52 | int64_t pid_; |
| 53 | int64_t tid_; |
| 54 | }; |
| 55 | |
| 56 | // Creates an analyzer for an existing activity |tracker|. A snapshot is taken |
| 57 | // immediately and the tracker is not referenced again. |
| 58 | explicit ThreadActivityAnalyzer(const ThreadActivityTracker& tracker); |
| 59 | |
| 60 | // Creates an analyzer for a block of memory currently or previously in-use |
| 61 | // by an activity-tracker. A snapshot is taken immediately and the memory |
| 62 | // is not referenced again. |
| 63 | ThreadActivityAnalyzer(void* base, size_t size); |
| 64 | |
| 65 | // Creates an analyzer for a block of memory held within a persistent-memory |
| 66 | // |allocator| at the given |reference|. A snapshot is taken immediately and |
| 67 | // the memory is not referenced again. |
| 68 | ThreadActivityAnalyzer(PersistentMemoryAllocator* allocator, |
| 69 | PersistentMemoryAllocator::Reference reference); |
| 70 | |
| 71 | ~ThreadActivityAnalyzer(); |
| 72 | |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 73 | // Adds information from the global analyzer. |
| 74 | void AddGlobalInformation(GlobalActivityAnalyzer* global); |
| 75 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 76 | // Returns true iff the contained data is valid. Results from all other |
| 77 | // methods are undefined if this returns false. |
| 78 | bool IsValid() { return activity_snapshot_valid_; } |
| 79 | |
| 80 | // Gets the name of the thread. |
| 81 | const std::string& GetThreadName() { |
| 82 | return activity_snapshot_.thread_name; |
| 83 | } |
| 84 | |
| 85 | // Gets the TheadKey for this thread. |
| 86 | ThreadKey GetThreadKey() { |
| 87 | return ThreadKey(activity_snapshot_.process_id, |
| 88 | activity_snapshot_.thread_id); |
| 89 | } |
| 90 | |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 91 | const Snapshot& activity_snapshot() { return activity_snapshot_; } |
manzagop | 54b190f | 2016-11-10 00:44:25 +0900 | [diff] [blame] | 92 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 93 | private: |
| 94 | friend class GlobalActivityAnalyzer; |
| 95 | |
| 96 | // The snapshot of the activity tracker taken at the moment of construction. |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 97 | Snapshot activity_snapshot_; |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 98 | |
| 99 | // Flag indicating if the snapshot data is valid. |
| 100 | bool activity_snapshot_valid_; |
| 101 | |
| 102 | // A reference into a persistent memory allocator, used by the global |
| 103 | // analyzer to know where this tracker came from. |
| 104 | PersistentMemoryAllocator::Reference allocator_reference_ = 0; |
| 105 | |
| 106 | DISALLOW_COPY_AND_ASSIGN(ThreadActivityAnalyzer); |
| 107 | }; |
| 108 | |
| 109 | |
| 110 | // This class manages analyzers for all known processes and threads as stored |
| 111 | // in a persistent memory allocator. It supports retrieval of them through |
| 112 | // iteration and directly using a ThreadKey, which allows for cross-references |
| 113 | // to be resolved. |
| 114 | // Note that though atomic snapshots are used and everything has its snapshot |
| 115 | // taken at the same time, the multi-snapshot itself is not atomic and thus may |
| 116 | // show small inconsistencies between threads if attempted on a live system. |
| 117 | class BASE_EXPORT GlobalActivityAnalyzer { |
| 118 | public: |
bcwhite | 60a440f | 2016-11-11 00:46:45 +0900 | [diff] [blame] | 119 | struct ProgramLocation { |
| 120 | int module; |
| 121 | uintptr_t offset; |
| 122 | }; |
| 123 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 124 | using ThreadKey = ThreadActivityAnalyzer::ThreadKey; |
| 125 | |
| 126 | // Creates a global analyzer from a persistent memory allocator. |
| 127 | explicit GlobalActivityAnalyzer( |
| 128 | std::unique_ptr<PersistentMemoryAllocator> allocator); |
| 129 | |
| 130 | ~GlobalActivityAnalyzer(); |
| 131 | |
| 132 | #if !defined(OS_NACL) |
| 133 | // Creates a global analyzer using the contents of a file given in |
| 134 | // |file_path|. |
| 135 | static std::unique_ptr<GlobalActivityAnalyzer> CreateWithFile( |
| 136 | const FilePath& file_path); |
| 137 | #endif // !defined(OS_NACL) |
| 138 | |
manzagop | bd97524 | 2016-09-20 07:31:03 +0900 | [diff] [blame] | 139 | // Iterates over all known valid analyzers or returns null if there are no |
| 140 | // more. Ownership stays with the global analyzer object and all existing |
| 141 | // analyzer pointers are invalidated when GetFirstAnalyzer() is called. |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 142 | ThreadActivityAnalyzer* GetFirstAnalyzer(); |
| 143 | ThreadActivityAnalyzer* GetNextAnalyzer(); |
| 144 | |
| 145 | // Gets the analyzer for a specific thread or null if there is none. |
| 146 | // Ownership stays with the global analyzer object. |
| 147 | ThreadActivityAnalyzer* GetAnalyzerForThread(const ThreadKey& key); |
| 148 | |
bcwhite | 2baebb1 | 2016-12-09 12:37:56 +0900 | [diff] [blame] | 149 | // Extract user data based on a reference and its identifier. |
| 150 | ActivityUserData::Snapshot GetUserDataSnapshot(uint32_t ref, uint32_t id); |
| 151 | |
| 152 | // Extract the global user data. |
| 153 | ActivityUserData::Snapshot GetGlobalUserDataSnapshot(); |
| 154 | |
bcwhite | 2d4c331 | 2016-12-03 06:23:40 +0900 | [diff] [blame] | 155 | // Gets all log messages stored within. |
| 156 | std::vector<std::string> GetLogMessages(); |
| 157 | |
bcwhite | 8f3021d | 2017-01-27 03:28:18 +0900 | [diff] [blame^] | 158 | // Gets all the known modules. |
| 159 | std::vector<GlobalActivityTracker::ModuleInfo> GetModules(); |
| 160 | |
bcwhite | 60a440f | 2016-11-11 00:46:45 +0900 | [diff] [blame] | 161 | // Gets the corresponding "program location" for a given "program counter". |
| 162 | // This will return {0,0} if no mapping could be found. |
| 163 | ProgramLocation GetProgramLocationFromAddress(uint64_t address); |
| 164 | |
bcwhite | a156944 | 2016-08-10 12:10:03 +0900 | [diff] [blame] | 165 | private: |
| 166 | using AnalyzerMap = |
| 167 | std::map<ThreadKey, std::unique_ptr<ThreadActivityAnalyzer>>; |
| 168 | |
| 169 | // Finds, creates, and indexes analyzers for all known processes and threads. |
| 170 | void PrepareAllAnalyzers(); |
| 171 | |
| 172 | // The persistent memory allocator holding all tracking data. |
| 173 | std::unique_ptr<PersistentMemoryAllocator> allocator_; |
| 174 | |
| 175 | // The iterator for finding tracking information in the allocator. |
| 176 | PersistentMemoryAllocator::Iterator allocator_iterator_; |
| 177 | |
| 178 | // A set of all tracker memory references found within the allocator. |
| 179 | std::set<PersistentMemoryAllocator::Reference> tracker_references_; |
| 180 | |
| 181 | // A map, keyed by ThreadKey, of all valid activity analyzers. |
| 182 | AnalyzerMap analyzers_; |
| 183 | |
| 184 | // The iterator within the analyzers_ map for returning analyzers through |
| 185 | // first/next iteration. |
| 186 | AnalyzerMap::iterator analyzers_iterator_; |
| 187 | |
| 188 | DISALLOW_COPY_AND_ASSIGN(GlobalActivityAnalyzer); |
| 189 | }; |
| 190 | |
| 191 | } // namespace debug |
| 192 | } // namespace base |
| 193 | |
| 194 | #endif // BASE_DEBUG_ACTIVITY_ANALYZER_H_ |