/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_PROFILING_DEOBFUSCATOR_H_ #define SRC_PROFILING_DEOBFUSCATOR_H_ #include #include #include #include #include #include "perfetto/base/status.h" namespace perfetto { namespace profiling { std::string FlattenClasses( const std::map>& m); class ObfuscatedClass { public: explicit ObfuscatedClass(std::string d) : deobfuscated_name_(std::move(d)) {} ObfuscatedClass( std::string d, std::map f, std::map>> m) : deobfuscated_name_(std::move(d)), deobfuscated_fields_(std::move(f)), deobfuscated_methods_(std::move(m)) {} const std::string& deobfuscated_name() const { return deobfuscated_name_; } const std::map& deobfuscated_fields() const { return deobfuscated_fields_; } std::map deobfuscated_methods() const { std::map result; for (const auto& p : deobfuscated_methods_) { result.emplace(p.first, FlattenClasses(p.second)); } return result; } bool redefined_methods() const { return redefined_methods_; } bool AddField(std::string obfuscated_name, std::string deobfuscated_name) { auto p = deobfuscated_fields_.emplace(std::move(obfuscated_name), deobfuscated_name); return p.second || p.first->second == deobfuscated_name; } void AddMethod(std::string obfuscated_name, std::string deobfuscated_name) { std::string cls = deobfuscated_name_; auto dot = deobfuscated_name.rfind('.'); if (dot != std::string::npos) { cls = deobfuscated_name.substr(0, dot); deobfuscated_name = deobfuscated_name.substr(dot + 1); } auto& deobfuscated_names_for_cls = deobfuscated_methods_[std::move(obfuscated_name)][std::move(cls)]; deobfuscated_names_for_cls.push_back(std::move(deobfuscated_name)); if (deobfuscated_names_for_cls.size() > 1 || deobfuscated_methods_.size() > 1) { redefined_methods_ = true; } } private: std::string deobfuscated_name_; std::map deobfuscated_fields_; std::map>> deobfuscated_methods_; bool redefined_methods_ = false; }; class ProguardParser { public: // A return value of false means this line failed to parse. This leaves the // parser in an undefined state and it should no longer be used. base::Status AddLine(std::string line); bool AddLines(std::string contents); std::map ConsumeMapping() { return std::move(mapping_); } private: std::map mapping_; ObfuscatedClass* current_class_ = nullptr; }; struct ProguardMap { std::string package; std::string filename; }; void MakeDeobfuscationPackets( const std::string& package_name, const std::map& mapping, std::function callback); std::vector GetPerfettoProguardMapPath(); bool ReadProguardMapsToDeobfuscationPackets( const std::vector& maps, std::function fn); } // namespace profiling } // namespace perfetto #endif // SRC_PROFILING_DEOBFUSCATOR_H_