Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Unified Diff: base/debug/activity_tracker.cc

Issue 2566983009: Support storing information about what modules are loaded in the process. (Closed)
Patch Set: rebased Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« base/debug/activity_tracker.h ('K') | « base/debug/activity_tracker.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/debug/activity_tracker.cc
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc
index 562e662c98972f0588ba3ee9266b73c813b8e620..c17239746c8f405b843cb0f626e64466c4838f79 100644
--- a/base/debug/activity_tracker.cc
+++ b/base/debug/activity_tracker.cc
@@ -16,6 +16,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/pending_task.h"
+#include "base/pickle.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/stl_util.h"
@@ -893,6 +894,80 @@ size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
GlobalActivityTracker* GlobalActivityTracker::g_tracker_ = nullptr;
+GlobalActivityTracker::ModuleInfo::ModuleInfo() {}
+GlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default;
+GlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default;
+GlobalActivityTracker::ModuleInfo::~ModuleInfo() {}
+
+GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
+ ModuleInfo&& rhs) = default;
+GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
+ const ModuleInfo& rhs) = default;
+
+bool GlobalActivityTracker::ModuleInfoRecord::DecodeTo(
+ GlobalActivityTracker::ModuleInfo* info,
+ size_t record_size) const {
+ std::atomic_thread_fence(std::memory_order_acquire);
+ if (offsetof(ModuleInfoRecord, pickle) + pickle_size > record_size)
+ return false;
+
+ info->is_loaded = loaded != 0;
+ info->address = static_cast<uintptr_t>(address);
+ info->size = static_cast<size_t>(size);
+
+ Pickle pickler(pickle, pickle_size);
+ PickleIterator iter(pickler);
+ return iter.ReadString(&info->file) && iter.ReadString(&info->version) &&
+ iter.ReadString(&info->identifier) &&
+ iter.ReadString(&info->debug_file) &&
+ iter.ReadString(&info->debug_identifier);
+}
+
+bool GlobalActivityTracker::ModuleInfoRecord::EncodeFrom(
+ const GlobalActivityTracker::ModuleInfo& info,
+ size_t record_size) {
+ Pickle pickler;
+ bool okay = pickler.WriteString(info.file) &&
+ pickler.WriteString(info.version) &&
+ pickler.WriteString(info.identifier) &&
+ pickler.WriteString(info.debug_file) &&
+ pickler.WriteString(info.debug_identifier);
+ if (!okay) {
+ NOTREACHED();
+ return false;
+ }
+ if (offsetof(ModuleInfoRecord, pickle) + pickler.size() > record_size) {
+ NOTREACHED();
+ return false;
+ }
+
+ memcpy(pickle, pickler.data(), pickler.size());
+ pickle_size = pickler.size();
+ return UpdateFrom(info);
+}
+
+bool GlobalActivityTracker::ModuleInfoRecord::UpdateFrom(
+ const GlobalActivityTracker::ModuleInfo& info) {
+ address = info.address;
+ size = info.size;
+ loaded = info.is_loaded ? 1 : 0;
+ std::atomic_thread_fence(std::memory_order_release);
+ return true;
+}
+
+// static
+size_t GlobalActivityTracker::ModuleInfoRecord::EncodedSize(
+ const GlobalActivityTracker::ModuleInfo& info) {
+ PickleSizer sizer;
+ sizer.AddString(info.file);
+ sizer.AddString(info.version);
+ sizer.AddString(info.identifier);
+ sizer.AddString(info.debug_file);
+ sizer.AddString(info.debug_identifier);
+
+ return offsetof(ModuleInfoRecord, pickle) + sizer.payload_size();
+}
+
GlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity(
const void* program_counter,
const void* origin,
@@ -1065,6 +1140,39 @@ void GlobalActivityTracker::RecordLogMessage(StringPiece message) {
}
}
+void GlobalActivityTracker::RecordModuleInfo(const ModuleInfo& info) {
+ AutoLock lock(modules_lock_);
+ auto found = modules_.find(info.file);
+ if (found != modules_.end()) {
+ ModuleInfoRecord* record = allocator_->GetAsObject<ModuleInfoRecord>(
+ found->second, kTypeIdModuleInfoRecord);
+ DCHECK(record);
+
+ // Get should never fail but need to be tolerant in production.
+ if (record) {
+ // Update the basic state of module information that has been already
+ // recorded. It is assumed that the string information (identifier,
+ // version, etc.) remain unchanged which means that there's no need
+ // to create a new record to accommodate a possibly longer length.
+ record->UpdateFrom(info);
+ return;
+ }
+ }
+
+ size_t required_size = ModuleInfoRecord::EncodedSize(info);
+ PersistentMemoryAllocator::Reference ref =
+ allocator_->Allocate(required_size, kTypeIdModuleInfoRecord);
+ ModuleInfoRecord* record =
+ allocator_->GetAsObject<ModuleInfoRecord>(ref, kTypeIdModuleInfoRecord);
+ if (!record)
+ return;
+
+ bool success = record->EncodeFrom(info, allocator_->GetAllocSize(ref));
+ DCHECK(success);
+ allocator_->MakeIterable(ref);
+ modules_.insert(std::make_pair(info.file, ref));
+}
+
GlobalActivityTracker::GlobalActivityTracker(
std::unique_ptr<PersistentMemoryAllocator> allocator,
int stack_depth)
@@ -1098,8 +1206,7 @@ GlobalActivityTracker::GlobalActivityTracker(
DCHECK(!g_tracker_);
g_tracker_ = this;
- // The global user-data record must be iterable in order to be found by an
- // analyzer.
+ // The global records must be iterable in order to be found by an analyzer.
allocator_->MakeIterable(allocator_->GetAsReference(
user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
}
« base/debug/activity_tracker.h ('K') | « base/debug/activity_tracker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698