blob: ac43eb8497ce2091194d47a18d80ccf6ef2dc6b4 [file] [log] [blame] [edit]
/*
* 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 <cstdint>
#include <functional>
#include <map>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "perfetto/base/status.h"
namespace perfetto {
namespace profiling {
std::string FlattenClasses(
const std::map<std::string, std::vector<std::string>>& m);
// R8 inline method mapping with line number information.
// Multiple entries with the same obfuscated_name and overlapping obfuscated
// line ranges form an inline chain, ordered innermost (inlined) first.
struct MethodMapping {
std::string obfuscated_name;
std::string deobfuscated_name; // Fully qualified: "com.example.Class.method"
std::optional<uint32_t> obfuscated_line_start;
std::optional<uint32_t> obfuscated_line_end;
std::optional<uint32_t> source_line_start;
std::optional<uint32_t> source_line_end;
};
class ObfuscatedClass {
public:
explicit ObfuscatedClass(std::string d) : deobfuscated_name_(std::move(d)) {}
const std::string& deobfuscated_name() const { return deobfuscated_name_; }
const std::map<std::string, std::string>& deobfuscated_fields() const {
return deobfuscated_fields_;
}
// Returns map of obfuscated_name -> deobfuscated_name.
// For R8 inline chains, returns the outermost method.
// For ambiguous mappings, joins names with " | ".
std::map<std::string, std::string> deobfuscated_methods() const;
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(MethodMapping mapping) {
method_mappings_.push_back(std::move(mapping));
}
const std::vector<MethodMapping>& method_mappings() const {
return method_mappings_;
}
private:
std::string deobfuscated_name_;
std::map<std::string, std::string> deobfuscated_fields_;
std::vector<MethodMapping> method_mappings_;
};
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<std::string, ObfuscatedClass> ConsumeMapping() {
return std::move(mapping_);
}
private:
std::map<std::string, ObfuscatedClass> mapping_;
ObfuscatedClass* current_class_ = nullptr;
};
struct ProguardMap {
std::string package;
std::string filename;
};
void MakeDeobfuscationPackets(
const std::string& package_name,
const std::map<std::string, profiling::ObfuscatedClass>& mapping,
std::function<void(const std::string&)> callback);
std::vector<ProguardMap> GetPerfettoProguardMapPath();
bool ReadProguardMapsToDeobfuscationPackets(
const std::vector<ProguardMap>& maps,
std::function<void(std::string)> fn);
} // namespace profiling
} // namespace perfetto
#endif // SRC_PROFILING_DEOBFUSCATOR_H_