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