blob: 95df69fd9b4abad4fb25eef7f8037a0ffb8785a6 [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>
bcwhitea1569442016-08-10 12:10:03 +090012
13#include "base/base_export.h"
14#include "base/debug/activity_tracker.h"
15
16namespace base {
17namespace debug {
18
bcwhite2baebb12016-12-09 12:37:56 +090019class GlobalActivityAnalyzer;
20
bcwhitea1569442016-08-10 12:10:03 +090021// 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.
24class BASE_EXPORT ThreadActivityAnalyzer {
25 public:
bcwhite2baebb12016-12-09 12:37:56 +090026 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
bcwhitea1569442016-08-10 12:10:03 +090035 // 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
bcwhite2baebb12016-12-09 12:37:56 +090073 // Adds information from the global analyzer.
74 void AddGlobalInformation(GlobalActivityAnalyzer* global);
75
bcwhitea1569442016-08-10 12:10:03 +090076 // 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
bcwhite2baebb12016-12-09 12:37:56 +090091 const Snapshot& activity_snapshot() { return activity_snapshot_; }
manzagop54b190f2016-11-10 00:44:25 +090092
bcwhitea1569442016-08-10 12:10:03 +090093 private:
94 friend class GlobalActivityAnalyzer;
95
96 // The snapshot of the activity tracker taken at the moment of construction.
bcwhite2baebb12016-12-09 12:37:56 +090097 Snapshot activity_snapshot_;
bcwhitea1569442016-08-10 12:10:03 +090098
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.
117class BASE_EXPORT GlobalActivityAnalyzer {
118 public:
bcwhite60a440f2016-11-11 00:46:45 +0900119 struct ProgramLocation {
120 int module;
121 uintptr_t offset;
122 };
123
bcwhitea1569442016-08-10 12:10:03 +0900124 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
manzagopbd975242016-09-20 07:31:03 +0900139 // 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.
bcwhitea1569442016-08-10 12:10:03 +0900142 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
bcwhite2baebb12016-12-09 12:37:56 +0900149 // 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
bcwhite2d4c3312016-12-03 06:23:40 +0900155 // Gets all log messages stored within.
156 std::vector<std::string> GetLogMessages();
157
bcwhite8f3021d2017-01-27 03:28:18 +0900158 // Gets all the known modules.
159 std::vector<GlobalActivityTracker::ModuleInfo> GetModules();
160
bcwhite60a440f2016-11-11 00:46:45 +0900161 // 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
bcwhitea1569442016-08-10 12:10:03 +0900165 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_