1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_ 6 #define BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_ 7 8 #include <string> 9 10 #include "base/base_export.h" 11 #include "base/containers/span.h" 12 #include "base/hash/hash.h" 13 #include "base/location.h" 14 #include "base/profiler/module_cache.h" 15 #include "base/trace_event/trace_event.h" 16 #include "third_party/abseil-cpp/absl/types/optional.h" 17 #include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h" 18 #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h" 19 20 namespace base { 21 namespace trace_event { 22 23 // TrackEventInternedDataIndex expects the same data structure to be used for 24 // all interned fields with the same field number. We can't use base::Location 25 // for log event's location since base::Location uses program counter based 26 // location. 27 struct BASE_EXPORT TraceSourceLocation { 28 const char* function_name = nullptr; 29 const char* file_name = nullptr; 30 int line_number = 0; 31 32 TraceSourceLocation() = default; TraceSourceLocationTraceSourceLocation33 TraceSourceLocation(const char* function_name, 34 const char* file_name, 35 int line_number) 36 : function_name(function_name), 37 file_name(file_name), 38 line_number(line_number) {} 39 // Construct a new source location from an existing base::Location, the only 40 // attributes that are read are |function_name|, |file_name| and 41 // |line_number|. TraceSourceLocationTraceSourceLocation42 explicit TraceSourceLocation(const base::Location& location) 43 : function_name(location.function_name()), 44 file_name(location.file_name()), 45 line_number(location.line_number()) {} 46 47 bool operator==(const TraceSourceLocation& other) const { 48 return file_name == other.file_name && 49 function_name == other.function_name && 50 line_number == other.line_number; 51 } 52 }; 53 54 // Data structure for constructing an interned 55 // perfetto.protos.UnsymbolizedSourceLocation proto message. 56 struct BASE_EXPORT UnsymbolizedSourceLocation { 57 uint64_t mapping_id = 0; 58 uint64_t rel_pc = 0; 59 60 UnsymbolizedSourceLocation() = default; UnsymbolizedSourceLocationUnsymbolizedSourceLocation61 UnsymbolizedSourceLocation(uint64_t mapping_id, uint64_t rel_pc) 62 : mapping_id(mapping_id), rel_pc(rel_pc) {} 63 64 bool operator==(const UnsymbolizedSourceLocation& other) const { 65 return mapping_id == other.mapping_id && rel_pc == other.rel_pc; 66 } 67 }; 68 69 } // namespace trace_event 70 } // namespace base 71 72 namespace std { 73 74 template <> 75 struct hash<base::trace_event::TraceSourceLocation> { 76 std::size_t operator()( 77 const base::trace_event::TraceSourceLocation& loc) const { 78 return base::HashInts( 79 base::HashInts(reinterpret_cast<uintptr_t>(loc.file_name), 80 reinterpret_cast<uintptr_t>(loc.function_name)), 81 static_cast<size_t>(loc.line_number)); 82 } 83 }; 84 85 template <> 86 struct hash<base::trace_event::UnsymbolizedSourceLocation> { 87 std::size_t operator()( 88 const base::trace_event::UnsymbolizedSourceLocation& module) const { 89 return base::HashInts(module.mapping_id, module.rel_pc); 90 } 91 }; 92 93 } // namespace std 94 95 namespace base { 96 namespace trace_event { 97 98 struct BASE_EXPORT InternedSourceLocation 99 : public perfetto::TrackEventInternedDataIndex< 100 InternedSourceLocation, 101 perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber, 102 TraceSourceLocation> { 103 static void Add(perfetto::protos::pbzero::InternedData* interned_data, 104 size_t iid, 105 const TraceSourceLocation& location); 106 using perfetto::TrackEventInternedDataIndex< 107 InternedSourceLocation, 108 perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber, 109 TraceSourceLocation>::Get; 110 static size_t Get(perfetto::EventContext* ctx, const Location& location) { 111 return perfetto::TrackEventInternedDataIndex< 112 InternedSourceLocation, 113 perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber, 114 TraceSourceLocation>::Get(ctx, TraceSourceLocation(location)); 115 } 116 }; 117 118 struct BASE_EXPORT InternedLogMessage 119 : public perfetto::TrackEventInternedDataIndex< 120 InternedLogMessage, 121 perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber, 122 std::string> { 123 static void Add(perfetto::protos::pbzero::InternedData* interned_data, 124 size_t iid, 125 const std::string& log_message); 126 }; 127 128 struct BASE_EXPORT InternedBuildId 129 : public perfetto::TrackEventInternedDataIndex< 130 InternedBuildId, 131 perfetto::protos::pbzero::InternedData::kBuildIdsFieldNumber, 132 std::string> { 133 static void Add(perfetto::protos::pbzero::InternedData* interned_data, 134 size_t iid, 135 const std::string& build_id); 136 }; 137 138 struct BASE_EXPORT InternedMappingPath 139 : public perfetto::TrackEventInternedDataIndex< 140 InternedMappingPath, 141 perfetto::protos::pbzero::InternedData::kMappingPathsFieldNumber, 142 std::string> { 143 static void Add(perfetto::protos::pbzero::InternedData* interned_data, 144 size_t iid, 145 const std::string& mapping_path); 146 }; 147 148 struct BASE_EXPORT InternedMapping 149 : public perfetto::TrackEventInternedDataIndex< 150 InternedMapping, 151 perfetto::protos::pbzero::InternedData::kMappingsFieldNumber, 152 const base::ModuleCache::Module*> { 153 // We need a custom implementation here to plumb EventContext to Add. 154 static size_t Get(perfetto::EventContext* ctx, 155 const base::ModuleCache::Module* module); 156 static void Add(perfetto::EventContext* ctx, 157 size_t iid, 158 const base::ModuleCache::Module* module); 159 }; 160 161 // Interns an unsymbolized source code location + all it's "dependencies", i.e. 162 // module, strings used in the module definition, and so on. 163 struct BASE_EXPORT InternedUnsymbolizedSourceLocation 164 : public perfetto::TrackEventInternedDataIndex< 165 InternedUnsymbolizedSourceLocation, 166 perfetto::protos::pbzero::InternedData:: 167 kUnsymbolizedSourceLocationsFieldNumber, 168 uintptr_t> { 169 // We need a custom Get implementation to use ModuleCache, and to return 170 // a nullopt if a module for the given address cannot be found. 171 static absl::optional<size_t> Get(perfetto::EventContext* ctx, 172 uintptr_t address); 173 static void Add(perfetto::protos::pbzero::InternedData* interned_data, 174 size_t iid, 175 const UnsymbolizedSourceLocation& location); 176 177 private: 178 // This implies that a module cache lifetime = incremental state. 179 // We don't want unlimited lifetime because it keeps modules pinned in 180 // memory on some platforms (Windows). 181 // TODO(b/237055179): Consider tying module cache to DataSource instead so 182 // that the cache is not unnecessarily cleared on incremental state change. 183 base::ModuleCache module_cache_; 184 }; 185 186 } // namespace trace_event 187 } // namespace base 188 189 #endif // BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_ 190