1 /* 2 * Copyright (C) 2019 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 #ifndef SRC_PROFILING_DEOBFUSCATOR_H_ 18 #define SRC_PROFILING_DEOBFUSCATOR_H_ 19 20 #include <functional> 21 #include <map> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 #include "perfetto/base/status.h" 26 27 namespace perfetto { 28 namespace profiling { 29 30 std::string FlattenClasses( 31 const std::map<std::string, std::vector<std::string>>& m); 32 33 class ObfuscatedClass { 34 public: ObfuscatedClass(std::string d)35 explicit ObfuscatedClass(std::string d) : deobfuscated_name_(std::move(d)) {} ObfuscatedClass(std::string d,std::map<std::string,std::string> f,std::map<std::string,std::map<std::string,std::vector<std::string>>> m)36 ObfuscatedClass( 37 std::string d, 38 std::map<std::string, std::string> f, 39 std::map<std::string, std::map<std::string, std::vector<std::string>>> m) 40 : deobfuscated_name_(std::move(d)), 41 deobfuscated_fields_(std::move(f)), 42 deobfuscated_methods_(std::move(m)) {} 43 deobfuscated_name()44 const std::string& deobfuscated_name() const { return deobfuscated_name_; } 45 deobfuscated_fields()46 const std::map<std::string, std::string>& deobfuscated_fields() const { 47 return deobfuscated_fields_; 48 } 49 deobfuscated_methods()50 std::map<std::string, std::string> deobfuscated_methods() const { 51 std::map<std::string, std::string> result; 52 for (const auto& p : deobfuscated_methods_) { 53 result.emplace(p.first, FlattenClasses(p.second)); 54 } 55 return result; 56 } 57 redefined_methods()58 bool redefined_methods() const { return redefined_methods_; } 59 AddField(std::string obfuscated_name,std::string deobfuscated_name)60 bool AddField(std::string obfuscated_name, std::string deobfuscated_name) { 61 auto p = deobfuscated_fields_.emplace(std::move(obfuscated_name), 62 deobfuscated_name); 63 return p.second || p.first->second == deobfuscated_name; 64 } 65 AddMethod(std::string obfuscated_name,std::string deobfuscated_name)66 void AddMethod(std::string obfuscated_name, std::string deobfuscated_name) { 67 std::string cls = deobfuscated_name_; 68 auto dot = deobfuscated_name.rfind('.'); 69 if (dot != std::string::npos) { 70 cls = deobfuscated_name.substr(0, dot); 71 deobfuscated_name = deobfuscated_name.substr(dot + 1); 72 } 73 auto& deobfuscated_names_for_cls = 74 deobfuscated_methods_[std::move(obfuscated_name)][std::move(cls)]; 75 deobfuscated_names_for_cls.push_back(std::move(deobfuscated_name)); 76 if (deobfuscated_names_for_cls.size() > 1 || 77 deobfuscated_methods_.size() > 1) { 78 redefined_methods_ = true; 79 } 80 } 81 82 private: 83 std::string deobfuscated_name_; 84 std::map<std::string, std::string> deobfuscated_fields_; 85 std::map<std::string, std::map<std::string, std::vector<std::string>>> 86 deobfuscated_methods_; 87 bool redefined_methods_ = false; 88 }; 89 90 class ProguardParser { 91 public: 92 // A return value of false means this line failed to parse. This leaves the 93 // parser in an undefined state and it should no longer be used. 94 base::Status AddLine(std::string line); 95 bool AddLines(std::string contents); 96 ConsumeMapping()97 std::map<std::string, ObfuscatedClass> ConsumeMapping() { 98 return std::move(mapping_); 99 } 100 101 private: 102 std::map<std::string, ObfuscatedClass> mapping_; 103 ObfuscatedClass* current_class_ = nullptr; 104 }; 105 106 struct ProguardMap { 107 std::string package; 108 std::string filename; 109 }; 110 111 void MakeDeobfuscationPackets( 112 const std::string& package_name, 113 const std::map<std::string, profiling::ObfuscatedClass>& mapping, 114 std::function<void(const std::string&)> callback); 115 116 std::vector<ProguardMap> GetPerfettoProguardMapPath(); 117 118 bool ReadProguardMapsToDeobfuscationPackets( 119 const std::vector<ProguardMap>& maps, 120 std::function<void(std::string)> fn); 121 122 } // namespace profiling 123 } // namespace perfetto 124 125 #endif // SRC_PROFILING_DEOBFUSCATOR_H_ 126