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 #include "base/trace_event/interned_args_helper.h"
6
7 #include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h"
8 #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
9 #include "third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h"
10 #include "third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h"
11 #include "third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h"
12 #include "third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h"
13
14 namespace base {
15 namespace trace_event {
16
17 namespace {
18
19 const void* const kModuleCacheForTracingKey = &kModuleCacheForTracingKey;
20
21 class ModuleCacheForTracing : public perfetto::TrackEventTlsStateUserData {
22 public:
23 ModuleCacheForTracing() = default;
24 ~ModuleCacheForTracing() override = default;
25
GetModuleCache()26 base::ModuleCache& GetModuleCache() { return module_cache_; }
27
28 private:
29 base::ModuleCache module_cache_;
30 };
31
32 } // namespace
33
34 // static
Add(perfetto::protos::pbzero::InternedData * interned_data,size_t iid,const TraceSourceLocation & location)35 void InternedSourceLocation::Add(
36 perfetto::protos::pbzero::InternedData* interned_data,
37 size_t iid,
38 const TraceSourceLocation& location) {
39 auto* msg = interned_data->add_source_locations();
40 msg->set_iid(iid);
41 if (location.file_name != nullptr)
42 msg->set_file_name(location.file_name);
43 if (location.function_name != nullptr)
44 msg->set_function_name(location.function_name);
45 // TODO(ssid): Add line number once it is allowed in internal proto.
46 // TODO(ssid): Add program counter to the proto fields when
47 // !BUILDFLAG(ENABLE_LOCATION_SOURCE).
48 // TODO(http://crbug.com760702) remove file name and just pass the program
49 // counter to the heap profiler macro.
50 // TODO(ssid): Consider writing the program counter of the current task
51 // (from the callback function pointer) instead of location that posted the
52 // task.
53 }
54
55 // static
Add(perfetto::protos::pbzero::InternedData * interned_data,size_t iid,const std::string & log_message)56 void InternedLogMessage::Add(
57 perfetto::protos::pbzero::InternedData* interned_data,
58 size_t iid,
59 const std::string& log_message) {
60 auto* msg = interned_data->add_log_message_body();
61 msg->set_iid(iid);
62 msg->set_body(log_message);
63 }
64
65 // static
Add(perfetto::protos::pbzero::InternedData * interned_data,size_t iid,const std::string & build_id)66 void InternedBuildId::Add(perfetto::protos::pbzero::InternedData* interned_data,
67 size_t iid,
68 const std::string& build_id) {
69 auto* msg = interned_data->add_build_ids();
70 msg->set_iid(iid);
71 msg->set_str(build_id);
72 }
73
74 // static
Add(perfetto::protos::pbzero::InternedData * interned_data,size_t iid,const std::string & mapping_path)75 void InternedMappingPath::Add(
76 perfetto::protos::pbzero::InternedData* interned_data,
77 size_t iid,
78 const std::string& mapping_path) {
79 auto* msg = interned_data->add_mapping_paths();
80 msg->set_iid(iid);
81 msg->set_str(mapping_path);
82 }
83
84 // static
Get(perfetto::EventContext * ctx,const base::ModuleCache::Module * module)85 size_t InternedMapping::Get(perfetto::EventContext* ctx,
86 const base::ModuleCache::Module* module) {
87 auto* index_for_field = GetOrCreateIndexForField(ctx->GetIncrementalState());
88 size_t iid;
89 if (index_for_field->index_.LookUpOrInsert(&iid, module)) {
90 return iid;
91 }
92 InternedMapping::Add(ctx, iid, module);
93 return iid;
94 }
95
96 // static
Add(perfetto::EventContext * ctx,size_t iid,const base::ModuleCache::Module * module)97 void InternedMapping::Add(perfetto::EventContext* ctx,
98 size_t iid,
99 const base::ModuleCache::Module* module) {
100 // TODO(b/270470700): Remove TransformModuleIDToSymbolServerFormat on all
101 // platforms once tools/tracing is fixed.
102 const auto build_id = InternedBuildId::Get(
103 ctx, base::TransformModuleIDToSymbolServerFormat(module->GetId()));
104 const auto path_id =
105 InternedMappingPath::Get(ctx, module->GetDebugBasename().MaybeAsASCII());
106
107 auto* msg =
108 ctx->GetIncrementalState()->serialized_interned_data->add_mappings();
109 msg->set_iid(iid);
110 msg->set_build_id(build_id);
111 msg->add_path_string_ids(path_id);
112 }
113
114 // static
Get(perfetto::EventContext * ctx,uintptr_t address)115 std::optional<size_t> InternedUnsymbolizedSourceLocation::Get(
116 perfetto::EventContext* ctx,
117 uintptr_t address) {
118 auto* index_for_field = GetOrCreateIndexForField(ctx->GetIncrementalState());
119 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
120 ModuleCacheForTracing* module_cache = static_cast<ModuleCacheForTracing*>(
121 ctx->GetTlsUserData(kModuleCacheForTracingKey));
122 if (!module_cache) {
123 auto new_module_cache = std::make_unique<ModuleCacheForTracing>();
124 module_cache = new_module_cache.get();
125 ctx->SetTlsUserData(kModuleCacheForTracingKey, std::move(new_module_cache));
126 }
127 const base::ModuleCache::Module* module =
128 module_cache->GetModuleCache().GetModuleForAddress(address);
129 #else
130 const base::ModuleCache::Module* module =
131 index_for_field->module_cache_.GetModuleForAddress(address);
132 #endif
133 if (!module) {
134 return std::nullopt;
135 }
136 size_t iid;
137 if (index_for_field->index_.LookUpOrInsert(&iid, address)) {
138 return iid;
139 }
140 const auto mapping_id = InternedMapping::Get(ctx, module);
141 const uintptr_t rel_pc = address - module->GetBaseAddress();
142 InternedUnsymbolizedSourceLocation::Add(
143 ctx->GetIncrementalState()->serialized_interned_data.get(), iid,
144 base::trace_event::UnsymbolizedSourceLocation(mapping_id, rel_pc));
145 return iid;
146 }
147
148 // static
Add(perfetto::protos::pbzero::InternedData * interned_data,size_t iid,const UnsymbolizedSourceLocation & location)149 void InternedUnsymbolizedSourceLocation::Add(
150 perfetto::protos::pbzero::InternedData* interned_data,
151 size_t iid,
152 const UnsymbolizedSourceLocation& location) {
153 auto* msg = interned_data->add_unsymbolized_source_locations();
154 msg->set_iid(iid);
155 msg->set_mapping_id(location.mapping_id);
156 msg->set_rel_pc(location.rel_pc);
157 }
158
159 } // namespace trace_event
160 } // namespace base
161