• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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