libredex/ConfigFiles.h (126 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 <map> #include <memory> #include <string> #include <unordered_set> #include <vector> #include "GlobalConfig.h" #include "JsonWrapper.h" #include "ProguardMap.h" class DexMethodRef; class DexType; struct ProguardMap; namespace Json { class Value; } // namespace Json namespace api { class AndroidSDK; } // namespace api namespace inliner { struct InlinerConfig; } // namespace inliner namespace method_profiles { class MethodProfiles; } // namespace method_profiles /** * ConfigFiles should be a readonly structure */ struct ConfigFiles { explicit ConfigFiles(const Json::Value& config); ConfigFiles(const Json::Value& config, const std::string& outdir); ~ConfigFiles(); const std::vector<std::string>& get_coldstart_classes() { if (m_coldstart_classes.empty()) { m_coldstart_classes = load_coldstart_classes(); } return m_coldstart_classes; } /** * NOTE: ONLY use if you know what you are doing! */ void update_coldstart_classes( std::vector<std::string> new_coldstart_classes) { m_coldstart_classes = std::move(new_coldstart_classes); } void ensure_class_lists_loaded() { if (!m_load_class_lists_attempted) { m_load_class_lists_attempted = true; m_class_lists = load_class_lists(); } } const std::unordered_map<std::string, std::vector<std::string>>& get_all_class_lists() { ensure_class_lists_loaded(); return m_class_lists; } bool has_class_list(const std::string& name) { ensure_class_lists_loaded(); return m_class_lists.count(name) != 0; } const std::vector<std::string>& get_class_list(const std::string& name) { ensure_class_lists_loaded(); return m_class_lists.at(name); } const std::vector<std::string>& get_dead_class_list(); const method_profiles::MethodProfiles& get_method_profiles() { ensure_agg_method_stats_loaded(); return *m_method_profiles; } void process_unresolved_method_profile_lines(); const std::unordered_set<DexType*>& get_no_optimizations_annos(); const std::unordered_set<DexMethodRef*>& get_pure_methods(); const std::unordered_set<const DexString*>& get_finalish_field_names(); const std::unordered_set<DexType*>& get_do_not_devirt_anon(); std::string metafile(const std::string& basename) const { if (basename.empty()) { return std::string(); } return outdir + "/meta/" + basename; } std::string get_outdir() const { return outdir; } // For development only! void set_outdir(const std::string& new_outdir); const ProguardMap& get_proguard_map() const; const std::string& get_printseeds() const { return m_printseeds; } uint32_t get_instruction_size_bitwidth_limit() const { return m_instruction_size_bitwidth_limit; } const JsonWrapper& get_json_config() const { return m_json; } const GlobalConfig& get_global_config() const { return m_global_config; } /** * Get the global inliner config from the "inliner" section. If there is not * such section, will also look up "MethodInlinePass" section for backward * compatibility. */ const inliner::InlinerConfig& get_inliner_config(); boost::optional<std::string> get_android_sdk_api_file(int32_t api_level) { std::string api_file; std::string key = "android_sdk_api_" + std::to_string(api_level) + "_file"; m_json.get(key.c_str(), "", api_file); if (api_file.empty()) { return boost::none; } return boost::optional<std::string>(api_file); } const api::AndroidSDK& get_android_sdk_api(int32_t min_sdk_api); void parse_global_config(); /** * Load configurations with the initial scope. */ void load(const Scope& scope); bool force_single_dex() const; bool emit_incoming_hashes() const; bool emit_outgoing_hashes() const; bool create_init_class_insns() const; bool finalize_resource_table() const; private: JsonWrapper m_json; std::string outdir; GlobalConfig m_global_config; std::vector<std::string> load_coldstart_classes(); std::unordered_map<std::string, std::vector<std::string>> load_class_lists(); void ensure_agg_method_stats_loaded(); void load_inliner_config(inliner::InlinerConfig*); bool m_load_class_lists_attempted{false}; std::unique_ptr<ProguardMap> m_proguard_map; std::string m_coldstart_class_filename; std::vector<std::string> m_coldstart_classes; std::unordered_map<std::string, std::vector<std::string>> m_class_lists; std::vector<std::string> m_dead_class_list; bool m_dead_class_list_attempted{false}; std::string m_printseeds; // Filename to dump computed seeds. std::unique_ptr<method_profiles::MethodProfiles> m_method_profiles; // limits the output instruction size of any DexMethod to 2^n // 0 when limit is not present uint32_t m_instruction_size_bitwidth_limit; std::unordered_set<DexType*> m_no_devirtualize_annos; // global no optimizations annotations std::unordered_set<DexType*> m_no_optimizations_annos; // global pure methods std::unordered_set<DexMethodRef*> m_pure_methods; // names of fields that behave similar to final fields, i.e. written once // before use std::unordered_set<const DexString*> m_finalish_field_names; // Global inliner config. std::unique_ptr<inliner::InlinerConfig> m_inliner_config; // min_sdk AndroidAPI int32_t m_min_sdk_api_level = 0; std::unique_ptr<api::AndroidSDK> m_android_min_sdk_api; };