activity_analyzer.h 9.5 KB

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