blob: e98046ea38b0b916bfac7172f8ff87171e088847 [file] [log] [blame]
bcwhitea1569442016-08-10 12:10:03 +09001// 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>
manzagop54b190f2016-11-10 00:44:25 +090011#include <string>
bcwhite0aa1f8c2017-04-01 01:21:53 +090012#include <vector>
bcwhitea1569442016-08-10 12:10:03 +090013
14#include "base/base_export.h"
15#include "base/debug/activity_tracker.h"
16
17namespace base {
18namespace debug {
19
bcwhite2baebb12016-12-09 12:37:56 +090020class GlobalActivityAnalyzer;
21
bcwhitea1569442016-08-10 12:10:03 +090022// This class provides analysis of data captured from a ThreadActivityTracker.
23// When created, it takes a snapshot of the data held by the tracker and
24// makes that information available to other code.
25class BASE_EXPORT ThreadActivityAnalyzer {
26 public:
bcwhite2baebb12016-12-09 12:37:56 +090027 struct BASE_EXPORT Snapshot : ThreadActivityTracker::Snapshot {
28 Snapshot();
29 ~Snapshot();
30
31 // The user-data snapshot for an activity, matching the |activity_stack|
32 // of ThreadActivityTracker::Snapshot, if any.
33 std::vector<ActivityUserData::Snapshot> user_data_stack;
34 };
35
bcwhitea1569442016-08-10 12:10:03 +090036 // This class provides keys that uniquely identify a thread, even across
37 // multiple processes.
38 class ThreadKey {
39 public:
40 ThreadKey(int64_t pid, int64_t tid) : pid_(pid), tid_(tid) {}
41
42 bool operator<(const ThreadKey& rhs) const {
43 if (pid_ != rhs.pid_)
44 return pid_ < rhs.pid_;
45 return tid_ < rhs.tid_;
46 }
47
48 bool operator==(const ThreadKey& rhs) const {
49 return (pid_ == rhs.pid_ && tid_ == rhs.tid_);
50 }
51
52 private:
53 int64_t pid_;
54 int64_t tid_;
55 };
56
57 // Creates an analyzer for an existing activity |tracker|. A snapshot is taken
58 // immediately and the tracker is not referenced again.
59 explicit ThreadActivityAnalyzer(const ThreadActivityTracker& tracker);
60
61 // Creates an analyzer for a block of memory currently or previously in-use
62 // by an activity-tracker. A snapshot is taken immediately and the memory
63 // is not referenced again.
64 ThreadActivityAnalyzer(void* base, size_t size);
65
66 // Creates an analyzer for a block of memory held within a persistent-memory
67 // |allocator| at the given |reference|. A snapshot is taken immediately and
68 // the memory is not referenced again.
69 ThreadActivityAnalyzer(PersistentMemoryAllocator* allocator,
70 PersistentMemoryAllocator::Reference reference);
71
72 ~ThreadActivityAnalyzer();
73
bcwhite2baebb12016-12-09 12:37:56 +090074 // Adds information from the global analyzer.
75 void AddGlobalInformation(GlobalActivityAnalyzer* global);
76
bcwhitea1569442016-08-10 12:10:03 +090077 // Returns true iff the contained data is valid. Results from all other
78 // methods are undefined if this returns false.
79 bool IsValid() { return activity_snapshot_valid_; }
80
bcwhite0aa1f8c2017-04-01 01:21:53 +090081 // Gets the process id and its creation stamp.
82 int64_t GetProcessId(int64_t* out_stamp = nullptr) {
83 if (out_stamp)
84 *out_stamp = activity_snapshot_.create_stamp;
85 return activity_snapshot_.process_id;
86 }
87
bcwhitea1569442016-08-10 12:10:03 +090088 // Gets the name of the thread.
89 const std::string& GetThreadName() {
90 return activity_snapshot_.thread_name;
91 }
92
93 // Gets the TheadKey for this thread.
94 ThreadKey GetThreadKey() {
95 return ThreadKey(activity_snapshot_.process_id,
96 activity_snapshot_.thread_id);
97 }
98
bcwhite2baebb12016-12-09 12:37:56 +090099 const Snapshot& activity_snapshot() { return activity_snapshot_; }
manzagop54b190f2016-11-10 00:44:25 +0900100
bcwhitea1569442016-08-10 12:10:03 +0900101 private:
102 friend class GlobalActivityAnalyzer;
103
104 // The snapshot of the activity tracker taken at the moment of construction.
bcwhite2baebb12016-12-09 12:37:56 +0900105 Snapshot activity_snapshot_;
bcwhitea1569442016-08-10 12:10:03 +0900106
107 // Flag indicating if the snapshot data is valid.
108 bool activity_snapshot_valid_;
109
110 // A reference into a persistent memory allocator, used by the global
111 // analyzer to know where this tracker came from.
112 PersistentMemoryAllocator::Reference allocator_reference_ = 0;
113
114 DISALLOW_COPY_AND_ASSIGN(ThreadActivityAnalyzer);
115};
116
117
118// This class manages analyzers for all known processes and threads as stored
119// in a persistent memory allocator. It supports retrieval of them through
120// iteration and directly using a ThreadKey, which allows for cross-references
121// to be resolved.
122// Note that though atomic snapshots are used and everything has its snapshot
123// taken at the same time, the multi-snapshot itself is not atomic and thus may
124// show small inconsistencies between threads if attempted on a live system.
125class BASE_EXPORT GlobalActivityAnalyzer {
126 public:
bcwhite60a440f2016-11-11 00:46:45 +0900127 struct ProgramLocation {
128 int module;
129 uintptr_t offset;
130 };
131
bcwhitea1569442016-08-10 12:10:03 +0900132 using ThreadKey = ThreadActivityAnalyzer::ThreadKey;
133
134 // Creates a global analyzer from a persistent memory allocator.
135 explicit GlobalActivityAnalyzer(
136 std::unique_ptr<PersistentMemoryAllocator> allocator);
137
138 ~GlobalActivityAnalyzer();
139
140#if !defined(OS_NACL)
141 // Creates a global analyzer using the contents of a file given in
142 // |file_path|.
143 static std::unique_ptr<GlobalActivityAnalyzer> CreateWithFile(
144 const FilePath& file_path);
145#endif // !defined(OS_NACL)
146
bcwhite0aa1f8c2017-04-01 01:21:53 +0900147 // Iterates over all known valid processes and returns their PIDs or zero
148 // if there are no more. Calls to GetFirstProcess() will perform a global
149 // snapshot in order to provide a relatively consistent state across the
150 // future calls to GetNextProcess() and GetFirst/NextAnalyzer(). PIDs are
151 // returned in the order they're found meaning that a first-launched
152 // controlling process will be found first. Note, however, that space
153 // freed by an exiting process may be re-used by a later process.
154 int64_t GetFirstProcess();
155 int64_t GetNextProcess();
156
157 // Iterates over all known valid analyzers for the a given process or returns
158 // null if there are no more.
159 //
160 // GetFirstProcess() must be called first in order to capture a global
161 // snapshot! Ownership stays with the global analyzer object and all existing
162 // analyzer pointers are invalidated when GetFirstProcess() is called.
163 ThreadActivityAnalyzer* GetFirstAnalyzer(int64_t pid);
bcwhitea1569442016-08-10 12:10:03 +0900164 ThreadActivityAnalyzer* GetNextAnalyzer();
165
166 // Gets the analyzer for a specific thread or null if there is none.
167 // Ownership stays with the global analyzer object.
168 ThreadActivityAnalyzer* GetAnalyzerForThread(const ThreadKey& key);
169
bcwhite2baebb12016-12-09 12:37:56 +0900170 // Extract user data based on a reference and its identifier.
bcwhite0aa1f8c2017-04-01 01:21:53 +0900171 ActivityUserData::Snapshot GetUserDataSnapshot(int64_t pid,
172 uint32_t ref,
173 uint32_t id);
bcwhite2baebb12016-12-09 12:37:56 +0900174
bcwhite0aa1f8c2017-04-01 01:21:53 +0900175 // Extract the data for a specific process. An empty snapshot will be
176 // returned if the process is not known.
177 const ActivityUserData::Snapshot& GetProcessDataSnapshot(int64_t pid);
178
bcwhite2d4c3312016-12-03 06:23:40 +0900179 // Gets all log messages stored within.
180 std::vector<std::string> GetLogMessages();
181
bcwhite8f3021d2017-01-27 03:28:18 +0900182 // Gets all the known modules.
183 std::vector<GlobalActivityTracker::ModuleInfo> GetModules();
184
bcwhite60a440f2016-11-11 00:46:45 +0900185 // Gets the corresponding "program location" for a given "program counter".
186 // This will return {0,0} if no mapping could be found.
187 ProgramLocation GetProgramLocationFromAddress(uint64_t address);
188
bcwhitea1569442016-08-10 12:10:03 +0900189 private:
190 using AnalyzerMap =
191 std::map<ThreadKey, std::unique_ptr<ThreadActivityAnalyzer>>;
192
bcwhite0aa1f8c2017-04-01 01:21:53 +0900193 struct UserDataSnapshot {
194 // Complex class needs out-of-line ctor/dtor.
195 UserDataSnapshot();
196 UserDataSnapshot(const UserDataSnapshot& rhs);
197 UserDataSnapshot(UserDataSnapshot&& rhs);
198 ~UserDataSnapshot();
199
200 int64_t process_id;
201 int64_t create_stamp;
202 ActivityUserData::Snapshot data;
203 };
204
bcwhitea1569442016-08-10 12:10:03 +0900205 // Finds, creates, and indexes analyzers for all known processes and threads.
206 void PrepareAllAnalyzers();
207
208 // The persistent memory allocator holding all tracking data.
209 std::unique_ptr<PersistentMemoryAllocator> allocator_;
210
bcwhite0aa1f8c2017-04-01 01:21:53 +0900211 // The time stamp when analysis began. This is used to prevent looking into
212 // process IDs that get reused when analyzing a live system.
213 int64_t analysis_stamp_;
214
bcwhitea1569442016-08-10 12:10:03 +0900215 // The iterator for finding tracking information in the allocator.
216 PersistentMemoryAllocator::Iterator allocator_iterator_;
217
bcwhite0aa1f8c2017-04-01 01:21:53 +0900218 // A set of all interesting memory references found within the allocator.
219 std::set<PersistentMemoryAllocator::Reference> memory_references_;
220
221 // A set of all process-data memory references found within the allocator.
222 std::map<int64_t, UserDataSnapshot> process_data_;
223
224 // A set of all process IDs collected during PrepareAllAnalyzers. These are
225 // popped and returned one-by-one with calls to GetFirst/NextProcess().
226 std::vector<int64_t> process_ids_;
bcwhitea1569442016-08-10 12:10:03 +0900227
228 // A map, keyed by ThreadKey, of all valid activity analyzers.
229 AnalyzerMap analyzers_;
230
231 // The iterator within the analyzers_ map for returning analyzers through
232 // first/next iteration.
233 AnalyzerMap::iterator analyzers_iterator_;
bcwhite0aa1f8c2017-04-01 01:21:53 +0900234 int64_t analyzers_iterator_pid_;
235
bcwhitea1569442016-08-10 12:10:03 +0900236 DISALLOW_COPY_AND_ASSIGN(GlobalActivityAnalyzer);
237};
238
239} // namespace debug
240} // namespace base
241
242#endif // BASE_DEBUG_ACTIVITY_ANALYZER_H_