xref: /aosp_15_r20/system/extras/simpleperf/report_utils.h (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #pragma once
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <inttypes.h>
20*288bf522SAndroid Build Coastguard Worker 
21*288bf522SAndroid Build Coastguard Worker #include <string>
22*288bf522SAndroid Build Coastguard Worker #include <string_view>
23*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
24*288bf522SAndroid Build Coastguard Worker #include <vector>
25*288bf522SAndroid Build Coastguard Worker 
26*288bf522SAndroid Build Coastguard Worker #include "RegEx.h"
27*288bf522SAndroid Build Coastguard Worker #include "dso.h"
28*288bf522SAndroid Build Coastguard Worker #include "thread_tree.h"
29*288bf522SAndroid Build Coastguard Worker #include "utils.h"
30*288bf522SAndroid Build Coastguard Worker 
31*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
32*288bf522SAndroid Build Coastguard Worker 
33*288bf522SAndroid Build Coastguard Worker class ProguardMappingRetrace {
34*288bf522SAndroid Build Coastguard Worker  public:
35*288bf522SAndroid Build Coastguard Worker   // Add proguard mapping.txt to de-obfuscate minified symbols.
36*288bf522SAndroid Build Coastguard Worker   bool AddProguardMappingFile(std::string_view mapping_file);
37*288bf522SAndroid Build Coastguard Worker 
38*288bf522SAndroid Build Coastguard Worker   bool DeObfuscateJavaMethods(std::string_view obfuscated_name, std::string* original_name,
39*288bf522SAndroid Build Coastguard Worker                               bool* synthesized);
40*288bf522SAndroid Build Coastguard Worker 
41*288bf522SAndroid Build Coastguard Worker  private:
42*288bf522SAndroid Build Coastguard Worker   struct MappingMethod {
43*288bf522SAndroid Build Coastguard Worker     std::string original_name;
44*288bf522SAndroid Build Coastguard Worker     bool contains_classname;
45*288bf522SAndroid Build Coastguard Worker     bool synthesized;
46*288bf522SAndroid Build Coastguard Worker   };
47*288bf522SAndroid Build Coastguard Worker 
48*288bf522SAndroid Build Coastguard Worker   struct MappingClass {
49*288bf522SAndroid Build Coastguard Worker     std::string original_classname;
50*288bf522SAndroid Build Coastguard Worker     bool synthesized = false;
51*288bf522SAndroid Build Coastguard Worker     // Map from obfuscated method names to MappingMethod.
52*288bf522SAndroid Build Coastguard Worker     std::unordered_map<std::string, MappingMethod> method_map;
53*288bf522SAndroid Build Coastguard Worker   };
54*288bf522SAndroid Build Coastguard Worker 
55*288bf522SAndroid Build Coastguard Worker   enum LineType {
56*288bf522SAndroid Build Coastguard Worker     SYNTHESIZED_COMMENT,
57*288bf522SAndroid Build Coastguard Worker     CLASS_LINE,
58*288bf522SAndroid Build Coastguard Worker     METHOD_LINE,
59*288bf522SAndroid Build Coastguard Worker     LINE_EOF,
60*288bf522SAndroid Build Coastguard Worker   };
61*288bf522SAndroid Build Coastguard Worker 
62*288bf522SAndroid Build Coastguard Worker   struct LineInfo {
63*288bf522SAndroid Build Coastguard Worker     LineType type;
64*288bf522SAndroid Build Coastguard Worker     std::string_view data;
65*288bf522SAndroid Build Coastguard Worker   };
66*288bf522SAndroid Build Coastguard Worker 
67*288bf522SAndroid Build Coastguard Worker   void ParseMethod(MappingClass& mapping_class);
68*288bf522SAndroid Build Coastguard Worker   void MoveToNextLine();
69*288bf522SAndroid Build Coastguard Worker 
70*288bf522SAndroid Build Coastguard Worker   // Map from obfuscated class names to ProguardMappingClass.
71*288bf522SAndroid Build Coastguard Worker   std::unordered_map<std::string, MappingClass> class_map_;
72*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<LineReader> line_reader_;
73*288bf522SAndroid Build Coastguard Worker   LineInfo cur_line_;
74*288bf522SAndroid Build Coastguard Worker };
75*288bf522SAndroid Build Coastguard Worker 
76*288bf522SAndroid Build Coastguard Worker enum class CallChainExecutionType {
77*288bf522SAndroid Build Coastguard Worker   NATIVE_METHOD,
78*288bf522SAndroid Build Coastguard Worker   INTERPRETED_JVM_METHOD,
79*288bf522SAndroid Build Coastguard Worker   JIT_JVM_METHOD,
80*288bf522SAndroid Build Coastguard Worker   // ART methods near interpreted/JIT JVM methods. They're shown only when RemoveArtFrame = false.
81*288bf522SAndroid Build Coastguard Worker   ART_METHOD,
82*288bf522SAndroid Build Coastguard Worker };
83*288bf522SAndroid Build Coastguard Worker 
84*288bf522SAndroid Build Coastguard Worker struct CallChainReportEntry {
85*288bf522SAndroid Build Coastguard Worker   uint64_t ip = 0;
86*288bf522SAndroid Build Coastguard Worker   const Symbol* symbol = nullptr;
87*288bf522SAndroid Build Coastguard Worker   Dso* dso = nullptr;
88*288bf522SAndroid Build Coastguard Worker   const char* dso_name = nullptr;
89*288bf522SAndroid Build Coastguard Worker   uint64_t vaddr_in_file = 0;
90*288bf522SAndroid Build Coastguard Worker   const MapEntry* map = nullptr;
91*288bf522SAndroid Build Coastguard Worker   CallChainExecutionType execution_type = CallChainExecutionType::NATIVE_METHOD;
92*288bf522SAndroid Build Coastguard Worker };
93*288bf522SAndroid Build Coastguard Worker 
94*288bf522SAndroid Build Coastguard Worker // a base class for modifying callchain reports
95*288bf522SAndroid Build Coastguard Worker class CallChainReportModifier {
96*288bf522SAndroid Build Coastguard Worker  public:
97*288bf522SAndroid Build Coastguard Worker   virtual ~CallChainReportModifier();
98*288bf522SAndroid Build Coastguard Worker 
99*288bf522SAndroid Build Coastguard Worker   virtual void Modify(std::vector<CallChainReportEntry>& callchain) = 0;
100*288bf522SAndroid Build Coastguard Worker };
101*288bf522SAndroid Build Coastguard Worker 
102*288bf522SAndroid Build Coastguard Worker class CallChainReportBuilder {
103*288bf522SAndroid Build Coastguard Worker  public:
104*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder(ThreadTree& thread_tree);
105*288bf522SAndroid Build Coastguard Worker   // If true, remove interpreter frames both before and after a Java frame.
106*288bf522SAndroid Build Coastguard Worker   // Default is true.
107*288bf522SAndroid Build Coastguard Worker   void SetRemoveArtFrame(bool enable);
108*288bf522SAndroid Build Coastguard Worker   // If true, convert a JIT method into its corresponding interpreted Java method. So they can be
109*288bf522SAndroid Build Coastguard Worker   // merged in reports like flamegraph. Default is true.
110*288bf522SAndroid Build Coastguard Worker   void SetConvertJITFrame(bool enable);
111*288bf522SAndroid Build Coastguard Worker   // Add proguard mapping.txt to de-obfuscate minified symbols.
112*288bf522SAndroid Build Coastguard Worker   bool AddProguardMappingFile(std::string_view mapping_file);
113*288bf522SAndroid Build Coastguard Worker   // Remove methods with name containing the given regular expression.
114*288bf522SAndroid Build Coastguard Worker   bool RemoveMethod(std::string_view method_name_regex);
115*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> Build(const ThreadEntry* thread,
116*288bf522SAndroid Build Coastguard Worker                                           const std::vector<uint64_t>& ips, size_t kernel_ip_count);
117*288bf522SAndroid Build Coastguard Worker 
118*288bf522SAndroid Build Coastguard Worker  private:
119*288bf522SAndroid Build Coastguard Worker   void MarkArtFrame(std::vector<CallChainReportEntry>& callchain);
120*288bf522SAndroid Build Coastguard Worker 
121*288bf522SAndroid Build Coastguard Worker   ThreadTree& thread_tree_;
122*288bf522SAndroid Build Coastguard Worker   bool remove_r8_synthesized_frame_ = false;
123*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<CallChainReportModifier> art_frame_remover_;
124*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<CallChainReportModifier> jit_frame_converter_;
125*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<CallChainReportModifier> java_method_deobfuscater_;
126*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<CallChainReportModifier> method_name_filter_;
127*288bf522SAndroid Build Coastguard Worker };
128*288bf522SAndroid Build Coastguard Worker 
129*288bf522SAndroid Build Coastguard Worker struct ThreadReport {
130*288bf522SAndroid Build Coastguard Worker   int pid;
131*288bf522SAndroid Build Coastguard Worker   int tid;
132*288bf522SAndroid Build Coastguard Worker   const char* thread_name;
133*288bf522SAndroid Build Coastguard Worker 
134*288bf522SAndroid Build Coastguard Worker   ThreadReport(int pid = 0, int tid = 0, const char* thread_name = nullptr)
pidThreadReport135*288bf522SAndroid Build Coastguard Worker       : pid(pid), tid(tid), thread_name(thread_name) {}
136*288bf522SAndroid Build Coastguard Worker };
137*288bf522SAndroid Build Coastguard Worker 
138*288bf522SAndroid Build Coastguard Worker // Report thread info of a sample.
139*288bf522SAndroid Build Coastguard Worker class ThreadReportBuilder {
140*288bf522SAndroid Build Coastguard Worker  public:
141*288bf522SAndroid Build Coastguard Worker   // Aggregate threads with names matching the same regex.
142*288bf522SAndroid Build Coastguard Worker   bool AggregateThreads(const std::vector<std::string>& thread_name_regex);
143*288bf522SAndroid Build Coastguard Worker   ThreadReport Build(const ThreadEntry& thread);
144*288bf522SAndroid Build Coastguard Worker 
145*288bf522SAndroid Build Coastguard Worker  private:
146*288bf522SAndroid Build Coastguard Worker   void ModifyReportToAggregateThreads(ThreadReport& report);
147*288bf522SAndroid Build Coastguard Worker 
148*288bf522SAndroid Build Coastguard Worker   struct ThreadNameRegInfo {
149*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<RegEx> re;
150*288bf522SAndroid Build Coastguard Worker     ThreadReport report;
151*288bf522SAndroid Build Coastguard Worker   };
152*288bf522SAndroid Build Coastguard Worker 
153*288bf522SAndroid Build Coastguard Worker   std::vector<ThreadNameRegInfo> thread_regs_;
154*288bf522SAndroid Build Coastguard Worker   // Map from thread name to the corresponding index in thread_regs_.
155*288bf522SAndroid Build Coastguard Worker   // Return -1 if the thread name doesn't match any regular expression.
156*288bf522SAndroid Build Coastguard Worker   std::unordered_map<std::string, int> thread_map_;
157*288bf522SAndroid Build Coastguard Worker };
158*288bf522SAndroid Build Coastguard Worker 
159*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf
160