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

Side by Side 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 unified diff | Download patch
« base/debug/activity_tracker.h ('K') | « base/debug/activity_tracker.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "base/debug/activity_tracker.h" 5 #include "base/debug/activity_tracker.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/debug/stack_trace.h" 9 #include "base/debug/stack_trace.h"
10 #include "base/files/file.h" 10 #include "base/files/file.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/files/memory_mapped_file.h" 12 #include "base/files/memory_mapped_file.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/metrics/field_trial.h" 16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/pending_task.h" 18 #include "base/pending_task.h"
19 #include "base/pickle.h"
19 #include "base/process/process.h" 20 #include "base/process/process.h"
20 #include "base/process/process_handle.h" 21 #include "base/process/process_handle.h"
21 #include "base/stl_util.h" 22 #include "base/stl_util.h"
22 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
23 #include "base/threading/platform_thread.h" 24 #include "base/threading/platform_thread.h"
24 25
25 namespace base { 26 namespace base {
26 namespace debug { 27 namespace debug {
27 28
28 namespace { 29 namespace {
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 } 887 }
887 888
888 // static 889 // static
889 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) { 890 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
890 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header); 891 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header);
891 } 892 }
892 893
893 894
894 GlobalActivityTracker* GlobalActivityTracker::g_tracker_ = nullptr; 895 GlobalActivityTracker* GlobalActivityTracker::g_tracker_ = nullptr;
895 896
897 GlobalActivityTracker::ModuleInfo::ModuleInfo() {}
898 GlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default;
899 GlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default;
900 GlobalActivityTracker::ModuleInfo::~ModuleInfo() {}
901
902 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
903 ModuleInfo&& rhs) = default;
904 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
905 const ModuleInfo& rhs) = default;
906
907 bool GlobalActivityTracker::ModuleInfoRecord::DecodeTo(
908 GlobalActivityTracker::ModuleInfo* info,
909 size_t record_size) const {
910 std::atomic_thread_fence(std::memory_order_acquire);
911 if (offsetof(ModuleInfoRecord, pickle) + pickle_size > record_size)
912 return false;
913
914 info->is_loaded = loaded != 0;
915 info->address = static_cast<uintptr_t>(address);
916 info->size = static_cast<size_t>(size);
917
918 Pickle pickler(pickle, pickle_size);
919 PickleIterator iter(pickler);
920 return iter.ReadString(&info->file) && iter.ReadString(&info->version) &&
921 iter.ReadString(&info->identifier) &&
922 iter.ReadString(&info->debug_file) &&
923 iter.ReadString(&info->debug_identifier);
924 }
925
926 bool GlobalActivityTracker::ModuleInfoRecord::EncodeFrom(
927 const GlobalActivityTracker::ModuleInfo& info,
928 size_t record_size) {
929 Pickle pickler;
930 bool okay = pickler.WriteString(info.file) &&
931 pickler.WriteString(info.version) &&
932 pickler.WriteString(info.identifier) &&
933 pickler.WriteString(info.debug_file) &&
934 pickler.WriteString(info.debug_identifier);
935 if (!okay) {
936 NOTREACHED();
937 return false;
938 }
939 if (offsetof(ModuleInfoRecord, pickle) + pickler.size() > record_size) {
940 NOTREACHED();
941 return false;
942 }
943
944 memcpy(pickle, pickler.data(), pickler.size());
945 pickle_size = pickler.size();
946 return UpdateFrom(info);
947 }
948
949 bool GlobalActivityTracker::ModuleInfoRecord::UpdateFrom(
950 const GlobalActivityTracker::ModuleInfo& info) {
951 address = info.address;
952 size = info.size;
953 loaded = info.is_loaded ? 1 : 0;
954 std::atomic_thread_fence(std::memory_order_release);
955 return true;
956 }
957
958 // static
959 size_t GlobalActivityTracker::ModuleInfoRecord::EncodedSize(
960 const GlobalActivityTracker::ModuleInfo& info) {
961 PickleSizer sizer;
962 sizer.AddString(info.file);
963 sizer.AddString(info.version);
964 sizer.AddString(info.identifier);
965 sizer.AddString(info.debug_file);
966 sizer.AddString(info.debug_identifier);
967
968 return offsetof(ModuleInfoRecord, pickle) + sizer.payload_size();
969 }
970
896 GlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity( 971 GlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity(
897 const void* program_counter, 972 const void* program_counter,
898 const void* origin, 973 const void* origin,
899 Activity::Type type, 974 Activity::Type type,
900 const ActivityData& data, 975 const ActivityData& data,
901 bool lock_allowed) 976 bool lock_allowed)
902 : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(lock_allowed), 977 : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(lock_allowed),
903 program_counter, 978 program_counter,
904 origin, 979 origin,
905 type, 980 type,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1058 PersistentMemoryAllocator::Reference ref = 1133 PersistentMemoryAllocator::Reference ref =
1059 allocator_->Allocate(message.size() + 1, kTypeIdGlobalLogMessage); 1134 allocator_->Allocate(message.size() + 1, kTypeIdGlobalLogMessage);
1060 char* memory = allocator_->GetAsArray<char>(ref, kTypeIdGlobalLogMessage, 1135 char* memory = allocator_->GetAsArray<char>(ref, kTypeIdGlobalLogMessage,
1061 message.size() + 1); 1136 message.size() + 1);
1062 if (memory) { 1137 if (memory) {
1063 memcpy(memory, message.data(), message.size()); 1138 memcpy(memory, message.data(), message.size());
1064 allocator_->MakeIterable(ref); 1139 allocator_->MakeIterable(ref);
1065 } 1140 }
1066 } 1141 }
1067 1142
1143 void GlobalActivityTracker::RecordModuleInfo(const ModuleInfo& info) {
1144 AutoLock lock(modules_lock_);
1145 auto found = modules_.find(info.file);
1146 if (found != modules_.end()) {
1147 ModuleInfoRecord* record = allocator_->GetAsObject<ModuleInfoRecord>(
1148 found->second, kTypeIdModuleInfoRecord);
1149 DCHECK(record);
1150
1151 // Get should never fail but need to be tolerant in production.
1152 if (record) {
1153 // Update the basic state of module information that has been already
1154 // recorded. It is assumed that the string information (identifier,
1155 // version, etc.) remain unchanged which means that there's no need
1156 // to create a new record to accommodate a possibly longer length.
1157 record->UpdateFrom(info);
1158 return;
1159 }
1160 }
1161
1162 size_t required_size = ModuleInfoRecord::EncodedSize(info);
1163 PersistentMemoryAllocator::Reference ref =
1164 allocator_->Allocate(required_size, kTypeIdModuleInfoRecord);
1165 ModuleInfoRecord* record =
1166 allocator_->GetAsObject<ModuleInfoRecord>(ref, kTypeIdModuleInfoRecord);
1167 if (!record)
1168 return;
1169
1170 bool success = record->EncodeFrom(info, allocator_->GetAllocSize(ref));
1171 DCHECK(success);
1172 allocator_->MakeIterable(ref);
1173 modules_.insert(std::make_pair(info.file, ref));
1174 }
1175
1068 GlobalActivityTracker::GlobalActivityTracker( 1176 GlobalActivityTracker::GlobalActivityTracker(
1069 std::unique_ptr<PersistentMemoryAllocator> allocator, 1177 std::unique_ptr<PersistentMemoryAllocator> allocator,
1070 int stack_depth) 1178 int stack_depth)
1071 : allocator_(std::move(allocator)), 1179 : allocator_(std::move(allocator)),
1072 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), 1180 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)),
1073 this_thread_tracker_(&OnTLSDestroy), 1181 this_thread_tracker_(&OnTLSDestroy),
1074 thread_tracker_count_(0), 1182 thread_tracker_count_(0),
1075 thread_tracker_allocator_(allocator_.get(), 1183 thread_tracker_allocator_(allocator_.get(),
1076 kTypeIdActivityTracker, 1184 kTypeIdActivityTracker,
1077 kTypeIdActivityTrackerFree, 1185 kTypeIdActivityTrackerFree,
(...skipping 13 matching lines...) Expand all
1091 PersistentMemoryAllocator::kSizeAny), 1199 PersistentMemoryAllocator::kSizeAny),
1092 kGlobalDataSize) { 1200 kGlobalDataSize) {
1093 // Ensure the passed memory is valid and empty (iterator finds nothing). 1201 // Ensure the passed memory is valid and empty (iterator finds nothing).
1094 uint32_t type; 1202 uint32_t type;
1095 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); 1203 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type));
1096 1204
1097 // Ensure that there is no other global object and then make this one such. 1205 // Ensure that there is no other global object and then make this one such.
1098 DCHECK(!g_tracker_); 1206 DCHECK(!g_tracker_);
1099 g_tracker_ = this; 1207 g_tracker_ = this;
1100 1208
1101 // The global user-data record must be iterable in order to be found by an 1209 // The global records must be iterable in order to be found by an analyzer.
1102 // analyzer.
1103 allocator_->MakeIterable(allocator_->GetAsReference( 1210 allocator_->MakeIterable(allocator_->GetAsReference(
1104 user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); 1211 user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
1105 } 1212 }
1106 1213
1107 GlobalActivityTracker::~GlobalActivityTracker() { 1214 GlobalActivityTracker::~GlobalActivityTracker() {
1108 DCHECK_EQ(g_tracker_, this); 1215 DCHECK_EQ(g_tracker_, this);
1109 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); 1216 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed));
1110 g_tracker_ = nullptr; 1217 g_tracker_ = nullptr;
1111 } 1218 }
1112 1219
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 : GlobalActivityTracker::ScopedThreadActivity( 1316 : GlobalActivityTracker::ScopedThreadActivity(
1210 program_counter, 1317 program_counter,
1211 nullptr, 1318 nullptr,
1212 Activity::ACT_PROCESS_WAIT, 1319 Activity::ACT_PROCESS_WAIT,
1213 ActivityData::ForProcess(process->Pid()), 1320 ActivityData::ForProcess(process->Pid()),
1214 /*lock_allowed=*/true) {} 1321 /*lock_allowed=*/true) {}
1215 #endif 1322 #endif
1216 1323
1217 } // namespace debug 1324 } // namespace debug
1218 } // namespace base 1325 } // namespace base
OLDNEW
« 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