Index: base/debug/activity_tracker.h |
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h |
index 62f983b5e87024f2334691db3db543ebfd2d6683..2d3c2bc7dbaf3666540cb9e7dda55e179685235a 100644 |
--- a/base/debug/activity_tracker.h |
+++ b/base/debug/activity_tracker.h |
@@ -646,6 +646,32 @@ class BASE_EXPORT GlobalActivityTracker { |
kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, |
}; |
+ // This structure contains information about a loaded module, as shown to |
+ // users of the tracker. |
+ struct BASE_EXPORT ModuleInfo { |
+ ModuleInfo(); |
+ ModuleInfo(ModuleInfo&& rhs); |
+ ModuleInfo(const ModuleInfo& rhs); |
+ ~ModuleInfo(); |
+ |
+ ModuleInfo& operator=(ModuleInfo&& rhs); |
+ ModuleInfo& operator=(const ModuleInfo& rhs); |
+ |
+ // Information about where and when the module was loaded/unloaded. |
+ bool is_loaded = false; // Was the last operation a load or unload? |
+ uintptr_t address = 0; // Address of the last load operation. |
+ int64_t load_time = 0; // Time of last change; set automatically. |
+ |
+ // Information about the module itself. These never change no matter how |
+ // many times a module may be loaded and unloaded. |
+ size_t size = 0; // The size of the loaded module. |
+ uint32_t timestamp = 0; // Opaque "timestamp" for the module. |
+ uint32_t age = 0; // Opaque "age" for the module. |
+ uint8_t identifier[16]; // Opaque identifier (GUID, etc.) for the module. |
+ std::string file; // The full path to the file. (UTF-8) |
+ std::string debug_file; // The full path to the debug file. |
+ }; |
+ |
// This is a thin wrapper around the thread-tracker's ScopedActivity that |
// accesses the global tracker to provide some of the information, notably |
// which thread-tracker to use. It is safe to create even if activity |
@@ -749,10 +775,15 @@ class BASE_EXPORT GlobalActivityTracker { |
// only store critical messages such as FATAL ones. |
void RecordLogMessage(StringPiece message); |
+ // Records a module load/unload event. This is safe to call multiple times |
+ // even with the same information. |
+ void RecordModuleInfo(const ModuleInfo& info); |
+ |
// Accesses the global data record for storing arbitrary key/value pairs. |
ActivityUserData& user_data() { return user_data_; } |
private: |
+ friend class GlobalActivityAnalyzer; |
friend class ScopedThreadActivity; |
friend class ActivityTrackerTest; |
@@ -764,6 +795,51 @@ class BASE_EXPORT GlobalActivityTracker { |
kCachedUserDataMemories = 10, |
}; |
+ // State of a module as stored in persistent memory. This supports a single |
+ // loading of a module only. If modules are loaded multiple times at |
+ // different addresses, only the last will be recorded and an unload will |
+ // not revert to the information of any other addresses. |
+ struct BASE_EXPORT ModuleInfoRecord { |
+ // SHA1(ModuleInfoRecord): Increment this if structure changes! |
+ static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; |
+ |
+ // Expected size for 32/64-bit check by PersistentMemoryAllocator. |
+ static constexpr size_t kExpectedInstanceSize = 56; |
+ |
+ // The atomic unfortunately makes this a "complex" class on some compilers |
+ // and thus requires an out-of-line constructor & destructor even though |
+ // they do nothing. |
+ ModuleInfoRecord(); |
+ ~ModuleInfoRecord(); |
+ |
+ uint64_t address; // The base address of the module. |
+ uint64_t load_time; // Time of last load/unload. |
+ uint64_t size; // The size of the module in bytes. |
+ uint32_t timestamp; // Opaque timestamp of the module. |
+ uint32_t age; // Opaque "age" associated with the module. |
+ uint8_t identifier[16]; // Opaque identifier for the module. |
+ std::atomic<uint32_t> changes; // Number load/unload actions. |
+ uint16_t pickle_size; // The size of the following pickle. |
+ uint8_t loaded; // Flag if module is loaded or not. |
+ char pickle[1]; // Other strings; may allocate larger. |
+ |
+ // Decodes/encodes storage structure from more generic info structure. |
+ bool DecodeTo(GlobalActivityTracker::ModuleInfo* info, |
+ size_t record_size) const; |
+ bool EncodeFrom(const GlobalActivityTracker::ModuleInfo& info, |
+ size_t record_size); |
+ |
+ // Updates the core information without changing the encoded strings. This |
+ // is useful when a known module changes state (i.e. new load or unload). |
+ bool UpdateFrom(const GlobalActivityTracker::ModuleInfo& info); |
+ |
+ // Determines the required memory size for the encoded storage. |
+ static size_t EncodedSize(const GlobalActivityTracker::ModuleInfo& info); |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ModuleInfoRecord); |
+ }; |
+ |
// A thin wrapper around the main thread-tracker that keeps additional |
// information that the global tracker needs to handle joined threads. |
class ManagedActivityTracker : public ThreadActivityTracker { |
@@ -825,6 +901,10 @@ class BASE_EXPORT GlobalActivityTracker { |
// be written from the main UI thread. |
ActivityUserData user_data_; |
+ // A map of global module information, keyed by module path. |
+ std::map<const std::string, ModuleInfoRecord*> modules_; |
+ base::Lock modules_lock_; |
+ |
// The active global activity tracker. |
static GlobalActivityTracker* g_tracker_; |