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