OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Activity tracking provides a low-overhead method of collecting information | 5 // Activity tracking provides a low-overhead method of collecting information |
6 // about the state of the application for analysis both while it is running | 6 // about the state of the application for analysis both while it is running |
7 // and after it has terminated unexpectedly. Its primary purpose is to help | 7 // and after it has terminated unexpectedly. Its primary purpose is to help |
8 // locate reasons the browser becomes unresponsive by providing insight into | 8 // locate reasons the browser becomes unresponsive by providing insight into |
9 // what all the various threads and processes are (or were) doing. | 9 // what all the various threads and processes are (or were) doing. |
10 | 10 |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 enum : uint32_t { | 639 enum : uint32_t { |
640 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 | 640 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 |
641 kTypeIdUserDataRecord = 0x615EDDD7 + 2, // SHA1(UserDataRecord) v2 | 641 kTypeIdUserDataRecord = 0x615EDDD7 + 2, // SHA1(UserDataRecord) v2 |
642 kTypeIdGlobalLogMessage = 0x4CF434F9 + 1, // SHA1(GlobalLogMessage) v1 | 642 kTypeIdGlobalLogMessage = 0x4CF434F9 + 1, // SHA1(GlobalLogMessage) v1 |
643 kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 1000, | 643 kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 1000, |
644 | 644 |
645 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, | 645 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, |
646 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, | 646 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, |
647 }; | 647 }; |
648 | 648 |
| 649 struct BASE_EXPORT ModuleInfo { |
| 650 ModuleInfo(); |
| 651 ModuleInfo(ModuleInfo&& rhs); |
| 652 ModuleInfo(const ModuleInfo& rhs); |
| 653 ~ModuleInfo(); |
| 654 |
| 655 ModuleInfo& operator=(ModuleInfo&& rhs); |
| 656 ModuleInfo& operator=(const ModuleInfo& rhs); |
| 657 |
| 658 bool is_loaded = false; |
| 659 uintptr_t address = 0; |
| 660 size_t size = 0; |
| 661 std::string file; |
| 662 std::string version; |
| 663 std::string identifier; |
| 664 std::string debug_file; |
| 665 std::string debug_identifier; |
| 666 }; |
| 667 |
649 // This is a thin wrapper around the thread-tracker's ScopedActivity that | 668 // This is a thin wrapper around the thread-tracker's ScopedActivity that |
650 // accesses the global tracker to provide some of the information, notably | 669 // accesses the global tracker to provide some of the information, notably |
651 // which thread-tracker to use. It is safe to create even if activity | 670 // which thread-tracker to use. It is safe to create even if activity |
652 // tracking is not enabled. | 671 // tracking is not enabled. |
653 class BASE_EXPORT ScopedThreadActivity | 672 class BASE_EXPORT ScopedThreadActivity |
654 : public ThreadActivityTracker::ScopedActivity { | 673 : public ThreadActivityTracker::ScopedActivity { |
655 public: | 674 public: |
656 ScopedThreadActivity(const void* program_counter, | 675 ScopedThreadActivity(const void* program_counter, |
657 const void* origin, | 676 const void* origin, |
658 Activity::Type type, | 677 Activity::Type type, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 // Creates an activity-tracker for the current thread. | 761 // Creates an activity-tracker for the current thread. |
743 ThreadActivityTracker* CreateTrackerForCurrentThread(); | 762 ThreadActivityTracker* CreateTrackerForCurrentThread(); |
744 | 763 |
745 // Releases the activity-tracker for the current thread (for testing only). | 764 // Releases the activity-tracker for the current thread (for testing only). |
746 void ReleaseTrackerForCurrentThreadForTesting(); | 765 void ReleaseTrackerForCurrentThreadForTesting(); |
747 | 766 |
748 // Records a log message. The current implementation does NOT recycle these | 767 // Records a log message. The current implementation does NOT recycle these |
749 // only store critical messages such as FATAL ones. | 768 // only store critical messages such as FATAL ones. |
750 void RecordLogMessage(StringPiece message); | 769 void RecordLogMessage(StringPiece message); |
751 | 770 |
| 771 // Records a module load/unload event. This is safe to call multiple times |
| 772 // even with the same information. |
| 773 void RecordModuleInfo(const ModuleInfo& info); |
| 774 |
752 // Accesses the global data record for storing arbitrary key/value pairs. | 775 // Accesses the global data record for storing arbitrary key/value pairs. |
753 ActivityUserData& user_data() { return user_data_; } | 776 ActivityUserData& user_data() { return user_data_; } |
754 | 777 |
755 private: | 778 private: |
| 779 friend class GlobalActivityAnalyzer; |
756 friend class ScopedThreadActivity; | 780 friend class ScopedThreadActivity; |
757 friend class ActivityTrackerTest; | 781 friend class ActivityTrackerTest; |
758 | 782 |
759 enum : int { | 783 enum : int { |
760 // The maximum number of threads that can be tracked within a process. If | 784 // The maximum number of threads that can be tracked within a process. If |
761 // more than this number run concurrently, tracking of new ones may cease. | 785 // more than this number run concurrently, tracking of new ones may cease. |
762 kMaxThreadCount = 100, | 786 kMaxThreadCount = 100, |
763 kCachedThreadMemories = 10, | 787 kCachedThreadMemories = 10, |
764 kCachedUserDataMemories = 10, | 788 kCachedUserDataMemories = 10, |
765 }; | 789 }; |
766 | 790 |
| 791 // State of a module as stored in persistent memory. This supports a single |
| 792 // loading of a module only. If modules are loaded multiple times at |
| 793 // different addresses, only the last will be recorded and an unload will |
| 794 // not revert to the information of any other addresses. |
| 795 struct BASE_EXPORT ModuleInfoRecord { |
| 796 // SHA1(ModuleInfoRecord): Increment this if structure changes! |
| 797 static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; |
| 798 |
| 799 // Expected size for 32/64-bit check by PersistentMemoryAllocator. |
| 800 static constexpr size_t kExpectedInstanceSize = 24; |
| 801 |
| 802 // The atomic unfortunately makes this a "complex" class on some compilers |
| 803 // and thus requires an out-of-line constructor & destructor even though |
| 804 // they do nothing. |
| 805 ModuleInfoRecord(); |
| 806 ~ModuleInfoRecord(); |
| 807 |
| 808 uint64_t address; // The base address of the module. |
| 809 uint64_t size; // The size of the module in bytes. |
| 810 std::atomic<uint32_t> changes; // Number load/unload actions. |
| 811 uint16_t pickle_size; // The size of the following pickle. |
| 812 uint8_t loaded; // Flag if module is loaded or not. |
| 813 char pickle[1]; // Other strings; may allocate larger. |
| 814 |
| 815 // Decodes/encodes storage structure from more generic info structure. |
| 816 bool DecodeTo(GlobalActivityTracker::ModuleInfo* info, |
| 817 size_t record_size) const; |
| 818 bool EncodeFrom(const GlobalActivityTracker::ModuleInfo& info, |
| 819 size_t record_size); |
| 820 |
| 821 // Updates the core information without changing the encoded strings. This |
| 822 // is useful when a known module changes state (i.e. new load or unload). |
| 823 bool UpdateFrom(const GlobalActivityTracker::ModuleInfo& info); |
| 824 |
| 825 // Determines the required memory size for the encoded storage. |
| 826 static size_t EncodedSize(const GlobalActivityTracker::ModuleInfo& info); |
| 827 |
| 828 private: |
| 829 DISALLOW_COPY_AND_ASSIGN(ModuleInfoRecord); |
| 830 }; |
| 831 |
767 // A thin wrapper around the main thread-tracker that keeps additional | 832 // A thin wrapper around the main thread-tracker that keeps additional |
768 // information that the global tracker needs to handle joined threads. | 833 // information that the global tracker needs to handle joined threads. |
769 class ManagedActivityTracker : public ThreadActivityTracker { | 834 class ManagedActivityTracker : public ThreadActivityTracker { |
770 public: | 835 public: |
771 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference, | 836 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference, |
772 void* base, | 837 void* base, |
773 size_t size); | 838 size_t size); |
774 ~ManagedActivityTracker() override; | 839 ~ManagedActivityTracker() override; |
775 | 840 |
776 // The reference into persistent memory from which the thread-tracker's | 841 // The reference into persistent memory from which the thread-tracker's |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 base::Lock thread_tracker_allocator_lock_; | 883 base::Lock thread_tracker_allocator_lock_; |
819 | 884 |
820 // A caching memory allocator for user data attached to activity data. | 885 // A caching memory allocator for user data attached to activity data. |
821 ActivityTrackerMemoryAllocator user_data_allocator_; | 886 ActivityTrackerMemoryAllocator user_data_allocator_; |
822 base::Lock user_data_allocator_lock_; | 887 base::Lock user_data_allocator_lock_; |
823 | 888 |
824 // An object for holding global arbitrary key value pairs. Values must always | 889 // An object for holding global arbitrary key value pairs. Values must always |
825 // be written from the main UI thread. | 890 // be written from the main UI thread. |
826 ActivityUserData user_data_; | 891 ActivityUserData user_data_; |
827 | 892 |
| 893 // A map of global module information, keyed by module path. |
| 894 std::map<const std::string, ModuleInfoRecord*> modules_; |
| 895 base::Lock modules_lock_; |
| 896 |
828 // The active global activity tracker. | 897 // The active global activity tracker. |
829 static GlobalActivityTracker* g_tracker_; | 898 static GlobalActivityTracker* g_tracker_; |
830 | 899 |
831 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); | 900 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); |
832 }; | 901 }; |
833 | 902 |
834 | 903 |
835 // Record entry in to and out of an arbitrary block of code. | 904 // Record entry in to and out of an arbitrary block of code. |
836 class BASE_EXPORT ScopedActivity | 905 class BASE_EXPORT ScopedActivity |
837 : public GlobalActivityTracker::ScopedThreadActivity { | 906 : public GlobalActivityTracker::ScopedThreadActivity { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 ScopedProcessWaitActivity(const void* program_counter, | 1024 ScopedProcessWaitActivity(const void* program_counter, |
956 const base::Process* process); | 1025 const base::Process* process); |
957 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 1026 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
958 }; | 1027 }; |
959 #endif | 1028 #endif |
960 | 1029 |
961 } // namespace debug | 1030 } // namespace debug |
962 } // namespace base | 1031 } // namespace base |
963 | 1032 |
964 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 1033 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
OLD | NEW |