libredex/PassManager.h (114 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <boost/optional.hpp>
#include <memory>
#include <string>
#include <typeinfo>
#include <unordered_map>
#include <utility>
#include <vector>
#include "AnalysisUsage.h"
#include "AssetManager.h"
#include "DexHasher.h"
#include "GlobalConfig.h"
#include "JsonWrapper.h"
#include "ProguardConfiguration.h"
#include "RedexOptions.h"
#include "Timer.h"
struct ConfigFiles;
class DexStore;
class Pass;
namespace Json {
class Value;
} // namespace Json
// Must match DexStore.
using DexStoresVector = std::vector<DexStore>;
class PassManager {
public:
explicit PassManager(const std::vector<Pass*>& passes);
explicit PassManager(const std::vector<Pass*>& passes,
const Json::Value& config,
const RedexOptions& options = RedexOptions{});
PassManager(const std::vector<Pass*>& passes,
std::unique_ptr<keep_rules::ProguardConfiguration> pg_config);
PassManager(const std::vector<Pass*>& passes,
std::unique_ptr<keep_rules::ProguardConfiguration> pg_config,
const Json::Value& config,
const RedexOptions& options = RedexOptions{});
~PassManager();
struct PassInfo {
const Pass* pass;
size_t order; // zero-based
size_t repeat; // zero-based
size_t total_repeat;
std::string name;
std::unordered_map<std::string, int64_t> metrics;
JsonWrapper config;
boost::optional<hashing::DexHash> hash;
};
void run_passes(DexStoresVector&, ConfigFiles&);
void incr_metric(const std::string& key, int64_t value);
void set_metric(const std::string& key, int64_t value);
int64_t get_metric(const std::string& key);
const std::vector<PassManager::PassInfo>& get_pass_info() const;
boost::optional<hashing::DexHash> get_initial_hash() const {
return m_initial_hash;
}
const RedexOptions& get_redex_options() const { return m_redex_options; }
// A temporary hack to return the interdex metrics. Will be removed later.
const std::unordered_map<std::string, int64_t>& get_interdex_metrics();
keep_rules::ProguardConfiguration& get_proguard_config() {
return *m_pg_config;
}
bool no_proguard_rules() {
return m_pg_config->keep_rules.empty() && !m_testing_mode;
}
// Call set_testing_mode() in tests that need passes to run which
// do not use ProGuard configuration keep rules.
void set_testing_mode() { m_testing_mode = true; }
const PassInfo* get_current_pass_info() const { return m_current_pass_info; }
AssetManager& asset_manager() { return m_asset_mgr; }
void record_running_regalloc() { m_regalloc_has_run = true; }
bool regalloc_has_run() const { return m_regalloc_has_run; }
void record_init_class_lowering() { m_init_class_lowering_has_run = true; }
bool init_class_lowering_has_run() const {
return m_init_class_lowering_has_run;
}
void record_running_interdex() { m_interdex_has_run = true; }
bool interdex_has_run() const { return m_interdex_has_run; }
void record_unreliable_virtual_scopes() {
m_unreliable_virtual_scopes = true;
}
bool unreliable_virtual_scopes() const { return m_unreliable_virtual_scopes; }
template <typename PassType>
PassType* get_preserved_analysis() const {
auto pass =
m_preserved_analysis_passes.find(get_analysis_id_by_pass<PassType>());
if (pass != m_preserved_analysis_passes.end()) {
return static_cast<PassType*>(pass->second);
}
return nullptr;
}
Pass* find_pass(const std::string& pass_name) const;
const AssessorConfig& get_assessor_config() const {
return m_assessor_config;
}
private:
void activate_pass(const std::string& name, const Json::Value& conf);
void init(const Json::Value& config);
hashing::DexHash run_hasher(const char* name, const Scope& scope);
void eval_passes(DexStoresVector&, ConfigFiles&);
AssetManager m_asset_mgr;
std::vector<Pass*> m_registered_passes;
std::vector<Pass*> m_activated_passes;
std::unordered_map<AnalysisID, Pass*> m_preserved_analysis_passes;
// Per-pass information and metrics
std::vector<PassManager::PassInfo> m_pass_info;
PassInfo* m_current_pass_info;
std::unique_ptr<keep_rules::ProguardConfiguration> m_pg_config;
const RedexOptions m_redex_options;
bool m_testing_mode{false};
bool m_regalloc_has_run{false};
bool m_init_class_lowering_has_run{false};
bool m_interdex_has_run{false};
bool m_unreliable_virtual_scopes{false};
Pass* m_malloc_profile_pass{nullptr};
boost::optional<hashing::DexHash> m_initial_hash;
AccumulatingTimer m_hashers_timer;
AccumulatingTimer m_check_unique_deobfuscateds_timer;
AssessorConfig m_assessor_config;
};