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