xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/args_translation_table.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <optional>
18 
19 #include "perfetto/ext/base/string_utils.h"
20 #include "perfetto/ext/base/string_view.h"
21 #include "src/trace_processor/importers/common/args_translation_table.h"
22 
23 namespace perfetto {
24 namespace trace_processor {
25 
26 namespace {
27 
28 // The raw symbol name is namespace::Interface::Method_Sym::IPCStableHash.
29 // We want to return namespace::Interface::Method.
ExtractMojoMethod(const std::string & method_symbol)30 std::string ExtractMojoMethod(const std::string& method_symbol) {
31   // The symbol ends with "()" for some platforms, but not for all of them.
32   std::string without_sym_suffix = base::StripSuffix(method_symbol, "()");
33   // This suffix is platform-independent, it's coming from Chromium code.
34   // https://source.chromium.org/chromium/chromium/src/+/main:mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl;l=66;drc=9d9e6f5ce548ecf228aed711f55b11c7ea8bdb55
35   constexpr char kSymSuffix[] = "_Sym::IPCStableHash";
36   return base::StripSuffix(without_sym_suffix, kSymSuffix);
37 }
38 
39 // The raw symbol name is namespace::Interface::Method_Sym::IPCStableHash.
40 // We want to return namespace.Interface (for historical compatibility).
ExtractMojoInterfaceTag(const std::string & method_symbol)41 std::string ExtractMojoInterfaceTag(const std::string& method_symbol) {
42   auto parts = base::SplitString(method_symbol, "::");
43   // If we have too few parts, return the original string as is to simplify
44   // debugging.
45   if (parts.size() <= 2) {
46     return method_symbol;
47   }
48   // Remove Method_Sym and IPCStableHash parts.
49   parts.erase(parts.end() - 2, parts.end());
50   return base::Join(parts, ".");
51 }
52 
53 }  // namespace
54 
ArgsTranslationTable(TraceStorage * storage)55 ArgsTranslationTable::ArgsTranslationTable(TraceStorage* storage)
56     : storage_(storage),
57       interned_chrome_histogram_hash_key_(
58           storage->InternString(kChromeHistogramHashKey)),
59       interned_chrome_histogram_name_key_(
60           storage->InternString(kChromeHistogramNameKey)),
61       interned_chrome_user_event_hash_key_(
62           storage->InternString(kChromeUserEventHashKey)),
63       interned_chrome_user_event_action_key_(
64           storage->InternString(kChromeUserEventActionKey)),
65       interned_chrome_performance_mark_site_hash_key_(
66           storage->InternString(kChromePerformanceMarkSiteHashKey)),
67       interned_chrome_performance_mark_site_key_(
68           storage->InternString(kChromePerformanceMarkSiteKey)),
69       interned_chrome_performance_mark_mark_hash_key_(
70           storage->InternString(kChromePerformanceMarkMarkHashKey)),
71       interned_chrome_performance_mark_mark_key_(
72           storage->InternString(kChromePerformanceMarkMarkKey)),
73       interned_chrome_trigger_hash_key_(
74           storage->InternString(kChromeTriggerHashKey)),
75       interned_chrome_trigger_name_key_(
76           storage->InternString(kChromeTriggerNameKey)),
77       interned_mojo_method_mapping_id_(
78           storage->InternString(kMojoMethodMappingIdKey)),
79       interned_mojo_method_rel_pc_(storage->InternString(kMojoMethodRelPcKey)),
80       interned_mojo_method_name_(storage->InternString(kMojoMethodNameKey)),
81       interned_mojo_interface_tag_(storage->InternString(kMojoIntefaceTagKey)),
82       interned_obfuscated_view_dump_class_name_flat_key_(
83           storage->InternString(kObfuscatedViewDumpClassNameFlatKey)) {}
84 
NeedsTranslation(StringId flat_key_id,StringId key_id,Variadic::Type type) const85 bool ArgsTranslationTable::NeedsTranslation(StringId flat_key_id,
86                                             StringId key_id,
87                                             Variadic::Type type) const {
88   return KeyIdAndTypeToEnum(flat_key_id, key_id, type).has_value();
89 }
90 
TranslateArgs(const ArgsTracker::CompactArgSet & arg_set,ArgsTracker::BoundInserter & inserter) const91 void ArgsTranslationTable::TranslateArgs(
92     const ArgsTracker::CompactArgSet& arg_set,
93     ArgsTracker::BoundInserter& inserter) const {
94   std::optional<uint64_t> mapping_id;
95   std::optional<uint64_t> rel_pc;
96 
97   for (const auto& arg : arg_set) {
98     const auto key_type =
99         KeyIdAndTypeToEnum(arg.flat_key, arg.key, arg.value.type);
100     if (!key_type.has_value()) {
101       inserter.AddArg(arg.flat_key, arg.key, arg.value, arg.update_policy);
102       continue;
103     }
104 
105     switch (*key_type) {
106       case KeyType::kChromeHistogramHash: {
107         inserter.AddArg(interned_chrome_histogram_hash_key_, arg.value);
108         const std::optional<base::StringView> translated_value =
109             TranslateChromeHistogramHash(arg.value.uint_value);
110         if (translated_value) {
111           inserter.AddArg(
112               interned_chrome_histogram_name_key_,
113               Variadic::String(storage_->InternString(*translated_value)));
114         }
115         break;
116       }
117       case KeyType::kChromeUserEventHash: {
118         inserter.AddArg(interned_chrome_user_event_hash_key_, arg.value);
119         const std::optional<base::StringView> translated_value =
120             TranslateChromeUserEventHash(arg.value.uint_value);
121         if (translated_value) {
122           inserter.AddArg(
123               interned_chrome_user_event_action_key_,
124               Variadic::String(storage_->InternString(*translated_value)));
125         }
126         break;
127       }
128       case KeyType::kChromePerformanceMarkMarkHash: {
129         inserter.AddArg(interned_chrome_performance_mark_mark_hash_key_,
130                         arg.value);
131         const std::optional<base::StringView> translated_value =
132             TranslateChromePerformanceMarkMarkHash(arg.value.uint_value);
133         if (translated_value) {
134           inserter.AddArg(
135               interned_chrome_performance_mark_mark_key_,
136               Variadic::String(storage_->InternString(*translated_value)));
137         }
138         break;
139       }
140       case KeyType::kChromePerformanceMarkSiteHash: {
141         inserter.AddArg(interned_chrome_performance_mark_site_hash_key_,
142                         arg.value);
143         const std::optional<base::StringView> translated_value =
144             TranslateChromePerformanceMarkSiteHash(arg.value.uint_value);
145         if (translated_value) {
146           inserter.AddArg(
147               interned_chrome_performance_mark_site_key_,
148               Variadic::String(storage_->InternString(*translated_value)));
149         }
150         break;
151       }
152       case KeyType::kClassName: {
153         const std::optional<StringId> translated_class_name =
154             TranslateClassName(arg.value.string_value);
155         if (translated_class_name) {
156           inserter.AddArg(arg.flat_key, arg.key,
157                           Variadic::String(*translated_class_name));
158         } else {
159           inserter.AddArg(arg.flat_key, arg.key, arg.value);
160         }
161         break;
162       }
163       case KeyType::kChromeTriggerHash: {
164         inserter.AddArg(interned_chrome_trigger_hash_key_, arg.value);
165         const std::optional<base::StringView> translated_value =
166             TranslateChromeStudyHash(arg.value.uint_value);
167         if (translated_value) {
168           inserter.AddArg(
169               interned_chrome_trigger_name_key_,
170               Variadic::String(storage_->InternString(*translated_value)));
171         }
172         break;
173       }
174       case KeyType::kMojoMethodMappingId: {
175         mapping_id = arg.value.uint_value;
176         break;
177       }
178       case KeyType::kMojoMethodRelPc: {
179         rel_pc = arg.value.uint_value;
180         break;
181       }
182     }
183   }
184   EmitMojoMethodLocation(mapping_id, rel_pc, inserter);
185 }
186 
187 std::optional<ArgsTranslationTable::KeyType>
KeyIdAndTypeToEnum(StringId flat_key_id,StringId key_id,Variadic::Type type) const188 ArgsTranslationTable::KeyIdAndTypeToEnum(StringId flat_key_id,
189                                          StringId key_id,
190                                          Variadic::Type type) const {
191   if (type == Variadic::Type::kUint) {
192     if (key_id == interned_chrome_histogram_hash_key_) {
193       return KeyType::kChromeHistogramHash;
194     }
195     if (key_id == interned_chrome_user_event_hash_key_) {
196       return KeyType::kChromeUserEventHash;
197     }
198     if (key_id == interned_chrome_performance_mark_mark_hash_key_) {
199       return KeyType::kChromePerformanceMarkMarkHash;
200     }
201     if (key_id == interned_chrome_performance_mark_site_hash_key_) {
202       return KeyType::kChromePerformanceMarkSiteHash;
203     }
204     if (key_id == interned_mojo_method_mapping_id_) {
205       return KeyType::kMojoMethodMappingId;
206     }
207     if (key_id == interned_mojo_method_rel_pc_) {
208       return KeyType::kMojoMethodRelPc;
209     }
210     if (key_id == interned_chrome_trigger_hash_key_) {
211       return KeyType::kChromeTriggerHash;
212     }
213   } else if (type == Variadic::Type::kString) {
214     if (flat_key_id == interned_obfuscated_view_dump_class_name_flat_key_) {
215       return KeyType::kClassName;
216     }
217   }
218   return std::nullopt;
219 }
220 
221 std::optional<base::StringView>
TranslateChromeHistogramHash(uint64_t hash) const222 ArgsTranslationTable::TranslateChromeHistogramHash(uint64_t hash) const {
223   auto* value = chrome_histogram_hash_to_name_.Find(hash);
224   if (!value) {
225     return std::nullopt;
226   }
227   return base::StringView(*value);
228 }
229 
230 std::optional<base::StringView>
TranslateChromeUserEventHash(uint64_t hash) const231 ArgsTranslationTable::TranslateChromeUserEventHash(uint64_t hash) const {
232   auto* value = chrome_user_event_hash_to_action_.Find(hash);
233   if (!value) {
234     return std::nullopt;
235   }
236   return base::StringView(*value);
237 }
238 
239 std::optional<base::StringView>
TranslateChromePerformanceMarkSiteHash(uint64_t hash) const240 ArgsTranslationTable::TranslateChromePerformanceMarkSiteHash(
241     uint64_t hash) const {
242   auto* value = chrome_performance_mark_site_hash_to_name_.Find(hash);
243   if (!value) {
244     return std::nullopt;
245   }
246   return base::StringView(*value);
247 }
248 
249 std::optional<base::StringView>
TranslateChromePerformanceMarkMarkHash(uint64_t hash) const250 ArgsTranslationTable::TranslateChromePerformanceMarkMarkHash(
251     uint64_t hash) const {
252   auto* value = chrome_performance_mark_mark_hash_to_name_.Find(hash);
253   if (!value) {
254     return std::nullopt;
255   }
256   return base::StringView(*value);
257 }
258 
TranslateChromeStudyHash(uint64_t hash) const259 std::optional<base::StringView> ArgsTranslationTable::TranslateChromeStudyHash(
260     uint64_t hash) const {
261   auto* value = chrome_study_hash_to_name_.Find(hash);
262   if (!value) {
263     return std::nullopt;
264   }
265   return base::StringView(*value);
266 }
267 
268 std::optional<ArgsTranslationTable::SourceLocation>
TranslateNativeSymbol(MappingId mapping_id,uint64_t rel_pc) const269 ArgsTranslationTable::TranslateNativeSymbol(MappingId mapping_id,
270                                             uint64_t rel_pc) const {
271   auto loc =
272       native_symbol_to_location_.Find(std::make_pair(mapping_id, rel_pc));
273   if (!loc) {
274     return std::nullopt;
275   }
276   return *loc;
277 }
278 
TranslateClassName(StringId obfuscated_class_name_id) const279 std::optional<StringId> ArgsTranslationTable::TranslateClassName(
280     StringId obfuscated_class_name_id) const {
281   return deobfuscation_mapping_table_.TranslateClass(obfuscated_class_name_id);
282 }
283 
EmitMojoMethodLocation(std::optional<uint64_t> mapping_id,std::optional<uint64_t> rel_pc,ArgsTracker::BoundInserter & inserter) const284 void ArgsTranslationTable::EmitMojoMethodLocation(
285     std::optional<uint64_t> mapping_id,
286     std::optional<uint64_t> rel_pc,
287     ArgsTracker::BoundInserter& inserter) const {
288   if (!mapping_id || !rel_pc) {
289     return;
290   }
291   const MappingId row_id(static_cast<uint32_t>(*mapping_id));
292   const auto loc = TranslateNativeSymbol(row_id, *rel_pc);
293   if (loc) {
294     inserter.AddArg(interned_mojo_method_name_,
295                     Variadic::String(storage_->InternString(base::StringView(
296                         ExtractMojoMethod((loc->function_name))))));
297     inserter.AddArg(interned_mojo_interface_tag_,
298                     Variadic::String(storage_->InternString(base::StringView(
299                         ExtractMojoInterfaceTag(loc->function_name)))),
300                     // If the trace already has interface tag as a raw string
301                     // (older Chromium versions, local traces, and so on), use
302                     // the raw string.
303                     GlobalArgsTracker::UpdatePolicy::kSkipIfExists);
304   } else {
305     // Could not find the corresponding source location. Let's emit raw arg
306     // values so that the data doesn't silently go missing.
307     inserter.AddArg(interned_mojo_method_mapping_id_,
308                     Variadic::UnsignedInteger(*mapping_id));
309     inserter.AddArg(interned_mojo_method_rel_pc_,
310                     Variadic::UnsignedInteger(*rel_pc));
311   }
312 }
313 
314 }  // namespace trace_processor
315 }  // namespace perfetto
316