libredex/GlobalConfig.cpp (156 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. */ #include "GlobalConfig.h" void InlinerConfig::bind_config() { bind("delete_non_virtuals", delete_non_virtuals, delete_non_virtuals); bind("true_virtual_inline", true_virtual_inline, true_virtual_inline); bind("intermediate_shrinking", intermediate_shrinking, intermediate_shrinking); bind("enforce_method_size_limit", enforce_method_size_limit, enforce_method_size_limit); bind("throws", throws_inline, throws_inline); bind("throw_after_no_return", throw_after_no_return, throw_after_no_return); bind("multiple_callers", multiple_callers, multiple_callers); bind("run_const_prop", shrinker.run_const_prop, shrinker.run_const_prop); bind("run_cse", shrinker.run_cse, shrinker.run_cse); bind("run_dedup_blocks", shrinker.run_dedup_blocks, shrinker.run_dedup_blocks); bind("run_copy_prop", shrinker.run_copy_prop, shrinker.run_copy_prop); bind("run_reg_alloc", shrinker.run_reg_alloc, shrinker.run_reg_alloc); bind("run_fast_reg_alloc", shrinker.run_fast_reg_alloc, shrinker.run_fast_reg_alloc); bind("run_local_dce", shrinker.run_local_dce, shrinker.run_local_dce); bind("no_inline_annos", {}, m_no_inline_annos); bind("force_inline_annos", {}, m_force_inline_annos); bind("blocklist", {}, m_blocklist); bind("blocklist", {}, m_blocklist); bind("caller_blocklist", {}, m_caller_blocklist); bind("intradex_allowlist", {}, m_intradex_allowlist, "The purpose of this white-list is to remove black-list entries when " "inlining after the InterDex pass has run. (This reduces the impact of " "black-list entries that avoid inlining conditional control-flow and " "catchers that cause issues with the SwitchMethodPartitioning analysis " "that tends to be used by passes that run before or during InterDex.)"); } void OptDecisionsConfig::bind_config() { bind("enable_logs", false, enable_logs, "Should we log Redex's optimization decisions?"); } void IRTypeCheckerConfig::bind_config() { bind("run_after_each_pass", {}, run_after_each_pass); bind("verify_moves", {}, verify_moves); bind("validate_invoke_super", {}, validate_invoke_super); bind("run_after_passes", {}, run_after_passes); bind("check_no_overwrite_this", {}, check_no_overwrite_this); bind("check_num_of_refs", {}, check_num_of_refs); bind("annotated_cfg_on_error", annotated_cfg_on_error, annotated_cfg_on_error); } void HasherConfig::bind_config() { bind("run_after_each_pass", {}, run_after_each_pass); } void AssessorConfig::bind_config() { bind("run_after_each_pass", run_after_each_pass, run_after_each_pass); bind("run_initially", run_initially, run_initially); bind("run_finally", run_finally, run_finally); } void CheckUniqueDeobfuscatedNamesConfig::bind_config() { bind("run_after_each_pass", run_after_each_pass, run_after_each_pass); bind("run_initially", run_initially, run_initially); bind("run_finally", run_finally, run_finally); } void MethodProfileOrderingConfig::bind_config() { bind("method_sorting_allowlisted_substrings", method_sorting_allowlisted_substrings, method_sorting_allowlisted_substrings); bind("legacy_profiled_code_item_sort_order", legacy_order, legacy_order); bind("min_appear_percent", min_appear_percent, min_appear_percent); bind("second_min_appear_percent", second_min_appear_percent, second_min_appear_percent); } void ProguardConfig::bind_config() { bind("blocklist", blocklist, blocklist); bind("disable_default_blocklist", disable_default_blocklist, disable_default_blocklist); } void GlobalConfig::bind_config() { bool bool_param; std::string string_param; std::unordered_map<std::string, std::string> string_map_param; std::vector<std::string> string_vector_param; uint32_t uint32_param; // Sorted alphabetically bind("agg_method_stats_files", {}, string_vector_param); bind("android_sdk_api_15_file", "", string_param); bind("android_sdk_api_16_file", "", string_param); bind("android_sdk_api_17_file", "", string_param); bind("android_sdk_api_18_file", "", string_param); bind("android_sdk_api_19_file", "", string_param); bind("android_sdk_api_21_file", "", string_param); bind("android_sdk_api_23_file", "", string_param); bind("android_sdk_api_25_file", "", string_param); bind("android_sdk_api_26_file", "", string_param); bind("android_sdk_api_27_file", "", string_param); bind("android_sdk_api_28_file", "", string_param); bind("android_sdk_api_29_file", "", string_param); bind("bytecode_sort_mode", {}, string_vector_param); bind("coldstart_classes", "", string_param); bind("compute_xml_reachability", false, bool_param); bind("unused_keep_rule_abort", false, bool_param); bind("debug_info_kind", "", string_param); bind("default_coldstart_classes", "", string_param); bind("emit_class_method_info_map", false, bool_param); bind("emit_locator_strings", {}, bool_param); bind("iodi_layer_mode", "full", string_param, "IODI layer mode. One of \"full\", \"skip-layer-0-at-api-26\" or " "\"always-skip-layer-0\""); bind("symbolicate_detached_methods", false, bool_param); bind("enable_quickening", false, bool_param); bind("ab_experiments_states", {}, string_map_param); bind("ab_experiments_states_override", {}, string_map_param); bind("ab_experiments_default", "", string_param); bind("force_single_dex", false, bool_param); bind("emit_incoming_hashes", false, bool_param); bind("emit_outgoing_hashes", false, bool_param); bind("instruction_size_bitwidth_limit", 0u, uint32_param); bind("json_serde_supercls", {}, string_vector_param); bind("keep_all_annotation_classes", true, bool_param); bind("keep_methods", {}, string_vector_param); bind("keep_packages", {}, string_vector_param); bind("legacy_reflection_reachability", false, bool_param); bind("lower_with_cfg", {}, bool_param); bind("no_optimizations_annotations", {}, string_vector_param); // TODO: Remove unused profiled_methods_file option and all build system // references bind("profiled_methods_file", "", string_param); bind("proguard_map", "", string_param); bind("prune_unexported_components", {}, string_vector_param); bind("pure_methods", {}, string_vector_param); bind("finalish_field_names", {}, string_vector_param); bind("record_keep_reasons", {}, bool_param); bind("dump_keep_reasons", {}, bool_param); bind("string_sort_mode", "", string_param); bind("write_cfg_each_pass", false, bool_param); bind("dump_cfg_classes", "", string_param); bind("slow_invariants_debug", false, bool_param); // Enabled for ease of testing, apps expected to opt-out bind("enable_bleeding_edge_app_bundle_support", true, bool_param); bind("no_devirtualize_annos", {}, string_vector_param); bind("create_init_class_insns", true, bool_param); bind("finalize_resource_table", false, bool_param); for (const auto& entry : m_registry) { m_global_configs.emplace(entry.name, entry.bind_operation(this, entry.name)); } } GlobalConfigRegistryEntry::GlobalConfigRegistryEntry( const std::string& name, BindOperationFn bind_operation) : name(name), bind_operation(std::move(bind_operation)) {} GlobalConfigRegistry& GlobalConfig::default_registry() { static GlobalConfigRegistry registry{ register_as<InlinerConfig>("inliner"), register_as<IRTypeCheckerConfig>("ir_type_checker"), register_as<HasherConfig>("hasher"), register_as<AssessorConfig>("assessor"), register_as<CheckUniqueDeobfuscatedNamesConfig>( "check_unique_deobfuscated_names"), register_as<OptDecisionsConfig>("opt_decisions"), register_as<MethodProfileOrderingConfig>("method_profile_order"), register_as<ProguardConfig>("proguard"), }; return registry; }